diff --git a/CREATE_OPTIMIZATION_INDEXES.sql b/CREATE_OPTIMIZATION_INDEXES.sql deleted file mode 100644 index 7251b99..0000000 --- a/CREATE_OPTIMIZATION_INDEXES.sql +++ /dev/null @@ -1,81 +0,0 @@ --- 数据库索引创建脚本 --- 此脚本用于优化应用性能,为常用查询字段创建索引 - --- ============================================ --- 用户相关表索引 --- ============================================ - --- users表索引 -CREATE INDEX IF NOT EXISTS idx_users_userId ON users(userId); -CREATE INDEX IF NOT EXISTS idx_users_phoneNumber ON users(phoneNumber); -CREATE INDEX IF NOT EXISTS idx_users_type ON users(type); -CREATE INDEX IF NOT EXISTS idx_users_level ON users(level); -CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at); - --- ============================================ --- 管理员相关表索引 --- ============================================ - --- managers表索引 -CREATE INDEX IF NOT EXISTS idx_managers_id ON managers(id); -CREATE INDEX IF NOT EXISTS idx_managers_userName ON managers(userName); -CREATE INDEX IF NOT EXISTS idx_managers_managerId ON managers(managerId); -CREATE INDEX IF NOT EXISTS idx_managers_organization ON managers(organization); -CREATE INDEX IF NOT EXISTS idx_managers_managerdepartment ON managers(managerdepartment); - --- ============================================ --- 用户管理相关表索引 --- ============================================ - --- usermanagements表索引 -CREATE INDEX IF NOT EXISTS idx_usermanagements_userId ON usermanagements(userId); -CREATE INDEX IF NOT EXISTS idx_usermanagements_managerId ON usermanagements(managerId); -CREATE INDEX IF NOT EXISTS idx_usermanagements_userName ON usermanagements(userName); -CREATE INDEX IF NOT EXISTS idx_usermanagements_organization ON usermanagements(organization); -CREATE INDEX IF NOT EXISTS idx_usermanagements_managerdepartment ON usermanagements(managerdepartment); - --- ============================================ --- 产品相关表索引 --- ============================================ - --- products表索引 -CREATE INDEX IF NOT EXISTS idx_products_sellerId ON products(sellerId); -CREATE INDEX IF NOT EXISTS idx_products_created_at ON products(created_at); - --- ============================================ --- 购物车相关表索引 --- ============================================ - --- cart_items表索引 -CREATE INDEX IF NOT EXISTS idx_cart_items_userId ON cart_items(userId); -CREATE INDEX IF NOT EXISTS idx_cart_items_productId ON cart_items(productId); - --- ============================================ --- 企业相关表索引 --- ============================================ - --- enterprise表索引 (假设存在) -CREATE INDEX IF NOT EXISTS idx_enterprise_id ON enterprise(id); -CREATE INDEX IF NOT EXISTS idx_enterprise_name ON enterprise(name); - --- ============================================ --- 联系方式相关表索引 --- ============================================ - --- contacts表索引 -CREATE INDEX IF NOT EXISTS idx_contacts_userId ON contacts(userId); - --- ============================================ --- 注意事项 --- ============================================ --- 1. 此脚本使用IF NOT EXISTS语法,可重复执行而不会报错 --- 2. 索引创建会占用额外的磁盘空间,提高写操作开销,但显著提升查询性能 --- 3. 建议在低峰期执行此脚本 --- 4. 执行后建议监控应用性能,确认优化效果 --- 5. 对于MySQL数据库,索引创建命令可能略有不同 --- ============================================ - --- MySQL版本的部分索引创建语法示例(仅供参考) --- ALTER TABLE users ADD INDEX idx_users_userId (userId); --- ALTER TABLE users ADD INDEX idx_users_phoneNumber (phoneNumber); --- 以此类推... \ No newline at end of file diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md deleted file mode 100644 index 18a210a..0000000 --- a/DEPLOYMENT_GUIDE.md +++ /dev/null @@ -1,224 +0,0 @@ -# Spring Boot应用部署到Tomcat 10.1.48指南(含性能优化) - -## 准备工作 - -1. **确认构建产物**: - - 已生成WAR文件:`web-0.0.1-SNAPSHOT.war`,位于`target`目录下 - - 确认包含最新性能优化:SQL查询优化、分页功能、二级缓存配置 - -2. **Tomcat环境要求**: - - Tomcat版本:10.1.48(Jakarta EE 10兼容) - - JDK版本:17或更高(与项目`pom.xml`中配置的Java版本一致) - - 数据库:需创建优化索引(详见数据库索引优化部分) - -## 部署步骤 - -### 1. 准备部署文件 - -```bash -# 将WAR文件重命名为DL.war(与context-path一致) -# 注意:在Windows命令提示符中使用 -copy target\web-0.0.1-SNAPSHOT.war target\DL.war - -# 或者在PowerShell中使用 -# Copy-Item -Path "target\web-0.0.1-SNAPSHOT.war" -Destination "target\DL.war" - -# 在Linux/Mac终端中使用(注意转义括号) -# cp d:\java\project\web\(8)\web\target\web-0.0.1-SNAPSHOT.war d:\java\project\web\(8)\web\target\DL.war -# 或者使用相对路径避免路径转义问题 -# cd d:\java\project\web(8)\web && cp target\web-0.0.1-SNAPSHOT.war target\DL.war -``` - -### 2. 上传WAR文件到服务器 - -使用SFTP或SCP工具将`DL.war`文件上传到服务器的Tomcat目录: - -```bash -# 示例:使用scp上传(注意处理路径中的括号) -# 方法1:转义括号 -scp d:\java\project\web\(8)\web\target\DL.war user@your-server:/opt/tomcat/webapps/ - -# 方法2:使用相对路径(推荐) -cd d:\java\project\web(8)\web -scp target\DL.war user@your-server:/opt/tomcat/webapps/ - -# 方法3:使用引号包裹路径(在某些终端中有效) -scp "d:\java\project\web(8)\web\target\DL.war" user@your-server:/opt/tomcat/webapps/ -``` - -### 3. 确保Tomcat目录权限正确 - -```bash -# 登录服务器后执行 -cd /opt/tomcat -# 确保tomcat用户对webapps目录有写权限 -chown -R tomcat:tomcat webapps/ -chmod -R 755 webapps/ -``` - -### 4. 配置Tomcat(可选但推荐) - -#### 4.1 配置context.xml(解决可能的内存泄漏问题) - -编辑`/opt/tomcat/conf/context.xml`文件,添加以下配置: - -```xml - - - WEB-INF/web.xml - ${catalina.base}/conf/web.xml - -``` - -#### 4.2 调整Tomcat内存配置 - -编辑`/opt/tomcat/bin/setenv.sh`(如果不存在则创建): - -```bash -#!/bin/bash -# 为Tomcat设置适当的内存 -JAVA_OPTS="-Xms512m -Xmx1024m -XX:MaxPermSize=256m" -# 添加Tomcat 10兼容性参数 -JAVA_OPTS="$JAVA_OPTS --add-opens=java.base/java.lang=ALL-UNNAMED" -``` - -给脚本添加执行权限: -```bash -chmod +x /opt/tomcat/bin/setenv.sh -``` - -### 5. 启动或重启Tomcat - -```bash -# 切换到Tomcat的bin目录 -cd /opt/tomcat/bin - -# 停止Tomcat(如果正在运行) -./shutdown.sh - -# 等待Tomcat完全停止(约30秒) - -# 启动Tomcat -./startup.sh -``` - -### 6. 验证部署 - -1. **检查Tomcat日志**: - ```bash - tail -f /opt/tomcat/logs/catalina.out - ``` - -2. **访问应用**: - - 应用应该可以通过以下URL访问:`http://your-server-ip:8080/DL` - - 登录页面:`http://your-server-ip:8080/DL/loginmm.html` - -## 常见问题排查 - -### 1. 端口冲突 - -如果Tomcat的8080端口已被占用,修改`/opt/tomcat/conf/server.xml`中的端口配置: - -```xml - -``` - -### 2. 数据库连接问题 - -确保数据库服务器允许来自Tomcat服务器IP的连接。检查应用配置中的数据库连接URL是否正确。 - -### 3. 类加载问题(Tomcat 10特有) - -Tomcat 10使用Jakarta EE,所有`javax.*`包已改为`jakarta.*`。如果出现类找不到的错误: - -- 检查是否有冲突的JAR包在WEB-INF/lib中 -- 确保使用的是支持Jakarta EE的依赖版本 - -### 4. 内存溢出 - -如果出现内存溢出错误,增加Tomcat的内存分配,修改`setenv.sh`文件: - -```bash -JAVA_OPTS="-Xms1024m -Xmx2048m -XX:MaxPermSize=512m" -``` - -## 数据库索引优化(重要) - -在部署新版本前,请在数据库服务器上执行以下索引创建脚本,以提升查询性能: - -```sql --- 执行CREATE_OPTIMIZATION_INDEXES.sql文件中的脚本 --- 在服务器上执行: -source /path/to/CREATE_OPTIMIZATION_INDEXES.sql - --- 或直接复制脚本内容执行 - --- 1. 为managers表创建索引 -CREATE INDEX idx_managers_enterprise_id ON managers(enterprise_id); -CREATE INDEX idx_managers_user_name ON managers(user_name); - --- 2. 为users表创建索引 -CREATE INDEX idx_users_user_id ON users(user_id); -CREATE INDEX idx_users_user_name ON users(user_name); -CREATE INDEX idx_users_status ON users(status); - --- 3. 为usermanagements表创建索引 -CREATE INDEX idx_usermanagements_user_id ON usermanagements(user_id); -CREATE INDEX idx_usermanagements_role_id ON usermanagements(role_id); -CREATE INDEX idx_usermanagements_permission_level ON usermanagements(permission_level); -``` - -## 应用更新流程 - -1. **执行数据库索引优化**:按照上方数据库索引优化部分执行索引创建脚本 -2. **停止Tomcat**:`./shutdown.sh` -3. **备份旧数据**:`cp -r /opt/tomcat/webapps/DL /path/to/backup/` -4. **删除旧的WAR文件和解压目录**:`rm -rf /opt/tomcat/webapps/DL*` -5. **上传新的WAR文件** -6. **启动Tomcat**:`./startup.sh` -7. **监控日志确认部署成功**:`tail -f /opt/tomcat/logs/catalina.out` - -## 性能优化验证 - -部署完成后,请执行以下验证步骤确认性能优化效果: - -1. **验证分页功能**: - - 访问负责人管理页面,确认列表显示已启用分页 - - 验证翻页功能正常,数据加载速度提升 - -2. **验证SQL查询性能**: - - 执行常用查询操作,确认响应时间明显改善 - - 监控数据库慢查询日志,检查是否有新的慢查询 - -3. **验证缓存效果**: - - 连续访问相同数据页面,确认第二次访问速度更快 - -## 回滚方案 - -如遇部署问题,请按以下步骤回滚: - -1. 停止Tomcat:`./shutdown.sh` -2. 删除新部署文件:`rm -rf /opt/tomcat/webapps/DL*` -3. 恢复备份:`cp -r /path/to/backup/DL /opt/tomcat/webapps/` -4. 恢复数据库索引(如需要) -5. 启动Tomcat:`./startup.sh` - -## 注意事项 - -1. **备份**:部署前请备份现有应用数据和配置 -2. **维护窗口**:选择低流量时段进行部署 -3. **监控**:部署后密切监控应用性能和日志 -4. **权限**:确保Tomcat用户对所有必要目录有正确权限 -5. **性能监控**:部署后持续监控系统性能指标,必要时进行进一步优化 -6. **索引维护**:定期检查数据库索引使用情况和碎片 - ---- - -部署时间:2024 -版本:2.0(包含性能优化) - ---- - -> 详细性能优化说明请参考:PERFORMANCE_OPTIMIZATION_GUIDE.md \ No newline at end of file diff --git a/DL.war b/DL.war deleted file mode 100644 index 8086386..0000000 Binary files a/DL.war and /dev/null differ diff --git a/INFORMATION_TRACKING_SCHEME.md b/INFORMATION_TRACKING_SCHEME.md deleted file mode 100644 index 4cfa50e..0000000 --- a/INFORMATION_TRACKING_SCHEME.md +++ /dev/null @@ -1,377 +0,0 @@ -# 客户信息跟踪系统解决方案 - -## 1. 需求分析 - -### 1.1 功能需求 -- 前端记录业务员操作事件(查看详情、编辑、跟进) -- 获取当前账号信息(公司、部门、组织、角色、姓名) -- 根据电话号码在两个数据源中查询客户 -- 将操作记录写入`informationtra`表 - -### 1.2 数据源要求 -- `wechat`数据源:`users`表和`informationtra`表 -- `primary`数据源:`contacts`表 - -### 1.3 数据流程 -1. 前端传递操作事件、电话号码、事件类型 -2. 后端获取当前用户认证信息 -3. 根据电话号码查询两个数据源 -4. 将查询结果与认证信息结合写入`informationtra`表 - -## 2. 数据库设计 - -### 2.1 现有表结构 -```sql -CREATE TABLE `informationtra` ( - `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `tracompany` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者公司', - `tradepartment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者部门', - `traorganization` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者组织', - `trarole` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者角色', - `trauserName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者名字', - `traassistant` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改协助人', - `userId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户ID', - `operationEvent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '操作事件', - `operationTime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', - `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - PRIMARY KEY (`id`), - KEY `idx_userId` (`userId`), - KEY `idx_operationTime` (`operationTime`), - KEY `idx_trauserName` (`trauserName`), - CONSTRAINT `fk_informationtra_userId` FOREIGN KEY (`userId`) REFERENCES `users` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='信息跟踪表'; -``` - -## 3. 代码设计 - -### 3.1 实体类设计 - -#### InformationTra.java -```java -package com.example.web.entity; - -import java.time.LocalDateTime; - -public class InformationTra { - private Integer id; - private String tracompany; - private String tradepartment; - private String traorganization; - private String trarole; - private String trauserName; - private String traassistant; - private String userId; - private String operationEvent; - private LocalDateTime operationTime; - private LocalDateTime createdAt; - private LocalDateTime updatedAt; - - // Getters and Setters - // ... -} -``` - -### 3.2 Mapper设计 - -#### InformationTraMapper.java -```java -package com.example.web.mapper; - -import com.example.web.entity.InformationTra; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface InformationTraMapper { - /** - * 插入操作记录 - */ - int insertInformationTra(InformationTra informationTra); - - /** - * 根据userId查询操作记录 - */ - InformationTra selectByUserId(@Param("userId") String userId); -} -``` - -#### InformationTraMapper.xml -```xml - - - - - - - - - - - - - - - - - - - - - INSERT INTO informationtra ( - tracompany, tradepartment, traorganization, trarole, - trauserName, traassistant, userId, operationEvent, - operationTime, created_at, updated_at - ) VALUES ( - #{tracompany}, #{tradepartment}, #{traorganization}, #{trarole}, - #{trauserName}, #{traassistant}, #{userId}, #{operationEvent}, - #{operationTime}, #{createdAt}, #{updatedAt} - ) - - - - -``` - -### 3.3 Service设计 - -#### InformationTraService.java -```java -package com.example.web.service; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.entity.InformationTra; -import com.example.web.mapper.*; -import com.example.web.config.DynamicDataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; - -@Service -public class InformationTraService { - - @Autowired - private InformationTraMapper informationTraMapper; - - @Autowired - private UsersMapper usersMapper; - - @Autowired - private ContactsMapper contactsMapper; - - /** - * 记录操作事件 - */ - public boolean recordOperationEvent(String phoneNumber, String operationEvent, ManagerAuthInfo authInfo) { - try { - // 1. 从两个数据源查询客户信息 - String userId = null; - - // 查询wechat数据源的users表 - DynamicDataSource.setDataSourceKey("wechat"); - com.example.web.entity.Users wechatUser = usersMapper.selectByPhoneNumber(phoneNumber); - - if (wechatUser != null) { - userId = wechatUser.getUserId(); - } else { - // 查询primary数据源的contacts表 - DynamicDataSource.setDataSourceKey("primary"); - com.example.web.entity.Contacts contact = contactsMapper.selectByPhoneNumber(phoneNumber); - - if (contact != null) { - userId = contact.getId(); - } - } - - // 如果都没找到,返回失败 - if (userId == null) { - return false; - } - - // 2. 构造操作记录 - InformationTra informationTra = new InformationTra(); - informationTra.setTracompany(authInfo.getManagercompany()); - informationTra.setTradepartment(authInfo.getManagerdepartment()); - informationTra.setTraorganization(authInfo.getOrganization()); - informationTra.setTrarole(authInfo.getRole()); - informationTra.setTrauserName(authInfo.getUserName()); - informationTra.setTraassistant(authInfo.getAssistant()); - informationTra.setUserId(userId); - informationTra.setOperationEvent(operationEvent); - informationTra.setOperationTime(LocalDateTime.now()); - informationTra.setCreatedAt(LocalDateTime.now()); - informationTra.setUpdatedAt(LocalDateTime.now()); - - // 3. 写入wechat数据源的informationtra表 - DynamicDataSource.setDataSourceKey("wechat"); - int result = informationTraMapper.insertInformationTra(informationTra); - - return result > 0; - } finally { - // 清除数据源标识 - DynamicDataSource.clearDataSourceKey(); - } - } -} -``` - -### 3.4 Controller设计 - -#### InformationTraController.java -```java -package com.example.web.controller; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.service.InformationTraService; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.HashMap; -import java.util.Map; - -@RestController -@RequestMapping("/api/information-tracking") -public class InformationTraController { - - @Autowired - private InformationTraService informationTraService; - - /** - * 记录操作事件 - */ - @PostMapping("/record") - public ResponseEntity> recordOperationEvent( - @RequestBody Map requestBody, - HttpServletRequest request) { - - Map response = new HashMap<>(); - - try { - // 获取请求参数 - String phoneNumber = requestBody.get("phoneNumber"); - String operationEvent = requestBody.get("operationEvent"); - - // 验证参数 - if (phoneNumber == null || phoneNumber.isEmpty() || operationEvent == null || operationEvent.isEmpty()) { - response.put("success", false); - response.put("message", "电话号码和操作事件不能为空"); - return ResponseEntity.badRequest().body(response); - } - - // 获取当前用户认证信息 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - - ManagerAuthInfo authInfo = null; - if (isSupplySide) { - // 供应端获取认证信息的逻辑 - authInfo = getManagerAuthInfoFromRequest(request, true); - } else { - // 销售端获取认证信息的逻辑 - authInfo = getManagerAuthInfoFromRequest(request, false); - } - - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(401).body(response); - } - - // 记录操作事件 - boolean success = informationTraService.recordOperationEvent(phoneNumber, operationEvent, authInfo); - - if (success) { - response.put("success", true); - response.put("message", "操作记录成功"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "未找到对应的客户信息"); - return ResponseEntity.badRequest().body(response); - } - - } catch (Exception e) { - response.put("success", false); - response.put("message", "记录操作事件失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 从请求中获取认证信息(复用现有逻辑) - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - // 复用SupplyCustomerController或CustomerController中的现有逻辑 - // 这里需要根据实际情况实现 - return null; - } -} -``` - -### 3.5 前端调用示例 - -```javascript -// 前端调用API示例 -function recordOperation(phoneNumber, operationEvent) { - fetch('/api/information-tracking/record?isSupplySide=true', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - phoneNumber: phoneNumber, - operationEvent: operationEvent - }) - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - console.log('操作记录成功'); - } else { - console.error('操作记录失败:', data.message); - } - }) - .catch(error => { - console.error('API调用失败:', error); - }); -} - -// 查看客户详情时调用 -recordOperation('13800138000', '查看客户详情'); - -// 编辑客户信息后调用 -recordOperation('13800138000', '修改客户信息'); - -// 跟进客户后调用 -recordOperation('13800138000', '更新客户跟进'); -``` - -## 4. 实现步骤 - -1. 创建InformationTra实体类 -2. 创建InformationTraMapper接口和XML文件 -3. 创建InformationTraService -4. 创建InformationTraController -5. 在前端页面添加API调用逻辑 -6. 测试功能完整性 - -## 5. 注意事项 - -1. 确保数据源切换正确,避免数据查询错误 -2. 验证电话号码格式,确保查询准确性 -3. 处理并发情况,确保操作记录的完整性 -4. 添加适当的日志记录,便于调试和监控 -5. 考虑添加权限控制,确保只有授权用户可以调用API - -## 6. 扩展建议 - -1. 添加操作记录查询功能,便于查看历史操作 -2. 实现操作记录统计分析,提供数据可视化 -3. 添加操作记录导出功能,支持Excel或PDF格式 -4. 实现操作记录告警功能,对异常操作进行告警 -5. 添加操作记录审计功能,满足合规要求 \ No newline at end of file diff --git a/LATEST_DEPLOYMENT_GUIDE.md b/LATEST_DEPLOYMENT_GUIDE.md deleted file mode 100644 index b38fdfe..0000000 --- a/LATEST_DEPLOYMENT_GUIDE.md +++ /dev/null @@ -1,184 +0,0 @@ -# Spring Boot应用最新部署指南(性能优化版) - -## 版本信息 -- **版本**: 2.0 -- **日期**: 2024 -- **更新内容**: 包含数据库性能优化、SQL查询优化、分页功能和缓存配置 - -## 一、优化内容概述 - -### 1.1 已完成的性能优化 - -#### SQL查询优化 -- 将`SELECT *`查询替换为显式字段列表,减少数据传输量 -- 优化复杂JOIN查询,减少不必要的表连接 - -#### 分页功能实现 -- 新增`selectAllManagersWithPagination`方法实现分页查询 -- 添加`getManagersCount`方法获取总数用于分页计算 - -#### 缓存配置 -- 为ManagersMapper添加LRU二级缓存配置 -- 提升重复查询性能 - -#### 数据库索引 -- 为关键字段创建索引,提升查询性能 -- 详细索引脚本位于`CREATE_OPTIMIZATION_INDEXES.sql` - -## 二、部署前准备 - -### 2.1 确认构建产物 -- **WAR文件**: `target\web-0.0.1-SNAPSHOT.war` -- **索引脚本**: `CREATE_OPTIMIZATION_INDEXES.sql` -- **验证文件**: `src\main\resources\mapper`目录下的优化后的XML文件 - -### 2.2 环境要求 -- **Tomcat**: 10.1.48(Jakarta EE 10兼容) -- **JDK**: 17或更高 -- **数据库**: 支持索引创建的关系型数据库 - -## 三、部署流程 - -### 3.1 本地准备部署文件 - -```bash -# 1. 清理并构建项目 -mvn clean package -DskipTests - -# 2. 重命名WAR文件 -copy target\web-0.0.1-SNAPSHOT.war target\DL.war -``` - -### 3.2 数据库索引优化(关键步骤) - -在数据库服务器上执行索引创建脚本: - -```sql --- 执行CREATE_OPTIMIZATION_INDEXES.sql文件 --- 或直接执行以下索引创建语句 - --- 为managers表创建索引 -CREATE INDEX idx_managers_enterprise_id ON managers(enterprise_id); -CREATE INDEX idx_managers_user_name ON managers(user_name); - --- 为users表创建索引 -CREATE INDEX idx_users_user_id ON users(user_id); -CREATE INDEX idx_users_user_name ON users(user_name); -CREATE INDEX idx_users_status ON users(status); - --- 为usermanagements表创建索引 -CREATE INDEX idx_usermanagements_user_id ON usermanagements(user_id); -CREATE INDEX idx_usermanagements_role_id ON usermanagements(role_id); -CREATE INDEX idx_usermanagements_permission_level ON usermanagements(permission_level); -``` - -### 3.3 上传部署文件 - -使用SFTP或SCP上传文件到服务器: - -```bash -# 上传WAR文件 -scp target\DL.war user@your-server:/opt/tomcat/webapps/ - -# 上传索引脚本(用于备份) -scp CREATE_OPTIMIZATION_INDEXES.sql user@your-server:/opt/tomcat/ -``` - -### 3.4 服务器部署操作 - -登录服务器后执行: - -```bash -# 1. 停止Tomcat -cd /opt/tomcat/bin -./shutdown.sh - -# 2. 等待Tomcat完全停止(约30秒) - -# 3. 备份旧应用 -cp -r /opt/tomcat/webapps/DL /opt/tomcat/backup/ - -# 4. 删除旧部署文件 -rm -rf /opt/tomcat/webapps/DL* - -# 5. 确保权限正确 -chown -R tomcat:tomcat /opt/tomcat/webapps/ -chmod -R 755 /opt/tomcat/webapps/ - -# 6. 启动Tomcat -./startup.sh - -# 7. 监控部署日志 -tail -f /opt/tomcat/logs/catalina.out -``` - -## 四、部署后验证 - -### 4.1 功能验证 -- **访问应用**: `http://your-server-ip:8080/DL` -- **登录验证**: 确认可以正常登录 -- **数据操作**: 验证增删改查功能正常 - -### 4.2 性能优化验证 - -#### 分页功能验证 -- 访问负责人管理页面 -- 确认列表显示已启用分页 -- 验证翻页功能正常工作 -- 检查数据加载速度是否提升 - -#### SQL查询性能验证 -- 执行常用查询操作 -- 确认响应时间明显改善 -- 监控数据库慢查询日志 - -#### 缓存效果验证 -- 连续访问相同数据页面 -- 确认第二次及后续访问速度更快 - -## 五、回滚方案 - -如遇部署问题,请按以下步骤回滚: - -```bash -# 1. 停止Tomcat -cd /opt/tomcat/bin -./shutdown.sh - -# 2. 删除新部署文件 -rm -rf /opt/tomcat/webapps/DL* - -# 3. 恢复备份 -cp -r /opt/tomcat/backup/DL /opt/tomcat/webapps/ - -# 4. 启动Tomcat -./startup.sh -``` - -## 六、批处理部署脚本 - -项目中提供了Windows批处理脚本`deploy_with_optimization.bat`,可以帮助准备部署文件。在项目根目录执行: - -```bash -# 运行批处理脚本 -.\deploy_with_optimization.bat -``` - -## 七、注意事项 - -1. **备份**: 部署前务必备份应用数据和数据库 -2. **维护窗口**: 选择低流量时段进行部署 -3. **索引优化**: 必须执行数据库索引创建脚本 -4. **性能监控**: 部署后持续监控系统性能 -5. **日志检查**: 定期检查应用日志,及时发现问题 -6. **权限问题**: 确保Tomcat用户对所有必要目录有正确权限 - -## 八、相关文档 - -- **性能优化详细说明**: `PERFORMANCE_OPTIMIZATION_GUIDE.md` -- **Mapper XML部署指南**: `MAPPER_XML_DEPLOYMENT_GUIDE.txt` -- **数据库索引脚本**: `CREATE_OPTIMIZATION_INDEXES.sql` - ---- - -> 部署完成后,请务必执行性能优化验证步骤,确保所有优化措施生效。 \ No newline at end of file diff --git a/MAPPER_SERVICE_UPDATE_GUIDE.txt b/MAPPER_SERVICE_UPDATE_GUIDE.txt deleted file mode 100644 index 4af069c..0000000 --- a/MAPPER_SERVICE_UPDATE_GUIDE.txt +++ /dev/null @@ -1,146 +0,0 @@ -# Mapper和Service代码更新部署指南 - -## 构建状态确认 - -✅ 所有Mapper和Service Java文件已成功编译为class文件 - -### Mapper文件(最后编译时间:2025/11/6 13:50) -- 位置:`target\classes\com\example\web\mapper` -- 文件数量:20个class文件 -- 包含:Cart_itemsMapper、EnterpriseMapper、ManagersMapper等所有必要的Mapper接口实现 - -### Service文件(最后编译时间:2025/11/6 13:50) -- 位置:`target\classes\com\example\web\service` -- 文件数量:11个class文件 -- 包含:CustomerService、EnterpriseService、LoginService等所有Service实现类 - -## 部署方案 - -### 方案一:完整WAR包部署(推荐) -这种方法最安全、最可靠,确保所有组件版本一致。 - -1. **准备WAR文件** - ```bash - # 确保WAR文件已生成 - ls -la target/DL.war - ``` - -2. **上传WAR文件到服务器** - ```bash - # 使用SCP上传文件 - scp target/DL.war user@server:/path/to/tomcat/webapps/ - ``` - -3. **设置文件权限** - ```bash - # 在服务器上执行 - sudo chown tomcat:tomcat /path/to/tomcat/webapps/DL.war - sudo chmod 644 /path/to/tomcat/webapps/DL.war - ``` - -4. **重启Tomcat服务** - ```bash - # 在服务器上执行 - sudo systemctl restart tomcat - # 或者 - sudo service tomcat restart - # 或者直接使用Tomcat的脚本 - /path/to/tomcat/bin/shutdown.sh - /path/to/tomcat/bin/startup.sh - ``` - -### 方案二:仅更新Mapper和Service的class文件(风险较高) -如果只修改了Mapper和Service代码,可以只更新这些class文件,但要注意版本兼容性问题。 - -1. **在服务器上定位目标目录** - ```bash - # 在服务器上执行,找到应用部署目录 - cd /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/ - ``` - -2. **备份当前文件** - ```bash - # 在服务器上执行 - mkdir -p ~/backup/mapper ~/backup/service - cp -r mapper/* ~/backup/mapper/ - cp -r service/* ~/backup/service/ - ``` - -3. **上传新的class文件** - ```bash - # 上传mapper文件 - scp target/classes/com/example/web/mapper/*.class user@server:/path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/mapper/ - - # 上传service文件 - scp target/classes/com/example/web/service/*.class user@server:/path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/service/ - ``` - -4. **设置文件权限** - ```bash - # 在服务器上执行 - sudo chown -R tomcat:tomcat /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/mapper/ - sudo chown -R tomcat:tomcat /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/service/ - sudo chmod 644 /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/mapper/*.class - sudo chmod 644 /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/service/*.class - ``` - -5. **重载应用(可选)** - - 方法1:重启Tomcat(最可靠) - ```bash - sudo systemctl restart tomcat - ``` - - 方法2:使用Tomcat Manager或JMX热重载(风险较高) - -## 验证部署 - -1. **检查Tomcat日志** - ```bash - # 在服务器上执行 - tail -f /path/to/tomcat/logs/catalina.out - ``` - -2. **测试应用功能** - - 访问应用的关键功能 - - 执行涉及更新的Mapper和Service的操作 - -## 回滚方案 - -如果遇到问题,按照以下步骤回滚: - -1. **方案一回滚** - ```bash - # 在服务器上执行 - sudo rm -f /path/to/tomcat/webapps/DL.war - sudo rm -rf /path/to/tomcat/webapps/DL/ - # 上传之前的备份WAR文件 - scp backup/DL.war user@server:/path/to/tomcat/webapps/ - sudo chown tomcat:tomcat /path/to/tomcat/webapps/DL.war - sudo systemctl restart tomcat - ``` - -2. **方案二回滚** - ```bash - # 在服务器上执行 - cp -r ~/backup/mapper/* /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/mapper/ - cp -r ~/backup/service/* /path/to/tomcat/webapps/DL/WEB-INF/classes/com/example/web/service/ - sudo systemctl restart tomcat - ``` - -## 注意事项 - -1. **版本兼容性**:确保Mapper和Service的修改与其他组件兼容 -2. **事务一致性**:特别注意涉及多个Mapper的事务操作 -3. **数据库变更**:如果Mapper修改涉及数据库结构变更,请先执行数据库迁移 -4. **缓存清理**:如有必要,清除相关缓存 -5. **生产环境建议**:在生产环境中,强烈推荐使用方案一进行完整部署 - -## 后续维护建议 - -1. **建立部署文档**:记录每次部署的变更内容 -2. **制定回滚计划**:为每次更新准备回滚方案 -3. **监控应用性能**:部署后密切关注应用性能指标 -4. **测试完整性**:执行完整的功能测试套件 - ---- - -此指南由自动化工具生成,最后更新时间:2025/11/6 13:51 \ No newline at end of file diff --git a/MAPPER_XML_DEPLOYMENT_GUIDE.txt b/MAPPER_XML_DEPLOYMENT_GUIDE.txt deleted file mode 100644 index bf9aa1a..0000000 --- a/MAPPER_XML_DEPLOYMENT_GUIDE.txt +++ /dev/null @@ -1,163 +0,0 @@ -# MyBatis Mapper XML文件部署指南(含性能优化) - -## 文件状态确认 - -✅ 所有MyBatis Mapper XML映射文件已成功复制到构建目录 - -### Mapper XML文件(最后修改时间与源代码一致) -- 源文件位置:`src\main\resources\mapper` -- 构建后位置:`target\classes\mapper` -- 文件数量:16个XML文件 -- 包含:Cart_itemsMapper.xml、EnterpriseMapper.xml、ManagersMapper.xml等所有必要的MyBatis映射文件 - -## 部署方案 - -### 方案一:完整WAR包部署(推荐) -这种方法最安全、最可靠,确保所有组件版本一致。 - -1. **准备WAR文件** - ```bash - # 确保WAR文件已生成 - ls -la target/DL.war - ``` - -2. **上传WAR文件到服务器** - ```bash - # 使用SCP上传文件 - scp target/DL.war user@server:/path/to/tomcat/webapps/ - ``` - -3. **设置文件权限** - ```bash - # 在服务器上执行 - sudo chown tomcat:tomcat /path/to/tomcat/webapps/DL.war - sudo chmod 644 /path/to/tomcat/webapps/DL.war - ``` - -4. **重启Tomcat服务** - ```bash - # 在服务器上执行 - sudo systemctl restart tomcat - # 或者 - sudo service tomcat restart - # 或者直接使用Tomcat的脚本 - /path/to/tomcat/bin/shutdown.sh - /path/to/tomcat/bin/startup.sh - ``` - -### 方案二:仅更新Mapper XML文件(中等风险) -如果只修改了Mapper XML文件,可以只更新这些文件,但要注意版本兼容性问题。 - -1. **在服务器上定位目标目录** - ```bash - # 在服务器上执行,找到应用部署目录 - cd /path/to/tomcat/webapps/DL/WEB-INF/classes/mapper/ - ``` - -2. **备份当前文件** - ```bash - # 在服务器上执行 - mkdir -p ~/backup/mapper_xml - cp -r * ~/backup/mapper_xml/ - ``` - -3. **上传新的XML文件** - ```bash - # 上传所有XML文件 - scp target/classes/mapper/*.xml user@server:/path/to/tomcat/webapps/DL/WEB-INF/classes/mapper/ - ``` - -4. **设置文件权限** - ```bash - # 在服务器上执行 - sudo chown -R tomcat:tomcat /path/to/tomcat/webapps/DL/WEB-INF/classes/mapper/ - sudo chmod 644 /path/to/tomcat/webapps/DL/WEB-INF/classes/mapper/*.xml - ``` - -5. **重载应用** - - 方法1:重启Tomcat(最可靠) - ```bash - sudo systemctl restart tomcat - ``` - - 方法2:使用Tomcat Manager重新加载应用(较快) - ```bash - # 使用curl命令重新加载应用 - curl -u username:password "http://localhost:8080/manager/text/reload?path=/DL" - ``` - -## 性能优化内容 - -1. **SQL查询优化**: - - 将SELECT *查询替换为显式字段列表 - - 移除不必要的连接操作 - -2. **分页功能**: - - 添加selectAllManagersWithPagination方法实现分页查询 - - 新增getManagersCount方法获取总数 - -3. **二级缓存配置**: - - 为ManagersMapper添加LRU二级缓存 - -4. **数据库索引**: - - 为关键字段创建索引,提升查询性能 - - 详细索引创建脚本请参考CREATE_OPTIMIZATION_INDEXES.sql - -## 验证部署 - -1. **检查Tomcat日志** - ```bash - # 在服务器上执行 - tail -f /path/to/tomcat/logs/catalina.out - ``` - -2. **测试数据库操作** - - 访问负责人管理页面,验证分页功能是否正常 - - 测试数据查询操作,确认响应速度提升 - - 检查应用日志,确保没有错误 - - 监控数据库性能,确认索引正常使用 - -## 回滚方案 - -如果遇到问题,按照以下步骤回滚: - -1. **方案一回滚** - ```bash - # 在服务器上执行 - sudo rm -f /path/to/tomcat/webapps/DL.war - sudo rm -rf /path/to/tomcat/webapps/DL/ - # 上传之前的备份WAR文件 - scp backup/DL.war user@server:/path/to/tomcat/webapps/ - sudo chown tomcat:tomcat /path/to/tomcat/webapps/DL.war - sudo systemctl restart tomcat - ``` - -2. **方案二回滚** - ```bash - # 在服务器上执行 - cp -r ~/backup/mapper_xml/* /path/to/tomcat/webapps/DL/WEB-INF/classes/mapper/ - sudo systemctl restart tomcat - ``` - -## 注意事项 - -1. **版本兼容性**:确保Mapper XML的修改与对应的Java接口兼容 -2. **SQL语法检查**:部署前确认XML中的SQL语句语法正确 -3. **数据库结构**:如果SQL修改涉及表结构变更,请先执行数据库迁移 -4. **缓存清理**:MyBatis可能缓存映射文件,重启Tomcat可以确保清除缓存 -5. **事务一致性**:特别注意涉及多个Mapper的事务操作 -6. **参数类型**:确保XML中定义的参数类型与Java代码中的参数类型匹配 -7. **数据库备份**:确保在部署前备份数据库 -8. **索引优化**:部署新版本后务必执行数据库索引优化脚本 -9. **分页验证**:验证分页功能是否正常工作 -10. **性能监控**:持续监控数据库查询性能,必要时进行进一步优化 - -## 后续维护建议 - -1. **版本控制**:对Mapper XML文件进行版本控制,记录每次变更 -2. **自动化部署**:考虑使用CI/CD工具自动化部署过程 -3. **监控查询性能**:部署后监控查询性能,特别是对于复杂的SQL语句 -4. **备份策略**:建立定期备份策略,包括数据库和应用配置 - ---- - -此指南由自动化工具生成,最后更新时间:2025/11/6 \ No newline at end of file diff --git a/PERFORMANCE_OPTIMIZATION_GUIDE.md b/PERFORMANCE_OPTIMIZATION_GUIDE.md deleted file mode 100644 index 389fc76..0000000 --- a/PERFORMANCE_OPTIMIZATION_GUIDE.md +++ /dev/null @@ -1,280 +0,0 @@ -# 数据库性能优化指南 - -## 问题分析 - -根据对Mapper XML文件的检查,发现以下可能导致数据返回慢的主要问题: - -### 1. 使用 SELECT * 查询所有字段 -- **问题**:`SELECT *` 查询会返回表中的所有列,增加网络传输量和处理时间 -- **影响文件**:ManagersMapper.xml中的多个查询 - -### 2. 复杂的JOIN和嵌套WHERE条件 -- **问题**:复杂的JOIN操作和多层嵌套条件会增加数据库解析和执行时间 -- **影响文件**:UsersMapper.xml中的`getAuthorizedCustomers`和`getAuthorizedUserIds`查询 - -### 3. 可能缺少必要的索引 -- **问题**:频繁用于查询条件的字段可能缺少索引,导致全表扫描 -- **影响字段**:userId, phoneNumber, type, level, managerId等 - -### 4. 未使用分页查询 -- **问题**:查询大量数据时未使用分页,一次性返回过多数据 -- **影响文件**:selectAllManagers等查询 - -## 优化方案 - -### 1. 优化SQL查询语句 - -#### 1.1 替换 SELECT * 为具体字段 - -**修改前** (ManagersMapper.xml): -```xml - -``` - -**修改后**: -```xml - -``` - -对其他使用 `SELECT *` 的查询也进行类似修改。 - -#### 1.2 优化复杂的JOIN查询 - -**修改建议** (UsersMapper.xml): -- 将复杂的嵌套条件拆分为更简单的部分 -- 使用子查询代替部分复杂JOIN -- 考虑使用临时表缓存中间结果 - -#### 1.3 添加分页查询 - -**修改前**: -```xml - -``` - -**修改后**: -```xml - -``` - -同时在Mapper接口中添加对应的方法。 - -### 2. 添加必要的数据库索引 - -建议在以下字段上添加索引: - -```sql --- 在users表上添加索引 -CREATE INDEX idx_users_userId ON users(userId); -CREATE INDEX idx_users_phoneNumber ON users(phoneNumber); -CREATE INDEX idx_users_type ON users(type); -CREATE INDEX idx_users_level ON users(level); -CREATE INDEX idx_users_created_at ON users(created_at); - --- 在managers表上添加索引 -CREATE INDEX idx_managers_id ON managers(id); -CREATE INDEX idx_managers_userName ON managers(userName); -CREATE INDEX idx_managers_managerId ON managers(managerId); - --- 在usermanagements表上添加索引 -CREATE INDEX idx_usermanagements_userId ON usermanagements(userId); -CREATE INDEX idx_usermanagements_managerId ON usermanagements(managerId); -CREATE INDEX idx_usermanagements_userName ON usermanagements(userName); -CREATE INDEX idx_usermanagements_organization ON usermanagements(organization); -CREATE INDEX idx_usermanagements_managerdepartment ON usermanagements(managerdepartment); -``` - -### 3. 添加缓存机制 - -#### 3.1 在MyBatis中添加二级缓存 - -在Mapper XML文件中添加缓存配置: - -```xml - - - - - - - -``` - -#### 3.2 在Service层添加本地缓存 - -在Service类中使用Guava Cache或Caffeine等本地缓存库。 - -### 4. 优化结果集映射 - -#### 4.1 优化ResultMap定义 - -确保ResultMap只映射必要的字段,避免不必要的映射。 - -#### 4.2 使用Constructor Args映射 - -对于频繁使用的DTO,可以考虑使用构造函数参数映射,提高性能。 - -## 具体优化实施 - -### 优化ManagersMapper.xml - -```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO managers ( - id, managerId, managercompany, managerdepartment, - organization, role, root, created_at, updated_at, - userName, assistant - ) VALUES ( - #{id}, #{managerId}, #{managercompany}, #{managerdepartment}, - #{organization}, #{role}, #{root}, #{created_at}, #{updated_at}, - #{userName}, #{assistant} - ) - - - - - UPDATE managers - SET - managercompany = #{managercompany}, - managerdepartment = #{managerdepartment}, - organization = #{organization}, - role = #{role}, - userName = #{userName}, - assistant = #{assistant}, - updated_at = #{updated_at} - WHERE id = #{id} - - -``` - -### 优化UsersMapper接口添加分页方法 - -在UsersMapper.java中添加分页查询方法: - -```java -// 分页查询授权客户 -List getAuthorizedCustomersWithPagination(Map params); - -// 获取授权客户总数 -int getAuthorizedCustomersCount(Map params); -``` - -## 验证优化效果 - -优化后,建议通过以下方式验证性能改进: - -1. **使用EXPLAIN分析SQL执行计划** - ```sql - EXPLAIN SELECT manager_id, id, managerId, managercompany, managerdepartment, - organization, role, root, userName, assistant - FROM managers WHERE userName = 'someName'; - ``` - -2. **添加性能监控日志** - 在Service层添加方法执行时间记录。 - -3. **压力测试** - 使用JMeter等工具进行压力测试,比较优化前后的响应时间。 - -## 额外建议 - -1. **考虑读写分离** - 对于高并发场景,考虑实现数据库读写分离。 - -2. **使用数据库连接池** - 确保使用高效的连接池管理数据库连接。 - -3. **定期清理和优化数据库** - 定期执行VACUUM(PostgreSQL)或OPTIMIZE TABLE(MySQL)等操作。 - -4. **考虑使用NoSQL缓存热点数据** - 对于频繁访问的数据,可以考虑使用Redis等NoSQL数据库进行缓存。 - ---- - -此优化指南由自动化工具生成,建议根据实际情况进行调整和测试。 \ No newline at end of file diff --git a/TOMCAT_DEPLOYMENT_STEPS.txt b/TOMCAT_DEPLOYMENT_STEPS.txt deleted file mode 100644 index dfc4365..0000000 --- a/TOMCAT_DEPLOYMENT_STEPS.txt +++ /dev/null @@ -1,118 +0,0 @@ -# TOMCAT 10.1.48 DEPLOYMENT STEPS - -## PREREQUISITES -1. Tomcat 10.1.48 installed at /opt/tomcat -2. JDK 17 or higher installed on the server -3. Generated DL.war file in target directory - -## DEPLOYMENT STEPS - -### 1. Prepare Deployment File -The DL.war file has been successfully created and is ready for deployment. - -### 2. Upload WAR File to Server - -```bash -# From Windows using WinSCP or FileZilla: -# - Connect to your server -# - Upload d:\java\project\web(8)\web\target\DL.war to /opt/tomcat/webapps/ - -# Or from command line using scp (open Command Prompt as Administrator): -scp "d:\java\project\web(8)\web\target\DL.war" user@your-server:/opt/tomcat/webapps/ -``` - -### 3. Set Permissions on Server - -Connect to your server via SSH and run: - -```bash -cd /opt/tomcat -sudo chown -R tomcat:tomcat webapps/ -sudo chmod -R 755 webapps/ -``` - -### 4. Configure Tomcat (Recommended) - -```bash -# Edit context.xml to prevent resource locking issues -sudo nano /opt/tomcat/conf/context.xml - -# Add antiResourceLocking and antiJARLocking attributes to Context element - - - - -# Save and exit (Ctrl+O, Enter, Ctrl+X) - -# Create setenv.sh for memory optimization -sudo nano /opt/tomcat/bin/setenv.sh - -# Add these lines: -#!/bin/bash -JAVA_OPTS="-Xms512m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m" -JAVA_OPTS="$JAVA_OPTS --add-opens=java.base/java.lang=ALL-UNNAMED" - -# Save and exit - -# Make it executable -sudo chmod +x /opt/tomcat/bin/setenv.sh -``` - -### 5. Restart Tomcat - -```bash -cd /opt/tomcat/bin - -# Stop Tomcat -sudo ./shutdown.sh - -# Wait for Tomcat to stop completely -sleep 30 - -# Start Tomcat -sudo ./startup.sh -``` - -### 6. Verify Deployment - -```bash -# Monitor Tomcat logs -tail -f /opt/tomcat/logs/catalina.out - -# Access the application in a browser -# http://your-server-ip:8080/DL -# http://your-server-ip:8080/DL/loginmm.html (for login page) -``` - -## TROUBLESHOOTING - -1. **Application not accessible**: - - Check if Tomcat is running: `ps aux | grep tomcat` - - Verify WAR file was deployed: `ls -la /opt/tomcat/webapps/` - - Look for errors in logs: `cat /opt/tomcat/logs/catalina.out` - -2. **Database connection issues**: - - Ensure database server is reachable from Tomcat server - - Verify database credentials in application.yaml - -3. **Port conflicts**: - - If port 8080 is in use, change it in server.xml: - `sudo nano /opt/tomcat/conf/server.xml` - Find and modify: ` nul -if %errorlevel% neq 0 ( - echo 错误:重命名WAR文件失败 - pause - exit /b 1 -) -echo 已将WAR文件重命名为:%DEPLOY_WAR% - -rem 5. 复制索引脚本到备份目录 -if exist "%INDEX_SCRIPT%" ( - copy "%INDEX_SCRIPT%" "%BACKUP_DIR%\%INDEX_SCRIPT%" > nul - echo 已复制数据库索引脚本到备份目录 -) - -rem 6. 提示数据库索引优化步骤 -echo. -echo ==================================== -echo 数据库索引优化(重要) -echo ==================================== -echo 请在数据库服务器上执行以下操作: -echo 1. 登录数据库服务器 -echo 2. 执行索引创建脚本: -echo source %BACKUP_DIR%\%INDEX_SCRIPT% -echo 或直接复制脚本内容执行 - -echo. -echo ==================================== -echo 部署准备完成! -echo ==================================== -echo 部署文件:%DEPLOY_WAR% -echo 备份位置:%BACKUP_DIR% -echo. -echo 下一步操作: -echo 1. 上传 %DEPLOY_WAR% 到Tomcat服务器的webapps目录 -echo 2. 在数据库服务器上执行索引优化脚本 -echo 3. 重启Tomcat服务器 -echo 4. 验证性能优化效果 -echo. -pause \ No newline at end of file diff --git a/mvnw b/mvnw deleted file mode 100644 index bd8896b..0000000 --- a/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100644 index 92450f9..0000000 --- a/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index 74a8a9b..51c6327 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,7 @@ com.mysql mysql-connector-j + 8.0.33 runtime @@ -116,6 +117,10 @@ org.springframework.boot spring-boot-starter-websocket + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/src/main/java/com/example/web/WebApplication.java b/src/main/java/com/example/web/WebApplication.java index 67d0c8a..fbff558 100644 --- a/src/main/java/com/example/web/WebApplication.java +++ b/src/main/java/com/example/web/WebApplication.java @@ -2,6 +2,7 @@ package com.example.web; import me.paulschwarz.springdotenv.DotenvPropertySource; import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.PropertySource; @@ -9,6 +10,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @MapperScan("com.example.web.mapper") +@EnableAspectJAutoProxy//启用AOP自动代理 @EnableScheduling//定时任务 /*@PropertySource(value = "classpath:.env", factory = DotenvPropertySource.class)*/ public class WebApplication { diff --git a/src/main/java/com/example/web/config/CharacterEncodingFilterConfig.java b/src/main/java/com/example/web/config/CharacterEncodingFilterConfig.java new file mode 100644 index 0000000..61910b1 --- /dev/null +++ b/src/main/java/com/example/web/config/CharacterEncodingFilterConfig.java @@ -0,0 +1,25 @@ +package com.example.web.config; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.CharacterEncodingFilter; + +/** + * 字符编码过滤器配置 + * 确保所有请求和响应都使用UTF-8编码 + */ +@Configuration +public class CharacterEncodingFilterConfig { + + @Bean + public FilterRegistrationBean characterEncodingFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + CharacterEncodingFilter filter = new CharacterEncodingFilter(); + filter.setEncoding("UTF-8"); + filter.setForceEncoding(true); + registrationBean.setFilter(filter); + registrationBean.addUrlPatterns("/*"); + return registrationBean; + } +} diff --git a/src/main/java/com/example/web/config/MyBatisConfig.java b/src/main/java/com/example/web/config/MyBatisConfig.java index 150b89f..0dd5172 100644 --- a/src/main/java/com/example/web/config/MyBatisConfig.java +++ b/src/main/java/com/example/web/config/MyBatisConfig.java @@ -29,6 +29,12 @@ public class MyBatisConfig { // 设置Mapper XML文件路径 factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/*.xml")); + + // 添加配置:开启下划线到驼峰命名的自动转换 + org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); + configuration.setMapUnderscoreToCamelCase(true); + factoryBean.setConfiguration(configuration); + return factoryBean.getObject(); } diff --git a/src/main/java/com/example/web/config/WebSocketConfig.java b/src/main/java/com/example/web/config/WebSocketConfig.java new file mode 100644 index 0000000..a2e580a --- /dev/null +++ b/src/main/java/com/example/web/config/WebSocketConfig.java @@ -0,0 +1,38 @@ +package com.example.web.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + // 配置消息代理,用于广播消息 + config.enableSimpleBroker("/topic"); + // 配置应用程序前缀,用于处理客户端发送的消息 + config.setApplicationDestinationPrefixes("/app"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + // 注册WebSocket端点,允许前端连接 + registry.addEndpoint("/ws") + .setAllowedOriginPatterns("*") + .withSockJS(); // 支持SockJS,兼容不支持WebSocket的浏览器 + } + + @Override + public void configureWebSocketTransport(WebSocketTransportRegistration registration) { + // 配置WebSocket传输的字符编码为UTF-8 + registration.setMessageSizeLimit(64 * 1024); // 64KB + registration.setSendBufferSizeLimit(128 * 1024); // 128KB + registration.setSendTimeLimit(20000); // 20 seconds + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/CustomerController.java b/src/main/java/com/example/web/controller/CustomerController.java deleted file mode 100644 index 3e6ab30..0000000 --- a/src/main/java/com/example/web/controller/CustomerController.java +++ /dev/null @@ -1,1031 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.UsersManagementsMapper; -import com.example.web.service.CustomerService; -import com.example.web.service.InformationTraService; -import com.example.web.service.PoolCustomerService; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 销售端客户管理控制器 - * 主要负责销售员的客户查询、更新、权限验证等操作 - * 路由前缀:/pool - */ -@RestController -@RequestMapping("/pool") -@CrossOrigin(origins = "*") -public class CustomerController { - // 核心业务服务注入 - @Autowired - private CustomerService customerService; - - @Autowired - private PoolCustomerService poolCustomerService; - - @Autowired - private UsersManagementsMapper usersManagementsMapper; - @Autowired - private com.example.web.mapper.UsersMapper usersMapper; - - @Autowired - private InformationTraService informationTraService; - - - /** - * 根据公司ID查询客户详情 - 优先处理wechat数据源 - * GET /pool/customers/{id} - */ - // 更新客户通知状态 - @PutMapping("/customers/{id}/notice") - public ResponseEntity> updateCustomerNotice(@PathVariable String id) { - try { - // 直接调用mapper更新通知状态 - System.out.println("🔄 手动更新通知状态, userId: " + id + ", 从banold改为old"); - usersMapper.updateNotice(id, "old"); - // 返回成功响应 - Map response = new HashMap<>(); - response.put("success", true); - response.put("message", "通知状态更新成功"); - return ResponseEntity.ok(response); - } catch (Exception e) { - System.err.println("❌ 更新通知状态失败: " + e.getMessage()); - // 返回失败响应 - Map response = new HashMap<>(); - response.put("success", false); - response.put("message", "通知状态更新失败: " + e.getMessage()); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); - } - } - - @GetMapping("/customers/{id}") - public ResponseEntity> getById(@PathVariable String id, HttpServletRequest request) { - System.out.println("===================================================="); - System.out.println("🔍 查询客户: " + id); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 从URL参数中获取ManagerAuthInfo - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - - if (authInfo == null) { - System.out.println("❌ 未找到用户认证信息"); - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("✅ 获取到用户认证信息: " + authInfo.getUserName()); - - // 🎯 重构:完全基于数据存在性判断,彻底消除对ID格式的依赖 - System.out.println("🎯 开始查询双数据源(优先wechat)..."); - - // 1. 首先尝试查询wechat数据源 - System.out.println("📊 优先查询 WECHAT 数据源..."); - UserProductCartDTO userInfo = poolCustomerService.getPublicSeaCustomerInfo(id); - - if (userInfo != null) { - System.out.println("✅ 在wechat数据源中找到客户基础信息"); - - // 使用统一的公海池判断逻辑 - boolean isPublicSea = poolCustomerService.isPublicSeaCustomerPublic(userInfo, authInfo); - System.out.println("📊 公海池判断结果: " + isPublicSea); - - if (isPublicSea) { - System.out.println("🎯 识别为公海池客户,返回 WECHAT 数据源数据"); - UnifiedCustomerDTO customer = convertToUnifiedDTOForPublicSea(userInfo, request); - customer.setDataSource("wechat"); - - response.put("success", true); - response.put("data", customer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - customer.getPhoneNumber(), - customer.getNickName() != null ? customer.getNickName() : "", - customer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } - - // 如果不是公海池客户,检查权限并返回wechat数据源的非公海池客户 - System.out.println("📊 处理 WECHAT 数据源非公海池客户..."); - boolean hasPermission = customerService.hasPermissionToViewWechatCustomer(userInfo, authInfo); - - if (hasPermission) { - System.out.println("✅ 有权限查看非公海池客户,返回 WECHAT 数据源数据"); - UnifiedCustomerDTO customer = convertToUnifiedDTOForPublicSea(userInfo, request); - customer.setDataSource("wechat"); - - response.put("success", true); - response.put("data", customer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - customer.getPhoneNumber(), - customer.getNickName() != null ? customer.getNickName() : "", - customer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } else { - System.out.println("❌ 无权限查看wechat数据源的非公海池客户"); - // 继续查询默认数据源 - } - } else { - System.out.println("ℹ️ 在wechat数据源中未找到客户"); - } - - // 2. 如果wechat数据源没找到或无权限,再尝试查询默认数据源 - System.out.println("📊 查询 DEFAULT 数据源..."); - UnifiedCustomerDTO defaultCustomer = customerService.getCustomerById(id, authInfo); - - if (defaultCustomer != null) { - System.out.println("✅ 在默认数据源中找到客户"); - response.put("success", true); - response.put("data", defaultCustomer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - defaultCustomer.getPhoneNumber(), - defaultCustomer.getNickName() != null ? defaultCustomer.getNickName() : "", - defaultCustomer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } - - // 3. 如果两个数据源都没找到 - System.out.println("❌ 未在任何数据源中找到客户信息"); - response.put("success", false); - response.put("message", "未找到对应的客户信息"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); - - } catch (Exception e) { - System.err.println("❌ 服务器错误: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - - - /** - * 从请求中获取ManagerAuthInfo - 增强版本,严格区分销售端和采购端 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - String managerId = request.getParameter("managerId"); - String managercompany = request.getParameter("company"); - String managerdepartment = request.getParameter("department"); - String organization = request.getParameter("organization"); - String role = request.getParameter("role"); - String userName = request.getParameter("userName"); - String assistant = request.getParameter("assistant"); - - // URL解码参数 - try { - if (managerId != null) managerId = java.net.URLDecoder.decode(managerId, "UTF-8"); - if (managercompany != null) managercompany = java.net.URLDecoder.decode(managercompany, "UTF-8"); - if (managerdepartment != null) managerdepartment = java.net.URLDecoder.decode(managerdepartment, "UTF-8"); - if (organization != null) organization = java.net.URLDecoder.decode(organization, "UTF-8"); - if (role != null) role = java.net.URLDecoder.decode(role, "UTF-8"); - if (userName != null) userName = java.net.URLDecoder.decode(userName, "UTF-8"); - if (assistant != null) assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - System.err.println("URL解码失败: " + e.getMessage()); - } - - // 检查必要参数 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名为空,无法获取认证信息"); - return null; - } - - // 部门检查 - if (managerdepartment == null) { - System.out.println("❌ 部门信息为空"); - return null; - } - - // 智能判断实际端类型:根据部门信息自动调整isSupplySide值 - boolean actualIsSupplySide = isSupplySide; - if (managerdepartment.contains("销售")) { - actualIsSupplySide = false; // 销售部门自动判定为销售端 - System.out.println("🔄 部门包含'销售',自动调整为销售端"); - } else if (managerdepartment.contains("采购")) { - actualIsSupplySide = true; // 采购部门自动判定为采购端 - System.out.println("🔄 部门包含'采购',自动调整为采购端"); - } - - System.out.println("🔍 认证信息检查,实际端类型: " + (actualIsSupplySide ? "采购端" : "销售端") + - ",部门: '" + managerdepartment + "'"); - System.out.println("✅ 认证信息检查通过"); - - // 验证公司信息一致性 - if (managercompany == null || managercompany.trim().isEmpty()) { - System.out.println("❌ 公司信息为空"); - return null; - } - - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId != null ? managerId : "", - managercompany != null ? managercompany : "", - managerdepartment != null ? managerdepartment : "", - organization != null ? organization : "", - role != null ? role : "", - userName, - assistant != null ? assistant : ""); - - // 设置实际的端类型 - try { - // 尝试通过反射或setter方法设置supplySide属性 - java.lang.reflect.Field field = authInfo.getClass().getDeclaredField("supplySide"); - field.setAccessible(true); - field.set(authInfo, actualIsSupplySide); - } catch (Exception e) { - System.out.println("ℹ️ 无法设置supplySide属性: " + e.getMessage()); - } - - System.out.println("🎯 认证信息详情: " + - "系统类型=" + (actualIsSupplySide ? "采购端" : "销售端") + - ", 公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - return authInfo; - } - - /** - * 查找选中的购物车项 - 修复版本 - * 优先使用前端传递的选中ID,如果没有则使用第一个 - */ - private UserProductCartDTO.CartItem findSelectedCartItem(UserProductCartDTO userInfo, String targetCartItemId) { - if (userInfo.getCartItems() == null || userInfo.getCartItems().isEmpty()) { - return null; - } - - // 🔥 关键修复:优先使用前端传递的选中购物车项ID - if (targetCartItemId != null && !targetCartItemId.trim().isEmpty()) { - for (UserProductCartDTO.CartItem cartItem : userInfo.getCartItems()) { - if (targetCartItemId.equals(cartItem.getCartItemId())) { - System.out.println("✅ 找到前端选中的购物车项: " + cartItem.getCartItemId()); - return cartItem; - } - } - System.out.println("⚠️ 未找到前端指定的购物车项: " + targetCartItemId); - } - - // 🔥 其次检查是否有标记为选中的购物车项 - for (UserProductCartDTO.CartItem cartItem : userInfo.getCartItems()) { - if (isCartItemSelected(cartItem)) { - System.out.println("✅ 找到标记为选中的购物车项: " + cartItem.getCartItemId()); - return cartItem; - } - } - - // 🔥 最后才返回第一个购物车项 - UserProductCartDTO.CartItem firstItem = userInfo.getCartItems().get(0); - System.out.println("🔄 使用第一个购物车项作为默认: " + firstItem.getCartItemId()); - return firstItem; - } - - /** - * 判断购物车项是否被选中(根据业务逻辑) - */ - private boolean isCartItemSelected(UserProductCartDTO.CartItem cartItem) { - // 这里可以根据业务需求实现选中逻辑 - // 例如:通过某个字段标识,或者外部传入的参数 - - // 临时方案:默认返回false,使用第一个购物车项 - return false; - } - - - - /** - * 专门为公海池客户转换DTO的方法 - 销售端使用购物车信息(修复版本) - * 新增HttpServletRequest参数用于获取选中的购物车项ID - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea(UserProductCartDTO userInfo, HttpServletRequest request) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - // 设置用户基础信息 - dto.setId(userInfo.getUserId() != null ? userInfo.getUserId() : ""); - dto.setPhoneNumber(userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""); - - // 设置公司信息 - dto.setCompany(userInfo.getCompany() != null ? userInfo.getCompany() : ""); - dto.setRegion(userInfo.getRegion() != null ? userInfo.getRegion() : ""); - - // 设置需求和规格 - dto.setDemand(userInfo.getDemand() != null ? userInfo.getDemand() : ""); - dto.setSpec(userInfo.getSpec() != null ? userInfo.getSpec() : ""); - - // 类型转换 - String frontendType = convertDatabaseTypeToFrontend(userInfo.getType()); - dto.setType(frontendType != null ? frontendType : ""); - - dto.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : ""); - dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - // 添加通知信息转换 - dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); - - // 关键:设置数据源标识为wechat - dto.setDataSource("wechat"); - - // 设置联系人信息 - 从usersContacts获取 - setContactInfoSafely(dto, userInfo); - - // 设置负责人信息 - setManagerInfoSafely(dto, userInfo.getUserId()); - - // 设置公海需求信息 - 从购物车表获取(销售端) - if (userInfo.getCartItems() != null && !userInfo.getCartItems().isEmpty()) { - // 🔥 关键修复:从HttpServletRequest中获取目标购物车项ID - String targetCartItemId = getTargetCartItemIdFromRequest(request); - - UserProductCartDTO.CartItem selectedCartItem = findSelectedCartItem(userInfo, targetCartItemId); - - // 设置到单个字段 - 使用选中的购物车项 - dto.setProductName(selectedCartItem.getProductName() != null ? selectedCartItem.getProductName() : ""); - dto.setSpecification(selectedCartItem.getSpecification() != null ? selectedCartItem.getSpecification() : ""); - dto.setQuantity(selectedCartItem.getQuantity() != null ? selectedCartItem.getQuantity() : 0); - dto.setGrossWeight(selectedCartItem.getGrossWeight() != null ? selectedCartItem.getGrossWeight() : ""); - dto.setYolk(selectedCartItem.getYolk() != null ? selectedCartItem.getYolk() : ""); - - // 🔥 关键修改:设置选中的购物车项ID - dto.setTargetCartItemId(selectedCartItem.getCartItemId() != null ? selectedCartItem.getCartItemId() : ""); - - // 设置customDetails为购物车信息 - dto.setCustomDetails(userInfo.getCartItems().toArray()); - - System.out.println("✅ 成功设置选中购物车项到DTO: " + selectedCartItem.getProductName() + - ", 购物车项ID: " + selectedCartItem.getCartItemId() + - ", 是否前端指定: " + (targetCartItemId != null)); - } else { - // 如果没有购物车信息,设置默认值 - setDefaultProductValues(dto); - System.out.println("⚠️ 没有购物车信息,使用默认值"); - } - - // 设置 cartItems 到 UnifiedCustomerDTO - 销售端关键修复 - if (userInfo.getCartItems() != null && !userInfo.getCartItems().isEmpty()) { - List unifiedCartItems = userInfo.getCartItems().stream() - .map(cartItem -> { - UnifiedCustomerDTO.CartItem unifiedItem = new UnifiedCustomerDTO.CartItem(); - unifiedItem.setCartItemId(cartItem.getCartItemId() != null ? cartItem.getCartItemId() : ""); - unifiedItem.setProductId(cartItem.getProductId() != null ? cartItem.getProductId() : ""); - unifiedItem.setProductName(cartItem.getProductName() != null ? cartItem.getProductName() : ""); - unifiedItem.setSpecification(cartItem.getSpecification() != null ? cartItem.getSpecification() : ""); - unifiedItem.setQuantity(cartItem.getQuantity() != null ? cartItem.getQuantity() : 0); - unifiedItem.setGrossWeight(cartItem.getGrossWeight() != null ? cartItem.getGrossWeight() : ""); - unifiedItem.setYolk(cartItem.getYolk() != null ? cartItem.getYolk() : ""); - return unifiedItem; - }) - .collect(Collectors.toList()); - dto.setCartItems(unifiedCartItems); - System.out.println("✅ 成功设置 cartItems 到 UnifiedCustomerDTO,数量: " + unifiedCartItems.size()); - } else { - System.out.println("❌ 没有购物车数据可设置到 cartItems"); - } - - return dto; - } - - /** - * 从请求参数中获取目标购物车项ID - 完整实现 - */ - private String getTargetCartItemIdFromRequest() { - try { - // 从当前线程的HttpServletRequest中获取请求参数 - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes != null) { - HttpServletRequest request = attributes.getRequest(); - - // 从URL查询参数中获取targetCartItemId - String targetCartItemId = request.getParameter("targetCartItemId"); - - if (targetCartItemId != null && !targetCartItemId.trim().isEmpty()) { - System.out.println("🎯 从请求参数获取到目标购物车项ID: " + targetCartItemId); - return targetCartItemId.trim(); - } - - // 如果URL参数中没有,尝试从请求属性中获取(前端可能通过其他方式设置) - Object attributeValue = request.getAttribute("targetCartItemId"); - if (attributeValue != null) { - String cartItemId = attributeValue.toString(); - System.out.println("🎯 从请求属性获取到目标购物车项ID: " + cartItemId); - return cartItemId; - } - } - - System.out.println("⚠️ 未从请求中获取到目标购物车项ID"); - return null; - - } catch (Exception e) { - System.err.println("❌ 获取目标购物车项ID失败: " + e.getMessage()); - return null; - } - } - - /** - * 重载方法:从指定的HttpServletRequest中获取目标购物车项ID - */ - private String getTargetCartItemIdFromRequest(HttpServletRequest request) { - try { - if (request == null) { - System.out.println("⚠️ HttpServletRequest为null"); - return null; - } - - // 1. 首先从URL查询参数中获取 - String targetCartItemId = request.getParameter("targetCartItemId"); - - if (targetCartItemId != null && !targetCartItemId.trim().isEmpty()) { - System.out.println("🎯 从URL参数获取到目标购物车项ID: " + targetCartItemId); - return targetCartItemId.trim(); - } - - // 2. 如果URL参数中没有,尝试从请求属性中获取 - Object attributeValue = request.getAttribute("targetCartItemId"); - if (attributeValue != null) { - String cartItemId = attributeValue.toString(); - System.out.println("🎯 从请求属性获取到目标购物车项ID: " + cartItemId); - return cartItemId; - } - - // 3. 尝试从Header中获取 - String headerValue = request.getHeader("X-Target-CartItem-Id"); - if (headerValue != null && !headerValue.trim().isEmpty()) { - System.out.println("🎯 从Header获取到目标购物车项ID: " + headerValue); - return headerValue.trim(); - } - - System.out.println("⚠️ 未从请求中获取到目标购物车项ID"); - return null; - - } catch (Exception e) { - System.err.println("❌ 获取目标购物车项ID失败: " + e.getMessage()); - return null; - } - } - - /** - * 安全设置负责人信息 - */ - private void setManagerInfoSafely(UnifiedCustomerDTO dto, String userId) { - try { - System.out.println("🔍 查询用户负责人信息,用户ID: " + userId); - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - - if (userManager != null) { - System.out.println("✅ 找到负责人信息,设置到DTO"); - // 设置负责人信息到统一的DTO字段 - dto.setManagercompany(userManager.getManagercompany() != null ? userManager.getManagercompany() : ""); - dto.setManagerdepartment(userManager.getManagerdepartment() != null ? userManager.getManagerdepartment() : ""); - dto.setOrganization(userManager.getOrganization() != null ? userManager.getOrganization() : ""); - dto.setRole(userManager.getRole() != null ? userManager.getRole() : ""); - dto.setUserName(userManager.getUserName() != null ? userManager.getUserName() : ""); - dto.setAssistant(userManager.getAssistant() != null ? userManager.getAssistant() : ""); - - // 调试日志 - System.out.println("📝 负责人信息详情: " + - "公司=" + dto.getManagercompany() + - ", 部门=" + dto.getManagerdepartment() + - ", 组织=" + dto.getOrganization() + - ", 角色=" + dto.getRole() + - ", 负责人=" + dto.getUserName() + - ", 协助人=" + dto.getAssistant()); - } else { - System.out.println("⚠️ 未找到负责人信息,用户可能为公海池客户"); - // 设置默认值 - setDefaultManagerValues(dto); - } - } catch (Exception e) { - System.err.println("❌ 查询负责人信息失败: " + e.getMessage()); - // 发生异常时设置默认值 - setDefaultManagerValues(dto); - } - } - - /** - * 设置默认负责人值 - */ - private void setDefaultManagerValues(UnifiedCustomerDTO dto) { - dto.setManagercompany(""); - dto.setManagerdepartment(""); - dto.setOrganization(""); - dto.setRole(""); - dto.setUserName(""); - dto.setAssistant(""); - } - - - /** - * 设置默认产品值 - */ - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - } - - /** - * 安全设置联系人信息 - */ - private void setContactInfoSafely(UnifiedCustomerDTO dto, UserProductCartDTO userInfo) { - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - UserProductCartDTO.UsersContacts contact = userInfo.getUsersContacts().get(0); - dto.setWechat(contact.getWechat() != null ? contact.getWechat() : ""); - dto.setAccount(contact.getAccount() != null ? contact.getAccount() : ""); - dto.setAccountNumber(contact.getAccountNumber() != null ? contact.getAccountNumber() : ""); - dto.setBank(contact.getBank() != null ? contact.getBank() : ""); - dto.setAddress(contact.getAddress() != null ? contact.getAddress() : ""); - } else { - setDefaultContactValues(dto); - } - } - - /** - * 设置默认联系人值 - */ - private void setDefaultContactValues(UnifiedCustomerDTO dto) { - dto.setWechat(""); - dto.setAccount(""); - dto.setAccountNumber(""); - dto.setBank(""); - dto.setAddress(""); - } - - /** - * 数据库类型转前端类型 - */ - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": - return "BOTH"; - default: - return databaseType; - } - } - - // 以下保持原有方法不变... - @GetMapping("/customers/by-phone") - public ResponseEntity> getByPhone(@RequestParam String phoneNumber, HttpServletRequest request) { - System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); - System.out.println("getByPhone: ---------------------------------------------------" + phoneNumber); - Map response = new HashMap<>(); - try { - //🔥 修复:从URL参数获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, false); - - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - UnifiedCustomerDTO customer = customerService.getCustomerByPhone(phoneNumber, authInfo); - - // 检查客户等级,如果是公海池客户,确保数据源正确 - if (customer != null && customer.getLevel() != null && - (customer.getLevel().contains("sea-pools") || "公海池".equals(customer.getLevel()))) { - customer.setDataSource("wechat"); - } - - response.put("success", true); - response.put("data", customer); - return ResponseEntity.ok(response); - } catch (IllegalArgumentException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.badRequest().body(response); - } catch (RuntimeException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.notFound().build(); - } catch (Exception e) { - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 更新基于电话号码的客户信息(专门用于公海池客户)- 销售员权限:只允许更新为buyer和both类型 - */ - @PutMapping("/phone-customers/update") - public ResponseEntity> updatePhoneCustomer(@RequestBody UnifiedCustomerDTO updatedDTO, HttpServletRequest request) { - Map response = new HashMap<>(); - - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("======= 开始处理公海池客户更新(wechat数据源) ======="); - System.out.println("手机号: " + updatedDTO.getPhoneNumber()); - System.out.println("原始等级: " + updatedDTO.getLevel()); - System.out.println("负责人信息: " + authInfo.getUserName()); - - // 🔥 在Controller层先进行类型转换 - System.out.println("🔄 Controller层类型转换前: " + updatedDTO.getType()); - String originalType = updatedDTO.getType(); - String convertedType = convertCustomerTypeInController(originalType); - updatedDTO.setType(convertedType); - System.out.println("🔄 Controller层类型转换后: " + originalType + " → " + convertedType); - - System.out.println("🔐 负责人认证信息: " + - "公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - // 销售员权限:校验客户类型,只允许buyer和both - if (!"buyer".equals(updatedDTO.getType()) && !"both".equals(updatedDTO.getType())) { - System.out.println("❌ 权限校验失败:销售员只能更新为buyer或both类型,当前类型: " + updatedDTO.getType()); - response.put("success", false); - response.put("message", "销售员权限只能更新为客户端类型客户"); - return ResponseEntity.badRequest().body(response); - } - - // 调用服务层 - 传递authInfo用于负责人信息更新 - System.out.println("🔄 调用Service更新方法..."); - boolean success = customerService.updatePhoneBasedCustomer(updatedDTO, authInfo); - - System.out.println("✅ Service返回结果: " + success); - - if (success) { - System.out.println("🎉 公海池客户信息更新成功"); - response.put("success", true); - response.put("message", "客户信息更新成功"); - - // 记录修改客户信息操作 - informationTraService.recordOperationEvent( - updatedDTO.getPhoneNumber(), - updatedDTO.getUserName() != null ? updatedDTO.getUserName() : "", - updatedDTO.getPhoneNumber() + "-更新客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } else { - System.out.println("❌ 公海池客户信息更新失败"); - response.put("success", false); - response.put("message", "客户信息更新失败"); - return ResponseEntity.internalServerError().body(response); - } - } catch (Exception e) { - System.err.println("💥 更新公海池客户信息异常: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * Controller层的类型转换方法 - */ - private String convertCustomerTypeInController(String originalType) { - if (originalType == null) { - return "buyer"; - } - - switch (originalType.toUpperCase()) { - case "BOTH": - return "both"; - case "客户端": - case "BUYER": - return "buyer"; - case "供应端": - case "SELLER": - return "seller"; - default: - return originalType; - } - } - - @PutMapping("/customers/update") - public ResponseEntity> updateCustomer( - @RequestBody UnifiedCustomerDTO updatedDTO, HttpServletRequest request) { - - Map response = new HashMap<>(); - try { - System.out.println("======= 🔄 开始更新非公海池客户信息(销售端) ======="); - System.out.println("数据源: " + updatedDTO.getDataSource()); - System.out.println("客户ID: " + updatedDTO.getId()); - System.out.println("手机号: " + updatedDTO.getPhoneNumber()); - System.out.println("客户类型(转换前): " + updatedDTO.getType()); - System.out.println("客户等级: " + updatedDTO.getLevel()); - System.out.println("公司: " + updatedDTO.getCompany()); - System.out.println("区域: " + updatedDTO.getRegion()); - System.out.println("昵称: " + updatedDTO.getNickName()); - System.out.println("微信: " + updatedDTO.getWechat()); - System.out.println("地址: " + updatedDTO.getAddress()); - - // 打印负责人信息 - System.out.println("=== 负责人信息 ==="); - System.out.println("负责人公司: " + updatedDTO.getManagercompany()); - System.out.println("负责人部门: " + updatedDTO.getManagerdepartment()); - System.out.println("负责人组织: " + updatedDTO.getOrganization()); - System.out.println("负责人角色: " + updatedDTO.getRole()); - System.out.println("负责人姓名: " + updatedDTO.getUserName()); - System.out.println("协助人: " + updatedDTO.getAssistant()); - - // 🎯 新增:数据源自动验证和修正 - String originalDataSource = updatedDTO.getDataSource(); - String verifiedDataSource = verifyAndCorrectDataSource(updatedDTO); - if (!originalDataSource.equals(verifiedDataSource)) { - System.out.println("🔄 数据源自动修正: " + originalDataSource + " → " + verifiedDataSource); - updatedDTO.setDataSource(verifiedDataSource); - } - - // 关键修复:添加客户类型转换逻辑(之前遗漏) - System.out.println("🔄 Controller层类型转换前: " + updatedDTO.getType()); - String originalType = updatedDTO.getType(); - String convertedType = convertCustomerTypeInController(originalType); - updatedDTO.setType(convertedType); - System.out.println("🔄 Controller层类型转换后: " + originalType + " → " + convertedType); - - System.out.println("=== 数据验证 ==="); - System.out.println("手机号是否为空: " + (updatedDTO.getPhoneNumber() == null || updatedDTO.getPhoneNumber().trim().isEmpty())); - System.out.println("客户类型是否有效: " + ("buyer".equals(updatedDTO.getType()) || "both".equals(updatedDTO.getType()))); - System.out.println("========================================="); - - // 验证数据源 - String dataSource = updatedDTO.getDataSource(); - if (dataSource == null || dataSource.trim().isEmpty()) { - System.out.println("❌ 数据源标识不能为空,请明确指定数据源(wechat或default)"); - response.put("success", false); - response.put("message", "数据源标识不能为空,请明确指定数据源(wechat或default)"); - return ResponseEntity.badRequest().body(response); - } - - System.out.println("🔄 使用验证后的数据源: " + dataSource); - - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - // 权限校验 - System.out.println("🔐 ====== 开始权限校验 ======"); - System.out.println("🔐 当前类型: " + updatedDTO.getType()); - if (!"buyer".equals(updatedDTO.getType()) && !"both".equals(updatedDTO.getType())) { - System.out.println("❌ 权限校验失败:销售员只能更新为buyer或both类型,当前类型: " + updatedDTO.getType()); - response.put("success", false); - response.put("message", "销售员权限只能更新为客户端或双向类型客户"); - return ResponseEntity.badRequest().body(response); - } - System.out.println("✅ 权限校验通过"); - - boolean success; - - // 根据数据源处理更新 - if ("wechat".equals(dataSource)) { - System.out.println("使用wechat数据源更新非公海池客户"); - if (updatedDTO.getPhoneNumber() == null || updatedDTO.getPhoneNumber().trim().isEmpty()) { - throw new IllegalArgumentException("更新微信数据源时手机号不能为空"); - } - success = customerService.updateWechatCustomer(updatedDTO, authInfo, true); - } else if ("default".equals(dataSource)) { - System.out.println("使用默认数据源更新"); - if (updatedDTO.getId() == null || updatedDTO.getId().trim().isEmpty()) { - throw new IllegalArgumentException("更新默认数据源时公司ID不能为空"); - } - - // 关键新增:检查default数据源中客户是否存在 - boolean exists = customerService.checkDefaultCustomerExists(updatedDTO.getId()); - if (!exists) { - System.out.println("❌ default数据源中不存在ID为" + updatedDTO.getId() + "的客户"); - - // 尝试检查该客户是否存在于wechat数据源 - boolean existsInWechat = false; - try { - // 先尝试通过手机号查找 - if (updatedDTO.getPhoneNumber() != null && !updatedDTO.getPhoneNumber().trim().isEmpty()) { - System.out.println("🔍 尝试通过手机号在wechat数据源中查找客户: " + updatedDTO.getPhoneNumber()); - UnifiedCustomerDTO wechatCustomerDTO = customerService.getCustomerByPhone(updatedDTO.getPhoneNumber(), authInfo); - if (wechatCustomerDTO != null) { - existsInWechat = true; - System.out.println("✅ 在wechat数据源中找到客户"); - } - } - // 如果手机号查找失败,尝试通过ID查找 - if (!existsInWechat && updatedDTO.getId() != null && !updatedDTO.getId().trim().isEmpty()) { - System.out.println("🔍 尝试通过ID在wechat数据源中查找客户: " + updatedDTO.getId()); - UnifiedCustomerDTO wechatCustomerDTO = customerService.getWechatCustomerById(updatedDTO.getId(), authInfo); - if (wechatCustomerDTO != null) { - existsInWechat = true; - System.out.println("✅ 在wechat数据源中找到客户"); - } - } - } catch (Exception e) { - System.err.println("⚠️ 检查wechat数据源时出错: " + e.getMessage()); - } - - if (existsInWechat) { - System.out.println("🔄 自动切换到wechat数据源进行更新"); - updatedDTO.setDataSource("wechat"); - success = customerService.updateWechatCustomer(updatedDTO, authInfo, true); - response.put("success", true); - response.put("message", "客户信息更新成功(自动切换到正确的数据源)"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "默认数据源中未找到该客户,请检查ID或数据源是否正确"); - return ResponseEntity.badRequest().body(response); - } - } - - success = customerService.updateDefaultCustomer(updatedDTO, authInfo); - - // 新增:验证更新结果 - if (!success) { - System.out.println("❌ SQL执行成功但未更新任何记录,可能数据未变化或记录不存在"); - response.put("success", false); - response.put("message", "更新失败,未找到可更新的客户记录(可能数据无变化或ID错误)"); - return ResponseEntity.internalServerError().body(response); - } - } else { - System.out.println("❌ 不支持的数据源: " + dataSource); - response.put("success", false); - response.put("message", "不支持的数据源: " + dataSource); - return ResponseEntity.badRequest().body(response); - } - - // 记录更新客户信息操作 - informationTraService.recordOperationEvent( - updatedDTO.getPhoneNumber(), - updatedDTO.getNickName() != null ? updatedDTO.getNickName() : "", - updatedDTO.getPhoneNumber() + "-更新客户", - updatedDTO.getManagercompany() != null ? updatedDTO.getManagercompany() : "", - updatedDTO.getManagerdepartment() != null ? updatedDTO.getManagerdepartment() : "", - updatedDTO.getOrganization() != null ? updatedDTO.getOrganization() : "", - updatedDTO.getRole() != null ? updatedDTO.getRole() : "", - updatedDTO.getUserName() != null ? updatedDTO.getUserName() : "", - updatedDTO.getAssistant() != null ? updatedDTO.getAssistant() : "" - ); - - response.put("success", true); - response.put("message", "客户信息更新成功"); - return ResponseEntity.ok(response); - - } catch (IllegalArgumentException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.badRequest().body(response); - } catch (RuntimeException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.notFound().build(); - } catch (Exception e) { - System.err.println("更新客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 验证并修正数据源 - * 根据客户ID和手机号自动检测客户实际所在的数据源 - */ - private String verifyAndCorrectDataSource(UnifiedCustomerDTO updatedDTO) { - String dataSource = updatedDTO.getDataSource(); - String customerId = updatedDTO.getId(); - String phoneNumber = updatedDTO.getPhoneNumber(); - - System.out.println("🔍 开始验证数据源..."); - System.out.println("📱 手机号: " + phoneNumber); - System.out.println("🆔 客户ID: " + customerId); - System.out.println("📊 前端指定数据源: " + dataSource); - - // 如果已经是wechat数据源,直接返回 - if ("wechat".equals(dataSource)) { - System.out.println("✅ 数据源验证通过:wechat"); - return dataSource; - } - - // 如果指定了default数据源,但客户实际上在wechat数据源中 - if ("default".equals(dataSource)) { - try { - // 优先通过手机号检查wechat数据源 - if (phoneNumber != null && !phoneNumber.trim().isEmpty()) { - System.out.println("🔍 通过手机号检查wechat数据源: " + phoneNumber); - UserProductCartDTO wechatCustomer = poolCustomerService.getWechatCustomerByPhone(phoneNumber); - if (wechatCustomer != null) { - System.out.println("🎯 检测到客户存在于wechat数据源(通过手机号),自动修正数据源"); - return "wechat"; - } - } - - // 其次通过客户ID检查wechat数据源 - if (customerId != null && !customerId.trim().isEmpty()) { - System.out.println("🔍 通过客户ID检查wechat数据源: " + customerId); - UserProductCartDTO wechatCustomer = poolCustomerService.getPublicSeaCustomerInfo(customerId); - if (wechatCustomer != null) { - System.out.println("🎯 检测到客户存在于wechat数据源(通过客户ID),自动修正数据源"); - return "wechat"; - } - } - - // 如果wechat数据源都没找到,保持default数据源 - System.out.println("✅ 数据源验证通过:default(客户确实在default数据源中)"); - return dataSource; - - } catch (Exception e) { - System.err.println("❌ 数据源验证失败: " + e.getMessage()); - // 发生异常时保持原数据源 - return dataSource; - } - } - - // 如果是不支持的数据源,保持原样(后续会报错) - System.out.println("⚠️ 不支持的数据源类型: " + dataSource); - return dataSource; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/CustomerRestController.java b/src/main/java/com/example/web/controller/CustomerRestController.java new file mode 100644 index 0000000..93a70bc --- /dev/null +++ b/src/main/java/com/example/web/controller/CustomerRestController.java @@ -0,0 +1,263 @@ +package com.example.web.controller; + +import com.example.web.entity.Login; +import com.example.web.service.CustomerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: 客户数据REST控制器 + */ +@RestController +@RequestMapping("/api/customer") +public class CustomerRestController { + + @Autowired + private CustomerService customerService; + + /** + * 新增客户数据 + * @param customerData 客户数据,包含企业、联系人和负责人信息 + * @return 响应结果 + */ + @PostMapping + public Map addCustomer(@RequestParam Map customerData) { + Map response = new HashMap<>(); + try { + // 调用服务层方法添加客户 + boolean success = customerService.addCustomer(customerData); + + if (success) { + response.put("success", true); + response.put("message", "客户添加成功"); + } else { + response.put("success", false); + response.put("message", "客户添加失败"); + } + } catch (Exception e) { + response.put("success", false); + response.put("message", "客户添加失败: " + e.getMessage()); + e.printStackTrace(); + } + return response; + } + + /** + * 更新客户数据 + * @param request 客户数据,包含企业、联系人和负责人信息,使用电话号码作为唯一标识,以及操作人信息 + * @return 响应结果 + */ + @PostMapping("/update") + public Map updateCustomer(@RequestBody Map request) { + Map response = new HashMap<>(); + try { + System.out.println("DEBUG: 收到客户更新请求,数据: " + request); + + // 获取客户数据 + Map customerData = new HashMap<>(request); + + // 获取操作人信息 + Map operatorInfo = (Map) request.get("operatorInfo"); + if (operatorInfo == null) { + operatorInfo = new HashMap<>(); + } + + // 创建登录者信息对象 + Login login = new Login(); + login.setProjectName((String) operatorInfo.get("role")); + login.setUserName((String) operatorInfo.get("userName")); + login.setManagercompany((String) operatorInfo.get("company")); + login.setManagerdepartment((String) operatorInfo.get("department")); + login.setOrganization((String) operatorInfo.get("organization")); + + // 调用服务层方法更新客户 + boolean success = customerService.updateCustomer(customerData, login); + + System.out.println("DEBUG: 客户更新结果: " + success); + + if (success) { + response.put("success", true); + response.put("message", "客户更新成功"); + } else { + response.put("success", false); + response.put("message", "客户更新失败: 未找到客户信息或更新操作失败"); + } + } catch (Exception e) { + System.out.println("DEBUG: 客户更新异常,异常信息: " + e.getMessage()); + e.printStackTrace(); + response.put("success", false); + response.put("message", "客户更新失败: " + e.getMessage()); + } + System.out.println("DEBUG: 客户更新响应: " + response); + return response; + } + + /** + * 跟进客户 + * @param request 跟进请求,包含电话号码、跟进内容、数据源和操作人信息 + * @return 响应结果 + */ + @PostMapping("/followup") + public Map followupCustomer(@RequestBody Map request) { + Map response = new HashMap<>(); + try { + System.out.println("DEBUG: 收到客户跟进请求,数据: " + request); + + String phoneNumber = (String) request.get("phoneNumber"); + String followupContent = (String) request.get("followup"); + String dataSource = (String) request.get("dataSource"); + + // 获取操作人信息 + Map operatorInfo = (Map) request.get("operatorInfo"); + if (operatorInfo == null) { + operatorInfo = new HashMap<>(); + } + + // 创建登录者信息对象 + Login login = new Login(); + login.setProjectName((String) operatorInfo.get("role")); + login.setUserName((String) operatorInfo.get("userName")); + login.setManagercompany((String) operatorInfo.get("company")); + login.setManagerdepartment((String) operatorInfo.get("department")); + login.setOrganization((String) operatorInfo.get("organization")); + + if (phoneNumber == null || phoneNumber.isEmpty() || followupContent == null || dataSource == null) { + response.put("success", false); + response.put("message", "跟进失败: 参数不完整"); + return response; + } + + // 调用服务层方法跟进客户 + boolean success = customerService.followupCustomer(phoneNumber, followupContent, dataSource, login); + + System.out.println("DEBUG: 客户跟进结果: " + success); + + if (success) { + response.put("success", true); + response.put("message", "跟进成功"); + } else { + response.put("success", false); + response.put("message", "跟进失败: 未找到客户信息或更新操作失败"); + } + } catch (Exception e) { + System.out.println("DEBUG: 客户跟进异常,异常信息: " + e.getMessage()); + e.printStackTrace(); + response.put("success", false); + response.put("message", "跟进失败: " + e.getMessage()); + } + System.out.println("DEBUG: 客户跟进响应: " + response); + return response; + } + + /** + * 记录客户查看操作 + * @param request 查看请求,包含客户ID和操作人信息 + * @return 响应结果 + */ + @PostMapping("/view") + public Map recordCustomerView(@RequestBody Map request) { + Map response = new HashMap<>(); + try { + System.out.println("DEBUG: 收到客户查看请求,数据: " + request); + + String userId = (String) request.get("userId"); + + // 获取操作人信息 + Map operatorInfo = (Map) request.get("operatorInfo"); + if (operatorInfo == null) { + operatorInfo = new HashMap<>(); + } + + // 创建登录者信息对象 + Login login = new Login(); + login.setProjectName((String) operatorInfo.get("role")); + login.setUserName((String) operatorInfo.get("userName")); + login.setManagercompany((String) operatorInfo.get("company")); + login.setManagerdepartment((String) operatorInfo.get("department")); + login.setOrganization((String) operatorInfo.get("organization")); + + if (userId == null || userId.isEmpty()) { + response.put("success", false); + response.put("message", "记录查看操作失败: 参数不完整"); + return response; + } + + // 调用服务层方法记录客户查看操作 + boolean success = customerService.recordCustomerView(userId, login); + + System.out.println("DEBUG: 记录客户查看操作结果: " + success); + + if (success) { + response.put("success", true); + response.put("message", "记录查看操作成功"); + } else { + response.put("success", false); + response.put("message", "记录查看操作失败"); + } + } catch (Exception e) { + System.out.println("DEBUG: 记录客户查看操作异常,异常信息: " + e.getMessage()); + e.printStackTrace(); + response.put("success", false); + response.put("message", "记录查看操作失败: " + e.getMessage()); + } + System.out.println("DEBUG: 记录客户查看操作响应: " + response); + return response; + } + + /** + * 认领客户 + * @param request 认领请求,包含客户ID和操作人信息 + * @return 响应结果 + */ + @PostMapping("/claim") + public Map claimCustomer(@RequestBody Map request) { + Map response = new HashMap<>(); + try { + System.out.println("DEBUG: 收到客户认领请求,数据: " + request); + + String customerId = (String) request.get("customerId"); + + // 获取操作人信息 + Map operatorInfo = (Map) request.get("operatorInfo"); + if (operatorInfo == null) { + operatorInfo = new HashMap<>(); + } + + // 创建登录者信息对象 + Login login = new Login(); + login.setProjectName((String) operatorInfo.get("role")); + login.setUserName((String) operatorInfo.get("userName")); + login.setManagercompany((String) operatorInfo.get("company")); + login.setManagerdepartment((String) operatorInfo.get("department")); + login.setOrganization((String) operatorInfo.get("organization")); + + if (customerId == null || customerId.isEmpty()) { + response.put("success", false); + response.put("message", "客户认领失败: 参数不完整"); + return response; + } + + // 调用服务层方法认领客户 + boolean success = customerService.claimCustomer(customerId, login); + + System.out.println("DEBUG: 客户认领结果: " + success); + + if (success) { + response.put("success", true); + response.put("message", "客户认领成功"); + } else { + response.put("success", false); + response.put("message", "客户认领失败"); + } + } catch (Exception e) { + System.out.println("DEBUG: 客户认领异常,异常信息: " + e.getMessage()); + e.printStackTrace(); + response.put("success", false); + response.put("message", "客户认领失败: " + e.getMessage()); + } + return response; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/CustomerWebSocketController.java b/src/main/java/com/example/web/controller/CustomerWebSocketController.java new file mode 100644 index 0000000..8d27b5a --- /dev/null +++ b/src/main/java/com/example/web/controller/CustomerWebSocketController.java @@ -0,0 +1,67 @@ +package com.example.web.controller; + +import com.example.web.entity.CustomerData; +import com.example.web.entity.Login; +import com.example.web.service.CustomerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.handler.annotation.DestinationVariable; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +import java.util.List; + +/** + * @Description: 客户数据WebSocket控制器 + */ +@Controller +public class CustomerWebSocketController { + + @Autowired + private CustomerService customerService; + + /** + * 广播所有客户数据 + * @return 客户数据列表 + */ + @MessageMapping("/customer/all") + @SendTo("/topic/customers") + public List broadcastAllCustomers() { + return customerService.getAllCustomers(); + } + + /** + * 根据用户信息获取部门公海池数据 + * @param role 用户角色(buyer/seller) + * @param login 用户登录信息 + * @return 部门公海池客户数据 + */ + @MessageMapping("/customer/departmentSeaPool/{role}") + @SendTo("/topic/departmentSeaPool/{role}") + public List getDepartmentSeaPool(@DestinationVariable String role, Login login) { + return customerService.getDepartmentSeaPool(role, login); + } + + /** + * 根据用户信息获取组织公海池数据 + * @param role 用户角色(buyer/seller) + * @param login 用户登录信息 + * @return 组织公海池客户数据 + */ + @MessageMapping("/customer/organizationSeaPool/{role}") + @SendTo("/topic/organizationSeaPool/{role}") + public List getOrganizationSeaPool(@DestinationVariable String role, Login login) { + return customerService.getOrganizationSeaPool(role, login); + } + + /** + * 根据用户角色获取对应的数据(销售或采购) + * @param role 用户角色(buyer/seller) + * @return 对应角色的客户数据 + */ + @MessageMapping("/customer/role/{role}") + @SendTo("/topic/role/{role}") + public List getCustomersByRole(@DestinationVariable String role, Login login) { + return customerService.getCustomersByRole(role, login); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/EnterpriseController.java b/src/main/java/com/example/web/controller/EnterpriseController.java deleted file mode 100644 index e4c3989..0000000 --- a/src/main/java/com/example/web/controller/EnterpriseController.java +++ /dev/null @@ -1,1170 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Enterprise; -import com.example.web.entity.Contacts; -import com.example.web.entity.Managers; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.UsersManagementsMapper; -import com.example.web.service.CustomerService; -import com.example.web.service.EnterpriseService; -import com.example.web.service.PoolCustomerService; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.*; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -/** - * 企业客户管理控制器 - * 负责企业客户的全生命周期管理,支持双数据源融合查询 - * 路由前缀:/pool - */ -@RestController -@RequestMapping("/pool") -@CrossOrigin(origins = "*") -public class EnterpriseController { - - @Autowired - private EnterpriseService enterpriseService; - @Autowired - private PoolCustomerService poolCustomerService; - @Autowired - private CustomerService customerService; - @Autowired - private UsersManagementsMapper usersManagementsMapper; - - // 修改类型转换方法 - 前端类型转数据库类型 - private String convertFrontendTypeToDatabase(String frontendType) { - if (frontendType == null) { - return null; - } - switch (frontendType) { - case "供应端": - return "seller"; - case "客户端": - return "buyer"; - case "BOTH": - return "both"; // 关键修改:改为小写 - default: - return frontendType; - } - } - - // 确保数据库类型转前端类型也正确 - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": // 关键修改:匹配小写的数据库存储 - return "BOTH"; - default: - return databaseType; - } - } - - // 添加完整的类型转换方法 - private Map convertTypesForFrontend(Map response) { - if (response.containsKey("data")) { - Object data = response.get("data"); - if (data instanceof Map) { - Map dataMap = (Map) data; - for (UnifiedCustomerDTO dto : dataMap.values()) { - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - // 添加数据源标识 - dto.setDataSource("wechat"); - } - } else if (data instanceof List) { - List dataList = (List) data; - for (Object item : dataList) { - if (item instanceof UnifiedCustomerDTO) { - UnifiedCustomerDTO dto = (UnifiedCustomerDTO) item; - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - dto.setDataSource("wechat"); - } else if (item instanceof EnterpriseInfoDTO) { - EnterpriseInfoDTO enterpriseInfo = (EnterpriseInfoDTO) item; - if (enterpriseInfo.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - enterpriseInfo.getEnterprise().setType(frontendType); - } - } - } - } else if (data instanceof UnifiedCustomerDTO) { - UnifiedCustomerDTO dto = (UnifiedCustomerDTO) data; - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - dto.setDataSource("wechat"); - } else if (data instanceof EnterpriseInfoDTO) { - EnterpriseInfoDTO enterpriseInfo = (EnterpriseInfoDTO) data; - if (enterpriseInfo.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - enterpriseInfo.getEnterprise().setType(frontendType); - } - } - } - return response; - } - - // 新增:电话号码重复检查接口(供前端预校验) - @GetMapping("/customers/check-phone") - public ResponseEntity> checkPhoneNumber(@RequestParam String phoneNumber) { - System.out.println("电话号码重复检查接口(双数据源):------------"+phoneNumber); - Map response = new HashMap<>(); - - // 1. 非空校验 - if (!StringUtils.hasText(phoneNumber)) { - response.put("success", false); - response.put("message", "电话号码不能为空"); - response.put("isDuplicate", false); - return ResponseEntity.badRequest().body(response); - } - - // 2. 格式校验(简单示例:11位数字) - if (!phoneNumber.matches("^1[3-9]\\d{9}$")) { - response.put("success", false); - response.put("message", "请输入有效的11位手机号码"); - response.put("isDuplicate", false); - return ResponseEntity.badRequest().body(response); - } - - // 3. 重复校验 - 现在检查双数据源 - boolean isDuplicate = enterpriseService.isPhoneNumberDuplicate(phoneNumber); - response.put("success", true); - response.put("isDuplicate", isDuplicate); - response.put("message", isDuplicate ? "电话号码已存在" : "电话号码可用"); - return ResponseEntity.ok(response); - } - - // 新增:处理前端提交的客户数据(保存到默认数据源) - @PostMapping("/inputcustomers") - public ResponseEntity> addCustomer(@Valid UnifiedCustomerDTO dto, BindingResult result) { - System.out.println("新增客户信息:------------"); - System.out.println("原始类型: " + dto.getType()); - System.out.println(dto.getPhoneNumber()+"----"+dto.getCreated_at()+"----"+dto.getNickName()+"----"+dto.getUserName()); - Map response = new HashMap<>(); - - // 1. 参数校验(包括手机号非空) - if (result.hasErrors()) { - response.put("success", false); - response.put("message", "参数错误:" + result.getFieldError().getDefaultMessage()); - return ResponseEntity.badRequest().body(response); - } - - - // 在检查重复之前转换类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - System.out.println("转换后类型: " + dto.getType()); - - // 销售端权限:校验客户类型,只允许buyer和both - System.out.println("权限校验 - 当前类型: " + dto.getType() + ", 是否buyer: " + "buyer".equals(dto.getType()) + ", 是否both: " + "both".equals(dto.getType())); - - if (!"buyer".equals(dto.getType()) && !"both".equals(dto.getType())) { - response.put("success", false); - response.put("message", "销售端权限只能新增客户端类型客户和BOTH类型客户"); - return ResponseEntity.badRequest().body(response); - } - - // 2. 检查电话号码是否重复(同时检查双数据源) - if (enterpriseService.isPhoneNumberDuplicate(dto.getPhoneNumber())) { - response.put("success", false); - response.put("message", "电话号码已存在,添加失败"); - response.put("isDuplicate", true); - return ResponseEntity.badRequest().body(response); - } - - // 3. 执行新增逻辑 - try { - boolean success = enterpriseService.addCustomer(dto); - if (success) { - response.put("success", true); - response.put("message", "新增客户成功"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "新增客户失败"); - return ResponseEntity.internalServerError().body(response); - } - } catch (Exception e) { - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取所有客户完整信息 - 融合双数据查询 + 负责人过滤 - * GET /pool/customers - */ - @ResponseBody - @GetMapping("/customers") - public ResponseEntity> getAllCustomers(HttpServletRequest request) { - System.out.println("===================================================="); - System.out.println("🔄 开始获取所有客户信息 - 双数据源查询 + 负责人过滤"); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 从URL参数中获取ManagerAuthInfo - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - - if (authInfo == null) { - System.out.println("❌ 未找到用户认证信息"); - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("✅ 获取到用户认证信息: " + authInfo.getUserName()); - System.out.println("🔐 负责人过滤条件: " + - "公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment()); - - // 1. 创建结果存储容器,优先使用手机号作为键 - Map resultMap = new HashMap<>(); - - // 2. 处理primary数据源(企业信息)- 添加负责人过滤 - System.out.println("🏢 开始获取企业数据..."); - List enterpriseData = enterpriseService.getAllEnterpriseInfo(); - - // 应用负责人过滤 - List filteredEnterpriseData = enterpriseData.stream() - .filter(enterpriseInfo -> hasManagerPermission(enterpriseInfo, authInfo)) - .collect(Collectors.toList()); - - long enterpriseEndTime = System.currentTimeMillis(); - - System.out.println("✅ 企业数据查询完成"); - System.out.println("📊 企业数据条数: " + enterpriseData.size() + " → 过滤后: " + filteredEnterpriseData.size()); - - int enterpriseCount = 0; - if (filteredEnterpriseData != null) { - for (EnterpriseInfoDTO enterpriseInfo : filteredEnterpriseData) { - try { - UnifiedCustomerDTO dto = convertToUnifiedDTOFromEnterprise(enterpriseInfo); - String key = dto.getPhoneNumber() != null && !dto.getPhoneNumber().isEmpty() - ? dto.getPhoneNumber() - : dto.getId(); - - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无有效标识的企业数据"); - continue; - } - - resultMap.put(key, dto); - enterpriseCount++; - - // 打印前几条数据的详细信息 - if (enterpriseCount <= 3) { - System.out.println("📝 企业客户样例 " + enterpriseCount + ": " + - "公司=" + dto.getCompany() + - ", 联系人=" + dto.getNickName() + - ", 手机=" + dto.getPhoneNumber() + - ", 类型=" + dto.getType()); - } - } catch (Exception e) { - System.err.println("❌ 处理企业数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ 企业数据源成功处理: " + enterpriseCount + " 条记录"); - } - - // 3. 处理wechat数据源(用户信息)- 添加负责人过滤 - System.out.println("📱 开始获取wechat数据..."); - long wechatStartTime = System.currentTimeMillis(); - - List userData = poolCustomerService.getAllCustomers(authInfo); - -// 🔥 新增:在Controller层进行负责人过滤之前,先收集所有用户ID用于批量查询 - List allUserIds = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - if (userInfo.getUserId() != null && !userInfo.getUserId().isEmpty()) { - allUserIds.add(userInfo.getUserId()); - } - } - } - -// 🔥 新增:批量查询所有用户的负责人信息 - Map managerMap = new HashMap<>(); - if (!allUserIds.isEmpty()) { - try { - List allManagers = usersManagementsMapper.findByUserIds(allUserIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询负责人信息失败: " + e.getMessage()); - // 即使批量查询失败,也不影响后续逻辑,只是会使用默认值 - } - } - -// 在Controller层进行负责人过滤 - List filteredUserData = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - try { - if (hasPermissionToViewWechatCustomer(userInfo, authInfo)) { - filteredUserData.add(userInfo); - } - } catch (Exception e) { - System.err.println("❌ 检查用户权限时出错: " + e.getMessage()); - } - } - } - - long wechatEndTime = System.currentTimeMillis(); - - System.out.println("✅ Wechat数据查询完成"); - System.out.println("📊 Wechat数据条数: " + userData.size() + " → 过滤后: " + filteredUserData.size()); - System.out.println("⏱️ Wechat查询耗时: " + (wechatEndTime - wechatStartTime) + "ms"); - - int wechatCount = 0; - int updateCount = 0; - if (filteredUserData != null) { - for (UserProductCartDTO userInfo : filteredUserData) { - try { - String key = userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""; - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无手机号的用户数据"); - continue; - } - - // 检查是否已存在该手机号的记录 - if (resultMap.containsKey(key)) { - // 更新现有记录(补充wechat数据源的信息) - UnifiedCustomerDTO existingDto = resultMap.get(key); - updateUnifiedDTOWithWechatData(existingDto, userInfo); - updateCount++; - } else { - // 🔥 修改:传入managerMap,避免N+1查询 - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo, managerMap); - resultMap.put(key, dto); - wechatCount++; - } - } catch (Exception e) { - System.err.println("❌ 处理用户数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ Wechat数据源成功处理: " + wechatCount + " 条新记录, " + updateCount + " 条更新记录"); - } - - // 4. 打印最终统计信息和详细信息 - printFinalStatistics(resultMap, enterpriseCount, wechatCount, updateCount); - - // 5. 构建响应 - response.put("success", true); - response.put("data", resultMap); - response.put("message", "获取客户信息成功"); - response.put("total", resultMap.size()); - response.put("enterpriseCount", enterpriseCount); - response.put("wechatCount", wechatCount); - response.put("updateCount", updateCount); - - return ResponseEntity.ok(convertTypesForFrontend(response)); - } catch (Exception e) { - System.err.println("❌ 获取客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 从请求中获取ManagerAuthInfo - 增强版本,严格区分销售端和采购端 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - String managerId = request.getParameter("managerId"); - String managercompany = request.getParameter("company"); - String managerdepartment = request.getParameter("department"); - String organization = request.getParameter("organization"); - String role = request.getParameter("role"); - String userName = request.getParameter("userName"); - String assistant = request.getParameter("assistant"); - - // URL解码参数 - try { - if (managerId != null) managerId = java.net.URLDecoder.decode(managerId, "UTF-8"); - if (managercompany != null) managercompany = java.net.URLDecoder.decode(managercompany, "UTF-8"); - if (managerdepartment != null) managerdepartment = java.net.URLDecoder.decode(managerdepartment, "UTF-8"); - if (organization != null) organization = java.net.URLDecoder.decode(organization, "UTF-8"); - if (role != null) role = java.net.URLDecoder.decode(role, "UTF-8"); - if (userName != null) userName = java.net.URLDecoder.decode(userName, "UTF-8"); - if (assistant != null) assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - System.err.println("URL解码失败: " + e.getMessage()); - } - - // 检查必要参数 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名为空,无法获取认证信息"); - return null; - } - - // 部门检查 - if (managerdepartment == null) { - System.out.println("❌ 部门信息为空"); - return null; - } - - // 智能判断实际端类型:根据部门信息自动调整isSupplySide值 - boolean actualIsSupplySide = isSupplySide; - if (managerdepartment.contains("销售")) { - actualIsSupplySide = false; // 销售部门自动判定为销售端 - System.out.println("🔄 部门包含'销售',自动调整为销售端"); - } else if (managerdepartment.contains("采购")) { - actualIsSupplySide = true; // 采购部门自动判定为采购端 - System.out.println("🔄 部门包含'采购',自动调整为采购端"); - } - - System.out.println("🔍 认证信息检查,实际端类型: " + (actualIsSupplySide ? "采购端" : "销售端") + - ",部门: '" + managerdepartment + "'"); - System.out.println("✅ 认证信息检查通过"); - - // 验证公司信息一致性 - if (managercompany == null || managercompany.trim().isEmpty()) { - System.out.println("❌ 公司信息为空"); - return null; - } - - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId != null ? managerId : "", - managercompany != null ? managercompany : "", - managerdepartment != null ? managerdepartment : "", - organization != null ? organization : "", - role != null ? role : "", - userName, - assistant != null ? assistant : ""); - - // 设置实际的端类型 - try { - // 尝试通过反射或setter方法设置supplySide属性 - java.lang.reflect.Field field = authInfo.getClass().getDeclaredField("supplySide"); - field.setAccessible(true); - field.set(authInfo, actualIsSupplySide); - } catch (Exception e) { - System.out.println("ℹ️ 无法设置supplySide属性: " + e.getMessage()); - } - - System.out.println("🎯 认证信息详情: " + - "系统类型=" + (actualIsSupplySide ? "采购端" : "销售端") + - ", 公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - return authInfo; - } - - /** - * 检查企业负责人权限 - */ - private boolean hasManagerPermission(EnterpriseInfoDTO enterpriseInfo, ManagerAuthInfo authInfo) { - if (enterpriseInfo.getManagers() == null) { - System.out.println("✅ 企业客户无负责人信息,允许查看"); - return true; - } - - return isManagerMatch(enterpriseInfo.getManagers(), authInfo); - } - - /** - * 检查负责人信息是否匹配(Managers) - */ - private boolean isManagerMatch(Managers manager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(manager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(manager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(manager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(manager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(manager.getUserName())); - - System.out.println("🔐 企业负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 检查是否有权限查看微信客户 - 修复版本 - */ - private boolean hasPermissionToViewWechatCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 开始检查微信客户权限,用户ID: " + userInfo.getUserId()); - - // 公海池客户对所有人可见 - if (isPublicSeaCustomer(userInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - System.out.println("🔍 非公海池客户,检查负责人权限..."); - boolean hasPermission = customerService.hasPermissionToViewWechatCustomer(userInfo, authInfo); - System.out.println("🔐 微信客户权限检查结果: " + (hasPermission ? "✅ 有权限" : "❌ 无权限")); - return hasPermission; - } catch (Exception e) { - System.err.println("❌ 检查微信客户权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 判断是否为公海池客户 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo) { - // 定义公海池等级 - java.util.Set publicSeaLevels = java.util.Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - - System.out.println("🔍 客户等级检查: " + userInfo.getLevel() + " → 是否公海池: " + isPublicSeaLevel); - - // 公海池客户:等级是公海池 - return isPublicSeaLevel; - } - - /** - * 从企业数据源转换DTO - */ - private UnifiedCustomerDTO convertToUnifiedDTOFromEnterprise(EnterpriseInfoDTO enterpriseInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - String companyId = enterpriseInfo.getEnterprise() != null ? enterpriseInfo.getEnterprise().getId() : ""; - - // 设置企业信息 - if (enterpriseInfo.getEnterprise() != null) { - dto.setId(enterpriseInfo.getEnterprise().getId() != null ? enterpriseInfo.getEnterprise().getId() : ""); - dto.setCompany(enterpriseInfo.getEnterprise().getCompany() != null ? enterpriseInfo.getEnterprise().getCompany() : ""); - dto.setRegion(enterpriseInfo.getEnterprise().getRegion() != null ? enterpriseInfo.getEnterprise().getRegion() : ""); - dto.setLevel(enterpriseInfo.getEnterprise().getLevel() != null ? enterpriseInfo.getEnterprise().getLevel() : ""); - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - dto.setType(frontendType != null ? frontendType : ""); - dto.setDemand(enterpriseInfo.getEnterprise().getDemand() != null ? enterpriseInfo.getEnterprise().getDemand() : ""); - dto.setSpec(enterpriseInfo.getEnterprise().getSpec() != null ? enterpriseInfo.getEnterprise().getSpec() : ""); - } - - // 设置联系人信息 - if (enterpriseInfo.getContacts() != null) { - dto.setNickName(enterpriseInfo.getContacts().getNickName() != null ? enterpriseInfo.getContacts().getNickName() : ""); - dto.setPhoneNumber(enterpriseInfo.getContacts().getPhoneNumber() != null ? enterpriseInfo.getContacts().getPhoneNumber() : ""); - dto.setWechat(enterpriseInfo.getContacts().getWechat() != null ? enterpriseInfo.getContacts().getWechat() : ""); - dto.setAccount(enterpriseInfo.getContacts().getAccount() != null ? enterpriseInfo.getContacts().getAccount() : ""); - dto.setAccountNumber(enterpriseInfo.getContacts().getAccountNumber() != null ? enterpriseInfo.getContacts().getAccountNumber() : ""); - dto.setBank(enterpriseInfo.getContacts().getBank() != null ? enterpriseInfo.getContacts().getBank() : ""); - dto.setAddress(enterpriseInfo.getContacts().getAddress() != null ? enterpriseInfo.getContacts().getAddress() : ""); - dto.setCreated_at(enterpriseInfo.getContacts().getCreated_at()); - dto.setUpdated_at(enterpriseInfo.getContacts().getUpdated_at()); - } - - // 设置负责人信息(根据新的表结构) - if (enterpriseInfo.getManagers() != null) { - // 使用新的字段名 - dto.setManagercompany(enterpriseInfo.getManagers().getManagercompany() != null ? enterpriseInfo.getManagers().getManagercompany() : ""); - dto.setManagerdepartment(enterpriseInfo.getManagers().getManagerdepartment() != null ? enterpriseInfo.getManagers().getManagerdepartment() : ""); - dto.setOrganization(enterpriseInfo.getManagers().getOrganization() != null ? enterpriseInfo.getManagers().getOrganization() : ""); - dto.setRole(enterpriseInfo.getManagers().getRole() != null ? enterpriseInfo.getManagers().getRole() : ""); - dto.setUserName(enterpriseInfo.getManagers().getUserName() != null ? enterpriseInfo.getManagers().getUserName() : ""); - dto.setAssistant(enterpriseInfo.getManagers().getAssistant() != null ? enterpriseInfo.getManagers().getAssistant() : ""); - } - - // 设置数据源标识 - dto.setDataSource("enterprise"); - - return dto; - } - - /** - * 专门为公海池客户转换DTO的方法 - 补充负责人信息(优化版本) - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea(UserProductCartDTO userInfo, Map managerMap) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - // 设置用户基础信息 - dto.setId(userInfo.getUserId() != null ? userInfo.getUserId() : ""); - dto.setPhoneNumber(userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""); - - // 设置公司信息 - dto.setCompany(userInfo.getCompany() != null ? userInfo.getCompany() : ""); - dto.setRegion(userInfo.getRegion() != null ? userInfo.getRegion() : ""); - - // 设置需求和规格 - dto.setDemand(userInfo.getDemand() != null ? userInfo.getDemand() : ""); - dto.setSpec(userInfo.getSpec() != null ? userInfo.getSpec() : ""); - - // 类型转换 - String frontendType = convertDatabaseTypeToFrontend(userInfo.getType()); - dto.setType(frontendType != null ? frontendType : ""); - - dto.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : ""); - dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - // 添加通知信息转换 - dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); - - // 关键:设置数据源标识为wechat - dto.setDataSource("wechat"); - - // 设置联系人信息 - 从usersContacts获取 - setContactInfoSafely(dto, userInfo); - - // 🔥 修改:从批量查询的managerMap中获取负责人信息,避免N+1查询 - setManagerInfoFromMap(dto, userInfo.getUserId(), managerMap); - - // 设置公海需求信息 - 从购物车表获取(销售端) - if (userInfo.getCartItems() != null && !userInfo.getCartItems().isEmpty()) { - UserProductCartDTO.CartItem cartItem = userInfo.getCartItems().get(0); - dto.setProductName(cartItem.getProductName() != null ? cartItem.getProductName() : ""); - dto.setSpecification(cartItem.getSpecification() != null ? cartItem.getSpecification() : ""); - dto.setQuantity(cartItem.getQuantity() != null ? cartItem.getQuantity() : 0); - dto.setGrossWeight(cartItem.getGrossWeight() != null ? cartItem.getGrossWeight() : ""); - dto.setYolk(cartItem.getYolk() != null ? cartItem.getYolk() : ""); - - // 购物车没有品种字段,所以留空或设置默认值 - dto.setVariety(""); - - // 设置customDetails为购物车信息 - dto.setCustomDetails(userInfo.getCartItems().toArray()); - } else { - // 如果没有购物车信息,设置默认值 - setDefaultProductValues(dto); - } - - return dto; - } - - - /** - * 从批量查询的Map中设置负责人信息 - 避免N+1查询 - */ - private void setManagerInfoFromMap(UnifiedCustomerDTO dto, String userId, Map managerMap) { - try { - System.out.println("🔍 从批量Map中查询用户负责人信息,用户ID: " + userId); - UsersManagements userManager = managerMap.get(userId); - - if (userManager != null) { - System.out.println("✅ 从批量Map中找到负责人信息,设置到DTO"); - // 设置负责人信息到统一的DTO字段 - dto.setManagercompany(userManager.getManagercompany() != null ? userManager.getManagercompany() : ""); - dto.setManagerdepartment(userManager.getManagerdepartment() != null ? userManager.getManagerdepartment() : ""); - dto.setOrganization(userManager.getOrganization() != null ? userManager.getOrganization() : ""); - dto.setRole(userManager.getRole() != null ? userManager.getRole() : ""); - dto.setUserName(userManager.getUserName() != null ? userManager.getUserName() : ""); - dto.setAssistant(userManager.getAssistant() != null ? userManager.getAssistant() : ""); - - // 调试日志 - System.out.println("📝 负责人信息详情: " + - "公司=" + dto.getManagercompany() + - ", 部门=" + dto.getManagerdepartment() + - ", 组织=" + dto.getOrganization() + - ", 角色=" + dto.getRole() + - ", 负责人=" + dto.getUserName() + - ", 协助人=" + dto.getAssistant()); - } else { - System.out.println("⚠️ 未在批量Map中找到负责人信息,用户可能为公海池客户"); - // 设置默认值 - setDefaultManagerValues(dto); - } - } catch (Exception e) { - System.err.println("❌ 从Map设置负责人信息失败: " + e.getMessage()); - // 发生异常时设置默认值 - setDefaultManagerValues(dto); - } - } - - - /** - * 设置默认负责人值 - */ - private void setDefaultManagerValues(UnifiedCustomerDTO dto) { - dto.setManagercompany(""); - dto.setManagerdepartment(""); - dto.setOrganization(""); - dto.setRole(""); - dto.setUserName(""); - dto.setAssistant(""); - } - - - /** - * 用wechat数据更新现有的DTO(用于数据合并) - */ - private void updateUnifiedDTOWithWechatData(UnifiedCustomerDTO existingDto, UserProductCartDTO userInfo) { - // 补充产品信息(如果企业数据中缺少) - if ((existingDto.getProductName() == null || existingDto.getProductName().isEmpty()) && - userInfo.getCartItems() != null && !userInfo.getCartItems().isEmpty()) { - - UserProductCartDTO.CartItem cartItem = userInfo.getCartItems().get(0); - existingDto.setProductName(cartItem.getProductName() != null ? cartItem.getProductName() : ""); - existingDto.setSpecification(cartItem.getSpecification() != null ? cartItem.getSpecification() : ""); - existingDto.setQuantity(cartItem.getQuantity() != null ? cartItem.getQuantity() : 0); - existingDto.setGrossWeight(cartItem.getGrossWeight() != null ? cartItem.getGrossWeight() : ""); - existingDto.setYolk(cartItem.getYolk() != null ? cartItem.getYolk() : ""); - - // 设置customDetails - existingDto.setCustomDetails(userInfo.getCartItems().toArray()); - } - - // 补充其他可能缺失的字段 - if (existingDto.getLevel() == null || existingDto.getLevel().isEmpty()) { - existingDto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - } - - // 标记为混合数据源 - existingDto.setDataSource("mixed"); - } - - /** - * 打印最终统计信息 - */ - private void printFinalStatistics(Map resultMap, int enterpriseCount, int wechatCount, int updateCount) { - System.out.println("===================================================="); - System.out.println("📈 数据源查询统计:"); - System.out.println("🏢 企业数据源: " + enterpriseCount + " 条记录"); - System.out.println("📱 Wechat数据源: " + (wechatCount + updateCount) + " 条记录 (" + wechatCount + " 新增, " + updateCount + " 更新)"); - System.out.println("📊 合并后总客户数: " + resultMap.size() + " 条记录"); - System.out.println("===================================================="); - - // 打印详细样例(限制数量避免日志过多) - int sampleCount = 0; - System.out.println("📋 最终数据样例:"); - for (Map.Entry entry : resultMap.entrySet()) { - if (sampleCount >= 1) break; - - String key = entry.getKey(); - UnifiedCustomerDTO dto = entry.getValue(); - - System.out.println("--- 客户 " + (sampleCount + 1) + " ---"); - System.out.println(" 键: " + key); - System.out.println(" 数据源: " + dto.getDataSource()); - System.out.println(" ID: " + dto.getId()); - System.out.println(" 公司: " + dto.getCompany()); - System.out.println(" 联系人: " + dto.getNickName()); - System.out.println(" 手机: " + dto.getPhoneNumber()); - System.out.println(" 微信号: " + dto.getWechat()); - System.out.println(" 类型: " + dto.getType()); - System.out.println(" 等级: " + dto.getLevel()); - System.out.println(" 地区: " + dto.getRegion()); - System.out.println(" 需求: " + dto.getDemand()); - System.out.println(" 规格: " + dto.getSpec()); - - // 产品信息 - System.out.println(" 产品名称: " + dto.getProductName()); - System.out.println(" 品种: " + dto.getVariety()); - System.out.println(" 规格说明: " + dto.getSpecification()); - System.out.println(" 数量: " + dto.getQuantity()); - System.out.println(" 毛重: " + dto.getGrossWeight()); - System.out.println(" 蛋黄: " + dto.getYolk()); - - // 联系人详细信息 - System.out.println(" 账户: " + dto.getAccount()); - System.out.println(" 账号: " + dto.getAccountNumber()); - System.out.println(" 银行: " + dto.getBank()); - System.out.println(" 地址: " + dto.getAddress()); - - // 负责人信息 - System.out.println(" 负责公司: " + dto.getManagercompany()); - System.out.println(" 负责部门: " + dto.getManagerdepartment()); - System.out.println(" 组织: " + dto.getOrganization()); - System.out.println(" 角色: " + dto.getRole()); - System.out.println(" 负责人: " + dto.getUserName()); - System.out.println(" 协助人: " + dto.getAssistant()); - - // 时间信息 - System.out.println(" 创建时间: " + dto.getCreated_at()); - System.out.println(" 更新时间: " + dto.getUpdated_at()); - - // 购物车信息 - if (dto.getCartItems() != null && !dto.getCartItems().isEmpty()) { - System.out.println(" 购物车项数量: " + dto.getCartItems().size()); - for (int i = 0; i < Math.min(dto.getCartItems().size(), 3); i++) { - UnifiedCustomerDTO.CartItem item = dto.getCartItems().get(i); - System.out.println(" 购物车项 " + (i + 1) + ":"); - System.out.println(" ID: " + item.getCartItemId()); - System.out.println(" 产品ID: " + item.getProductId()); - System.out.println(" 产品名称: " + item.getProductName()); - System.out.println(" 规格: " + item.getSpecification()); - System.out.println(" 数量: " + item.getQuantity()); - System.out.println(" 毛重: " + item.getGrossWeight()); - System.out.println(" 蛋黄: " + item.getYolk()); - } - } else { - System.out.println(" 购物车项: 无"); - } - - // 联系人列表信息 - if (dto.getContacts() != null && !dto.getContacts().isEmpty()) { - System.out.println(" 联系人数量: " + dto.getContacts().size()); - for (int i = 0; i < Math.min(dto.getContacts().size(), 3); i++) { - UnifiedCustomerDTO.ContactInfo contact = dto.getContacts().get(i); - System.out.println(" 联系人 " + (i + 1) + ":"); - System.out.println(" ID: " + contact.getContactId()); - System.out.println(" 微信: " + contact.getWechat()); - System.out.println(" 账户: " + contact.getAccount()); - System.out.println(" 账号: " + contact.getAccountNumber()); - System.out.println(" 银行: " + contact.getBank()); - System.out.println(" 地址: " + contact.getAddress()); - } - } else { - System.out.println(" 联系人列表: 无"); - } - - // 自定义详情 - if (dto.getCustomDetails() != null && dto.getCustomDetails().length > 0) { - System.out.println(" 自定义详情数量: " + dto.getCustomDetails().length); - } else { - System.out.println(" 自定义详情: 无"); - } - - sampleCount++; - System.out.println(); // 空行分隔 - } - System.out.println("===================================================="); - } - - // 保留原有的辅助方法 - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - } - - private void setContactInfoSafely(UnifiedCustomerDTO dto, UserProductCartDTO userInfo) { - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - List validContacts = userInfo.getUsersContacts().stream() - .filter(contact -> contact != null) - .collect(Collectors.toList()); - - if (!validContacts.isEmpty()) { - UserProductCartDTO.UsersContacts contact = validContacts.get(0); - dto.setWechat(contact.getWechat() != null ? contact.getWechat() : ""); - dto.setAccount(contact.getAccount() != null ? contact.getAccount() : ""); - dto.setAccountNumber(contact.getAccountNumber() != null ? contact.getAccountNumber() : ""); - dto.setBank(contact.getBank() != null ? contact.getBank() : ""); - dto.setAddress(contact.getAddress() != null ? contact.getAddress() : ""); - } else { - setDefaultContactValues(dto); - } - } else { - setDefaultContactValues(dto); - } - } - - private void setDefaultContactValues(UnifiedCustomerDTO dto) { - dto.setWechat(""); - dto.setAccount(""); - dto.setAccountNumber(""); - dto.setBank(""); - dto.setAddress(""); - } - - /** - * 根据ID获取客户详细信息 - * GET /pool/customers/{id} - */ - @GetMapping("/{id}") - public ResponseEntity> getCustomerById(@PathVariable String id) { - Map response = new HashMap<>(); - try { - EnterpriseInfoDTO customer = enterpriseService.getEnterpriseInfoById(id); - if (customer != null) { - response.put("success", true); - response.put("data", customer); - response.put("message", "获取客户信息成功"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "未找到对应的客户信息"); - return ResponseEntity.notFound().build(); - } - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 搜索客户信息 - * GET /pool/customers/search?keyword=xxx - */ - @GetMapping("/search") - public ResponseEntity> searchCustomers(@RequestParam(required = false) String keyword) { - Map response = new HashMap<>(); - try { - List customers = enterpriseService.searchEnterprises(keyword); - // 类型转换:将每个企业类型从数据库类型转换为前端类型 - for (EnterpriseInfoDTO customer : customers) { - if (customer.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(customer.getEnterprise().getType()); - customer.getEnterprise().setType(frontendType); - } - } - response.put("success", true); - response.put("data", customers); - response.put("message", "搜索客户信息成功"); - response.put("total", customers.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "搜索客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取所有企业基本信息 - * GET /pool/customers/enterprises - */ - @GetMapping("/enterprises") - public ResponseEntity> getAllEnterprises() { - Map response = new HashMap<>(); - try { - List enterprises = enterpriseService.getAllEnterprises(); - // 类型转换:将每个企业类型从数据库类型转换为前端类型 - for (Enterprise enterprise : enterprises) { - String frontendType = convertDatabaseTypeToFrontend(enterprise.getType()); - enterprise.setType(frontendType); - } - response.put("success", true); - response.put("data", enterprises); - response.put("message", "获取企业信息成功"); - response.put("total", enterprises.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取企业信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取指定企业的联系人信息 - * GET /pool/customers/{id}/contacts - */ - @GetMapping("/{id}/contacts") - public ResponseEntity> getContactsByEnterpriseId(@PathVariable String id) { - Map response = new HashMap<>(); - try { - List contacts = enterpriseService.getContactsByEnterpriseId(id); - response.put("success", true); - response.put("data", contacts); - response.put("message", "获取联系人信息成功"); - response.put("total", contacts.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取联系人信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取指定企业的负责人信息 - * GET /pool/customers/{id}/managers - */ - @GetMapping("/{id}/managers") - public ResponseEntity> getManagersByEnterpriseId(@PathVariable String id) { - Map response = new HashMap<>(); - try { - List managers = enterpriseService.getManagersByEnterpriseId(id); - response.put("success", true); - response.put("data", managers); - response.put("message", "获取负责人信息成功"); - response.put("total", managers.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取负责人信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 健康检查接口 - * GET /pool/customers/health - */ - @GetMapping("/health") - public ResponseEntity> healthCheck() { - Map response = new HashMap<>(); - response.put("success", true); - response.put("message", "客户信息服务运行正常"); - response.put("timestamp", System.currentTimeMillis()); - return ResponseEntity.ok(response); - } - - /** - * 获取所有客户信息 - 不使用前端参数,直接查询双数据源所有数据 - * GET /pool/all-customers - */ - @ResponseBody - @GetMapping("/all-customers") - public ResponseEntity> getAllCustomersWithoutFilter() { - System.out.println("===================================================="); - System.out.println("🔄 开始获取所有客户信息 - 双数据源查询(无负责人过滤)"); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 1. 创建结果存储容器,优先使用手机号作为键 - Map resultMap = new HashMap<>(); - - // 2. 处理primary数据源(企业信息)- 不进行负责人过滤 - System.out.println("🏢 开始获取企业数据..."); - List enterpriseData = enterpriseService.getAllEnterpriseInfo(); - - System.out.println("✅ 企业数据查询完成"); - System.out.println("📊 企业数据条数: " + enterpriseData.size()); - - int enterpriseCount = 0; - if (enterpriseData != null) { - for (EnterpriseInfoDTO enterpriseInfo : enterpriseData) { - try { - UnifiedCustomerDTO dto = convertToUnifiedDTOFromEnterprise(enterpriseInfo); - String key = dto.getPhoneNumber() != null && !dto.getPhoneNumber().isEmpty() - ? dto.getPhoneNumber() - : dto.getId(); - - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无有效标识的企业数据"); - continue; - } - - resultMap.put(key, dto); - enterpriseCount++; - - // 打印前几条数据的详细信息 - if (enterpriseCount <= 3) { - System.out.println("📝 企业客户样例 " + enterpriseCount + ": " + - "公司=" + dto.getCompany() + - ", 联系人=" + dto.getNickName() + - ", 手机=" + dto.getPhoneNumber() + - ", 类型=" + dto.getType()); - } - } catch (Exception e) { - System.err.println("❌ 处理企业数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ 企业数据源成功处理: " + enterpriseCount + " 条记录"); - } - - // 3. 处理wechat数据源(用户信息)- 不进行负责人过滤 - System.out.println("📱 开始获取wechat数据..."); - List userData = poolCustomerService.getAllCustomersWithoutFilter(); - -// 🔥 新增:批量查询负责人信息(与getAllCustomers方法相同) - List allUserIds = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - if (userInfo.getUserId() != null && !userInfo.getUserId().isEmpty()) { - allUserIds.add(userInfo.getUserId()); - } - } - } - - Map managerMap = new HashMap<>(); - if (!allUserIds.isEmpty()) { - try { - List allManagers = usersManagementsMapper.findByUserIds(allUserIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询负责人信息失败: " + e.getMessage()); - } - } - - System.out.println("✅ Wechat数据查询完成"); - System.out.println("📊 Wechat数据条数: " + userData.size()); - - int wechatCount = 0; - int updateCount = 0; - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - try { - String key = userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""; - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无手机号的用户数据"); - continue; - } - - // 检查是否已存在该手机号的记录 - if (resultMap.containsKey(key)) { - UnifiedCustomerDTO existingDto = resultMap.get(key); - updateUnifiedDTOWithWechatData(existingDto, userInfo); - updateCount++; - } else { - // 🔥 修改:传入managerMap - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo, managerMap); - resultMap.put(key, dto); - wechatCount++; - } - } catch (Exception e) { - System.err.println("❌ 处理用户数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ Wechat数据源成功处理: " + wechatCount + " 条新记录, " + updateCount + " 条更新记录"); - } - - // 4. 打印最终统计信息和详细信息 - printFinalStatistics(resultMap, enterpriseCount, wechatCount, updateCount); - - // 5. 构建响应 - response.put("success", true); - response.put("data", resultMap); - response.put("message", "获取客户信息成功"); - response.put("total", resultMap.size()); - response.put("enterpriseCount", enterpriseCount); - response.put("wechatCount", wechatCount); - response.put("updateCount", updateCount); - - return ResponseEntity.ok(convertTypesForFrontend(response)); - } catch (Exception e) { - System.err.println("❌ 获取客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/FollowupController.java b/src/main/java/com/example/web/controller/FollowupController.java deleted file mode 100644 index 689df49..0000000 --- a/src/main/java/com/example/web/controller/FollowupController.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.service.FollowUpService; -import com.example.web.service.InformationTraService; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping("/api/followup") -public class FollowupController { - - @Autowired - private FollowUpService followUpService; - - @Autowired - private InformationTraService informationTraService; - - /** - * 根据电话号码获取跟进信息 - * @param phoneNumber 电话号码 - * @param dataSource 数据源(primary或wechat) - * @return 跟进信息 - */ - @GetMapping("/get") - public ResponseEntity getFollowUp( - @RequestParam String phoneNumber) { - try { - String followup = followUpService.getFollowUpByPhone(phoneNumber); - return ResponseEntity.ok(followup); - } catch (Exception e) { - return ResponseEntity.internalServerError().body("获取跟进信息失败:" + e.getMessage()); - } - } - - /** - * 从请求中获取管理员认证信息 - * @param request 请求对象 - * @return 管理员认证信息 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request) { - try { - // 记录请求中所有参数,便于调试 - System.out.println("🔍 开始获取认证信息,请求参数:"); - java.util.Enumeration parameterNames = request.getParameterNames(); - while (parameterNames.hasMoreElements()) { - String paramName = parameterNames.nextElement(); - String paramValue = request.getParameter(paramName); - System.out.println(" " + paramName + " = " + paramValue); - } - System.out.println("🔍 请求参数记录完成"); - - // 记录URL查询参数 - System.out.println("🔍 URL查询参数:"); - String queryString = request.getQueryString(); - System.out.println(" queryString = " + queryString); - - // 从请求参数和URL查询参数中获取认证信息 - // 优先从请求参数中获取,其次从URL查询参数中获取 - String managerId = getParameterFromRequestOrQueryString(request, "managerId"); - String organization = getParameterFromRequestOrQueryString(request, "organization"); - String role = getParameterFromRequestOrQueryString(request, "role"); - String userName = getParameterFromRequestOrQueryString(request, "userName"); - String assistant = getParameterFromRequestOrQueryString(request, "assistant"); - - // 支持两种参数名:managerCompany/managerDepartment 和 company/department - String managerCompany = getParameterFromRequestOrQueryString(request, "managerCompany"); - String managerDepartment = getParameterFromRequestOrQueryString(request, "managerDepartment"); - - // 如果managerCompany或managerDepartment为空,尝试使用company和department参数 - if (managerCompany == null || managerCompany.trim().isEmpty()) { - managerCompany = getParameterFromRequestOrQueryString(request, "company"); - } - if (managerDepartment == null || managerDepartment.trim().isEmpty()) { - managerDepartment = getParameterFromRequestOrQueryString(request, "department"); - } - - // 解码URL编码的参数 - if (organization != null) { - organization = java.net.URLDecoder.decode(organization, "UTF-8"); - } - if (role != null) { - role = java.net.URLDecoder.decode(role, "UTF-8"); - } - if (userName != null) { - userName = java.net.URLDecoder.decode(userName, "UTF-8"); - } - if (assistant != null) { - assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } - if (managerCompany != null) { - managerCompany = java.net.URLDecoder.decode(managerCompany, "UTF-8"); - } - if (managerDepartment != null) { - managerDepartment = java.net.URLDecoder.decode(managerDepartment, "UTF-8"); - } - - // 记录解码后的参数值 - System.out.println("🔍 解码后的参数值:"); - System.out.println(" managerId = " + managerId); - System.out.println(" organization = " + organization); - System.out.println(" role = " + role); - System.out.println(" userName = " + userName); - System.out.println(" assistant = " + assistant); - System.out.println(" managerCompany = " + managerCompany); - System.out.println(" managerDepartment = " + managerDepartment); - - // 验证必填参数 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名不能为空"); - return null; - } - - // 验证公司和部门信息 - if (managerCompany == null || managerCompany.trim().isEmpty()) { - System.out.println("❌ 公司信息不能为空"); - return null; - } - if (managerDepartment == null || managerDepartment.trim().isEmpty()) { - System.out.println("❌ 部门信息不能为空"); - return null; - } - - // 使用正确的构造器创建ManagerAuthInfo对象 - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId, - managerCompany, - managerDepartment, - organization, - role, - userName, - assistant - ); - - System.out.println("✅ 认证信息获取成功:" + authInfo.toString()); - return authInfo; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** - * 从请求参数或URL查询参数中获取参数值 - * 优先从请求参数中获取,其次从URL查询参数中获取 - * @param request 请求对象 - * @param paramName 参数名 - * @return 参数值 - */ - private String getParameterFromRequestOrQueryString(HttpServletRequest request, String paramName) { - // 先从请求参数中获取 - String paramValue = request.getParameter(paramName); - if (paramValue != null && !paramValue.trim().isEmpty()) { - return paramValue; - } - - // 如果请求参数中没有,尝试从URL查询参数中获取 - try { - String queryString = request.getQueryString(); - if (queryString != null) { - // 解析queryString - String[] pairs = queryString.split("&"); - for (String pair : pairs) { - String[] keyValue = pair.split("="); - if (keyValue.length == 2 && keyValue[0].equals(paramName)) { - return keyValue[1]; - } - } - } - } catch (Exception e) { - System.err.println("解析URL查询参数失败:" + e.getMessage()); - } - - return null; - } - - /** - * 保存跟进信息 - * @param phoneNumber 电话号码 - * @param followup 跟进信息 - * @return 保存结果 - */ - @PostMapping("/save") - public ResponseEntity saveFollowUp( - @RequestParam String phoneNumber, - @RequestParam String followup, - HttpServletRequest request) { - try { - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request); - boolean result = followUpService.saveFollowUp(phoneNumber, followup); - if (result) { - // 只有当authInfo不为null时才记录操作事件,确保负责人信息完整 - if (authInfo != null) { - // 记录跟进信息更新操作 - informationTraService.recordOperationEvent( - phoneNumber, - "", // 跟进记录可能无法获取客户名称,留空 - phoneNumber + "-更新跟进", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - } else { - System.err.println("❌ 认证信息为空,无法记录操作事件"); - } - return ResponseEntity.ok("跟进信息保存成功"); - } else { - return ResponseEntity.badRequest().body("跟进信息保存失败"); - } - } catch (Exception e) { - return ResponseEntity.internalServerError().body("保存跟进信息失败:" + e.getMessage()); - } - } -} diff --git a/src/main/java/com/example/web/controller/InformationTraController.java b/src/main/java/com/example/web/controller/InformationTraController.java deleted file mode 100644 index 3e92d89..0000000 --- a/src/main/java/com/example/web/controller/InformationTraController.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.service.InformationTraService; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashMap; -import java.util.Map; - -/** - * 信息操作记录控制器 - * 处理前端操作记录请求,包括查看客户详情、修改客户信息、更新客户跟进等操作 - */ -@RestController -@RequestMapping("/api/info-tracking") -public class InformationTraController { - - @Autowired - private InformationTraService informationTraService; - - /** - * 记录操作事件 - * @param request HttpServletRequest对象,包含操作信息和认证信息 - * @return ResponseEntity> 响应结果 - */ - @PostMapping("/record") - public ResponseEntity> recordOperation(HttpServletRequest request) { - Map result = new HashMap<>(); - try { - // 获取操作类型 - String operationType = request.getParameter("operationType"); - // 获取电话号码 - String phoneNumber = request.getParameter("phoneNumber"); - // 获取客户名称 - String customerName = request.getParameter("customerName"); - - // 验证必要参数 - if (operationType == null || operationType.trim().isEmpty()) { - result.put("success", false); - result.put("message", "操作类型不能为空"); - return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST); - } - if (phoneNumber == null || phoneNumber.trim().isEmpty()) { - result.put("success", false); - result.put("message", "电话号码不能为空"); - return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST); - } - - // 获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, false); // 默认销售端,后续根据部门自动调整 - if (authInfo == null) { - result.put("success", false); - result.put("message", "获取认证信息失败"); - return new ResponseEntity<>(result, HttpStatus.UNAUTHORIZED); - } - - // 记录操作事件 - boolean success = informationTraService.recordOperationEvent( - phoneNumber, - customerName != null ? customerName : "", - operationType, - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - if (success) { - result.put("success", true); - result.put("message", "操作记录成功"); - return new ResponseEntity<>(result, HttpStatus.OK); - } else { - result.put("success", false); - result.put("message", "操作记录失败"); - return new ResponseEntity<>(result, HttpStatus.INTERNAL_SERVER_ERROR); - } - } catch (Exception e) { - e.printStackTrace(); - result.put("success", false); - result.put("message", "操作记录异常: " + e.getMessage()); - return new ResponseEntity<>(result, HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - /** - * 从请求中获取管理员认证信息 - * @param request HttpServletRequest对象 - * @param isSupplySide 是否为采购端 - * @return ManagerAuthInfo 认证信息对象 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - String managerId = request.getParameter("managerId"); - String managercompany = request.getParameter("company"); - String managerdepartment = request.getParameter("department"); - String organization = request.getParameter("organization"); - String role = request.getParameter("role"); - String userName = request.getParameter("userName"); - String assistant = request.getParameter("assistant"); - - // URL解码参数 - try { - if (managerId != null) managerId = java.net.URLDecoder.decode(managerId, "UTF-8"); - if (managercompany != null) managercompany = java.net.URLDecoder.decode(managercompany, "UTF-8"); - if (managerdepartment != null) managerdepartment = java.net.URLDecoder.decode(managerdepartment, "UTF-8"); - if (organization != null) organization = java.net.URLDecoder.decode(organization, "UTF-8"); - if (role != null) role = java.net.URLDecoder.decode(role, "UTF-8"); - if (userName != null) userName = java.net.URLDecoder.decode(userName, "UTF-8"); - if (assistant != null) assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - System.err.println("URL解码失败: " + e.getMessage()); - } - - // 检查必要参数 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名为空,无法获取认证信息"); - return null; - } - - // 部门检查 - if (managerdepartment == null) { - System.out.println("⚠️ 部门信息为空,使用默认值"); - managerdepartment = ""; - } - - // 智能判断实际端类型:根据部门信息自动调整isSupplySide值 - boolean actualIsSupplySide = isSupplySide; - if (managerdepartment.contains("销售")) { - actualIsSupplySide = false; // 销售部门自动判定为销售端 - System.out.println("🔄 部门包含'销售',自动调整为销售端"); - } else if (managerdepartment.contains("采购")) { - actualIsSupplySide = true; // 采购部门自动判定为采购端 - System.out.println("🔄 部门包含'采购',自动调整为采购端"); - } - - System.out.println("🔍 认证信息检查,实际端类型: " + (actualIsSupplySide ? "采购端" : "销售端") + - ",部门: '" + managerdepartment + "'"); - System.out.println("✅ 认证信息检查通过"); - - // 验证公司信息一致性 - if (managercompany == null || managercompany.trim().isEmpty()) { - System.out.println("❌ 公司信息为空"); - return null; - } - - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId != null ? managerId : "", - managercompany != null ? managercompany : "", - managerdepartment != null ? managerdepartment : "", - organization != null ? organization : "", - role != null ? role : "", - userName, - assistant != null ? assistant : ""); - - // 设置实际的端类型 - try { - // 尝试通过反射或setter方法设置supplySide属性 - java.lang.reflect.Field field = authInfo.getClass().getDeclaredField("supplySide"); - field.setAccessible(true); - field.set(authInfo, actualIsSupplySide); - } catch (Exception e) { - System.out.println("ℹ️ 无法设置supplySide属性: " + e.getMessage()); - } - - System.out.println("🎯 认证信息详情: " + - "系统类型=" + (actualIsSupplySide ? "采购端" : "销售端") + - ", 公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - return authInfo; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/LoginController.java b/src/main/java/com/example/web/controller/LoginController.java index c27aaed..8aa735f 100644 --- a/src/main/java/com/example/web/controller/LoginController.java +++ b/src/main/java/com/example/web/controller/LoginController.java @@ -1,39 +1,67 @@ package com.example.web.controller; +import com.example.web.entity.Login; +import com.example.web.entity.Personnel; import com.example.web.service.LoginService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import java.util.HashMap; import java.util.Map; -@RestController -@RequestMapping("/") +/** + * @Description: 登录控制器 + * @Author: + * @Date: 2025-12-17 + */ +@Controller public class LoginController { @Autowired private LoginService loginService; + /** + * 处理登录请求 + * @param projectName 工位名 + * @param userName 用户名 + * @param password 密码 + * @return 包含登录结果和用户信息的Map + */ @PostMapping("/logins") - public Map login(@RequestParam String projectName, - @RequestParam String userName, + @ResponseBody + public Map login(@RequestParam String projectName, + @RequestParam String userName, @RequestParam String password) { - - System.out.println("=== Controller收到登录请求 ==="); - System.out.println("工位名: " + projectName + ", 用户名: " + userName + ", 密码: " + password); - - Map result = loginService.authenticate(projectName, userName, password); - - System.out.println("Controller返回结果: " + result); - System.out.println("成功状态: " + result.get("success")); - - if (result.get("success").equals(true)) { - System.out.println("权限等级: " + result.get("root")); - System.out.println("Token: " + result.get("token")); - System.out.println("系统类型: " + (Boolean.TRUE.equals(result.get("isSupplySide")) ? "采购端" : "销售端")); - Map user = (Map) result.get("user"); - System.out.println("用户信息: " + user); + // 创建响应结果Map + Map result = new HashMap<>(); + + try { + // 验证登录信息 + Login login = loginService.verifyLogin(projectName, userName, password); + + if (login != null) { + // 登录成功,获取员工详细信息 + Personnel personnel = loginService.getPersonnelInfo(login.getManagerId()); + + // 设置响应结果 + result.put("success", true); + result.put("userInfo", personnel); + result.put("message", "登录成功"); + } else { + // 登录失败 + result.put("success", false); + result.put("message", "用户名或密码不正确"); + } + } catch (Exception e) { + // 处理异常 + result.put("success", false); + result.put("message", "登录失败,请稍后重试"); + e.printStackTrace(); } - System.out.println(result.get("user")); + return result; } } \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/PersonnelController.java b/src/main/java/com/example/web/controller/PersonnelController.java new file mode 100644 index 0000000..f08cf44 --- /dev/null +++ b/src/main/java/com/example/web/controller/PersonnelController.java @@ -0,0 +1,28 @@ +package com.example.web.controller; + +import com.example.web.entity.Personnel; +import com.example.web.service.PersonnelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @Description: 员工信息控制器 + */ +@RestController +public class PersonnelController { + + @Autowired + private PersonnelService personnelService; + + /** + * 根据负责人ID获取员工信息 + * @param managerId 负责人ID + * @return Personnel对象 + */ + @GetMapping("/api/personnel") + public Personnel getPersonnelByManagerId(@RequestParam String managerId) { + return personnelService.getPersonnelByManagerId(managerId); + } +} diff --git a/src/main/java/com/example/web/controller/PoolCustomerController.java b/src/main/java/com/example/web/controller/PoolCustomerController.java deleted file mode 100644 index 011fe18..0000000 --- a/src/main/java/com/example/web/controller/PoolCustomerController.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.UserProductCartDTO; -import com.example.web.service.PoolCustomerService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.HashMap; -import java.util.Map; - -@RestController -@RequestMapping("/pool/") -public class PoolCustomerController { - - @Autowired - private PoolCustomerService poolCustomerService; - - /** - * 根据用户ID获取客户信息 - * GET /pool/customers/{userId} - */ - @GetMapping("/customersss/{userId}") - public ResponseEntity getCustomerById(@PathVariable String userId) { - try { - UserProductCartDTO customerInfo = poolCustomerService.getCustomerInfo(userId); - return ResponseEntity.ok(customerInfo); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(createErrorResponse("参数错误", e.getMessage())); - } catch (RuntimeException e) { - return ResponseEntity.notFound().build(); - } catch (Exception e) { - return ResponseEntity.internalServerError() - .body(createErrorResponse("服务器错误", "获取客户信息失败")); - } - } - - /** - * 查询客户信息(支持按类型过滤) - * GET /pool/customers?type=seller&page=1&size=10 - */ - @GetMapping("/customersss") - public ResponseEntity getCustomers( - @RequestParam(required = false) String type, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int size) { - - try { - Map response = new HashMap<>(); - response.put("page", page); - response.put("size", size); - response.put("type", type); - response.put("message", "分页查询功能待实现"); - - return ResponseEntity.ok(response); - } catch (Exception e) { - return ResponseEntity.internalServerError() - .body(createErrorResponse("查询失败", e.getMessage())); - } - } - - /** - * 创建统一的错误响应格式 - */ - private Map createErrorResponse(String error, String message) { - Map errorResponse = new HashMap<>(); - errorResponse.put("error", error); - errorResponse.put("message", message); - errorResponse.put("timestamp", System.currentTimeMillis()); - return errorResponse; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/SupplyCustomerController.java b/src/main/java/com/example/web/controller/SupplyCustomerController.java deleted file mode 100644 index f8e8501..0000000 --- a/src/main/java/com/example/web/controller/SupplyCustomerController.java +++ /dev/null @@ -1,996 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.SupplyUsersManagementsMapper; -import com.example.web.service.InformationTraService; -import com.example.web.service.SupplyCustomerService; -import com.example.web.service.SupplyPoolCustomerService; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@RestController -@RequestMapping("/supply/pool") -@CrossOrigin(origins = "*") -public class SupplyCustomerController { - - @Autowired - private SupplyCustomerService supplyCustomerService; - - @Autowired - private SupplyPoolCustomerService supplyPoolCustomerService; - - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; - @Autowired - private com.example.web.mapper.SupplyUsersMapper supplyUsersMapper; - - @Autowired - private InformationTraService informationTraService; - - /** - * 采购端 - 更新客户通知状态 - */ - @PutMapping("/customers/{id}/notice") - public ResponseEntity> updateCustomerNotice(@PathVariable String id) { - try { - // 直接调用mapper更新通知状态 - System.out.println("🔄 采购端手动更新通知状态, userId: " + id + ", 从banold改为old"); - supplyUsersMapper.updateNotice(id, "old"); - // 返回成功响应 - Map response = new HashMap<>(); - response.put("success", true); - response.put("message", "通知状态更新成功"); - return ResponseEntity.ok(response); - } catch (Exception e) { - System.err.println("❌ 采购端更新通知状态失败: " + e.getMessage()); - // 返回失败响应 - Map response = new HashMap<>(); - response.put("success", false); - response.put("message", "通知状态更新失败: " + e.getMessage()); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); - } - } - - /** - * 根据公司ID查询客户详情 - 优先处理wechat数据源 - * GET /supply/pool/customers/{id} - */ - @GetMapping("/customers/{id}") - public ResponseEntity> getById(@PathVariable String id, HttpServletRequest request) { - System.out.println("===================================================="); - System.out.println("🔍 查询客户: " + id); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 从URL参数中获取ManagerAuthInfo - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - - if (authInfo == null) { - System.out.println("❌ 未找到用户认证信息"); - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("✅ 获取到用户认证信息: " + authInfo.getUserName()); - - // 🎯 重构:完全基于数据存在性判断,彻底消除对ID格式的依赖 - System.out.println("🎯 开始查询双数据源(优先wechat)..."); - - // 1. 首先尝试查询wechat数据源 - System.out.println("📊 优先查询 WECHAT 数据源..."); - UserProductCartDTO userInfo = supplyPoolCustomerService.getPublicSeaCustomerInfo(id); - - if (userInfo != null) { - System.out.println("✅ 在wechat数据源中找到客户基础信息"); - - // 使用统一的公海池判断逻辑 - boolean isPublicSea = supplyPoolCustomerService.isPublicSeaCustomerPublic(userInfo, authInfo); - System.out.println("📊 公海池判断结果: " + isPublicSea); - - if (isPublicSea) { - System.out.println("🎯 识别为公海池客户,返回 WECHAT 数据源数据"); - UnifiedCustomerDTO customer = convertToUnifiedDTOForPublicSea(userInfo, request); - customer.setDataSource("wechat"); - - response.put("success", true); - response.put("data", customer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - customer.getPhoneNumber(), - customer.getUserName() != null ? customer.getUserName() : "", - customer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } - - // 如果不是公海池客户,检查权限并返回wechat数据源的非公海池客户 - System.out.println("📊 处理 WECHAT 数据源非公海池客户..."); - boolean hasPermission = supplyCustomerService.hasPermissionToViewWechatCustomer(userInfo, authInfo); - - if (hasPermission) { - System.out.println("✅ 有权限查看非公海池客户,返回 WECHAT 数据源数据"); - UnifiedCustomerDTO customer = convertToUnifiedDTOForPublicSea(userInfo, request); - customer.setDataSource("wechat"); - - response.put("success", true); - response.put("data", customer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - customer.getPhoneNumber(), - customer.getUserName() != null ? customer.getUserName() : "", - customer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } else { - System.out.println("❌ 无权限查看wechat数据源的非公海池客户"); - // 继续查询默认数据源 - } - } else { - System.out.println("ℹ️ 在wechat数据源中未找到客户"); - } - - // 2. 如果wechat数据源没找到或无权限,再尝试查询默认数据源 - System.out.println("📊 查询 DEFAULT 数据源..."); - UnifiedCustomerDTO defaultCustomer = supplyCustomerService.getCustomerById(id, authInfo); - - if (defaultCustomer != null) { - System.out.println("✅ 在默认数据源中找到客户"); - response.put("success", true); - response.put("data", defaultCustomer); - - // 记录查看客户详情操作 - informationTraService.recordOperationEvent( - defaultCustomer.getPhoneNumber(), - defaultCustomer.getUserName() != null ? defaultCustomer.getUserName() : "", - defaultCustomer.getPhoneNumber() + "-查看客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } - - // 3. 如果两个数据源都没找到 - System.out.println("❌ 未在任何数据源中找到客户信息"); - response.put("success", false); - response.put("message", "未找到对应的客户信息"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); - - } catch (Exception e) { - System.err.println("❌ 服务器错误: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 从请求中获取ManagerAuthInfo - 增强版本,严格区分销售端和采购端 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - String managerId = request.getParameter("managerId"); - String managercompany = request.getParameter("company"); - String managerdepartment = request.getParameter("department"); - String organization = request.getParameter("organization"); - String role = request.getParameter("role"); - String userName = request.getParameter("userName"); - String assistant = request.getParameter("assistant"); - - // URL解码参数 - try { - if (managerId != null) managerId = java.net.URLDecoder.decode(managerId, "UTF-8"); - if (managercompany != null) managercompany = java.net.URLDecoder.decode(managercompany, "UTF-8"); - if (managerdepartment != null) managerdepartment = java.net.URLDecoder.decode(managerdepartment, "UTF-8"); - if (organization != null) organization = java.net.URLDecoder.decode(organization, "UTF-8"); - if (role != null) role = java.net.URLDecoder.decode(role, "UTF-8"); - if (userName != null) userName = java.net.URLDecoder.decode(userName, "UTF-8"); - if (assistant != null) assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - System.err.println("URL解码失败: " + e.getMessage()); - } - - // 检查必要参数 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名为空,无法获取认证信息"); - return null; - } - - // 部门检查 - if (managerdepartment == null) { - System.out.println("⚠️ 部门信息为空,使用默认值"); - managerdepartment = ""; - } - - // 智能判断实际端类型:根据部门信息自动调整isSupplySide值 - boolean actualIsSupplySide = isSupplySide; - if (managerdepartment.contains("销售")) { - actualIsSupplySide = false; // 销售部门自动判定为销售端 - System.out.println("🔄 部门包含'销售',自动调整为销售端"); - } else if (managerdepartment.contains("采购")) { - actualIsSupplySide = true; // 采购部门自动判定为采购端 - System.out.println("🔄 部门包含'采购',自动调整为采购端"); - } - - System.out.println("🔍 认证信息检查,实际端类型: " + (actualIsSupplySide ? "采购端" : "销售端") + - ",部门: '" + managerdepartment + "'"); - System.out.println("✅ 认证信息检查通过"); - - // 验证公司信息一致性 - if (managercompany == null || managercompany.trim().isEmpty()) { - System.out.println("❌ 公司信息为空"); - return null; - } - - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId != null ? managerId : "", - managercompany != null ? managercompany : "", - managerdepartment != null ? managerdepartment : "", - organization != null ? organization : "", - role != null ? role : "", - userName, - assistant != null ? assistant : ""); - - // 设置实际的端类型 - try { - // 尝试通过反射或setter方法设置supplySide属性 - java.lang.reflect.Field field = authInfo.getClass().getDeclaredField("supplySide"); - field.setAccessible(true); - field.set(authInfo, actualIsSupplySide); - } catch (Exception e) { - System.out.println("ℹ️ 无法设置supplySide属性: " + e.getMessage()); - } - - System.out.println("🎯 认证信息详情: " + - "系统类型=" + (actualIsSupplySide ? "采购端" : "销售端") + - ", 公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - return authInfo; - } - - /** - * 查找选中的产品项 - 修复版本 - * 优先使用前端传递的选中ID,如果没有则使用第一个 - */ - private UserProductCartDTO.ProductInfo findSelectedProduct(UserProductCartDTO userInfo, String targetProductItemId) { - if (userInfo.getProducts() == null || userInfo.getProducts().isEmpty()) { - return null; - } - - // 🔥 关键修复:优先使用前端传递的选中产品项ID - if (targetProductItemId != null && !targetProductItemId.trim().isEmpty()) { - for (UserProductCartDTO.ProductInfo product : userInfo.getProducts()) { - if (targetProductItemId.equals(product.getProductId())) { - System.out.println("✅ 找到前端选中的产品项: " + product.getProductId()); - return product; - } - } - System.out.println("⚠️ 未找到前端指定的产品项: " + targetProductItemId); - } - - // 🔥 其次检查是否有标记为选中的产品项 - for (UserProductCartDTO.ProductInfo product : userInfo.getProducts()) { - if (isProductSelected(product)) { - System.out.println("✅ 找到标记为选中的产品项: " + product.getProductId()); - return product; - } - } - - // 🔥 最后才返回第一个产品项 - UserProductCartDTO.ProductInfo firstItem = userInfo.getProducts().get(0); - System.out.println("🔄 使用第一个产品项作为默认: " + firstItem.getProductId()); - return firstItem; - } - - /** - * 判断产品项是否被选中(根据业务逻辑) - */ - private boolean isProductSelected(UserProductCartDTO.ProductInfo product) { - // 这里可以根据业务需求实现选中逻辑 - // 例如:通过某个字段标识,或者外部传入的参数 - - // 临时方案:默认返回false,使用第一个产品项 - return false; - } - - /** - * 专门为公海池客户转换DTO的方法 - 采购端使用产品信息(修复版本) - * 新增HttpServletRequest参数用于获取选中的产品项ID - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea(UserProductCartDTO userInfo, HttpServletRequest request) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - // 设置用户基础信息 - dto.setId(userInfo.getUserId() != null ? userInfo.getUserId() : ""); - dto.setPhoneNumber(userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""); - - // 设置公司信息 - dto.setCompany(userInfo.getCompany() != null ? userInfo.getCompany() : ""); - dto.setRegion(userInfo.getRegion() != null ? userInfo.getRegion() : ""); - - // 设置需求和规格 - dto.setDemand(userInfo.getDemand() != null ? userInfo.getDemand() : ""); - dto.setSpec(userInfo.getSpec() != null ? userInfo.getSpec() : ""); - - // 类型转换 - String frontendType = convertDatabaseTypeToFrontend(userInfo.getType()); - dto.setType(frontendType != null ? frontendType : ""); - - dto.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : ""); - dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - // 添加通知信息转换 - dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); - - // 关键:设置数据源标识为wechat - dto.setDataSource("wechat"); - - // 设置联系人信息 - 从usersContacts获取 - setContactInfoSafely(dto, userInfo); - - // 设置负责人信息 - setManagerInfoSafely(dto, userInfo.getUserId()); - - // 设置公海需求信息 - 从产品表获取(采购端) - if (userInfo.getProducts() != null && !userInfo.getProducts().isEmpty()) { - // 🔥 关键修复:从HttpServletRequest中获取目标产品项ID - String targetProductItemId = getTargetProductItemIdFromRequest(request); - - UserProductCartDTO.ProductInfo selectedProduct = findSelectedProduct(userInfo, targetProductItemId); - - // 设置到单个字段 - 使用选中的产品项 - dto.setProductName(selectedProduct.getProductName() != null ? selectedProduct.getProductName() : ""); - dto.setVariety(selectedProduct.getVariety() != null ? selectedProduct.getVariety() : ""); - dto.setSpecification(selectedProduct.getSpecification() != null ? selectedProduct.getSpecification() : ""); - dto.setQuantity(selectedProduct.getQuantity() != null ? selectedProduct.getQuantity() : 0); - dto.setGrossWeight(selectedProduct.getGrossWeight() != null ? selectedProduct.getGrossWeight() : ""); - dto.setYolk(selectedProduct.getYolk() != null ? selectedProduct.getYolk() : ""); - - // 🔥 关键修改:设置选中的产品项ID - dto.setTargetProductItemId(selectedProduct.getProductId() != null ? selectedProduct.getProductId() : ""); - - // 设置customDetails为产品信息 - dto.setCustomDetails(userInfo.getProducts().toArray()); - - System.out.println("✅ 成功设置选中产品项到DTO: " + selectedProduct.getProductName() + - ", 产品项ID: " + selectedProduct.getProductId() + - ", 是否前端指定: " + (targetProductItemId != null)); - } else { - // 如果没有产品信息,设置默认值 - setDefaultProductValues(dto); - System.out.println("⚠️ 没有产品信息,使用默认值"); - } - - // 设置 productItems 到 UnifiedCustomerDTO - 采购端关键修复 - if (userInfo.getProducts() != null && !userInfo.getProducts().isEmpty()) { - List unifiedProductItems = userInfo.getProducts().stream() - .map(product -> { - UnifiedCustomerDTO.ProductItem unifiedItem = new UnifiedCustomerDTO.ProductItem(); - unifiedItem.setProductId(product.getProductId() != null ? product.getProductId() : ""); - unifiedItem.setProductName(product.getProductName() != null ? product.getProductName() : ""); - unifiedItem.setVariety(product.getVariety() != null ? product.getVariety() : ""); - unifiedItem.setSpecification(product.getSpecification() != null ? product.getSpecification() : ""); - unifiedItem.setQuantity(product.getQuantity() != null ? product.getQuantity() : 0); - unifiedItem.setGrossWeight(product.getGrossWeight() != null ? product.getGrossWeight() : ""); - unifiedItem.setYolk(product.getYolk() != null ? product.getYolk() : ""); - return unifiedItem; - }) - .collect(Collectors.toList()); - dto.setProductItems(unifiedProductItems); - System.out.println("✅ 成功设置 productItems 到 UnifiedCustomerDTO,数量: " + unifiedProductItems.size()); - } else { - System.out.println("❌ 没有产品数据可设置到 productItems"); - } - - return dto; - } - - /** - * 从请求参数中获取目标产品项ID - 完整实现 - */ - private String getTargetProductItemIdFromRequest(HttpServletRequest request) { - try { - if (request == null) { - System.out.println("⚠️ HttpServletRequest为null"); - return null; - } - - // 1. 首先从URL查询参数中获取 - String targetProductItemId = request.getParameter("targetProductItemId"); - - if (targetProductItemId != null && !targetProductItemId.trim().isEmpty()) { - System.out.println("🎯 从URL参数获取到目标产品项ID: " + targetProductItemId); - return targetProductItemId.trim(); - } - - // 2. 如果URL参数中没有,尝试从请求属性中获取 - Object attributeValue = request.getAttribute("targetProductItemId"); - if (attributeValue != null) { - String productItemId = attributeValue.toString(); - System.out.println("🎯 从请求属性获取到目标产品项ID: " + productItemId); - return productItemId; - } - - // 3. 尝试从Header中获取 - String headerValue = request.getHeader("X-Target-ProductItem-Id"); - if (headerValue != null && !headerValue.trim().isEmpty()) { - System.out.println("🎯 从Header获取到目标产品项ID: " + headerValue); - return headerValue.trim(); - } - - System.out.println("⚠️ 未从请求中获取到目标产品项ID"); - return null; - - } catch (Exception e) { - System.err.println("❌ 获取目标产品项ID失败: " + e.getMessage()); - return null; - } - } - - /** - * 安全设置负责人信息 - */ - private void setManagerInfoSafely(UnifiedCustomerDTO dto, String userId) { - try { - System.out.println("🔍 查询用户负责人信息,用户ID: " + userId); - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - - if (userManager != null) { - System.out.println("✅ 找到负责人信息,设置到DTO"); - // 设置负责人信息到统一的DTO字段 - dto.setManagercompany(userManager.getManagercompany() != null ? userManager.getManagercompany() : ""); - dto.setManagerdepartment(userManager.getManagerdepartment() != null ? userManager.getManagerdepartment() : ""); - dto.setOrganization(userManager.getOrganization() != null ? userManager.getOrganization() : ""); - dto.setRole(userManager.getRole() != null ? userManager.getRole() : ""); - dto.setUserName(userManager.getUserName() != null ? userManager.getUserName() : ""); - dto.setAssistant(userManager.getAssistant() != null ? userManager.getAssistant() : ""); - - // 调试日志 - System.out.println("📝 负责人信息详情: " + - "公司=" + dto.getManagercompany() + - ", 部门=" + dto.getManagerdepartment() + - ", 组织=" + dto.getOrganization() + - ", 角色=" + dto.getRole() + - ", 负责人=" + dto.getUserName() + - ", 协助人=" + dto.getAssistant()); - } else { - System.out.println("⚠️ 未找到负责人信息,用户可能为公海池客户"); - // 设置默认值 - setDefaultManagerValues(dto); - } - } catch (Exception e) { - System.err.println("❌ 查询负责人信息失败: " + e.getMessage()); - // 发生异常时设置默认值 - setDefaultManagerValues(dto); - } - } - - /** - * 设置默认负责人值 - */ - private void setDefaultManagerValues(UnifiedCustomerDTO dto) { - dto.setManagercompany(""); - dto.setManagerdepartment(""); - dto.setOrganization(""); - dto.setRole(""); - dto.setUserName(""); - dto.setAssistant(""); - } - - /** - * 设置默认产品值 - */ - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - } - - /** - * 安全设置联系人信息 - */ - private void setContactInfoSafely(UnifiedCustomerDTO dto, UserProductCartDTO userInfo) { - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - UserProductCartDTO.UsersContacts contact = userInfo.getUsersContacts().get(0); - dto.setWechat(contact.getWechat() != null ? contact.getWechat() : ""); - dto.setAccount(contact.getAccount() != null ? contact.getAccount() : ""); - dto.setAccountNumber(contact.getAccountNumber() != null ? contact.getAccountNumber() : ""); - dto.setBank(contact.getBank() != null ? contact.getBank() : ""); - dto.setAddress(contact.getAddress() != null ? contact.getAddress() : ""); - } else { - setDefaultContactValues(dto); - } - } - - /** - * 设置默认联系人值 - */ - private void setDefaultContactValues(UnifiedCustomerDTO dto) { - dto.setWechat(""); - dto.setAccount(""); - dto.setAccountNumber(""); - dto.setBank(""); - dto.setAddress(""); - } - - /** - * 数据库类型转前端类型 - */ - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": - return "BOTH"; - default: - return databaseType; - } - } - - /** - * 根据手机号查询客户详情 - */ - @GetMapping("/customers/by-phone") - public ResponseEntity> getByPhone(@RequestParam String phoneNumber, HttpServletRequest request) { - System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); - System.out.println("getByPhone: ---------------------------------------------------" + phoneNumber); - Map response = new HashMap<>(); - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 从URL参数获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - UnifiedCustomerDTO customer = supplyCustomerService.getCustomerByPhone(phoneNumber, authInfo); - - // 检查客户等级,如果是公海池客户,确保数据源正确 - if (customer != null && customer.getLevel() != null && - (customer.getLevel().contains("sea-pools") || "公海池".equals(customer.getLevel()))) { - customer.setDataSource("wechat"); - } - - response.put("success", true); - response.put("data", customer); - return ResponseEntity.ok(response); - } catch (IllegalArgumentException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.badRequest().body(response); - } catch (RuntimeException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.notFound().build(); - } catch (Exception e) { - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 更新基于电话号码的客户信息(专门用于公海池客户)- 采购员权限:只允许更新为seller和both类型 - */ - @PutMapping("/phone-customers/update") - public ResponseEntity> updatePhoneCustomer(@RequestBody UnifiedCustomerDTO updatedDTO, HttpServletRequest request) { - Map response = new HashMap<>(); - - try { - // 从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 获取认证信息 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("======= 开始处理公海池客户更新(wechat数据源)- 采购端 ======="); - System.out.println("手机号: " + updatedDTO.getPhoneNumber()); - System.out.println("原始等级: " + updatedDTO.getLevel()); - System.out.println("负责人信息: " + authInfo.getUserName()); - - // 🔥 在Controller层先进行类型转换 - System.out.println("🔄 Controller层类型转换前: " + updatedDTO.getType()); - String originalType = updatedDTO.getType(); - String convertedType = convertCustomerTypeInController(originalType); - updatedDTO.setType(convertedType); - System.out.println("🔄 Controller层类型转换后: " + originalType + " → " + convertedType); - - System.out.println("🔐 负责人认证信息: " + - "公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - // 采购员权限:校验客户类型,只允许seller和both - if (!"seller".equals(updatedDTO.getType()) && !"both".equals(updatedDTO.getType())) { - System.out.println("❌ 权限校验失败:采购员只能更新为seller或both类型,当前类型: " + updatedDTO.getType()); - response.put("success", false); - response.put("message", "采购员权限只能更新为供应端类型客户"); - return ResponseEntity.badRequest().body(response); - } - - // 调用服务层 - 传递authInfo用于负责人信息更新 - System.out.println("🔄 调用Service更新方法..."); - boolean success = supplyCustomerService.updatePhoneBasedCustomer(updatedDTO, authInfo); - - System.out.println("✅ Service返回结果: " + success); - - if (success) { - System.out.println("🎉 公海池客户信息更新成功"); - response.put("success", true); - response.put("message", "客户信息更新成功"); - - // 记录修改客户信息操作 - informationTraService.recordOperationEvent( - updatedDTO.getPhoneNumber(), - updatedDTO.getUserName() != null ? updatedDTO.getUserName() : "", - updatedDTO.getPhoneNumber() + "-更新客户", - authInfo.getManagercompany(), - authInfo.getManagerdepartment(), - authInfo.getOrganization(), - authInfo.getRole(), - authInfo.getUserName(), - authInfo.getAssistant() - ); - - return ResponseEntity.ok(response); - } else { - System.out.println("❌ 公海池客户信息更新失败"); - response.put("success", false); - response.put("message", "客户信息更新失败"); - return ResponseEntity.internalServerError().body(response); - } - } catch (Exception e) { - System.err.println("💥 更新公海池客户信息异常: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * Controller层的类型转换方法 - 采购端 - */ - private String convertCustomerTypeInController(String originalType) { - if (originalType == null) { - return "seller"; - } - - switch (originalType.toUpperCase()) { - case "BOTH": - return "both"; - case "客户端": - case "BUYER": - return "buyer"; - case "供应端": - case "SELLER": - return "seller"; - default: - return originalType; - } - } - - /** - * 更新基于电话号码的客户信息(专门用于公海池客户)- 采购员权限:只允许更新为seller和both类型 - */ - @PutMapping("/customers/update") - public ResponseEntity> updateCustomer( - @RequestBody UnifiedCustomerDTO updatedDTO, HttpServletRequest request) { - - Map response = new HashMap<>(); - try { - System.out.println("======= 🔄 开始更新非公海池客户信息(采购端) ======="); - System.out.println("数据源: " + updatedDTO.getDataSource()); - System.out.println("客户ID: " + updatedDTO.getId()); - System.out.println("手机号: " + updatedDTO.getPhoneNumber()); - System.out.println("客户类型(转换前): " + updatedDTO.getType()); - System.out.println("客户等级: " + updatedDTO.getLevel()); - System.out.println("公司: " + updatedDTO.getCompany()); - System.out.println("区域: " + updatedDTO.getRegion()); - System.out.println("昵称: " + updatedDTO.getNickName()); - System.out.println("微信: " + updatedDTO.getWechat()); - System.out.println("地址: " + updatedDTO.getAddress()); - - // 打印负责人信息 - System.out.println("=== 负责人信息 ==="); - System.out.println("负责人公司: " + updatedDTO.getManagercompany()); - System.out.println("负责人部门: " + updatedDTO.getManagerdepartment()); - System.out.println("负责人组织: " + updatedDTO.getOrganization()); - System.out.println("负责人角色: " + updatedDTO.getRole()); - System.out.println("负责人姓名: " + updatedDTO.getUserName()); - System.out.println("协助人: " + updatedDTO.getAssistant()); - - // 🎯 关键修复:先进行数据源验证和修正 - String originalDataSource = updatedDTO.getDataSource(); - String verifiedDataSource = verifyAndCorrectDataSource(updatedDTO); - - if (!originalDataSource.equals(verifiedDataSource)) { - System.out.println("🔄 数据源自动修正: " + originalDataSource + " → " + verifiedDataSource); - updatedDTO.setDataSource(verifiedDataSource); - } - - // 🎯 关键修复:从URL参数获取用户类型,与前端保持一致 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🎯 根据URL参数选择认证类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 获取认证信息 - 根据URL参数选择 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - if (authInfo == null) { - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - // 关键修复:添加客户类型转换逻辑 - System.out.println("🔄 Controller层类型转换前: " + updatedDTO.getType()); - String originalType = updatedDTO.getType(); - String convertedType = convertCustomerTypeInController(originalType); - updatedDTO.setType(convertedType); - System.out.println("🔄 Controller层类型转换后: " + originalType + " → " + convertedType); - - System.out.println("=== 数据验证 ==="); - System.out.println("手机号是否为空: " + (updatedDTO.getPhoneNumber() == null || updatedDTO.getPhoneNumber().trim().isEmpty())); - System.out.println("客户类型是否有效: " + ("seller".equals(updatedDTO.getType()) || "both".equals(updatedDTO.getType()))); - System.out.println("========================================="); - - // 使用修正后的数据源 - String dataSource = verifiedDataSource; - System.out.println("🔄 使用修正后的数据源: " + dataSource); - - // 权限校验 - System.out.println("🔐 ====== 开始权限校验 ======"); - System.out.println("🔐 当前类型: " + updatedDTO.getType()); - if (!"seller".equals(updatedDTO.getType()) && !"both".equals(updatedDTO.getType())) { - System.out.println("❌ 权限校验失败:采购员只能更新为seller或both类型,当前类型: " + updatedDTO.getType()); - response.put("success", false); - response.put("message", "采购员权限只能更新为供应端类型客户"); - return ResponseEntity.badRequest().body(response); - } - System.out.println("✅ 权限校验通过"); - - boolean success; - - // 🎯 关键修复:根据修正后的数据源处理更新 - if ("wechat".equals(dataSource)) { - System.out.println("🎯 使用wechat数据源更新客户信息"); - if (updatedDTO.getPhoneNumber() == null || updatedDTO.getPhoneNumber().trim().isEmpty()) { - throw new IllegalArgumentException("更新微信数据源时手机号不能为空"); - } - - // 🚨 重要:检查客户是否真的在wechat数据源中 - UserProductCartDTO wechatCustomer = supplyPoolCustomerService.getWechatCustomerByPhone(updatedDTO.getPhoneNumber()); - if (wechatCustomer == null) { - System.out.println("❌ wechat数据源中未找到该客户,手机号: " + updatedDTO.getPhoneNumber()); - response.put("success", false); - response.put("message", "微信数据源中未找到该客户信息"); - return ResponseEntity.badRequest().body(response); - } - - // 🎯 关键修复:确保传递正确的负责人信息处理标志 - success = supplyCustomerService.updateWechatCustomer(updatedDTO, authInfo, true); - - } else if ("default".equals(dataSource)) { - System.out.println("🎯 使用默认数据源更新"); - if (updatedDTO.getId() == null || updatedDTO.getId().trim().isEmpty()) { - throw new IllegalArgumentException("更新默认数据源时公司ID不能为空"); - } - - // 检查default数据源中客户是否存在 - boolean exists = supplyCustomerService.checkDefaultCustomerExists(updatedDTO.getId()); - if (!exists) { - System.out.println("❌ default数据源中不存在ID为" + updatedDTO.getId() + "的客户"); - - // 尝试检查该客户是否存在于wechat数据源 - boolean existsInWechat = false; - try { - // 先尝试通过手机号查找 - if (updatedDTO.getPhoneNumber() != null && !updatedDTO.getPhoneNumber().trim().isEmpty()) { - System.out.println("🔍 尝试通过手机号在wechat数据源中查找客户: " + updatedDTO.getPhoneNumber()); - UnifiedCustomerDTO wechatCustomerDTO = supplyCustomerService.getCustomerByPhone(updatedDTO.getPhoneNumber(), authInfo); - if (wechatCustomerDTO != null) { - existsInWechat = true; - System.out.println("✅ 在wechat数据源中找到客户"); - } - } - // 如果手机号查找失败,尝试通过ID查找 - if (!existsInWechat && updatedDTO.getId() != null && !updatedDTO.getId().trim().isEmpty()) { - System.out.println("🔍 尝试通过ID在wechat数据源中查找客户: " + updatedDTO.getId()); - UnifiedCustomerDTO wechatCustomerDTO = supplyCustomerService.getWechatCustomerById(updatedDTO.getId(), authInfo); - if (wechatCustomerDTO != null) { - existsInWechat = true; - System.out.println("✅ 在wechat数据源中找到客户"); - } - } - } catch (Exception e) { - System.err.println("⚠️ 检查wechat数据源时出错: " + e.getMessage()); - } - - if (existsInWechat) { - System.out.println("🔄 自动切换到wechat数据源进行更新"); - updatedDTO.setDataSource("wechat"); - success = supplyCustomerService.updateWechatCustomer(updatedDTO, authInfo, true); - response.put("success", true); - response.put("message", "客户信息更新成功(自动切换到正确的数据源)"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "默认数据源中未找到该客户,请检查ID或数据源是否正确"); - return ResponseEntity.badRequest().body(response); - } - } - - success = supplyCustomerService.updateDefaultCustomer(updatedDTO, authInfo); - - // 验证更新结果 - if (!success) { - System.out.println("❌ SQL执行成功但未更新任何记录,可能数据未变化或记录不存在"); - response.put("success", false); - response.put("message", "更新失败,未找到可更新的客户记录(可能数据无变化或ID错误)"); - return ResponseEntity.internalServerError().body(response); - } - } else { - System.out.println("❌ 不支持的数据源: " + dataSource); - response.put("success", false); - response.put("message", "不支持的数据源: " + dataSource); - return ResponseEntity.badRequest().body(response); - } - - // 记录更新客户信息操作 - informationTraService.recordOperationEvent( - updatedDTO.getPhoneNumber(), - updatedDTO.getNickName() != null ? updatedDTO.getNickName() : "", - updatedDTO.getPhoneNumber() + "-更新客户", - updatedDTO.getManagercompany() != null ? updatedDTO.getManagercompany() : "", - updatedDTO.getManagerdepartment() != null ? updatedDTO.getManagerdepartment() : "", - updatedDTO.getOrganization() != null ? updatedDTO.getOrganization() : "", - updatedDTO.getRole() != null ? updatedDTO.getRole() : "", - updatedDTO.getUserName() != null ? updatedDTO.getUserName() : "", - updatedDTO.getAssistant() != null ? updatedDTO.getAssistant() : "" - ); - - // 🎯 关键修复:返回修正后的数据源信息给前端 - Map result = new HashMap<>(); - result.put("success", true); - result.put("message", "客户信息更新成功"); - result.put("correctedDataSource", verifiedDataSource); - result.put("originalDataSource", originalDataSource); - - if (!originalDataSource.equals(verifiedDataSource)) { - result.put("dataSourceCorrected", true); - result.put("message", "客户信息更新成功(数据源已自动修正)"); - } - - return ResponseEntity.ok(result); - - } catch (IllegalArgumentException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.badRequest().body(response); - } catch (RuntimeException e) { - response.put("success", false); - response.put("message", e.getMessage()); - return ResponseEntity.notFound().build(); - } catch (Exception e) { - System.err.println("更新客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 验证并修正数据源 - * 根据客户ID和手机号自动检测客户实际所在的数据源 - */ - private String verifyAndCorrectDataSource(UnifiedCustomerDTO updatedDTO) { - String dataSource = updatedDTO.getDataSource(); - String customerId = updatedDTO.getId(); - String phoneNumber = updatedDTO.getPhoneNumber(); - - System.out.println("🔍 开始验证数据源..."); - System.out.println("📱 手机号: " + phoneNumber); - System.out.println("🆔 客户ID: " + customerId); - System.out.println("📊 前端指定数据源: " + dataSource); - - // 🔥 关键修复:尊重前端指定的数据源,只在明确错误时修正 - if ("default".equals(dataSource)) { - // 检查default数据源中客户是否存在 - boolean existsInDefault = supplyCustomerService.checkDefaultCustomerExists(customerId); - - if (existsInDefault) { - System.out.println("✅ 客户确实在default数据源中,保持数据源不变"); - return "default"; - } else { - System.out.println("⚠️ default数据源中未找到客户,尝试检查wechat数据源"); - // 只有在default数据源不存在时才检查wechat - try { - UserProductCartDTO wechatCustomer = supplyPoolCustomerService.getWechatCustomerByPhone(phoneNumber); - if (wechatCustomer != null) { - System.out.println("🔄 检测到客户存在于wechat数据源,自动修正数据源"); - return "wechat"; - } - } catch (Exception e) { - System.err.println("❌ 检查wechat数据源失败: " + e.getMessage()); - } - } - } - - // 保持原数据源 - System.out.println("✅ 保持原数据源: " + dataSource); - return dataSource; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/SupplyCustomerRecycleController.java b/src/main/java/com/example/web/controller/SupplyCustomerRecycleController.java deleted file mode 100644 index f96eaf5..0000000 --- a/src/main/java/com/example/web/controller/SupplyCustomerRecycleController.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.web.controller; - -import com.example.web.service.SupplyCustomerRecycleService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashMap; -import java.util.Map; - -@RestController -@RequestMapping("/supply/pool") -public class SupplyCustomerRecycleController { - - @Autowired - private SupplyCustomerRecycleService supplycustomerRecycleService; - - /** - * 手动触发客户回流 - * POST /supply/pool/customers/recycle - */ - @PostMapping("/customers/recycle") - public ResponseEntity> manualRecycle() { - Map response = new HashMap<>(); - - try { - supplycustomerRecycleService.manualRecycle(); - - response.put("success", true); - response.put("message", "客户回流任务执行成功"); - response.put("config", supplycustomerRecycleService.getRecycleConfigInfo()); - return ResponseEntity.ok(response); - - } catch (Exception e) { - response.put("success", false); - response.put("message", "客户回流任务执行失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取回流配置信息 - * GET /supply/pool/customers/recycle/config - */ - @GetMapping("/customers/recycle/config") - public ResponseEntity> getRecycleConfig() { - Map response = new HashMap<>(); - - try { - response.put("success", true); - response.put("config", supplycustomerRecycleService.getRecycleConfigInfo()); - return ResponseEntity.ok(response); - - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取回流配置失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/SupplyEnterpriseController.java b/src/main/java/com/example/web/controller/SupplyEnterpriseController.java deleted file mode 100644 index e15d03d..0000000 --- a/src/main/java/com/example/web/controller/SupplyEnterpriseController.java +++ /dev/null @@ -1,1107 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Contacts; -import com.example.web.entity.Enterprise; -import com.example.web.entity.Managers; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.SupplyUsersManagementsMapper; -import com.example.web.service.*; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.*; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@RestController -@RequestMapping("/supply/pool") -@CrossOrigin(origins = "*") -public class SupplyEnterpriseController { - - @Autowired - private SupplyEnterpriseService supplyenterpriseService; - @Autowired - private SupplyPoolCustomerService supplypoolCustomerService; - @Autowired - private SupplyCustomerService supplycustomerService; - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; - - // 修改类型转换方法 - 前端类型转数据库类型 - private String convertFrontendTypeToDatabase(String frontendType) { - if (frontendType == null) { - return null; - } - switch (frontendType) { - case "供应端": - return "seller"; - case "客户端": - return "buyer"; - case "BOTH": - return "both"; - default: - return frontendType; - } - } - - // 确保数据库类型转前端类型也正确 - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": - return "BOTH"; - default: - return databaseType; - } - } - - // 添加完整的类型转换方法 - private Map convertTypesForFrontend(Map response) { - if (response.containsKey("data")) { - Object data = response.get("data"); - if (data instanceof Map) { - Map dataMap = (Map) data; - for (UnifiedCustomerDTO dto : dataMap.values()) { - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - // 不再设置固定的数据源,数据源由实际来源决定 - } - } else if (data instanceof List) { - List dataList = (List) data; - for (Object item : dataList) { - if (item instanceof UnifiedCustomerDTO) { - UnifiedCustomerDTO dto = (UnifiedCustomerDTO) item; - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - // 不再设置固定的数据源,数据源由实际来源决定 - } else if (item instanceof EnterpriseInfoDTO) { - EnterpriseInfoDTO enterpriseInfo = (EnterpriseInfoDTO) item; - if (enterpriseInfo.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - enterpriseInfo.getEnterprise().setType(frontendType); - } - } - } - } else if (data instanceof UnifiedCustomerDTO) { - UnifiedCustomerDTO dto = (UnifiedCustomerDTO) data; - String frontendType = convertDatabaseTypeToFrontend(dto.getType()); - dto.setType(frontendType); - // 不再设置固定的数据源,数据源由实际来源决定 - } else if (data instanceof EnterpriseInfoDTO) { - EnterpriseInfoDTO enterpriseInfo = (EnterpriseInfoDTO) data; - if (enterpriseInfo.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - enterpriseInfo.getEnterprise().setType(frontendType); - } - } - } - return response; - } - - // 新增:电话号码重复检查接口(供前端预校验) - @GetMapping("/customers/check-phone") - public ResponseEntity> checkPhoneNumber(@RequestParam String phoneNumber) { - System.out.println("电话号码重复检查接口(双数据源):------------"+phoneNumber); - Map response = new HashMap<>(); - - // 1. 非空校验 - if (!StringUtils.hasText(phoneNumber)) { - response.put("success", false); - response.put("message", "电话号码不能为空"); - response.put("isDuplicate", false); - return ResponseEntity.badRequest().body(response); - } - - // 2. 格式校验(简单示例:11位数字) - if (!phoneNumber.matches("^1[3-9]\\d{9}$")) { - response.put("success", false); - response.put("message", "请输入有效的11位手机号码"); - response.put("isDuplicate", false); - return ResponseEntity.badRequest().body(response); - } - - // 3. 重复校验 - 现在检查双数据源 - boolean isDuplicate = supplyenterpriseService.isPhoneNumberDuplicate(phoneNumber); - response.put("success", true); - response.put("isDuplicate", isDuplicate); - response.put("message", isDuplicate ? "电话号码已存在" : "电话号码可用"); - return ResponseEntity.ok(response); - } - - // 新增:处理前端提交的客户数据(保存到默认数据源) - @PostMapping("/inputcustomers") - public ResponseEntity> addCustomer(@Valid UnifiedCustomerDTO dto, BindingResult result) { - System.out.println("新增客户信息:------------"); - System.out.println("原始类型: " + dto.getType()); - System.out.println(dto.getPhoneNumber()+"----"+dto.getCreated_at()+"----"+dto.getNickName()+"----"+dto.getUserName()); - Map response = new HashMap<>(); - - // 1. 参数校验(包括手机号非空) - if (result.hasErrors()) { - response.put("success", false); - response.put("message", "参数错误:" + result.getFieldError().getDefaultMessage()); - return ResponseEntity.badRequest().body(response); - } - - // 在检查重复之前转换类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - System.out.println("转换后类型: " + dto.getType()); - - // 采购端权限:校验客户类型,只允许seller和both - System.out.println("权限校验 - 当前类型: " + dto.getType() + ", 是否seller: " + "seller".equals(dto.getType()) + ", 是否both: " + "both".equals(dto.getType())); - - if (!"seller".equals(dto.getType()) && !"both".equals(dto.getType())) { - response.put("success", false); - response.put("message", "采购端权限只能新增供应端类型客户和BOTH类型客户"); - return ResponseEntity.badRequest().body(response); - } - - // 2. 检查电话号码是否重复(同时检查双数据源) - if (supplyenterpriseService.isPhoneNumberDuplicate(dto.getPhoneNumber())) { - response.put("success", false); - response.put("message", "电话号码已存在,添加失败"); - response.put("isDuplicate", true); - return ResponseEntity.badRequest().body(response); - } - - // 3. 执行新增逻辑 - try { - boolean success = supplyenterpriseService.addCustomer(dto); - if (success) { - response.put("success", true); - response.put("message", "新增客户成功"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "新增客户失败"); - return ResponseEntity.internalServerError().body(response); - } - } catch (Exception e) { - response.put("success", false); - response.put("message", "服务器错误:" + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取所有客户完整信息 - 融合双数据查询 + 负责人过滤 - * GET /supply/pool/customers - */ - @ResponseBody - @GetMapping("/customers") - public ResponseEntity> getAllCustomers(HttpServletRequest request) { - System.out.println("===================================================="); - System.out.println("🔄 获取所有客户信息 - 双数据源查询 + 负责人过滤"); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 从URL参数中获取用户类型,默认为采购端 - String isSupplySideParam = request.getParameter("isSupplySide"); - boolean isSupplySide = !"false".equalsIgnoreCase(isSupplySideParam); - System.out.println("🔍 根据登录信息判断用户类型: " + (isSupplySide ? "采购端" : "销售端")); - - // 获取认证信息,基于登录信息判断用户类型 - ManagerAuthInfo authInfo = getManagerAuthInfoFromRequest(request, isSupplySide); - - if (authInfo == null) { - System.out.println("❌ 未找到用户认证信息"); - response.put("success", false); - response.put("message", "用户未登录或认证信息缺失"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); - } - - System.out.println("✅ 获取到用户认证信息: " + authInfo.getUserName()); - System.out.println("🔐 负责人过滤条件: " + - "公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment()); - - // 1. 创建结果存储容器,优先使用手机号作为键 - Map resultMap = new HashMap<>(); - - // 2. 处理primary数据源(企业信息)- 添加负责人过滤 - System.out.println("🏢 开始获取企业数据..."); - List enterpriseData = supplyenterpriseService.getAllEnterpriseInfo(); - - // 应用负责人过滤 - List filteredEnterpriseData = enterpriseData.stream() - .filter(enterpriseInfo -> hasManagerPermission(enterpriseInfo, authInfo)) - .collect(Collectors.toList()); - - long enterpriseEndTime = System.currentTimeMillis(); - - System.out.println("✅ 企业数据查询完成"); - System.out.println("📊 企业数据条数: " + enterpriseData.size() + " → 过滤后: " + filteredEnterpriseData.size()); - - int enterpriseCount = 0; - if (filteredEnterpriseData != null) { - for (EnterpriseInfoDTO enterpriseInfo : filteredEnterpriseData) { - try { - UnifiedCustomerDTO dto = convertToUnifiedDTOFromEnterprise(enterpriseInfo); - String key = dto.getPhoneNumber() != null && !dto.getPhoneNumber().isEmpty() - ? dto.getPhoneNumber() - : dto.getId(); - - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无有效标识的企业数据"); - continue; - } - - resultMap.put(key, dto); - enterpriseCount++; - - // 打印前几条数据的详细信息 - if (enterpriseCount <= 3) { - System.out.println("📝 企业客户样例 " + enterpriseCount + ": " + - "公司=" + dto.getCompany() + - ", 联系人=" + dto.getNickName() + - ", 手机=" + dto.getPhoneNumber() + - ", 类型=" + dto.getType()); - } - } catch (Exception e) { - System.err.println("❌ 处理企业数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ 企业数据源成功处理: " + enterpriseCount + " 条记录"); - } - - // 3. 处理wechat数据源(用户信息)- 添加负责人过滤 - System.out.println("📱 开始获取wechat数据..."); - long wechatStartTime = System.currentTimeMillis(); - - List userData = supplypoolCustomerService.getAllCustomers(authInfo); - - - // 🔥 新增:在Controller层进行负责人过滤之前,先收集所有用户ID用于批量查询 - List allUserIds = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - if (userInfo.getUserId() != null && !userInfo.getUserId().isEmpty()) { - allUserIds.add(userInfo.getUserId()); - } - } - } - -// 🔥 新增:批量查询所有用户的负责人信息 - Map managerMap = new HashMap<>(); - if (!allUserIds.isEmpty()) { - try { - List allManagers = supplyUsersManagementsMapper.findByUserIds(allUserIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询负责人信息失败: " + e.getMessage()); - // 即使批量查询失败,也不影响后续逻辑,只是会使用默认值 - } - } - - // 在Controller层进行负责人过滤 - List filteredUserData = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - try { - if (hasPermissionToViewWechatCustomer(userInfo, authInfo)) { - filteredUserData.add(userInfo); - } - } catch (Exception e) { - System.err.println("❌ 检查用户权限时出错: " + e.getMessage()); - // 单个用户权限检查失败不影响其他用户 - } - } - } - - long wechatEndTime = System.currentTimeMillis(); - - System.out.println("✅ Wechat数据查询完成"); - System.out.println("📊 Wechat数据条数: " + userData.size() + " → 过滤后: " + filteredUserData.size()); - System.out.println("⏱️ Wechat查询耗时: " + (wechatEndTime - wechatStartTime) + "ms"); - - int wechatCount = 0; - int updateCount = 0; - if (filteredUserData != null) { - for (UserProductCartDTO userInfo : filteredUserData) { - try { - String key = userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""; - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无手机号的用户数据"); - continue; - } -// 检查是否已存在该手机号的记录 - if (resultMap.containsKey(key)) { - // 更新现有记录(补充wechat数据源的信息) - UnifiedCustomerDTO existingDto = resultMap.get(key); - updateUnifiedDTOWithWechatData(existingDto, userInfo); - updateCount++; - } else { - // 🔥 修改:传入managerMap,避免N+1查询 - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo, managerMap); - resultMap.put(key, dto); - wechatCount++; - } - } catch (Exception e) { - System.err.println("❌ 处理用户数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ Wechat数据源成功处理: " + wechatCount + " 条新记录, " + updateCount + " 条更新记录"); - } - - // 4. 打印最终统计信息和详细信息 - printFinalStatistics(resultMap, enterpriseCount, wechatCount, updateCount); - - // 5. 构建响应 - response.put("success", true); - response.put("data", resultMap); - response.put("message", "获取客户信息成功"); - response.put("total", resultMap.size()); - response.put("enterpriseCount", enterpriseCount); - response.put("wechatCount", wechatCount); - response.put("updateCount", updateCount); - - return ResponseEntity.ok(convertTypesForFrontend(response)); - } catch (Exception e) { - System.err.println("❌ 获取客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 从请求中获取ManagerAuthInfo - 基于登录信息判断用户类型 - */ - private ManagerAuthInfo getManagerAuthInfoFromRequest(HttpServletRequest request, boolean isSupplySide) { - System.out.println("🔍 获取认证信息,用户类型: " + (isSupplySide ? "采购端" : "销售端")); - - String managerId = request.getParameter("managerId"); - String managercompany = request.getParameter("company"); - String managerdepartment = request.getParameter("department"); - String organization = request.getParameter("organization"); - String role = request.getParameter("role"); - String userName = request.getParameter("userName"); - String assistant = request.getParameter("assistant"); - - // URL解码参数 - try { - if (managerId != null) managerId = java.net.URLDecoder.decode(managerId, "UTF-8"); - if (managercompany != null) managercompany = java.net.URLDecoder.decode(managercompany, "UTF-8"); - if (managerdepartment != null) managerdepartment = java.net.URLDecoder.decode(managerdepartment, "UTF-8"); - if (organization != null) organization = java.net.URLDecoder.decode(organization, "UTF-8"); - if (role != null) role = java.net.URLDecoder.decode(role, "UTF-8"); - if (userName != null) userName = java.net.URLDecoder.decode(userName, "UTF-8"); - if (assistant != null) assistant = java.net.URLDecoder.decode(assistant, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - System.err.println("URL解码失败: " + e.getMessage()); - } - - // 基本参数检查 - if (userName == null || userName.trim().isEmpty()) { - System.out.println("❌ 用户名为空,无法获取认证信息"); - return null; - } - - // 不再严格检查部门名称,而是基于登录信息判断用户类型 - if (managerdepartment == null) { - System.out.println("⚠️ 部门信息为空,使用默认值"); - managerdepartment = ""; - } - - // 记录用户类型,但不进行严格的部门名称验证 - System.out.println("✅ 用户认证信息获取成功: " + (isSupplySide ? "采购端" : "销售端")); - - // 验证公司信息一致性 - if (managercompany == null || managercompany.trim().isEmpty()) { - System.out.println("❌ 公司信息为空"); - return null; - } - - ManagerAuthInfo authInfo = new ManagerAuthInfo( - managerId != null ? managerId : "", - managercompany != null ? managercompany : "", - managerdepartment != null ? managerdepartment : "", - organization != null ? organization : "", - role != null ? role : "", - userName, - assistant != null ? assistant : "" - ); - - System.out.println("🎯 认证信息详情: " + - "系统类型=" + (isSupplySide ? "采购端" : "销售端") + - ", 公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment() + - ", 组织=" + authInfo.getOrganization() + - ", 角色=" + authInfo.getRole() + - ", 负责人=" + authInfo.getUserName() + - ", 协助人=" + authInfo.getAssistant()); - - return authInfo; - } - - /** - * 检查企业负责人权限 - */ - private boolean hasManagerPermission(EnterpriseInfoDTO enterpriseInfo, ManagerAuthInfo authInfo) { - if (enterpriseInfo.getManagers() == null) { - System.out.println("✅ 企业客户无负责人信息,允许查看"); - return true; - } - - return isManagerMatch(enterpriseInfo.getManagers(), authInfo); - } - - /** - * 检查负责人信息是否匹配(Managers) - */ - private boolean isManagerMatch(Managers manager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(manager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(manager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(manager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(manager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(manager.getUserName())); - - System.out.println("🔐 企业负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 检查是否有权限查看微信客户 - 修复版本 - */ - private boolean hasPermissionToViewWechatCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 开始检查微信客户权限,用户ID: " + userInfo.getUserId()); - - // 公海池客户对所有人可见 - if (isPublicSeaCustomer(userInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - System.out.println("🔍 非公海池客户,检查负责人权限..."); - boolean hasPermission = supplycustomerService.hasPermissionToViewWechatCustomer(userInfo, authInfo); - System.out.println("🔐 微信客户权限检查结果: " + (hasPermission ? "✅ 有权限" : "❌ 无权限")); - return hasPermission; - } catch (Exception e) { - System.err.println("❌ 检查微信客户权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 判断是否为公海池客户 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo) { - // 定义公海池等级 - java.util.Set publicSeaLevels = java.util.Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - - System.out.println("🔍 客户等级检查: " + userInfo.getLevel() + " → 是否公海池: " + isPublicSeaLevel); - - // 公海池客户:等级是公海池 - return isPublicSeaLevel; - } - - /** - * 从企业数据源转换DTO - */ - private UnifiedCustomerDTO convertToUnifiedDTOFromEnterprise(EnterpriseInfoDTO enterpriseInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - // 设置企业信息 - if (enterpriseInfo.getEnterprise() != null) { - dto.setId(enterpriseInfo.getEnterprise().getId() != null ? enterpriseInfo.getEnterprise().getId() : ""); - dto.setCompany(enterpriseInfo.getEnterprise().getCompany() != null ? enterpriseInfo.getEnterprise().getCompany() : ""); - dto.setRegion(enterpriseInfo.getEnterprise().getRegion() != null ? enterpriseInfo.getEnterprise().getRegion() : ""); - dto.setLevel(enterpriseInfo.getEnterprise().getLevel() != null ? enterpriseInfo.getEnterprise().getLevel() : ""); - String frontendType = convertDatabaseTypeToFrontend(enterpriseInfo.getEnterprise().getType()); - dto.setType(frontendType != null ? frontendType : ""); - dto.setDemand(enterpriseInfo.getEnterprise().getDemand() != null ? enterpriseInfo.getEnterprise().getDemand() : ""); - dto.setSpec(enterpriseInfo.getEnterprise().getSpec() != null ? enterpriseInfo.getEnterprise().getSpec() : ""); - } - - // 设置联系人信息 - if (enterpriseInfo.getContacts() != null) { - dto.setNickName(enterpriseInfo.getContacts().getNickName() != null ? enterpriseInfo.getContacts().getNickName() : ""); - dto.setPhoneNumber(enterpriseInfo.getContacts().getPhoneNumber() != null ? enterpriseInfo.getContacts().getPhoneNumber() : ""); - dto.setWechat(enterpriseInfo.getContacts().getWechat() != null ? enterpriseInfo.getContacts().getWechat() : ""); - dto.setAccount(enterpriseInfo.getContacts().getAccount() != null ? enterpriseInfo.getContacts().getAccount() : ""); - dto.setAccountNumber(enterpriseInfo.getContacts().getAccountNumber() != null ? enterpriseInfo.getContacts().getAccountNumber() : ""); - dto.setBank(enterpriseInfo.getContacts().getBank() != null ? enterpriseInfo.getContacts().getBank() : ""); - dto.setAddress(enterpriseInfo.getContacts().getAddress() != null ? enterpriseInfo.getContacts().getAddress() : ""); - dto.setCreated_at(enterpriseInfo.getContacts().getCreated_at()); - dto.setUpdated_at(enterpriseInfo.getContacts().getUpdated_at()); - } - - // 设置负责人信息(根据新的表结构) - if (enterpriseInfo.getManagers() != null) { - // 使用新的字段名 - dto.setManagercompany(enterpriseInfo.getManagers().getManagercompany() != null ? enterpriseInfo.getManagers().getManagercompany() : ""); - dto.setManagerdepartment(enterpriseInfo.getManagers().getManagerdepartment() != null ? enterpriseInfo.getManagers().getManagerdepartment() : ""); - dto.setOrganization(enterpriseInfo.getManagers().getOrganization() != null ? enterpriseInfo.getManagers().getOrganization() : ""); - dto.setRole(enterpriseInfo.getManagers().getRole() != null ? enterpriseInfo.getManagers().getRole() : ""); - dto.setUserName(enterpriseInfo.getManagers().getUserName() != null ? enterpriseInfo.getManagers().getUserName() : ""); - dto.setAssistant(enterpriseInfo.getManagers().getAssistant() != null ? enterpriseInfo.getManagers().getAssistant() : ""); - } - - // 设置数据源标识 - dto.setDataSource("enterprise"); - - return dto; - } - - /** - * 专门为公海池客户转换DTO的方法 - 补充负责人信息(优化版本) - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea( - UserProductCartDTO userInfo, - Map managerMap) { // 🔥 新增参数:批量查询的负责人信息 - - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - // 设置用户基础信息 - dto.setId(userInfo.getUserId() != null ? userInfo.getUserId() : ""); - dto.setPhoneNumber(userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""); - - // 设置公司信息 - dto.setCompany(userInfo.getCompany() != null ? userInfo.getCompany() : ""); - dto.setRegion(userInfo.getRegion() != null ? userInfo.getRegion() : ""); - - // 设置需求和规格 - dto.setDemand(userInfo.getDemand() != null ? userInfo.getDemand() : ""); - dto.setSpec(userInfo.getSpec() != null ? userInfo.getSpec() : ""); - - // 类型转换 - String frontendType = convertDatabaseTypeToFrontend(userInfo.getType()); - dto.setType(frontendType != null ? frontendType : ""); - - dto.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : ""); - dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - // 添加通知信息转换 - dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); - - // 关键:设置数据源标识为wechat - dto.setDataSource("wechat"); - - // 设置联系人信息 - 从usersContacts获取 - setContactInfoSafely(dto, userInfo); - - // 🔥 关键修改:从批量查询的managerMap中获取负责人信息,避免N+1查询 - setManagerInfoFromMap(dto, userInfo.getUserId(), managerMap); - - // 设置公海需求信息 - 从产品表获取(采购端特有逻辑) - if (userInfo.getProducts() != null && !userInfo.getProducts().isEmpty()) { - UserProductCartDTO.ProductInfo selectedProduct = userInfo.getProducts().get(0); - - dto.setProductName(selectedProduct.getProductName() != null ? selectedProduct.getProductName() : ""); - dto.setVariety(selectedProduct.getVariety() != null ? selectedProduct.getVariety() : ""); - dto.setSpecification(selectedProduct.getSpecification() != null ? selectedProduct.getSpecification() : ""); - dto.setQuantity(selectedProduct.getQuantity() != null ? selectedProduct.getQuantity() : 0); - dto.setGrossWeight(selectedProduct.getGrossWeight() != null ? selectedProduct.getGrossWeight() : ""); - dto.setYolk(selectedProduct.getYolk() != null ? selectedProduct.getYolk() : ""); - - // 设置选中的产品项ID(采购端特有字段) - dto.setTargetProductItemId(selectedProduct.getProductId() != null ? selectedProduct.getProductId() : ""); - - // 设置customDetails为产品信息 - dto.setCustomDetails(userInfo.getProducts().toArray()); - } else { - // 如果没有产品信息,设置默认值 - setDefaultProductValues(dto); - } - - return dto; - } - - /** - * 从批量查询的Map中设置负责人信息 - 避免N+1查询(与销售端保持一致) - */ - private void setManagerInfoFromMap(UnifiedCustomerDTO dto, String userId, Map managerMap) { - try { - System.out.println("🔍 从批量Map中查询用户负责人信息,用户ID: " + userId); - UsersManagements userManager = managerMap.get(userId); - - if (userManager != null) { - System.out.println("✅ 从批量Map中找到负责人信息,设置到DTO"); - // 设置负责人信息到统一的DTO字段(与销售端保持相同字段) - dto.setManagercompany(userManager.getManagercompany() != null ? userManager.getManagercompany() : ""); - dto.setManagerdepartment(userManager.getManagerdepartment() != null ? userManager.getManagerdepartment() : ""); - dto.setOrganization(userManager.getOrganization() != null ? userManager.getOrganization() : ""); - dto.setRole(userManager.getRole() != null ? userManager.getRole() : ""); - dto.setUserName(userManager.getUserName() != null ? userManager.getUserName() : ""); - dto.setAssistant(userManager.getAssistant() != null ? userManager.getAssistant() : ""); - - // 调试日志 - System.out.println("📝 负责人信息详情: " + - "公司=" + dto.getManagercompany() + - ", 部门=" + dto.getManagerdepartment() + - ", 组织=" + dto.getOrganization() + - ", 角色=" + dto.getRole() + - ", 负责人=" + dto.getUserName() + - ", 协助人=" + dto.getAssistant()); - } else { - System.out.println("⚠️ 未在批量Map中找到负责人信息,用户可能为公海池客户"); - // 设置默认值 - setDefaultManagerValues(dto); - } - } catch (Exception e) { - System.err.println("❌ 从Map设置负责人信息失败: " + e.getMessage()); - // 发生异常时设置默认值 - setDefaultManagerValues(dto); - } - } - - /** - * 设置默认负责人信息(与销售端保持一致) - */ - private void setDefaultManagerValues(UnifiedCustomerDTO dto) { - dto.setManagercompany(""); - dto.setManagerdepartment(""); - dto.setOrganization(""); - dto.setRole(""); - dto.setUserName(""); - dto.setAssistant(""); - } - - /** - * 用wechat数据更新现有的DTO(用于数据合并)- 采购端使用产品信息 - */ - private void updateUnifiedDTOWithWechatData(UnifiedCustomerDTO existingDto, UserProductCartDTO userInfo) { - // 补充产品信息(如果企业数据中缺少) - if ((existingDto.getProductName() == null || existingDto.getProductName().isEmpty()) && - userInfo.getProducts() != null && !userInfo.getProducts().isEmpty()) { - - UserProductCartDTO.ProductInfo product = userInfo.getProducts().get(0); - existingDto.setProductName(product.getProductName() != null ? product.getProductName() : ""); - existingDto.setVariety(product.getVariety() != null ? product.getVariety() : ""); - existingDto.setSpecification(product.getSpecification() != null ? product.getSpecification() : ""); - existingDto.setQuantity(product.getQuantity() != null ? product.getQuantity() : 0); - existingDto.setGrossWeight(product.getGrossWeight() != null ? product.getGrossWeight() : ""); - existingDto.setYolk(product.getYolk() != null ? product.getYolk() : ""); - - // 设置customDetails - existingDto.setCustomDetails(userInfo.getProducts().toArray()); - } - - // 补充其他可能缺失的字段 - if (existingDto.getLevel() == null || existingDto.getLevel().isEmpty()) { - existingDto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); - } - - // 标记为混合数据源 - existingDto.setDataSource("mixed"); - } - - /** - * 打印最终统计信息 - 采购端版本 - */ - private void printFinalStatistics(Map resultMap, int enterpriseCount, int wechatCount, int updateCount) { - System.out.println("===================================================="); - System.out.println("📈 [采购端] 数据源查询统计:"); - System.out.println("🏢 企业数据源: " + enterpriseCount + " 条记录"); - System.out.println("📱 Wechat数据源: " + (wechatCount + updateCount) + " 条记录 (" + wechatCount + " 新增, " + updateCount + " 更新)"); - System.out.println("📊 合并后总客户数: " + resultMap.size() + " 条记录"); - System.out.println("===================================================="); - - // 打印详细样例(限制数量避免日志过多) - int sampleCount = 0; - System.out.println("📋 [采购端] 最终数据样例:"); - for (Map.Entry entry : resultMap.entrySet()) { - if (sampleCount >= 5) break; - - String key = entry.getKey(); - UnifiedCustomerDTO dto = entry.getValue(); - - System.out.println("--- 客户 " + (sampleCount + 1) + " ---"); - System.out.println(" 键: " + key); - System.out.println(" 数据源: " + dto.getDataSource()); - System.out.println(" ID: " + dto.getId()); - System.out.println(" 公司: " + dto.getCompany()); - System.out.println(" 联系人: " + dto.getNickName()); - System.out.println(" 手机: " + dto.getPhoneNumber()); - System.out.println(" 微信号: " + dto.getWechat()); - System.out.println(" 类型: " + dto.getType()); - System.out.println(" 等级: " + dto.getLevel()); - System.out.println(" 地区: " + dto.getRegion()); - System.out.println(" 需求: " + dto.getDemand()); - System.out.println(" 规格: " + dto.getSpec()); - - // 产品信息 - System.out.println(" 产品名称: " + dto.getProductName()); - System.out.println(" 品种: " + dto.getVariety()); - System.out.println(" 规格说明: " + dto.getSpecification()); - System.out.println(" 数量: " + dto.getQuantity()); - System.out.println(" 毛重: " + dto.getGrossWeight()); - System.out.println(" 蛋黄: " + dto.getYolk()); - - // 联系人详细信息 - System.out.println(" 账户: " + dto.getAccount()); - System.out.println(" 账号: " + dto.getAccountNumber()); - System.out.println(" 银行: " + dto.getBank()); - System.out.println(" 地址: " + dto.getAddress()); - - // 负责人信息 - System.out.println(" 负责公司: " + dto.getManagercompany()); - System.out.println(" 负责部门: " + dto.getManagerdepartment()); - System.out.println(" 组织: " + dto.getOrganization()); - System.out.println(" 角色: " + dto.getRole()); - System.out.println(" 负责人: " + dto.getUserName()); - System.out.println(" 协助人: " + dto.getAssistant()); - - // 时间信息 - System.out.println(" 创建时间: " + dto.getCreated_at()); - System.out.println(" 更新时间: " + dto.getUpdated_at()); - - sampleCount++; - System.out.println(); // 空行分隔 - } - System.out.println("===================================================="); - } - - // 保留原有的辅助方法 - 采购端版本 - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - } - - private void setContactInfoSafely(UnifiedCustomerDTO dto, UserProductCartDTO userInfo) { - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - List validContacts = userInfo.getUsersContacts().stream() - .filter(contact -> contact != null) - .collect(Collectors.toList()); - - if (!validContacts.isEmpty()) { - UserProductCartDTO.UsersContacts contact = validContacts.get(0); - dto.setWechat(contact.getWechat() != null ? contact.getWechat() : ""); - dto.setAccount(contact.getAccount() != null ? contact.getAccount() : ""); - dto.setAccountNumber(contact.getAccountNumber() != null ? contact.getAccountNumber() : ""); - dto.setBank(contact.getBank() != null ? contact.getBank() : ""); - dto.setAddress(contact.getAddress() != null ? contact.getAddress() : ""); - } else { - setDefaultContactValues(dto); - } - } else { - setDefaultContactValues(dto); - } - } - - private void setDefaultContactValues(UnifiedCustomerDTO dto) { - dto.setWechat(""); - dto.setAccount(""); - dto.setAccountNumber(""); - dto.setBank(""); - dto.setAddress(""); - } - - // 其他方法保持不变... - /** - * 根据ID获取客户详细信息 - * GET /supply/pool/customers/{id} - */ - @GetMapping("/{id}") - public ResponseEntity> getCustomerById(@PathVariable String id) { - Map response = new HashMap<>(); - try { - EnterpriseInfoDTO customer = supplyenterpriseService.getEnterpriseInfoById(id); - if (customer != null) { - response.put("success", true); - response.put("data", customer); - response.put("message", "获取客户信息成功"); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "未找到对应的客户信息"); - return ResponseEntity.notFound().build(); - } - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 搜索客户信息 - * GET /supply/pool/customers/search?keyword=xxx - */ - @GetMapping("/search") - public ResponseEntity> searchCustomers(@RequestParam(required = false) String keyword) { - Map response = new HashMap<>(); - try { - List customers = supplyenterpriseService.searchEnterprises(keyword); - // 类型转换:将每个企业类型从数据库类型转换为前端类型 - for (EnterpriseInfoDTO customer : customers) { - if (customer.getEnterprise() != null) { - String frontendType = convertDatabaseTypeToFrontend(customer.getEnterprise().getType()); - customer.getEnterprise().setType(frontendType); - } - } - response.put("success", true); - response.put("data", customers); - response.put("message", "搜索客户信息成功"); - response.put("total", customers.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "搜索客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取所有企业基本信息 - * GET /supply/pool/customers/enterprises - */ - @GetMapping("/enterprises") - public ResponseEntity> getAllEnterprises() { - Map response = new HashMap<>(); - try { - List enterprises = supplyenterpriseService.getAllEnterprises(); - // 类型转换:将每个企业类型从数据库类型转换为前端类型 - for (Enterprise enterprise : enterprises) { - String frontendType = convertDatabaseTypeToFrontend(enterprise.getType()); - enterprise.setType(frontendType); - } - response.put("success", true); - response.put("data", enterprises); - response.put("message", "获取企业信息成功"); - response.put("total", enterprises.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取企业信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取指定企业的联系人信息 - * GET /supply/pool/customers/{id}/contacts - */ - @GetMapping("/{id}/contacts") - public ResponseEntity> getContactsByEnterpriseId(@PathVariable String id) { - Map response = new HashMap<>(); - try { - List contacts = supplyenterpriseService.getContactsByEnterpriseId(id); - response.put("success", true); - response.put("data", contacts); - response.put("message", "获取联系人信息成功"); - response.put("total", contacts.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取联系人信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - /** - * 获取指定企业的负责人信息 - * GET /supply/pool/customers/{id}/managers - */ - @GetMapping("/{id}/managers") - public ResponseEntity> getManagersByEnterpriseId(@PathVariable String id) { - Map response = new HashMap<>(); - try { - List managers = supplyenterpriseService.getManagersByEnterpriseId(id); - response.put("success", true); - response.put("data", managers); - response.put("message", "获取负责人信息成功"); - response.put("total", managers.size()); - return ResponseEntity.ok(response); - } catch (Exception e) { - response.put("success", false); - response.put("message", "获取负责人信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } - - - /** - * 健康检查接口 - * GET /supply/pool/customers/health - */ - @GetMapping("/health") - public ResponseEntity> healthCheck() { - Map response = new HashMap<>(); - response.put("success", true); - response.put("message", "客户信息服务运行正常"); - response.put("timestamp", System.currentTimeMillis()); - return ResponseEntity.ok(response); - } - - /** - * 获取所有客户信息 - 不使用前端参数,直接查询双数据源所有数据 - * GET /pool/all-customers - */ - @ResponseBody - @GetMapping("/all-customers") - public ResponseEntity> getAllCustomersWithoutFilter() { - System.out.println("===================================================="); - System.out.println("🔄 开始获取所有客户信息 - 双数据源查询(无负责人过滤)"); - System.out.println("===================================================="); - - Map response = new HashMap<>(); - try { - // 1. 创建结果存储容器,优先使用手机号作为键 - Map resultMap = new HashMap<>(); - - // 2. 处理primary数据源(企业信息)- 不进行负责人过滤 - System.out.println("🏢 开始获取企业数据..."); - List enterpriseData = supplyenterpriseService.getAllEnterpriseInfo(); - - System.out.println("✅ 企业数据查询完成"); - System.out.println("📊 企业数据条数: " + enterpriseData.size()); - - int enterpriseCount = 0; - if (enterpriseData != null) { - for (EnterpriseInfoDTO enterpriseInfo : enterpriseData) { - try { - UnifiedCustomerDTO dto = convertToUnifiedDTOFromEnterprise(enterpriseInfo); - String key = dto.getPhoneNumber() != null && !dto.getPhoneNumber().isEmpty() - ? dto.getPhoneNumber() - : dto.getId(); - - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无有效标识的企业数据"); - continue; - } - - resultMap.put(key, dto); - enterpriseCount++; - - // 打印前几条数据的详细信息 - if (enterpriseCount <= 3) { - System.out.println("📝 企业客户样例 " + enterpriseCount + ": " + - "公司=" + dto.getCompany() + - ", 联系人=" + dto.getNickName() + - ", 手机=" + dto.getPhoneNumber() + - ", 类型=" + dto.getType()); - } - } catch (Exception e) { - System.err.println("❌ 处理企业数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ 企业数据源成功处理: " + enterpriseCount + " 条记录"); - } - - // 3. 处理wechat数据源(用户信息)- 不进行负责人过滤 - System.out.println("📱 开始获取wechat数据..."); - List userData = supplypoolCustomerService.getAllCustomersWithoutFilter(); - -// 🔥 新增:批量查询负责人信息(与getAllCustomers方法相同) - List allUserIds = new ArrayList<>(); - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - if (userInfo.getUserId() != null && !userInfo.getUserId().isEmpty()) { - allUserIds.add(userInfo.getUserId()); - } - } - } - - Map managerMap = new HashMap<>(); - if (!allUserIds.isEmpty()) { - try { - List allManagers = supplyUsersManagementsMapper.findByUserIds(allUserIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询负责人信息失败: " + e.getMessage()); - } - } - - System.out.println("✅ Wechat数据查询完成"); - System.out.println("📊 Wechat数据条数: " + userData.size()); - - int wechatCount = 0; - int updateCount = 0; - if (userData != null) { - for (UserProductCartDTO userInfo : userData) { - try { - String key = userInfo.getPhoneNumber() != null ? userInfo.getPhoneNumber() : ""; - if (!StringUtils.hasText(key)) { - System.out.println("⚠️ 跳过无手机号的用户数据"); - continue; - } - - // 检查是否已存在该手机号的记录 - if (resultMap.containsKey(key)) { - UnifiedCustomerDTO existingDto = resultMap.get(key); - updateUnifiedDTOWithWechatData(existingDto, userInfo); - updateCount++; - } else { - // 🔥 修改:传入managerMap - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo, managerMap); - resultMap.put(key, dto); - wechatCount++; - } - } catch (Exception e) { - System.err.println("❌ 处理用户数据时出错: " + e.getMessage()); - e.printStackTrace(); - } - } - System.out.println("✅ Wechat数据源成功处理: " + wechatCount + " 条新记录, " + updateCount + " 条更新记录"); - } - - // 4. 打印最终统计信息和详细信息 - printFinalStatistics(resultMap, enterpriseCount, wechatCount, updateCount); - - // 5. 构建响应 - response.put("success", true); - response.put("data", resultMap); - response.put("message", "获取客户信息成功"); - response.put("total", resultMap.size()); - response.put("enterpriseCount", enterpriseCount); - response.put("wechatCount", wechatCount); - response.put("updateCount", updateCount); - - return ResponseEntity.ok(convertTypesForFrontend(response)); - } catch (Exception e) { - System.err.println("❌ 获取客户信息失败: " + e.getMessage()); - e.printStackTrace(); - response.put("success", false); - response.put("message", "获取客户信息失败: " + e.getMessage()); - return ResponseEntity.internalServerError().body(response); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/controller/SupplyPoolCustomerController.java b/src/main/java/com/example/web/controller/SupplyPoolCustomerController.java deleted file mode 100644 index cebfb3d..0000000 --- a/src/main/java/com/example/web/controller/SupplyPoolCustomerController.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.example.web.controller; - -import com.example.web.dto.UserProductCartDTO; -import com.example.web.service.PoolCustomerService; -import com.example.web.service.SupplyPoolCustomerService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.HashMap; -import java.util.Map; - -@RestController -@RequestMapping("/supply/pool/") -public class SupplyPoolCustomerController { - - @Autowired - private SupplyPoolCustomerService supplypoolCustomerService; - - /** - * 根据用户ID获取客户信息 - * GET /pool/customers/{userId} - */ - @GetMapping("/customersss/{userId}") - public ResponseEntity getCustomerById(@PathVariable String userId) { - try { - UserProductCartDTO customerInfo = supplypoolCustomerService.getCustomerInfo(userId); - return ResponseEntity.ok(customerInfo); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(createErrorResponse("参数错误", e.getMessage())); - } catch (RuntimeException e) { - return ResponseEntity.notFound().build(); - } catch (Exception e) { - return ResponseEntity.internalServerError() - .body(createErrorResponse("服务器错误", "获取客户信息失败")); - } - } - - /** - * 查询客户信息(支持按类型过滤) - * GET /pool/customers?type=seller&page=1&size=10 - */ - @GetMapping("/customersss") - public ResponseEntity getCustomers( - @RequestParam(required = false) String type, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int size) { - - try { - Map response = new HashMap<>(); - response.put("page", page); - response.put("size", size); - response.put("type", type); - response.put("message", "分页查询功能待实现"); - - return ResponseEntity.ok(response); - } catch (Exception e) { - return ResponseEntity.internalServerError() - .body(createErrorResponse("查询失败", e.getMessage())); - } - } - - /** - * 创建统一的错误响应格式 - */ - private Map createErrorResponse(String error, String message) { - Map errorResponse = new HashMap<>(); - errorResponse.put("error", error); - errorResponse.put("message", message); - errorResponse.put("timestamp", System.currentTimeMillis()); - return errorResponse; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/dao/LoginMapper.java b/src/main/java/com/example/web/dao/LoginMapper.java new file mode 100644 index 0000000..1ec2909 --- /dev/null +++ b/src/main/java/com/example/web/dao/LoginMapper.java @@ -0,0 +1,22 @@ +package com.example.web.dao; + +import com.example.web.entity.Login; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * @Description: 登录Mapper接口 + */ +@Mapper +public interface LoginMapper { + /** + * 验证用户登录信息 + * @param projectName 职位名称 + * @param userName 用户名 + * @param password 密码 + * @return Login对象,如果存在则返回,否则返回null + */ + @Select("SELECT * FROM login WHERE projectName = #{projectName} AND userName = #{userName} AND password = #{password}") + Login validateLogin(@Param("projectName") String projectName, @Param("userName") String userName, @Param("password") String password); +} diff --git a/src/main/java/com/example/web/dao/PersonnelMapper.java b/src/main/java/com/example/web/dao/PersonnelMapper.java new file mode 100644 index 0000000..23d1075 --- /dev/null +++ b/src/main/java/com/example/web/dao/PersonnelMapper.java @@ -0,0 +1,20 @@ +package com.example.web.dao; + +import com.example.web.entity.Personnel; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * @Description: 员工信息Mapper接口 + */ +@Mapper +public interface PersonnelMapper { + /** + * 根据负责人ID获取员工信息 + * @param managerId 负责人ID + * @return Personnel对象,如果存在则返回,否则返回null + */ + @Select("SELECT * FROM personnel WHERE managerId = #{managerId}") + Personnel getPersonnelByManagerId(@Param("managerId") String managerId); +} diff --git a/src/main/java/com/example/web/dto/EnterpriseInfoDTO.java b/src/main/java/com/example/web/dto/EnterpriseInfoDTO.java index 410e8c4..b5dbcc9 100644 --- a/src/main/java/com/example/web/dto/EnterpriseInfoDTO.java +++ b/src/main/java/com/example/web/dto/EnterpriseInfoDTO.java @@ -3,45 +3,16 @@ package com.example.web.dto; import com.example.web.entity.Contacts; import com.example.web.entity.Enterprise; import com.example.web.entity.Managers; -// 企业信息数据传输对象(DTO),用于封装企业完整信息(企业基本信息+联系人+负责人等) -// getter和setter:提供属性的获取和设置方法,用于在各层之间传递数据 +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description: 企业信息DTO,包含企业、联系人和负责人信息 + */ +@Data +@NoArgsConstructor public class EnterpriseInfoDTO { - - private Enterprise enterprise; - private Contacts contacts; - private Managers managers; - - // 构造方法 - public EnterpriseInfoDTO() {} - - public EnterpriseInfoDTO(Enterprise enterprise, Contacts contacts, Managers managers) { - this.enterprise = enterprise; - this.contacts = contacts; - this.managers = managers; - } - - // getter和setter - public Enterprise getEnterprise() { - return enterprise; - }// 获取企业基本信息对象(包含公司名称、地区、类型等核心字段) - - public void setEnterprise(Enterprise enterprise) { - this.enterprise = enterprise; - } - - public Contacts getContacts() { - return contacts; - } - - public void setContacts(Contacts contacts) { - this.contacts = contacts; - } - - public Managers getManagers() { - return managers; - } - - public void setManagers(Managers managers) { - this.managers = managers; - } - } + private Enterprise enterprise; + private Contacts contacts; + private Managers managers; +} \ No newline at end of file diff --git a/src/main/java/com/example/web/dto/ManagerAuthInfo.java b/src/main/java/com/example/web/dto/ManagerAuthInfo.java deleted file mode 100644 index 9f25ac9..0000000 --- a/src/main/java/com/example/web/dto/ManagerAuthInfo.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.example.web.dto; - -import lombok.Data; - -@Data -public class ManagerAuthInfo { - private String managerId; - private String managercompany; - private String managerdepartment; - private String organization; - private String role; - private String userName; - private String assistant; - - public ManagerAuthInfo(String managerId, String managercompany, String managerdepartment, String organization, String role, String userName, String assistant) { - this.managerId = managerId; - this.managercompany = managercompany; - this.managerdepartment = managerdepartment; - this.organization = organization; - this.role = role; - this.userName = userName; - this.assistant = assistant; - } - - public String getManagerId() { - return managerId; - } - - public void setManagerId(String managerId) { - this.managerId = managerId; - } - - public String getManagercompany() { - return managercompany; - } - - public void setManagercompany(String managercompany) { - this.managercompany = managercompany; - } - - public String getManagerdepartment() { - return managerdepartment; - } - - public void setManagerdepartment(String managerdepartment) { - this.managerdepartment = managerdepartment; - } - - public String getOrganization() { - return organization; - } - - public void setOrganization(String organization) { - this.organization = organization; - } - - public String getRole() { - return role; - } - - public void setRole(String role) { - this.role = role; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getAssistant() { - return assistant; - } - - public void setAssistant(String assistant) { - this.assistant = assistant; - } -} diff --git a/src/main/java/com/example/web/dto/NotificationDTO.java b/src/main/java/com/example/web/dto/NotificationDTO.java new file mode 100644 index 0000000..ee358a7 --- /dev/null +++ b/src/main/java/com/example/web/dto/NotificationDTO.java @@ -0,0 +1,55 @@ +package com.example.web.dto; + +import java.time.LocalDateTime; + +/** + * WebSocket通知DTO + */ +public class NotificationDTO { + private String type; // 通知类型 + private String title; // 通知标题 + private String message; // 通知内容 + private String customerId; // 相关客户ID + private LocalDateTime timestamp; // 时间戳 + + // getter和setter方法 + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + + public LocalDateTime getTimestamp() { + return timestamp; + } + + public void setTimestamp(LocalDateTime timestamp) { + this.timestamp = timestamp; + } +} diff --git a/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java b/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java deleted file mode 100644 index fca85ee..0000000 --- a/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java +++ /dev/null @@ -1,331 +0,0 @@ -package com.example.web.dto; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Data -public class UnifiedCustomerDTO { - private String id = ""; - private String company = ""; - private String region = ""; - private String level = ""; - private String type = ""; - private String demand = ""; - private String spec = ""; - private String nickName = ""; - - @NotBlank(message = "手机号不能为空") - private String phoneNumber = ""; - - // 向后兼容的单个联系人字段 - private String wechat = ""; - private String account = ""; - private String accountNumber = ""; - private String bank = ""; - private String address = ""; - - // 向后兼容的单个产品字段 - private String productName = ""; - private String variety = ""; - private String specification = ""; - private Integer quantity = 0; - private String grossWeight = ""; - private String yolk = ""; - - // 负责人信息字段 - private String managerId =""; //负责人id - private String managercompany = ""; // 负责人公司 - private String managerdepartment = ""; // 负责人部门 - private String organization = ""; // 负责人组织 - private String role = ""; // 负责人角色 - private String userName = ""; // 负责人用户名 - private String assistant = ""; // 协助人 - private String notice = ""; // 通知信息 - - // 时间信息 - private LocalDateTime created_at; - private LocalDateTime updated_at; - - // 扩展信息 - private Object[] customDetails = new Object[0]; - private String dataSource; // "wechat" 或 "default" 或 "mixed" - - // ==================== 一对多字段 ==================== - private List contacts = new ArrayList<>(); - private List cartItems = new ArrayList<>(); // 销售端使用 - private List productItems = new ArrayList<>(); // 采购端使用 - - // ==================== 精确修改字段 ==================== - private String targetContactId; // 要修改的联系人ID - private String targetCartItemId; // 要修改的购物车项ID - private String targetProductItemId; // 要修改的产品项ID - - // ==================== 更新数据字段 ==================== - // 修改字段名以保持与Service的一致性 - private ContactInfo updateContactData; // 联系人更新数据(与Service中的使用保持一致) - private CartItem updateCartItemData; // 购物车项更新数据(与Service中的使用保持一致) - private ProductItem updateProductItemData; // 产品项更新数据 - - // ==================== 内部类定义 ==================== - - /** - * 联系人信息 - */ - public static class ContactInfo { - private String contactId = ""; - private String wechat = ""; - private String account = ""; - private String accountNumber = ""; - private String bank = ""; - private String address = ""; - - // Getter 和 Setter 方法 - public String getContactId() { return contactId; } - public void setContactId(String contactId) { this.contactId = contactId; } - public String getWechat() { return wechat; } - public void setWechat(String wechat) { this.wechat = wechat; } - public String getAccount() { return account; } - public void setAccount(String account) { this.account = account; } - public String getAccountNumber() { return accountNumber; } - public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } - public String getBank() { return bank; } - public void setBank(String bank) { this.bank = bank; } - public String getAddress() { return address; } - public void setAddress(String address) { this.address = address; } - } - - /** - * 购物车项信息(销售端使用) - */ - public static class CartItem { - private String cartItemId = ""; - private String productId = ""; - private String productName = ""; - private String specification = ""; - private Integer quantity = 0; - private String grossWeight = ""; - private String yolk = ""; - - // Getter 和 Setter 方法 - public String getCartItemId() { return cartItemId; } - public void setCartItemId(String cartItemId) { this.cartItemId = cartItemId; } - public String getProductId() { return productId; } - public void setProductId(String productId) { this.productId = productId; } - public String getProductName() { return productName; } - public void setProductName(String productName) { this.productName = productName; } - public String getSpecification() { return specification; } - public void setSpecification(String specification) { this.specification = specification; } - public Integer getQuantity() { return quantity; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } - public String getGrossWeight() { return grossWeight; } - public void setGrossWeight(String grossWeight) { this.grossWeight = grossWeight; } - public String getYolk() { return yolk; } - public void setYolk(String yolk) { this.yolk = yolk; } - } - - /** - * 产品项信息(采购端使用) - */ - public static class ProductItem { - private String productId = ""; - private String productName = ""; - private String variety = ""; - private String specification = ""; - private Integer quantity = 0; - private String grossWeight = ""; - private String yolk = ""; - - // Getter 和 Setter 方法 - public String getProductId() { return productId; } - public void setProductId(String productId) { this.productId = productId; } - public String getProductName() { return productName; } - public void setProductName(String productName) { this.productName = productName; } - public String getVariety() { return variety; } - public void setVariety(String variety) { this.variety = variety; } - public String getSpecification() { return specification; } - public void setSpecification(String specification) { this.specification = specification; } - public Integer getQuantity() { return quantity; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } - public String getGrossWeight() { return grossWeight; } - public void setGrossWeight(String grossWeight) { this.grossWeight = grossWeight; } - public String getYolk() { return yolk; } - public void setYolk(String yolk) { this.yolk = yolk; } - } - - // ==================== Getter 和 Setter 方法 ==================== - - // 一对多字段的getter/setter - public List getContacts() { return contacts; } - public void setContacts(List contacts) { this.contacts = contacts; } - - public List getCartItems() { return cartItems; } - public void setCartItems(List cartItems) { this.cartItems = cartItems; } - - public List getProductItems() { return productItems; } - public void setProductItems(List productItems) { this.productItems = productItems; } - - // 精确修改字段的getter/setter - public String getTargetContactId() { return targetContactId; } - public void setTargetContactId(String targetContactId) { this.targetContactId = targetContactId; } - - public String getTargetCartItemId() { return targetCartItemId; } - public void setTargetCartItemId(String targetCartItemId) { this.targetCartItemId = targetCartItemId; } - - public String getTargetProductItemId() { return targetProductItemId; } - public void setTargetProductItemId(String targetProductItemId) { this.targetProductItemId = targetProductItemId; } - - // 更新数据字段的getter/setter - public ContactInfo getUpdateContactData() { return updateContactData; } - public void setUpdateContactData(ContactInfo updateContactData) { this.updateContactData = updateContactData; } - - public CartItem getUpdateCartItemData() { return updateCartItemData; } - public void setUpdateCartItemData(CartItem updateCartItemData) { this.updateCartItemData = updateCartItemData; } - - public ProductItem getUpdateProductItemData() { return updateProductItemData; } - public void setUpdateProductItemData(ProductItem updateProductItemData) { this.updateProductItemData = updateProductItemData; } - - // 向后兼容:为旧的updateContact字段提供兼容性(如果需要) - /** - * @deprecated 请使用 getUpdateContactData() - */ - public ContactInfo getUpdateContact() { return updateContactData; } - - /** - * @deprecated 请使用 setUpdateContactData() - */ - public void setUpdateContact(ContactInfo updateContact) { this.updateContactData = updateContact; } - - /** - * @deprecated 请使用 getUpdateCartItemData() - */ - public CartItem getUpdateCartItem() { return updateCartItemData; } - - /** - * @deprecated 请使用 setUpdateCartItemData() - */ - public void setUpdateCartItem(CartItem updateCartItem) { this.updateCartItemData = updateCartItem; } - - /** - * @deprecated 请使用 getUpdateProductItemData() - */ - public ProductItem getUpdateProductItem() { return updateProductItemData; } - - /** - * @deprecated 请使用 setUpdateProductItemData() - */ - public void setUpdateProductItem(ProductItem updateProductItem) { this.updateProductItemData = updateProductItem; } - - // 基础字段的getter/setter - public String getId() { return id; } - public void setId(String id) { this.id = id; } - - public String getCompany() { return company; } - public void setCompany(String company) { this.company = company; } - - public String getRegion() { return region; } - public void setRegion(String region) { this.region = region; } - - public String getLevel() { return level; } - public void setLevel(String level) { this.level = level; } - - public String getType() { return type; } - public void setType(String type) { this.type = type; } - - public String getDemand() { return demand; } - public void setDemand(String demand) { this.demand = demand; } - - public String getSpec() { return spec; } - public void setSpec(String spec) { this.spec = spec; } - - public String getNickName() { return nickName; } - public void setNickName(String nickName) { this.nickName = nickName; } - - public String getPhoneNumber() { return phoneNumber; } - public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } - - public String getWechat() { return wechat; } - public void setWechat(String wechat) { this.wechat = wechat; } - - public String getAccount() { return account; } - public void setAccount(String account) { this.account = account; } - - public String getAccountNumber() { return accountNumber; } - public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } - - public String getBank() { return bank; } - public void setBank(String bank) { this.bank = bank; } - - public String getAddress() { return address; } - public void setAddress(String address) { this.address = address; } - - public String getProductName() { return productName; } - public void setProductName(String productName) { this.productName = productName; } - - public String getVariety() { return variety; } - public void setVariety(String variety) { this.variety = variety; } - - public String getSpecification() { return specification; } - public void setSpecification(String specification) { this.specification = specification; } - - public Integer getQuantity() { return quantity; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } - - public String getGrossWeight() { return grossWeight; } - public void setGrossWeight(String grossWeight) { this.grossWeight = grossWeight; } - - public String getYolk() { return yolk; } - public void setYolk(String yolk) { this.yolk = yolk; } - - public String getManagerId() { - return managerId; - } - - public void setManagerId(String managerId) { - this.managerId = managerId; - } - - public String getManagercompany() { return managercompany; } - public void setManagercompany(String managercompany) { this.managercompany = managercompany; } - - public String getManagerdepartment() { return managerdepartment; } - public void setManagerdepartment(String managerdepartment) { this.managerdepartment = managerdepartment; } - - public String getOrganization() { return organization; } - public void setOrganization(String organization) { this.organization = organization; } - - public String getRole() { return role; } - public void setRole(String role) { this.role = role; } - - public String getUserName() { return userName; } - public void setUserName(String userName) { this.userName = userName; } - - public String getAssistant() { return assistant; } - public void setAssistant(String assistant) { - this.assistant = assistant; - } - - public String getNotice() { - return notice; - } - - public void setNotice(String notice) { - this.notice = notice; - } - - public LocalDateTime getCreated_at() { return created_at; } - public void setCreated_at(LocalDateTime created_at) { this.created_at = created_at; } - - public LocalDateTime getUpdated_at() { return updated_at; } - public void setUpdated_at(LocalDateTime updated_at) { this.updated_at = updated_at; } - - public Object[] getCustomDetails() { return customDetails; } - public void setCustomDetails(Object[] customDetails) { this.customDetails = customDetails; } - - public String getDataSource() { return dataSource; } - public void setDataSource(String dataSource) { this.dataSource = dataSource; } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/dto/UserProductCartDTO.java b/src/main/java/com/example/web/dto/UserProductCartDTO.java deleted file mode 100644 index 7d3c195..0000000 --- a/src/main/java/com/example/web/dto/UserProductCartDTO.java +++ /dev/null @@ -1,432 +0,0 @@ -package com.example.web.dto; - -import com.example.web.entity.UsersManagements; -import lombok.Data; - - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - - -@Data -public class UserProductCartDTO { - private String userId;//用户id - private String phoneNumber;//用户手机号 - private String type;//用户类型 - private String nickName;//用户昵称 - private String company;//客户公司 - private String region;//客户地区 - private String level;//客户等级 - private String demand;//客户需求 - private String spec;//规格 - private LocalDateTime created_at;//创建时间 - private LocalDateTime updated_at;//更新时间 - private String notice;//通知状态 - private List products= new ArrayList<>();;//产品信息 - private List cartItems= new ArrayList<>();;//购物车信息 - private List usersContacts= new ArrayList<>();;//联系人信息 - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getPhoneNumber() { - return phoneNumber; - } - - public void setPhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getNickName() { - return nickName; - } - - public void setNickName(String nickName) { - this.nickName = nickName; - } - - public String getCompany() { - return company; - } - - public void setCompany(String company) { - this.company = company; - } - - public String getRegion() { - return region; - } - - public void setRegion(String region) { - this.region = region; - } - - public String getLevel() { - return level; - } - - public void setLevel(String level) { - this.level = level; - } - - public String getDemand() { - return demand; - } - - public void setDemand(String demand) { - this.demand = demand; - } - - public String getSpec() { - return spec; - } - - public void setSpec(String spec) { - this.spec = spec; - } - - public String getNotice() { - return notice; - } - - public void setNotice(String notice) { - this.notice = notice; - } - - public LocalDateTime getCreated_at() { - return created_at; - } - - public void setCreated_at(LocalDateTime created_at) { - this.created_at = created_at; - } - - public LocalDateTime getUpdated_at() { - return updated_at; - } - - public void setUpdated_at(LocalDateTime updated_at) { - this.updated_at = updated_at; - } - - public List getProducts() { - return products; - } - - public void setProducts(List products) { - this.products = products; - } - - public List getCartItems() { - return cartItems; - } - - public void setCartItems(List cartItems) { - this.cartItems = cartItems; - } - - public List getUsersContacts() { - return usersContacts; - } - - public void setUsersContacts(List usersContacts) { - this.usersContacts = usersContacts; - } - - @Data - public static class ProductInfo { - private String productName = ""; - private String variety = ""; - private String specification = ""; - private Integer quantity = 0; - private String grossWeight = ""; - private String yolk = ""; - private String productId = ""; - private String price = ""; - private String sellerId = ""; - private String sellerNickName = ""; - private String sellerPhone = ""; - private LocalDateTime created_at; - private LocalDateTime updated_at; - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public String getVariety() { - return variety; - } - - public void setVariety(String variety) { - this.variety = variety; - } - - public String getSpecification() { - return specification; - } - - public void setSpecification(String specification) { - this.specification = specification; - } - - public Integer getQuantity() { - return quantity; - } - - public void setQuantity(Integer quantity) { - this.quantity = quantity; - } - - public String getGrossWeight() { - return grossWeight; - } - - public void setGrossWeight(String grossWeight) { - this.grossWeight = grossWeight; - } - - public String getYolk() { - return yolk; - } - - public void setYolk(String yolk) { - this.yolk = yolk; - } - - public String getProductId() { - return productId; - } - - public void setProductId(String productId) { - this.productId = productId; - } - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } - - public String getSellerId() { - return sellerId; - } - - public void setSellerId(String sellerId) { - this.sellerId = sellerId; - } - - public String getSellerNickName() { - return sellerNickName; - } - - public void setSellerNickName(String sellerNickName) { - this.sellerNickName = sellerNickName; - } - - public String getSellerPhone() { - return sellerPhone; - } - - public void setSellerPhone(String sellerPhone) { - this.sellerPhone = sellerPhone; - } - - public LocalDateTime getCreated_at() { - return created_at; - } - - public void setCreated_at(LocalDateTime created_at) { - this.created_at = created_at; - } - - public LocalDateTime getUpdated_at() { - return updated_at; - } - - public void setUpdated_at(LocalDateTime updated_at) { - this.updated_at = updated_at; - } - } - - @Data - public static class CartItem { - private String cartItemId = ""; // 新增:购物车项唯一标识 - private String productName = ""; - private String variety = ""; - private String specification = ""; - private Integer quantity = 0; - private String grossWeight = ""; - private String yolk = ""; - private String productId = ""; - private String price = ""; - private Boolean selected = false; - private LocalDateTime added_at; - - public String getCartItemId() { - return cartItemId; - } - - public void setCartItemId(String cartItemId) { - this.cartItemId = cartItemId; - } - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public String getSpecification() { - return specification; - } - - public void setSpecification(String specification) { - this.specification = specification; - } - - public Integer getQuantity() { - return quantity; - } - - public void setQuantity(Integer quantity) { - this.quantity = quantity; - } - - public String getGrossWeight() { - return grossWeight; - } - - public void setGrossWeight(String grossWeight) { - this.grossWeight = grossWeight; - } - - public String getYolk() { - return yolk; - } - - public void setYolk(String yolk) { - this.yolk = yolk; - } - - public String getProductId() { - return productId; - } - - public void setProductId(String productId) { - this.productId = productId; - } - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } - - public Boolean getSelected() { - return selected; - } - - public void setSelected(Boolean selected) { - this.selected = selected; - } - - public LocalDateTime getAdded_at() { - return added_at; - } - - public void setAdded_at(LocalDateTime added_at) { - this.added_at = added_at; - } - } - @Data - public static class UsersContacts { - private String contactId = ""; // 新增:联系人唯一标识 - private String wechat = ""; - private String account = ""; - private String accountNumber = ""; - private String bank = ""; - private String address = ""; - - public UsersContacts(String wechat, String account, String accountNumber, String bank, String address) { - this.wechat = wechat; - this.account = account; - this.accountNumber = accountNumber; - this.bank = bank; - this.address = address; - } - public UsersContacts() {} - - public String getContactId() { - return contactId; - } - - public void setContactId(String contactId) { - this.contactId = contactId; - } - - public String getWechat() { - return wechat; - } - - public void setWechat(String wechat) { - this.wechat = wechat; - } - - public String getAccount() { - return account; - } - - public void setAccount(String account) { - this.account = account; - } - - public String getAccountNumber() { - return accountNumber; - } - - public void setAccountNumber(String accountNumber) { - this.accountNumber = accountNumber; - } - - public String getBank() { - return bank; - } - - public void setBank(String bank) { - this.bank = bank; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - } - -} \ No newline at end of file diff --git a/src/main/java/com/example/web/entity/Contacts.java b/src/main/java/com/example/web/entity/Contacts.java index d175e95..d9b792e 100644 --- a/src/main/java/com/example/web/entity/Contacts.java +++ b/src/main/java/com/example/web/entity/Contacts.java @@ -21,6 +21,7 @@ public class Contacts { private String bank;//联系人银行 private String address;//联系人地址 private String followup;//跟进信息 + private LocalDateTime followup_at;//最后跟进时间 private LocalDateTime created_at;//创建时间 private LocalDateTime updated_at;//更新时间 @@ -43,7 +44,7 @@ public class Contacts { public Contacts() { } - public Contacts(String contact_id, String id, String nickName, String phoneNumber, String wechat, String account, String accountNumber, String bank, String address, String followup) { + public Contacts(String contact_id, String id, String nickName, String phoneNumber, String wechat, String account, String accountNumber, String bank, String address, String followup, LocalDateTime followup_at) { this.contact_id = contact_id; this.id = id; this.nickName = nickName; @@ -54,6 +55,7 @@ public class Contacts { this.bank = bank; this.address = address; this.followup = followup; + this.followup_at = followup_at; } public String getContact_id() { @@ -135,4 +137,12 @@ public class Contacts { public void setFollowup(String followup) { this.followup = followup; } + + public LocalDateTime getFollowup_at() { + return followup_at; + } + + public void setFollowup_at(LocalDateTime followup_at) { + this.followup_at = followup_at; + } } diff --git a/src/main/java/com/example/web/entity/CustomerData.java b/src/main/java/com/example/web/entity/CustomerData.java new file mode 100644 index 0000000..6c83852 --- /dev/null +++ b/src/main/java/com/example/web/entity/CustomerData.java @@ -0,0 +1,66 @@ +package com.example.web.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @Description: 客户数据统一实体类,用于WebSocket通信 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CustomerData { + // 基本信息 + private String id; // 客户ID + private String nickName; // 姓名 + private String phoneNumber; // 电话号码 + private String wechat; // 微信号 + private String account; // 账户 + private String accountNumber; // 账号 + private String bank; // 银行 + private String address; // 地址 + private String followup; // 跟进 + private String notice; // 通知状态 + private LocalDateTime followup_at; // 最后跟进时间 + private LocalDateTime created_at; // 创建时间 + private LocalDateTime updated_at; // 更新时间 + + // 企业信息 + private String company; // 客户公司 + private String region; // 客户地区 + private String level; // 客户等级 + private String type; // 客户类型 + private String demand; // 客户需求 + private String spec; // 规格 + + // 负责人信息 + private String managercompany; // 负责人公司 + private String managerdepartment; // 负责人部门 + private String organization; // 负责人组织 + private String projectName; // 职位 + private String userName; // 负责人姓名 + private String assistant; // 协助人 + private String role; // 用户角色 + + // 产品收藏信息 + private List favorites; // 收藏的产品列表 + + /** + * 产品收藏内部类 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ProductFavorite { + private String productName; // 产品名称 + private String price; // 价格 + private String quantity; // 数量 + private String grossWeight; // 毛重 + private String yolk; // 蛋黄 + private LocalDateTime favoriteDate; // 收藏时间 + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/entity/Favorites.java b/src/main/java/com/example/web/entity/Favorites.java new file mode 100644 index 0000000..852f20a --- /dev/null +++ b/src/main/java/com/example/web/entity/Favorites.java @@ -0,0 +1,52 @@ +package com.example.web.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @Description: 用户收藏实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Favorites { + private Integer id; // 控制唯一值 + private String user_phone; // 用户手机号 + private String productId; // 产品ID + private LocalDateTime date; // 收藏的时间 + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUser_phone() { + return user_phone; + } + + public void setUser_phone(String user_phone) { + this.user_phone = user_phone; + } + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public LocalDateTime getDate() { + return date; + } + + public void setDate(LocalDateTime date) { + this.date = date; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/entity/InformationTra.java b/src/main/java/com/example/web/entity/InformationTra.java index 39c6248..f095809 100644 --- a/src/main/java/com/example/web/entity/InformationTra.java +++ b/src/main/java/com/example/web/entity/InformationTra.java @@ -15,6 +15,9 @@ public class InformationTra { private LocalDateTime operationTime; private LocalDateTime createdAt; private LocalDateTime updatedAt; + private String originalData; // 原始数据JSON + private String modifiedData; // 修改后数据JSON + private String changedFields; // 变更字段列表JSON // Getters and Setters public Integer getId() { @@ -112,4 +115,28 @@ public class InformationTra { public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } + + public String getOriginalData() { + return originalData; + } + + public void setOriginalData(String originalData) { + this.originalData = originalData; + } + + public String getModifiedData() { + return modifiedData; + } + + public void setModifiedData(String modifiedData) { + this.modifiedData = modifiedData; + } + + public String getChangedFields() { + return changedFields; + } + + public void setChangedFields(String changedFields) { + this.changedFields = changedFields; + } } \ No newline at end of file diff --git a/src/main/java/com/example/web/entity/Login.java b/src/main/java/com/example/web/entity/Login.java index 36a0dcf..293d806 100644 --- a/src/main/java/com/example/web/entity/Login.java +++ b/src/main/java/com/example/web/entity/Login.java @@ -15,6 +15,10 @@ public class Login { private String userName;//用户名 private String password;//密码 private Integer id;//用户id + private String managerId;//负责人ID + private String managercompany; // 负责人公司 + private String managerdepartment; // 负责人部门 + private String organization; // 负责人组织 public String getProjectName() { @@ -48,4 +52,36 @@ public class Login { public void setUserName(String userName) { this.userName = userName; } + + public String getManagerId() { + return managerId; + } + + public void setManagerId(String managerId) { + this.managerId = managerId; + } + + public String getManagercompany() { + return managercompany; + } + + public void setManagercompany(String managercompany) { + this.managercompany = managercompany; + } + + public String getManagerdepartment() { + return managerdepartment; + } + + public void setManagerdepartment(String managerdepartment) { + this.managerdepartment = managerdepartment; + } + + public String getOrganization() { + return organization; + } + + public void setOrganization(String organization) { + this.organization = organization; + } } diff --git a/src/main/java/com/example/web/entity/Notification.java b/src/main/java/com/example/web/entity/Notification.java new file mode 100644 index 0000000..d19dbec --- /dev/null +++ b/src/main/java/com/example/web/entity/Notification.java @@ -0,0 +1,23 @@ +package com.example.web.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 通知实体类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Notification { + private Long id; + private String title; + private String message; + private String type; + private String userId; + private boolean read; + private LocalDateTime created_at; +} \ No newline at end of file diff --git a/src/main/java/com/example/web/entity/Personnel.java b/src/main/java/com/example/web/entity/Personnel.java new file mode 100644 index 0000000..c2add57 --- /dev/null +++ b/src/main/java/com/example/web/entity/Personnel.java @@ -0,0 +1,28 @@ +package com.example.web.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.sql.Timestamp; + +/** + * @Description: 员工信息实体类 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Personnel { + private Integer id; // 员工ID + private String managerId; // 负责人ID + private String managercompany; // 负责公司 + private String managerdepartment; // 负责部门 + private String organization; // 负责小组 + private String projectName; // 职位名称 + private String alias; // 负责人别名 + private String name; // 负责人名 + private String phoneNumber; // 负责人电话 + private Timestamp createdAt; // 创建时间 + private Timestamp updatedAt; // 更新时间 + private String avatarUrl; // 头像 +} diff --git a/src/main/java/com/example/web/entity/Users.java b/src/main/java/com/example/web/entity/Users.java index bfe9b9a..e14826c 100644 --- a/src/main/java/com/example/web/entity/Users.java +++ b/src/main/java/com/example/web/entity/Users.java @@ -34,8 +34,9 @@ public class Users { private String spec;//规格 private String followup;//跟进信息 private String notice;//通知状态 + private LocalDateTime followup_at;//最后跟进时间 - public Users(Integer id, String openid, String userId, String nickName, String avatarUrl, String phoneNumber, String type, Integer gender, String country, String province, String city, String language, String session_key, LocalDateTime created_at, LocalDateTime updated_at, String company, String region, String level, String demand, String spec, String followup, String notice) { + public Users(Integer id, String openid, String userId, String nickName, String avatarUrl, String phoneNumber, String type, Integer gender, String country, String province, String city, String language, String session_key, LocalDateTime created_at, LocalDateTime updated_at, String company, String region, String level, String demand, String spec, String followup, String notice, LocalDateTime followup_at) { this.id = id; this.openid = openid; this.userId = userId; @@ -58,6 +59,7 @@ public class Users { this.spec = spec; this.followup = followup; this.notice = notice; + this.followup_at = followup_at; } public Integer getId() { @@ -235,4 +237,12 @@ public class Users { public void setNotice(String notice) { this.notice = notice; } + + public LocalDateTime getFollowup_at() { + return followup_at; + } + + public void setFollowup_at(LocalDateTime followup_at) { + this.followup_at = followup_at; + } } diff --git a/src/main/java/com/example/web/entity/UsersContacts.java b/src/main/java/com/example/web/entity/UsersContacts.java index 936c747..37d7e86 100644 --- a/src/main/java/com/example/web/entity/UsersContacts.java +++ b/src/main/java/com/example/web/entity/UsersContacts.java @@ -1,14 +1,14 @@ package com.example.web.entity; import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Data +@NoArgsConstructor public class UsersContacts { private String userId;//用户id private String id;//联系人id - private String nickName;//联系人姓名 - private String phoneNumber;//联系人电话 private String wechat;//联系人微信 private String account;//联系人账号 private String accountNumber;//联系人账号 @@ -18,11 +18,9 @@ public class UsersContacts { private LocalDateTime updated_at;//更新时间 - public UsersContacts(String userId, String id, String nickName, String phoneNumber, String wechat, String account, String accountNumber, String bank, String address, LocalDateTime created_at, LocalDateTime updated_at) { + public UsersContacts(String userId, String id, String wechat, String account, String accountNumber, String bank, String address, LocalDateTime created_at, LocalDateTime updated_at) { this.userId = userId; this.id = id; - this.nickName = nickName; - this.phoneNumber = phoneNumber; this.wechat = wechat; this.account = account; this.accountNumber = accountNumber; @@ -48,22 +46,6 @@ public class UsersContacts { this.id = id; } - public String getNickName() { - return nickName; - } - - public void setNickName(String nickName) { - this.nickName = nickName; - } - - public String getPhoneNumber() { - return phoneNumber; - } - - public void setPhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - public String getWechat() { return wechat; } diff --git a/src/main/java/com/example/web/mapper/ContactsMapper.java b/src/main/java/com/example/web/mapper/ContactsMapper.java index e560bc6..550dd6d 100644 --- a/src/main/java/com/example/web/mapper/ContactsMapper.java +++ b/src/main/java/com/example/web/mapper/ContactsMapper.java @@ -6,6 +6,7 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; +import java.time.LocalDateTime; import java.util.List; @Mapper @@ -30,6 +31,6 @@ public interface ContactsMapper { String getFollowUpByPhone(@Param("phoneNumber") String phoneNumber); // 更新跟进信息 - @Update("UPDATE contacts SET followup = #{followup} WHERE phoneNumber = #{phoneNumber}") - int updateFollowUpByPhone(@Param("phoneNumber") String phoneNumber, @Param("followup") String followup); + @Update("UPDATE contacts SET followup = #{followup}, updated_at = #{updatedAt} WHERE phoneNumber = #{phoneNumber}") + int updateFollowUpByPhone(@Param("phoneNumber") String phoneNumber, @Param("followup") String followup, @Param("updatedAt") LocalDateTime updatedAt); } diff --git a/src/main/java/com/example/web/mapper/CustomerMapper.java b/src/main/java/com/example/web/mapper/CustomerMapper.java new file mode 100644 index 0000000..d8afb8c --- /dev/null +++ b/src/main/java/com/example/web/mapper/CustomerMapper.java @@ -0,0 +1,136 @@ +package com.example.web.mapper; + +import com.example.web.annotation.DataSource; +import com.example.web.entity.Contacts; +import com.example.web.entity.Enterprise; +import com.example.web.entity.Managers; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: 客户数据Mapper接口(primary数据源) + */ +@Mapper +@DataSource("primary") +public interface CustomerMapper { + + /** + * 获取所有联系人信息 + * @return 联系人列表 + */ + List getAllContacts(); + + /** + * 根据联系人ID获取企业信息 + * @param contactId 联系人ID + * @return 企业信息 + */ + Enterprise getEnterpriseByContactId(@Param("contactId") String contactId); + + /** + * 根据联系人ID获取负责人信息 + * @param contactId 联系人ID + * @return 负责人信息 + */ + Managers getManagerByContactId(@Param("contactId") String contactId); + + /** + * 获取部门公海池数据 + * @param role 用户角色(buyer/seller) + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @return 部门公海池客户数据 + */ + List getDepartmentSeaPoolContacts( + @Param("role") String role, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment); + + /** + * 获取组织公海池数据 + * @param role 用户角色(buyer/seller) + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @param organization 负责人组织 + * @return 组织公海池客户数据 + */ + List getOrganizationSeaPoolContacts( + @Param("role") String role, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment, + @Param("organization") String organization); + + /** + * 插入企业信息 + * @param enterprise 企业信息 + * @return 插入结果 + */ + int insertEnterprise(Enterprise enterprise); + + /** + * 插入联系人信息 + * @param contacts 联系人信息 + * @return 插入结果 + */ + int insertContacts(Contacts contacts); + + /** + * 插入负责人信息 + * @param managers 负责人信息 + * @return 插入结果 + */ + int insertManagers(Managers managers); + + /** + * 根据电话号码获取联系人信息 + * @param phoneNumber 电话号码 + * @return 联系人信息 + */ + Contacts getContactsByPhoneNumber(@Param("phoneNumber") String phoneNumber); + + /** + * 根据ID获取联系人信息 + * @param id 联系人ID + * @return 联系人信息 + */ + Contacts getContactsById(@Param("id") String id); + + /** + * 更新联系人信息 + * @param contacts 联系人信息 + * @return 更新结果 + */ + int updateContacts(Contacts contacts); + + /** + * 更新企业信息 + * @param enterprise 企业信息 + * @return 更新结果 + */ + int updateEnterprise(Enterprise enterprise); + + /** + * 根据角色和登录信息获取客户数据 + * @param role 角色 + * @param userName 用户名 + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @param organization 负责人组织 + * @return 客户数据列表 + */ + List getCustomersByRole( + @Param("role") String role, + @Param("userName") String userName, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment, + @Param("organization") String organization); + + /** + * 更新负责人信息 + * @param managers 负责人信息 + * @return 更新结果 + */ + int updateManagers(Managers managers); +} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/EnterpriseMapper.java b/src/main/java/com/example/web/mapper/EnterpriseMapper.java deleted file mode 100644 index e61c412..0000000 --- a/src/main/java/com/example/web/mapper/EnterpriseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.entity.Enterprise; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface EnterpriseMapper { - - // 查询所有企业及其联系人和负责人信息 - List selectAllEnterpriseInfo(); - - // 根据企业ID查询详细信息 - EnterpriseInfoDTO selectEnterpriseInfoById(String id); - - // 查询所有企业基本信息 - List selectAllEnterprises(); - // 新增企业 - int insertEnterprise(Enterprise enterprise); - //编辑修改 - int updateEnterprise(Enterprise enterprise); -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/InformationTraMapper.java b/src/main/java/com/example/web/mapper/InformationTraMapper.java index 2261831..c2b7422 100644 --- a/src/main/java/com/example/web/mapper/InformationTraMapper.java +++ b/src/main/java/com/example/web/mapper/InformationTraMapper.java @@ -1,18 +1,20 @@ package com.example.web.mapper; +import com.example.web.annotation.DataSource; import com.example.web.entity.InformationTra; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; +/** + * @Description: 信息跟踪Mapper接口 + */ @Mapper +@DataSource("wechat") public interface InformationTraMapper { + /** - * 插入操作记录 + * 插入信息跟踪记录 + * @param informationTra 信息跟踪记录 + * @return 插入结果 */ int insertInformationTra(InformationTra informationTra); - - /** - * 根据userId查询操作记录 - */ - InformationTra selectByUserId(@Param("userId") String userId); -} \ No newline at end of file +} diff --git a/src/main/java/com/example/web/mapper/LoginMapper.java b/src/main/java/com/example/web/mapper/LoginMapper.java index 59a7ef9..89c90a9 100644 --- a/src/main/java/com/example/web/mapper/LoginMapper.java +++ b/src/main/java/com/example/web/mapper/LoginMapper.java @@ -5,18 +5,18 @@ import com.example.web.entity.Login; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import java.util.List; - +/** + * @Description: 登录Mapper接口 + * @TableName: login + */ @Mapper @DataSource("primary") public interface LoginMapper { - - - // 移除 @Select 注解,使用 XML 配置 - Login findByProjectNameAndUserName(@Param("projectName") String projectName, - @Param("userName") String userName); - - // 新增方法 - 支持动态查询 - List findByConditions(@Param("projectName") String projectName, - @Param("userName") String userName); + /** + * 根据用户名和工位名查询用户 + * @param userName 用户名 + * @param projectName 工位名 + * @return Login对象 + */ + Login selectByUserNameAndProjectName(@Param("userName") String userName, @Param("projectName") String projectName); } \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/PersonnelMapper.java b/src/main/java/com/example/web/mapper/PersonnelMapper.java new file mode 100644 index 0000000..b412e9f --- /dev/null +++ b/src/main/java/com/example/web/mapper/PersonnelMapper.java @@ -0,0 +1,21 @@ +package com.example.web.mapper; + +import com.example.web.annotation.DataSource; +import com.example.web.entity.Personnel; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: 员工信息Mapper接口 + * @TableName: personnel + */ +@Mapper +@DataSource("primary") +public interface PersonnelMapper { + /** + * 根据负责人ID查询员工信息 + * @param managerId 负责人ID + * @return Personnel对象 + */ + Personnel selectByManagerId(@Param("managerId") String managerId); +} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/SupplyCart_itemsMapper.java b/src/main/java/com/example/web/mapper/SupplyCart_itemsMapper.java deleted file mode 100644 index 5441a23..0000000 --- a/src/main/java/com/example/web/mapper/SupplyCart_itemsMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -@DataSource("wechat") -public interface SupplyCart_itemsMapper { - -} diff --git a/src/main/java/com/example/web/mapper/SupplyContactsMapper.java b/src/main/java/com/example/web/mapper/SupplyContactsMapper.java deleted file mode 100644 index e672326..0000000 --- a/src/main/java/com/example/web/mapper/SupplyContactsMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.entity.Contacts; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SupplyContactsMapper { - - // 根据企业ID查询联系人信息 - List selectContactsByEnterpriseId(String id); - - // 查询所有联系人信息 - List selectAllContacts(); - // 新增联系人 - int insertContacts(Contacts contacts); - // 新增:根据电话号码查询记录数(用于判断是否重复) - int countByPhoneNumber(String phoneNumber); - // 新增:根据手机号查询联系人(关联企业信息) - Contacts selectByPhoneNumber(String phoneNumber); - // 修改编辑功能 - int updateContacts(Contacts contacts); -} diff --git a/src/main/java/com/example/web/mapper/SupplyEnterpriseMapper.java b/src/main/java/com/example/web/mapper/SupplyEnterpriseMapper.java deleted file mode 100644 index 47f7eb9..0000000 --- a/src/main/java/com/example/web/mapper/SupplyEnterpriseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.entity.Enterprise; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SupplyEnterpriseMapper { - - // 查询所有企业及其联系人和负责人信息 - List selectAllEnterpriseInfo(); - - // 根据企业ID查询详细信息 - EnterpriseInfoDTO selectEnterpriseInfoById(String id); - - // 查询所有企业基本信息 - List selectAllEnterprises(); - // 新增企业 - int insertEnterprise(Enterprise enterprise); - //编辑修改 - int updateEnterprise(Enterprise enterprise); -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/SupplyManagersMapper.java b/src/main/java/com/example/web/mapper/SupplyManagersMapper.java deleted file mode 100644 index 19cd8d0..0000000 --- a/src/main/java/com/example/web/mapper/SupplyManagersMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.entity.Managers; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -@Mapper -public interface SupplyManagersMapper { - List selectManagersByEnterpriseId(String id); - - // 查询所有负责人信息 - List selectAllManagers(); - - // 新增负责人 - int insertManagers(Managers managers); - - //编辑修改 - int updateManagers(Managers managers); - - // 根据负责人姓名查询 - List selectByUserName(@Param("userName") String userName); - - // 🔥 新增:根据用户名和managerId查询 - List selectByUserNameAndManagerId(@Param("userName") String userName, - @Param("managerId") String managerId); -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/SupplyProductsMapper.java b/src/main/java/com/example/web/mapper/SupplyProductsMapper.java deleted file mode 100644 index 91768a5..0000000 --- a/src/main/java/com/example/web/mapper/SupplyProductsMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -@DataSource("wechat") -public interface SupplyProductsMapper { - - - -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/SupplyUsersManagementsMapper.java b/src/main/java/com/example/web/mapper/SupplyUsersManagementsMapper.java deleted file mode 100644 index 3044876..0000000 --- a/src/main/java/com/example/web/mapper/SupplyUsersManagementsMapper.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.entity.UsersManagements; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 负责人信息Mapper接口 - * 对应wechat_app数据源中的负责人信息表操作 - * 使用@DataSource("wechat")注解指定数据源 - */ -@Mapper -@DataSource("wechat") -public interface SupplyUsersManagementsMapper { - // 负责人信息相关的数据库操作方法将在这里定义 - - // 🔥 新增:根据用户名和managerId查询 - List findByUserNameAndManagerId(@Param("userName") String userName, - @Param("managerId") String managerId); - - // 新增方法 - List findByDepartment(@Param("department") String department); - - List findByConditions(@Param("userName") String userName, - @Param("department") String department, - @Param("company") String company, - @Param("role") String role); - /** - * 根据用户ID查询负责人信息 - */ - UsersManagements findByUserId(@Param("userId") String userId); - - /** - * 插入负责人信息 - */ - int insertUsersManagements(UsersManagements usersManagements); - - /** - * 更新负责人信息 - */ - int updateUsersManagements(UsersManagements usersManagements); - - // 🔥 新增:更新负责人信息的更新时间(不改变负责人本身) - boolean updateManagerUpdateTime(@Param("userId") String userId, @Param("updatedAt") LocalDateTime updatedAt); - - // 🔥 新增:查询指定客户的完整负责人信息 - UsersManagements findCompleteManagerInfoByUserId(String userId); - - // 新增:根据用户ID和认证信息直接查询匹配的负责人 - UsersManagements findByUserIdAndAuthInfo(@Param("userId") String userId, - @Param("authInfo") ManagerAuthInfo authInfo); - - // 新增:批量查询用户权限 - List findAuthorizedUserIds(@Param("authInfo") ManagerAuthInfo authInfo); - - // 🔥 新增:批量查询用户负责人信息 - List findByUserIds(@Param("userIds") List userIds); - -} diff --git a/src/main/java/com/example/web/mapper/SupplyUsersMapper.java b/src/main/java/com/example/web/mapper/SupplyUsersMapper.java deleted file mode 100644 index c39ce85..0000000 --- a/src/main/java/com/example/web/mapper/SupplyUsersMapper.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UserProductCartDTO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - - -import java.time.LocalDateTime; -import java.util.List; - -@Mapper -@DataSource("wechat") -public interface SupplyUsersMapper { - // 获取用户基本信息 - UserProductCartDTO getUserBasicInfo(@Param("userId") String userId); - - // 获取卖家的产品信息 - List getSellerProducts(@Param("sellerId") String sellerId); - - - /** - * 获取所有用户的基本信息 - */ - List getAllUserBasicInfo(); - - // 新增根据手机号查询用户的方法 - UserProductCartDTO selectByPhone(@Param("phoneNumber") String phoneNumber); - - // 新增:根据用户ID精确查询用户 - UserProductCartDTO selectByUserId(@Param("userId") String userId); - - // 新增:更新公海需求信息 - int updateProduct( - @Param("sellerId") String sellerId, - @Param("productId") String productId, - @Param("product") UserProductCartDTO.ProductInfo product - ); - - /** - * 根据手机号更新用户信息 - */ - int updateByPhone(UserProductCartDTO user); - - /** - * 更新卖家产品信息 - */ - int updateProductBySellerId( - @Param("sellerId") String sellerId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - - /** - * 更新用户联系人信息 - 更新第一个联系人(向后兼容) - */ - int updateContactsByUserId( - @Param("userId") String userId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 获取用户联系人信息 - 获取第一个联系人(向后兼容) - */ - List getUserContacts(@Param("userId") String userId); - - /** - * 更新或插入联系人信息 - */ - int updateOrInsertContact( - @Param("userId") String userId, - @Param("contactId") String contactId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 采购端:更新或插入产品信息(类似购物车的updateOrInsertCartItem) - */ - int updateOrInsertProduct( - @Param("sellerId") String sellerId, - @Param("productId") String productId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk, - @Param("price") String price - ); - - /** - * 更新特定联系人信息 - 一对多逻辑新增 - */ - int updateSpecificContact( - @Param("userId") String userId, - @Param("contactId") String contactId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 采购端:更新特定产品信息 - 一对多逻辑新增 - */ - int updateSpecificProduct( - @Param("sellerId") String sellerId, - @Param("productId") String productId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - /** - * 获取用户所有联系人 - 一对多逻辑新增 - */ - List getUserAllContacts(@Param("userId") String userId); - - - /** - * 采购端:获取用户所有产品信息 - 一对多逻辑新增 - */ - List getUserAllProducts(@Param("sellerId") String sellerId); - - // 联系人信息内部类 - 用于一对多查询 - class ContactInfo { - private String contactId; - private String userId; - private String wechat; - private String account; - private String accountNumber; - private String bank; - private String address; - - public String getContactId() { return contactId; } - public void setContactId(String contactId) { this.contactId = contactId; } - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getWechat() { return wechat; } - public void setWechat(String wechat) { this.wechat = wechat; } - public String getAccount() { return account; } - public void setAccount(String account) { this.account = account; } - public String getAccountNumber() { return accountNumber; } - public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } - public String getBank() { return bank; } - public void setBank(String bank) { this.bank = bank; } - public String getAddress() { return address; } - public void setAddress(String address) { this.address = address; } - } - - // 产品信息内部类 - 用于一对多查询 - class ProductInfo { - private String productId; - private String userId; - private String productName; - private String variety; - private String specification; - private Integer quantity; - private String grossWeight; - private String yolk; - - public String getProductId() { return productId; } - public void setProductId(String productId) { this.productId = productId; } - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getProductName() { return productName; } - public void setProductName(String productName) { this.productName = productName; } - public String getVariety() { return variety; } - public void setVariety(String variety) { this.variety = variety; } - public String getSpecification() { return specification; } - public void setSpecification(String specification) { this.specification = specification; } - public Integer getQuantity() { return quantity; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } - public String getGrossWeight() { return grossWeight; } - public void setGrossWeight(String grossWeight) { this.grossWeight = grossWeight; } - public String getYolk() { return yolk; } - public void setYolk(String yolk) { this.yolk = yolk; } - } - /** - * 根据产品ID精确更新产品信息 - */ - int updateProductByProductId( - @Param("productId") String productId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - // 在 SupplyUsersMapper.java 中添加以下方法 - - /** - * 查询超过指定时间的未分级客户 - */ - List findUnclassifiedCustomersOlderThan(LocalDateTime thresholdTime); - - /** - * 查询超过指定时间的组织公海池客户 - */ - List findOrganizationSeaPoolsCustomersOlderThan(LocalDateTime thresholdTime); - - /** - * 更新客户等级 - */ - @Update("UPDATE users SET level = #{level}, updated_at = #{updateTime} WHERE user_id = #{userId}") - boolean updateCustomerLevel(@Param("userId") String userId, - @Param("level") String level, - @Param("updateTime") LocalDateTime updateTime); - // 🔥 新增:查询最近回流的客户 - List findRecentlyRecycledCustomers(@Param("sinceTime") LocalDateTime sinceTime); - - // 新增:直接查询有权限的客户列表(支持分页) - List getAuthorizedCustomers(@Param("authInfo") ManagerAuthInfo authInfo, @Param("limit") int limit, @Param("offset") int offset); - - /** - * 根据认证信息获取有权限的用户ID列表 - */ - List getAuthorizedUserIds(@Param("authInfo") ManagerAuthInfo authInfo); - - // 获取授权客户总数 - int getAuthorizedCustomersCount(@Param("authInfo") ManagerAuthInfo authInfo); - - /** - * 根据手机号和权限查询用户 - */ - UserProductCartDTO selectByPhoneWithAuth(@Param("phoneNumber") String phoneNumber, - @Param("authInfo") ManagerAuthInfo authInfo); - - // 🔥 新增:批量查询用户联系人信息 - List getUserContactsByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:批量查询用户产品信息 - List getSellerProductsByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:批量查询用户基本信息 - List getUserBasicInfoByUserIds(@Param("userIds") List userIds); - - // 查询跟进信息 - @Select("SELECT followup FROM users WHERE phoneNumber = #{phoneNumber}") - String getFollowUpByPhone(@Param("phoneNumber") String phoneNumber); - - // 更新跟进信息 - @Update("UPDATE users SET followup = #{followup} WHERE phoneNumber = #{phoneNumber}") - int updateFollowUpByPhone(@Param("phoneNumber") String phoneNumber, @Param("followup") String followup); - - // 🔥 新增:更新用户通知状态 - @Update("UPDATE users SET notice = #{notice} WHERE userId = #{userId}") - int updateNotice(@Param("userId") String userId, @Param("notice") String notice); -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/UsersManagementsMapper.java b/src/main/java/com/example/web/mapper/UsersManagementsMapper.java deleted file mode 100644 index 09a248c..0000000 --- a/src/main/java/com/example/web/mapper/UsersManagementsMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.entity.UsersManagements; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 负责人信息Mapper接口 - * 对应wechat_app数据源中的负责人信息表操作 - * 使用@DataSource("wechat")注解指定数据源 - */ -@Mapper -@DataSource("wechat") -public interface UsersManagementsMapper { - // 负责人信息相关的数据库操作方法将在这里定义 - - // 🔥 新增:根据用户名和managerId查询 - List findByUserNameAndManagerId(@Param("userName") String userName, - @Param("managerId") String managerId); - - // 新增方法 - List findByDepartment(@Param("department") String department); - - List findByConditions(@Param("userName") String userName, - @Param("department") String department, - @Param("company") String company, - @Param("role") String role); - /** - * 根据用户ID查询负责人信息 - */ - UsersManagements findByUserId(@Param("userId") String userId); - - /** - * 插入负责人信息 - */ - int insertUsersManagements(UsersManagements usersManagements); - - /** - * 更新负责人信息 - */ - int updateUsersManagements(UsersManagements usersManagements); - - // 🔥 新增:更新负责人信息的更新时间(不改变负责人本身) - boolean updateManagerUpdateTime(@Param("userId") String userId, @Param("updatedAt") LocalDateTime updatedAt); - - // 🔥 新增:查询指定客户的完整负责人信息 - UsersManagements findCompleteManagerInfoByUserId(String userId); - - // 新增:根据用户ID和认证信息直接查询匹配的负责人 - UsersManagements findByUserIdAndAuthInfo(@Param("userId") String userId, - @Param("authInfo") ManagerAuthInfo authInfo); - - // 新增:批量查询用户权限 - List findAuthorizedUserIds(@Param("authInfo") ManagerAuthInfo authInfo); - - // 🔥 新增:批量查询用户负责人信息 - List findByUserIds(@Param("userIds") List userIds); -} diff --git a/src/main/java/com/example/web/mapper/UsersMapper.java b/src/main/java/com/example/web/mapper/UsersMapper.java deleted file mode 100644 index d22c6a2..0000000 --- a/src/main/java/com/example/web/mapper/UsersMapper.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.example.web.mapper; - -import com.example.web.annotation.DataSource; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UserProductCartDTO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; - - -import java.time.LocalDateTime; -import java.util.List; - -@Mapper -@DataSource("wechat") -public interface UsersMapper { - // 获取用户基本信息 - UserProductCartDTO getUserBasicInfo(@Param("userId") String userId); - - // 获取卖家的产品信息 - List getSellerProducts(@Param("sellerId") String sellerId); - - // 销售端:获取买家的购物车信息(公海需求) - List getBuyerCartItems(@Param("userId") String userId); - - /** - * 销售端:获取所有买家用户的基本信息(类型为buyer和both) - */ - List getAllUserBasicInfo(); - - // 销售端:根据手机号查询买家用户 - UserProductCartDTO selectByPhone(@Param("phoneNumber") String phoneNumber); - - // 新增:根据用户ID精确查询用户 - UserProductCartDTO selectByUserId(@Param("userId") String userId); - - // 新增:更新公海需求信息 - int updateProduct( - @Param("sellerId") String sellerId, - @Param("productId") String productId, - @Param("product") UserProductCartDTO.ProductInfo product - ); - - /** - * 根据手机号更新用户信息 - */ - int updateByPhone(UserProductCartDTO user); - - /** - * 更新卖家产品信息 - */ - int updateProductBySellerId( - @Param("sellerId") String sellerId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - /** - * 销售端:更新买家购物车信息 - 更新第一个购物车项(向后兼容) - */ - int updateCartItemByBuyerId( - @Param("buyerId") String buyerId, - @Param("productId") String productId, - @Param("productName") String productName, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - /** - * 更新用户联系人信息 - 更新第一个联系人(向后兼容) - */ - int updateContactsByUserId( - @Param("userId") String userId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 获取用户联系人信息 - 获取第一个联系人(向后兼容) - */ - List getUserContacts(@Param("userId") String userId); - - /** - * 更新或插入联系人信息 - */ - int updateOrInsertContact( - @Param("userId") String userId, - @Param("contactId") String contactId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 更新或插入购物车项 - */ - int updateOrInsertCartItem( - @Param("userId") String userId, - @Param("cartItemId") String cartItemId, - @Param("productId") String productId, - @Param("productName") String productName, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - /** - * 更新特定联系人信息 - 一对多逻辑新增 - */ - int updateSpecificContact( - @Param("userId") String userId, - @Param("contactId") String contactId, - @Param("wechat") String wechat, - @Param("account") String account, - @Param("accountNumber") String accountNumber, - @Param("bank") String bank, - @Param("address") String address - ); - - /** - * 更新特定购物车项信息 - 一对多逻辑新增 - */ - int updateSpecificCartItem( - @Param("userId") String userId, - @Param("cartItemId") String cartItemId, - @Param("productId") String productId, - @Param("productName") String productName, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - - /** - * 获取用户所有联系人 - 一对多逻辑新增 - */ - List getUserAllContacts(@Param("userId") String userId); - - /** - * 获取用户所有购物车项 - 一对多逻辑新增 - */ - List getUserAllCartItems(@Param("userId") String userId); - - // 联系人信息内部类 - 用于一对多查询 - class ContactInfo { - private String contactId; - private String userId; - private String wechat; - private String account; - private String accountNumber; - private String bank; - private String address; - - public String getContactId() { return contactId; } - public void setContactId(String contactId) { this.contactId = contactId; } - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getWechat() { return wechat; } - public void setWechat(String wechat) { this.wechat = wechat; } - public String getAccount() { return account; } - public void setAccount(String account) { this.account = account; } - public String getAccountNumber() { return accountNumber; } - public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } - public String getBank() { return bank; } - public void setBank(String bank) { this.bank = bank; } - public String getAddress() { return address; } - public void setAddress(String address) { this.address = address; } - } - - // 购物车项内部类 - 用于一对多查询 - class CartItem { - private String cartItemId; - private String userId; - private String productId; - private String productName; - private String specification; - private Integer quantity; - private String grossWeight; - private String yolk; - - public String getCartItemId() { return cartItemId; } - public void setCartItemId(String cartItemId) { this.cartItemId = cartItemId; } - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getProductId() { return productId; } - public void setProductId(String productId) { this.productId = productId; } - public String getProductName() { return productName; } - public void setProductName(String productName) { this.productName = productName; } - public String getSpecification() { return specification; } - public void setSpecification(String specification) { this.specification = specification; } - public Integer getQuantity() { return quantity; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } - public String getGrossWeight() { return grossWeight; } - public void setGrossWeight(String grossWeight) { this.grossWeight = grossWeight; } - public String getYolk() { return yolk; } - public void setYolk(String yolk) { this.yolk = yolk; } - } - /** - * 根据产品ID精确更新产品信息 - */ - int updateProductByProductId( - @Param("productId") String productId, - @Param("productName") String productName, - @Param("variety") String variety, - @Param("specification") String specification, - @Param("quantity") Integer quantity, - @Param("grossWeight") String grossWeight, - @Param("yolk") String yolk - ); - // 在 SupplyUsersMapper.java 中添加以下方法 - - /** - * 查询超过指定时间的未分级客户 - */ - List findUnclassifiedCustomersOlderThan(LocalDateTime thresholdTime); - - /** - * 查询超过指定时间的组织公海池客户 - */ - List findOrganizationSeaPoolsCustomersOlderThan(LocalDateTime thresholdTime); - - /** - * 更新客户等级 - */ - @Update("UPDATE users SET level = #{level}, updated_at = #{updateTime} WHERE user_id = #{userId}") - boolean updateCustomerLevel(@Param("userId") String userId, - @Param("level") String level, - @Param("updateTime") LocalDateTime updateTime); - // 🔥 新增:查询最近回流的客户 - List findRecentlyRecycledCustomers(@Param("sinceTime") LocalDateTime sinceTime); - - // 新增:直接查询有权限的客户列表(支持分页) - List getAuthorizedCustomers(@Param("authInfo") ManagerAuthInfo authInfo, @Param("limit") int limit, @Param("offset") int offset); - - /** - * 根据认证信息获取有权限的用户ID列表 - */ - List getAuthorizedUserIds(@Param("authInfo") ManagerAuthInfo authInfo); - - // 获取授权客户总数 - int getAuthorizedCustomersCount(@Param("authInfo") ManagerAuthInfo authInfo); - - /** - * 根据手机号和权限查询用户 - */ - UserProductCartDTO selectByPhoneWithAuth(@Param("phoneNumber") String phoneNumber, - @Param("authInfo") ManagerAuthInfo authInfo); - - // 🔥 新增:批量查询用户联系人信息 - List getUserContactsByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:批量查询用户购物车信息 - List getBuyerCartItemsByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:批量查询用户购物车信息(兼容旧方法名) - List getCartItemsByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:批量查询用户基本信息 - List getUserBasicInfoByUserIds(@Param("userIds") List userIds); - - // 🔥 新增:更新用户通知状态 - @Update("UPDATE users SET notice = #{notice} WHERE userId = #{userId}") - int updateNotice(@Param("userId") String userId, @Param("notice") String notice); -} \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/WechatCustomerMapper.java b/src/main/java/com/example/web/mapper/WechatCustomerMapper.java new file mode 100644 index 0000000..b11c24c --- /dev/null +++ b/src/main/java/com/example/web/mapper/WechatCustomerMapper.java @@ -0,0 +1,145 @@ +package com.example.web.mapper; + +import com.example.web.annotation.DataSource; +import com.example.web.entity.Favorites; +import com.example.web.entity.Products; +import com.example.web.entity.Users; +import com.example.web.entity.UsersContacts; +import com.example.web.entity.UsersManagements; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: 微信客户数据Mapper接口(wechat数据源) + */ +@Mapper +@DataSource("wechat") +public interface WechatCustomerMapper { + + /** + * 获取所有用户信息 + * @return 用户列表 + */ + List getAllUsers(); + + /** + * 根据用户手机号获取联系人信息 + * @param phoneNumber 用户手机号 + * @return 联系人信息 + */ + UsersContacts getContactsByPhoneNumber(@Param("phoneNumber") String phoneNumber); + + /** + * 根据用户ID获取联系人信息 + * @param userId 用户ID + * @return 联系人信息 + */ + UsersContacts getContactsByUserId(@Param("userId") String userId); + + /** + * 根据用户手机号获取负责人信息 + * @param phoneNumber 用户手机号 + * @return 负责人信息 + */ + UsersManagements getManagementsByPhoneNumber(@Param("phoneNumber") String phoneNumber); + + /** + * 根据用户ID获取负责人信息 + * @param userId 用户ID + * @return 负责人信息 + */ + UsersManagements getManagementsByUserId(@Param("userId") String userId); + + /** + * 根据用户手机号获取收藏的产品ID列表 + * @param userPhone 用户手机号 + * @return 产品收藏列表 + */ + List getFavoritesByUserPhone(@Param("userPhone") String userPhone); + + /** + * 根据产品ID获取产品信息 + * @param productId 产品ID + * @return 产品信息 + */ + Products getProductById(@Param("productId") String productId); + + /** + * 获取部门公海池数据(微信数据源) + * @param role 用户角色(buyer/seller) + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @return 部门公海池客户数据 + */ + List getDepartmentSeaPoolUsers( + @Param("role") String role, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment); + + /** + * 获取组织公海池数据(微信数据源) + * @param role 用户角色(buyer/seller) + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @param organization 负责人组织 + * @return 组织公海池客户数据 + */ + List getOrganizationSeaPoolUsers( + @Param("role") String role, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment, + @Param("organization") String organization); + + /** + * 根据电话号码获取用户信息 + * @param phoneNumber 电话号码 + * @return 用户信息 + */ + Users getUsersByPhoneNumber(@Param("phoneNumber") String phoneNumber); + + /** + * 更新用户信息 + * @param users 用户信息 + * @return 更新结果 + */ + int updateUsers(Users users); + + /** + * 根据角色和登录信息获取客户数据 + * @param role 角色 + * @param userName 用户名 + * @param managercompany 负责人公司 + * @param managerdepartment 负责人部门 + * @param organization 负责人组织 + * @return 客户数据列表 + */ + List getCustomersByRole( + @Param("role") String role, + @Param("userName") String userName, + @Param("managercompany") String managercompany, + @Param("managerdepartment") String managerdepartment, + @Param("organization") String organization); + + /** + * 更新联系人信息 + * @param contacts 联系人信息 + * @return 更新结果 + */ + int updateUsersContacts(UsersContacts contacts); + + /** + * 更新负责人信息 + * @param managements 负责人信息 + * @return 更新结果 + */ + int updateUsersManagements(UsersManagements managements); + + /** + * 根据用户ID获取用户信息 + * @param userId 用户ID + * @return 用户信息 + */ + Users getUsersByUserId(@Param("userId") String userId); +} \ No newline at end of file diff --git a/src/main/java/com/example/web/scheduler/CustomerStatusScheduler.java b/src/main/java/com/example/web/scheduler/CustomerStatusScheduler.java new file mode 100644 index 0000000..9e5ee0c --- /dev/null +++ b/src/main/java/com/example/web/scheduler/CustomerStatusScheduler.java @@ -0,0 +1,203 @@ +package com.example.web.scheduler; + +import com.example.web.entity.Contacts; +import com.example.web.entity.CustomerData; +import com.example.web.entity.Enterprise; +import com.example.web.entity.Users; +import com.example.web.mapper.CustomerMapper; +import com.example.web.mapper.WechatCustomerMapper; +import com.example.web.service.CustomerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; + +/** + * 客户状态流转定时任务 + */ +@Component +public class CustomerStatusScheduler { + + @Autowired + private CustomerService customerService; + + @Autowired + private CustomerMapper customerMapper; + + @Autowired + private WechatCustomerMapper wechatCustomerMapper; + + /** + * 执行客户状态流转 + * 每天凌晨执行 + */ + @Scheduled(cron = "0 0 0 * * ?") + public void executeCustomerStatusFlow() { + System.out.println("DEBUG: 开始执行客户状态流转定时任务,当前时间: " + LocalDateTime.now()); + + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + + // 1. 处理primary数据源 + processPrimaryDataSource(now); + + // 2. 处理wechat数据源 + processWechatDataSource(now); + + System.out.println("DEBUG: 客户状态流转定时任务执行完成,当前时间: " + LocalDateTime.now()); + } + + /** + * 处理primary数据源的客户状态流转 + * @param now 当前时间 + */ + private void processPrimaryDataSource(LocalDateTime now) { + System.out.println("DEBUG: 开始处理primary数据源"); + + // 获取所有联系人 + List contactsList = customerMapper.getAllContacts(); + System.out.println("DEBUG: primary数据源联系人总数: " + contactsList.size()); + + for (Contacts contacts : contactsList) { + try { + // 获取企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getContact_id()); + if (enterprise == null) { + continue; + } + + // 获取客户等级 + String currentLevel = enterprise.getLevel(); + + // 计算跟进时间差 + LocalDateTime followupAt = contacts.getFollowup_at(); + if (followupAt == null) { + followupAt = contacts.getCreated_at(); + } + long daysSinceFollowup = ChronoUnit.DAYS.between(followupAt, now); + + // 状态流转逻辑 + boolean needUpdate = false; + + // 第一次筛选:查找 followup_at ≤ 3天前的客户 + if (daysSinceFollowup >= 3 && "unclassified".equals(currentLevel)) { + // 当前状态为"未分级" → 变更为"组织公海池客户" + enterprise.setLevel("organization-sea-pools"); + needUpdate = true; + System.out.println("DEBUG: primary数据源 - 客户 " + contacts.getNickName() + " 从 未分级 转为 组织公海池客户,已" + daysSinceFollowup + "天未跟进"); + } + + // 第二次筛选:查找 followup_at ≤ 6天前的客户 + if (daysSinceFollowup >= 6 && "organization-sea-pools".equals(currentLevel)) { + // 当前状态为"组织公海池客户" → 变更为"部门公海池" + enterprise.setLevel("department-sea-pools"); + needUpdate = true; + System.out.println("DEBUG: primary数据源 - 客户 " + contacts.getNickName() + " 从 组织公海池客户 转为 部门公海池,已" + daysSinceFollowup + "天未跟进"); + } + + // 如果需要更新,执行更新操作 + if (needUpdate) { + // 更新企业信息 + customerMapper.updateEnterprise(enterprise); + + // 更新联系人的updated_at为当前时间 + contacts.setUpdated_at(now); + customerMapper.updateContacts(contacts); + } + + // 提前一天提醒功能:如果距离回流还有1天,发送通知 + if (daysSinceFollowup == 2 && "unclassified".equals(currentLevel)) { + // 距离转为组织公海池还有1天 + System.out.println("DEBUG: 提醒 - 客户 " + contacts.getNickName() + " 将在明天转为组织公海池,请及时跟进"); + // 这里可以添加通知逻辑,比如发送消息给相关业务员 + } + + if (daysSinceFollowup == 5 && "organization-sea-pools".equals(currentLevel)) { + // 距离转为部门公海池还有1天 + System.out.println("DEBUG: 提醒 - 客户 " + contacts.getNickName() + " 将在明天转为部门公海池,请及时跟进"); + // 这里可以添加通知逻辑,比如发送消息给相关业务员 + } + + } catch (Exception e) { + System.out.println("DEBUG: 处理primary数据源客户 " + contacts.getNickName() + " 时出错: " + e.getMessage()); + e.printStackTrace(); + } + } + + System.out.println("DEBUG: primary数据源处理完成"); + } + + /** + * 处理wechat数据源的客户状态流转 + * @param now 当前时间 + */ + private void processWechatDataSource(LocalDateTime now) { + System.out.println("DEBUG: 开始处理wechat数据源"); + + // 获取所有用户 + List usersList = wechatCustomerMapper.getAllUsers(); + System.out.println("DEBUG: wechat数据源用户总数: " + usersList.size()); + + for (Users user : usersList) { + try { + // 获取客户等级 + String currentLevel = user.getLevel(); + + // 计算跟进时间差 + LocalDateTime followupAt = user.getFollowup_at(); + if (followupAt == null) { + followupAt = user.getCreated_at(); + } + long daysSinceFollowup = ChronoUnit.DAYS.between(followupAt, now); + + // 状态流转逻辑 + boolean needUpdate = false; + + // 第一次筛选:查找 followup_at ≤ 3天前的客户 + if (daysSinceFollowup >= 3 && "unclassified".equals(currentLevel)) { + // 当前状态为"未分级" → 变更为"组织公海池客户" + user.setLevel("organization-sea-pools"); + needUpdate = true; + System.out.println("DEBUG: wechat数据源 - 客户 " + user.getNickName() + " 从 未分级 转为 组织公海池客户,已" + daysSinceFollowup + "天未跟进"); + } + + // 第二次筛选:查找 followup_at ≤ 6天前的客户 + if (daysSinceFollowup >= 6 && "organization-sea-pools".equals(currentLevel)) { + // 当前状态为"组织公海池客户" → 变更为"部门公海池" + user.setLevel("department-sea-pools"); + needUpdate = true; + System.out.println("DEBUG: wechat数据源 - 客户 " + user.getNickName() + " 从 组织公海池客户 转为 部门公海池,已" + daysSinceFollowup + "天未跟进"); + } + + // 如果需要更新,执行更新操作 + if (needUpdate) { + // 更新updated_at为当前时间 + user.setUpdated_at(now); + wechatCustomerMapper.updateUsers(user); + } + + // 提前一天提醒功能:如果距离回流还有1天,发送通知 + if (daysSinceFollowup == 2 && "unclassified".equals(currentLevel)) { + // 距离转为组织公海池还有1天 + System.out.println("DEBUG: 提醒 - 客户 " + user.getNickName() + " 将在明天转为组织公海池,请及时跟进"); + // 这里可以添加通知逻辑,比如发送消息给相关业务员 + } + + if (daysSinceFollowup == 5 && "organization-sea-pools".equals(currentLevel)) { + // 距离转为部门公海池还有1天 + System.out.println("DEBUG: 提醒 - 客户 " + user.getNickName() + " 将在明天转为部门公海池,请及时跟进"); + // 这里可以添加通知逻辑,比如发送消息给相关业务员 + } + + } catch (Exception e) { + System.out.println("DEBUG: 处理wechat数据源客户 " + user.getNickName() + " 时出错: " + e.getMessage()); + e.printStackTrace(); + } + } + + System.out.println("DEBUG: wechat数据源处理完成"); + } +} diff --git a/src/main/java/com/example/web/service/CustomerService.java b/src/main/java/com/example/web/service/CustomerService.java index d550ed9..01a4f31 100644 --- a/src/main/java/com/example/web/service/CustomerService.java +++ b/src/main/java/com/example/web/service/CustomerService.java @@ -1,1328 +1,96 @@ package com.example.web.service; -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Managers; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.*; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; +import com.example.web.entity.CustomerData; +import com.example.web.entity.Login; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Set; - -@Service -@RequiredArgsConstructor -public class CustomerService { - - @Autowired - private ContactsMapper contactsMapper; - - @Autowired - private UsersMapper usersMapper; - - @Autowired - private EnterpriseMapper enterpriseMapper; - - @Autowired - private UsersManagementsMapper usersManagementsMapper; - - @Autowired - private EnterpriseService enterpriseService; - - @Autowired - private PoolCustomerService poolCustomerService; - +import java.util.Map; - // ==================== 精确更新方法 ==================== +/** + * @Description: 客户数据服务接口 + */ +public interface CustomerService { /** - * 精确更新基于电话号码的客户信息 - 支持精确修改特定联系人或购物车项 - * 专门用于公海池客户更新,处理客户等级变化时的负责人信息更新 + * 获取所有客户数据(包括primary和wechat数据源) + * @return 客户数据列表 */ - public boolean updatePhoneBasedCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - validatePhoneNumber(dto.getPhoneNumber()); - - System.out.println("🚀 开始精确更新公海池客户信息,手机号: " + dto.getPhoneNumber()); - - try { - // 1. 验证客户存在性 - UserProductCartDTO existingUser = validateAndGetUser(dto.getPhoneNumber()); - String userId = existingUser.getUserId(); - - // 记录原始等级用于比较 - String originalLevel = existingUser.getLevel(); - String newLevel = dto.getLevel(); - - System.out.println("📊 客户等级变化检查 - 原始: " + originalLevel + ", 新: " + newLevel); - - // 🔥 修复:添加详细的类型转换日志 - System.out.println("🔄 开始类型转换,原始类型: " + dto.getType()); - - // 类型转换逻辑 - String originalType = dto.getType(); - String convertedType = convertCustomerType(originalType); - dto.setType(convertedType); - - System.out.println("🔄 类型转换完成: " + originalType + " → " + convertedType); - - // 2. 权限校验 - System.out.println("🔐 开始权限校验,当前类型: " + dto.getType()); - validateSalesPermission(dto.getType()); - - // 3. 更新用户基本信息 - updateUserBasicInfo(dto, existingUser); - - // 4. 精确更新联系人信息 - updateContactInfoPrecise(dto, userId); - - // 5. 精确更新购物车信息 - updateCartItemInfoPrecise(dto, userId); - - // 6. 检查是否需要生成/更新负责人信息(从公海池变为非公海池)- 传递authInfo - checkAndUpdateManagerInfo(originalLevel, newLevel, dto, userId, authInfo); - - System.out.println("✅ 公海池客户信息精确更新成功"); - return true; - - } catch (Exception e) { - System.err.println("❌ 精确更新公海池客户信息失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("更新公海池客户信息失败: " + e.getMessage(), e); - } - } + List getAllCustomers(); /** - * 统一的客户类型转换方法 + * 获取部门公海池数据 + * @param role 用户角色(buyer/seller) + * @param login 用户登录信息 + * @return 部门公海池客户数据 */ - private String convertCustomerType(String originalType) { - if (originalType == null) { - System.out.println("⚠️ 客户类型为空,使用默认值 buyer"); - return "buyer"; - } - - switch (originalType.toUpperCase()) { - case "BOTH": - case "供应端&BOTH": - System.out.println("🔄 转换 BOTH 类型"); - return "both"; - case "客户端": - case "BUYER": - System.out.println("🔄 转换 buyer 类型"); - return "buyer"; - case "供应端": - case "SELLER": - System.out.println("🔄 转换 seller 类型"); - return "seller"; - default: - System.out.println("⚠️ 未知类型: " + originalType + ",使用原值"); - return originalType; - } - } + List getDepartmentSeaPool(String role, Login login); /** - * 检查并更新负责人信息(当客户从公海池变为非公海池时,或者前端修改了负责人信息时) + * 获取组织公海池数据 + * @param role 用户角色(buyer/seller) + * @param login 用户登录信息 + * @return 组织公海池客户数据 */ - private void checkAndUpdateManagerInfo(String originalLevel, String newLevel, - UnifiedCustomerDTO dto, String userId, ManagerAuthInfo authInfo) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 定义非公海池等级 - Set nonPublicSeaLevels = Set.of("important", "normal", "low-value", "logistics", "unclassified"); - - // 检查是否从公海池变为非公海池 - boolean isFromPublicSeaToNonPublic = publicSeaLevels.contains(originalLevel) && - nonPublicSeaLevels.contains(newLevel); - - // 🔥 新增:检查前端是否修改了负责人信息 - boolean hasFrontendManagerInfo = hasFrontendManagerInfo(dto); - boolean isNonPublicSeaCustomer = nonPublicSeaLevels.contains(newLevel); - - System.out.println("🎯 等级变化分析: " + - "原始=" + originalLevel + - ", 新=" + newLevel + - ", 是否公海池变为非公海池=" + isFromPublicSeaToNonPublic + - ", 是否非公海池客户=" + isNonPublicSeaCustomer + - ", 前端是否提交负责人信息=" + hasFrontendManagerInfo); - - // 🔥 修改条件:公海池变为非公海池 OR (已经是非公海池客户且前端提交了负责人信息) - boolean shouldUpdateManager = isFromPublicSeaToNonPublic || - (isNonPublicSeaCustomer && hasFrontendManagerInfo); - - if (shouldUpdateManager) { - System.out.println("🎯 检测到需要更新负责人信息,开始处理"); - - if (hasFrontendManagerInfo) { - System.out.println("✅ 前端提交了负责人信息,使用前端数据"); - System.out.println("👤 前端负责人信息:"); - System.out.println(" 公司: " + dto.getManagercompany()); - System.out.println(" 部门: " + dto.getManagerdepartment()); - System.out.println(" 组织: " + dto.getOrganization()); - System.out.println(" 角色: " + dto.getRole()); - System.out.println(" 负责人: " + dto.getUserName()); - System.out.println(" 协助人: " + dto.getAssistant()); - } else { - System.out.println("🔄 前端未提交负责人信息,使用当前登录用户信息"); - System.out.println("👤 使用当前登录用户信息填充负责人记录:"); - System.out.println(" 公司: " + authInfo.getManagercompany()); - System.out.println(" 部门: " + authInfo.getManagerdepartment()); - System.out.println(" 组织: " + authInfo.getOrganization()); - System.out.println(" 角色: " + authInfo.getRole()); - System.out.println(" 负责人: " + authInfo.getUserName()); - System.out.println(" 协助人: " + authInfo.getAssistant()); - } - - try { - // 处理负责人信息记录 - 根据是否有前端信息选择数据源 - handleManagerRecord(userId, dto, authInfo, hasFrontendManagerInfo); - System.out.println("✅ 负责人信息处理成功"); - } catch (Exception e) { - System.err.println("❌ 处理负责人信息失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("处理负责人信息失败: " + e.getMessage(), e); - } - } else { - System.out.println("ℹ️ 无需处理负责人信息 - " + - (isFromPublicSeaToNonPublic ? "" : "客户等级未从公海池变为非公海池") + - (hasFrontendManagerInfo && !isNonPublicSeaCustomer ? "且客户不是非公海池客户" : "")); - System.out.println(" 原始等级: " + originalLevel + ", 新等级: " + newLevel); - } - } + List getOrganizationSeaPool(String role, Login login); /** - * 检查前端是否提交了负责人信息 + * 根据用户角色获取客户数据 + * @param role 用户角色(buyer/seller) + * @param login 用户登录信息 + * @return 对应角色的客户数据 */ - private boolean hasFrontendManagerInfo(UnifiedCustomerDTO dto) { - return StringUtils.hasText(dto.getManagercompany()) || - StringUtils.hasText(dto.getManagerdepartment()) || - StringUtils.hasText(dto.getOrganization()) || - StringUtils.hasText(dto.getRole()) || - StringUtils.hasText(dto.getUserName()) || - StringUtils.hasText(dto.getAssistant()); - } - - + List getCustomersByRole(String role, Login login); + /** - * 处理负责人信息记录 - 更新或创建(支持前端数据和登录数据) + * 新增客户数据 + * @param customerData 客户数据,包含企业、联系人和负责人信息 + * @return 是否成功 */ - private void handleManagerRecord(String userId, UnifiedCustomerDTO dto, ManagerAuthInfo authInfo, boolean useFrontendData) { - try { - System.out.println("🔍 开始处理负责人记录,用户ID: " + userId); - System.out.println("📝 数据来源: " + (useFrontendData ? "前端提交" : "登录信息")); - - // 检查是否已存在负责人记录 - UsersManagements existingManager = usersManagementsMapper.findByUserId(userId); - - if (existingManager != null) { - System.out.println("🔄 负责人记录已存在,进行更新"); - // 更新现有记录 - 根据数据来源选择 - updateExistingManagerRecord(existingManager, dto, authInfo, useFrontendData); - } else { - System.out.println("➕ 创建新的负责人记录"); - // 创建新记录 - 根据数据来源选择 - createNewManagerRecord(userId, dto, authInfo, useFrontendData); - } - - // 验证负责人信息是否成功处理 - UsersManagements verifiedManager = usersManagementsMapper.findByUserId(userId); - System.out.println("✅ 负责人信息验证: " + (verifiedManager != null ? "成功" : "失败")); - if (verifiedManager != null) { - System.out.println("📝 验证后的负责人信息: " + - "公司=" + verifiedManager.getManagercompany() + - ", 部门=" + verifiedManager.getManagerdepartment() + - ", 组织=" + verifiedManager.getOrganization() + - ", 角色=" + verifiedManager.getRole() + - ", 负责人=" + verifiedManager.getUserName() + - ", 协助人=" + verifiedManager.getAssistant()); - } - - } catch (Exception e) { - System.err.println("❌ 处理负责人记录失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("处理负责人记录失败: " + e.getMessage(), e); - } - } - + boolean addCustomer(Map customerData); + /** - * 更新现有的负责人记录 - 支持前端数据和登录数据 + * 更新客户数据 + * @param customerData 客户数据,包含企业、联系人和负责人信息,使用电话号码作为唯一标识 + * @param login 登录者信息 + * @return 是否成功 */ - private void updateExistingManagerRecord(UsersManagements existingManager, UnifiedCustomerDTO dto, - ManagerAuthInfo authInfo, boolean useFrontendData) { - if (useFrontendData) { - // 使用前端提交的数据 - existingManager.setManagercompany(getSafeString(dto.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(dto.getManagerdepartment())); - existingManager.setOrganization(getSafeString(dto.getOrganization())); - existingManager.setRole(getSafeString(dto.getRole())); - existingManager.setUserName(getSafeString(dto.getUserName())); - existingManager.setAssistant(getSafeString(dto.getAssistant())); - } else { - // 使用当前登录用户信息 - existingManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - existingManager.setOrganization(getSafeString(authInfo.getOrganization())); - existingManager.setRole(getSafeString(authInfo.getRole())); - existingManager.setUserName(getSafeString(authInfo.getUserName())); - existingManager.setAssistant(getSafeString(authInfo.getAssistant())); - } - - // 确保managerId不为空 - if (existingManager.getManagerId() == null || existingManager.getManagerId().isEmpty()) { - existingManager.setManagerId(authInfo.getManagerId()); - } - - // 确保root不为空 - if (existingManager.getRoot() == null || existingManager.getRoot().isEmpty()) { - existingManager.setRoot("3"); - } - - existingManager.setUpdated_at(LocalDateTime.now()); - - int rows = usersManagementsMapper.updateUsersManagements(existingManager); - System.out.println("✅ 更新负责人记录影响行数: " + rows); - } - - + boolean updateCustomer(Map customerData, Login login); + /** - * 创建新的负责人记录 - 支持前端数据和登录数据 + * 跟进客户 + * @param phoneNumber 客户电话号码 + * @param followupContent 跟进内容 + * @param dataSource 数据源类型(primary/wechat) + * @param login 登录者信息 + * @return 是否成功 */ - private void createNewManagerRecord(String userId, UnifiedCustomerDTO dto, - ManagerAuthInfo authInfo, boolean useFrontendData) { - UsersManagements newManager = new UsersManagements(); - newManager.setUserId(userId); - - if (useFrontendData) { - // 使用前端提交的数据 - newManager.setManagercompany(getSafeString(dto.getManagercompany())); - newManager.setManagerdepartment(getSafeString(dto.getManagerdepartment())); - newManager.setOrganization(getSafeString(dto.getOrganization())); - newManager.setRole(getSafeString(dto.getRole())); - newManager.setUserName(getSafeString(dto.getUserName())); - newManager.setAssistant(getSafeString(dto.getAssistant())); - } else { - // 使用当前登录用户信息 - newManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - newManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - newManager.setOrganization(getSafeString(authInfo.getOrganization())); - newManager.setRole(getSafeString(authInfo.getRole())); - newManager.setUserName(getSafeString(authInfo.getUserName())); - newManager.setAssistant(getSafeString(authInfo.getAssistant())); - } - - newManager.setManagerId(getSafeString(authInfo.getManagerId())); - newManager.setRoot("3"); // 默认权限 - - newManager.setCreated_at(LocalDateTime.now()); - newManager.setUpdated_at(LocalDateTime.now()); - - int rows = usersManagementsMapper.insertUsersManagements(newManager); - System.out.println("✅ 插入负责人记录影响行数: " + rows); - } - + boolean followupCustomer(String phoneNumber, String followupContent, String dataSource, Login login); + /** - * 处理负责人信息记录 - 更新或创建 + * 记录客户查看操作 + * @param userId 客户ID + * @param login 登录者信息 + * @return 是否成功 */ - private void handleManagerRecord(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔍 开始处理负责人记录,用户ID: " + userId); - - // 检查是否已存在负责人记录 - UsersManagements existingManager = usersManagementsMapper.findByUserId(userId); - - if (existingManager != null) { - System.out.println("🔄 负责人记录已存在,进行更新"); - // 更新现有记录 - 使用当前登录用户信息 - updateExistingManagerRecord(existingManager, authInfo); - } else { - System.out.println("➕ 创建新的负责人记录"); - // 创建新记录 - 使用当前登录用户信息 - createNewManagerRecord(userId, authInfo); - } - - // 验证负责人信息是否成功处理 - UsersManagements verifiedManager = usersManagementsMapper.findByUserId(userId); - System.out.println("✅ 负责人信息验证: " + (verifiedManager != null ? "成功" : "失败")); - if (verifiedManager != null) { - System.out.println("📝 验证后的负责人信息: " + - "公司=" + verifiedManager.getManagercompany() + - ", 部门=" + verifiedManager.getManagerdepartment() + - ", 组织=" + verifiedManager.getOrganization() + - ", 角色=" + verifiedManager.getRole() + - ", 负责人=" + verifiedManager.getUserName() + - ", 协助人=" + verifiedManager.getAssistant()); - } - - } catch (Exception e) { - System.err.println("❌ 处理负责人记录失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("处理负责人记录失败: " + e.getMessage(), e); - } - } - - - + boolean recordCustomerView(String userId, Login login); + /** - * 更新wechat数据源客户信息 - 重载方法,支持控制是否处理负责人信息 + * 保存客户操作记录 + * @param userId 客户ID + * @param login 登录者信息 + * @param operationEvent 操作事件 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否成功 */ - public boolean updateWechatCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo, boolean handleManagerInfo) { - validatePhoneNumber(dto.getPhoneNumber()); - - System.out.println("开始更新微信用户(wechat数据源),手机号: " + dto.getPhoneNumber()); - System.out.println("处理负责人信息: " + handleManagerInfo); - - UserProductCartDTO existingUser; - String userId = dto.getId(); // 优先使用DTO中的ID - - // 关键修复:优先使用用户ID进行精确查询,避免多结果问题 - if (userId != null && !userId.trim().isEmpty()) { - System.out.println("优先通过用户ID查询:" + userId); - try { - existingUser = usersMapper.selectByUserId(userId); - if (existingUser == null) { - throw new RuntimeException("未找到ID对应的客户:" + userId); - } - } catch (Exception e) { - System.out.println("通过ID查询失败,尝试通过手机号查询: " + e.getMessage()); - existingUser = validateAndGetUser(dto.getPhoneNumber()); - userId = existingUser.getUserId(); - } - } else { - // 如果没有提供ID,回退到通过手机号查询 - existingUser = validateAndGetUser(dto.getPhoneNumber()); - userId = existingUser.getUserId(); - } - - // 记录原始等级用于比较 - String originalLevel = existingUser.getLevel(); - String newLevel = dto.getLevel(); - - System.out.println("📊 客户等级变化检查 - 原始: " + originalLevel + ", 新: " + newLevel); - - // 🔥 修复:完善类型转换逻辑 - String type = dto.getType(); - if (type != null) { - switch (type) { - case "BOTH": - case "供应端&BOTH": - type = "both"; - break; - case "客户端": - case "buyer": - type = "buyer"; - break; - case "供应端": - case "seller": - type = "seller"; - break; - default: - // 保持原值 - break; - } - dto.setType(type); - System.out.println("🔄 类型转换结果: " + dto.getType() + " → " + type); - } else { - System.out.println("⚠️ 客户类型为空,使用默认值"); - dto.setType("buyer"); // 默认设为buyer - } - - validateSalesPermission(type); - - // 更新用户基本信息 - boolean success = updateWechatDataSource(dto, existingUser); - - // 根据参数决定是否处理负责人信息 - if (success && handleManagerInfo) { - checkAndUpdateManagerInfo(originalLevel, newLevel, dto, userId, authInfo); - } - - // 对于非公海池客户更新,不处理负责人信息 - return success; - } - - - - - /** - * 更新现有的负责人记录 - 使用当前登录用户信息 - */ - private void updateExistingManagerRecord(UsersManagements existingManager, ManagerAuthInfo authInfo) { - // 使用当前登录用户的认证信息填充 - existingManager.setManagerId(getSafeString(authInfo.getManagerId())); - existingManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - existingManager.setOrganization(getSafeString(authInfo.getOrganization())); - existingManager.setRole(getSafeString(authInfo.getRole())); - existingManager.setUserName(getSafeString(authInfo.getUserName())); - existingManager.setAssistant(getSafeString(authInfo.getAssistant())); - - // 确保managerId不为空 - if (existingManager.getManagerId() == null || existingManager.getManagerId().isEmpty()) { - existingManager.setManagerId(authInfo.getManagerId()); - } - - // 确保root不为空 - if (existingManager.getRoot() == null || existingManager.getRoot().isEmpty()) { - existingManager.setRoot("3"); - } - - existingManager.setUpdated_at(LocalDateTime.now()); - - int rows = usersManagementsMapper.updateUsersManagements(existingManager); - System.out.println("✅ 更新负责人记录影响行数: " + rows); - } - - /** - * 创建新的负责人记录 - 使用当前登录用户信息 - */ - private void createNewManagerRecord(String userId, ManagerAuthInfo authInfo) { - UsersManagements newManager = new UsersManagements(); - newManager.setUserId(userId); - - // 使用当前登录用户的认证信息填充 - newManager.setManagerId(getSafeString(authInfo.getManagerId())); - newManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - newManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - newManager.setOrganization(getSafeString(authInfo.getOrganization())); - newManager.setRole(getSafeString(authInfo.getRole())); - newManager.setRoot("3"); // 默认权限 - newManager.setUserName(getSafeString(authInfo.getUserName())); - newManager.setAssistant(getSafeString(authInfo.getAssistant())); - - newManager.setCreated_at(LocalDateTime.now()); - newManager.setUpdated_at(LocalDateTime.now()); - - int rows = usersManagementsMapper.insertUsersManagements(newManager); - System.out.println("✅ 插入负责人记录影响行数: " + rows); - } - - - + boolean saveOperationRecord(String userId, Login login, String operationEvent, String originalData, String modifiedData, String changedFields); + /** - * 更新默认数据源客户信息 + * 认领客户 + * @param customerId 客户ID + * @param login 登录者信息 + * @return 是否成功 */ - public boolean updateDefaultCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - validateCompanyId(dto.getId()); - validateSalesPermission(dto.getType()); - - return enterpriseService.updateDefaultCustomer(dto, authInfo); - } - - - // ==================== 查询方法 ==================== - - /** - * 根据手机号查询客户 - 使用数据库权限过滤 - */ - public UnifiedCustomerDTO getCustomerByPhone(String phoneNumber, ManagerAuthInfo authInfo) { - validatePhoneNumber(phoneNumber); - - System.out.println("🔍 开始根据手机号查询授权客户: " + phoneNumber); - - try { - // 🎯 优化:使用带权限检查的查询方法 - UserProductCartDTO userInfo = usersMapper.selectByPhoneWithAuth(phoneNumber, authInfo); - if (userInfo == null) { - throw new RuntimeException("未找到手机号对应的客户:" + phoneNumber); - } - - // 🎯 优化:不再需要手动权限检查 - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo); - dto.setDataSource("wechat"); - return dto; - - } catch (Exception e) { - System.err.println("❌ 查询授权客户失败: " + e.getMessage()); - throw new RuntimeException("查询客户信息失败: " + e.getMessage()); - } - } - /** - * 检查是否有权限查看客户(统一权限检查方法) - */ - private boolean hasPermissionToViewCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 使用新的公海池判断逻辑 - if (isPublicSeaCustomer(userInfo, authInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - /** - * 检查是否有权限查看微信客户 - */ - public boolean hasPermissionToViewWechatCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 公海池客户对所有人可见 - if (isPublicSeaCustomer(userInfo,authInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - - /** - * 判断是否为公海池客户 - 根据认证字段是否有值判断 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - System.out.println("🔍 CustomerService - 客户等级检查: " + userInfo.getLevel() + " → 是否公海池等级: " + isPublicSeaLevel); - - if (!isPublicSeaLevel) { - return false; - } - - // 根据不同类型的公海池使用不同判断逻辑 - String level = userInfo.getLevel(); - - if ("company-sea-pools".equals(level) || "公海池".equals(level)) { - // 公司公海池:必须没有负责人信息 - boolean result = !hasManagerAuthInfo(userInfo.getUserId()); - System.out.println("🏢 公司公海池检查结果: " + result); - return result; - } else if ("organization-sea-pools".equals(level)) { - // 组织公海池:必须有负责人信息且组织匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 组织公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameOrganization = hasSameOrganization(userInfo.getUserId(), authInfo); - System.out.println("🏢 组织公海池检查结果 - 有负责人: " + hasManager + ", 组织匹配: " + sameOrganization + " → 结果: " + sameOrganization); - return sameOrganization; - } else if ("department-sea-pools".equals(level)) { - // 部门公海池:必须有负责人信息且部门匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 部门公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameDepartment = hasSameDepartment(userInfo.getUserId(), authInfo); - System.out.println("🏢 部门公海池检查结果 - 有负责人: " + hasManager + ", 部门匹配: " + sameDepartment + " → 结果: " + sameDepartment); - return sameDepartment; - } - - return false; - } - - - /** - * 检查是否有负责人认证信息 - */ - private boolean hasManagerAuthInfo(String userId) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - // 检查认证字段是否为空 - 只要有一个认证字段有值,就有负责人信息 - boolean hasAuthInfo = StringUtils.hasText(userManager.getManagerId()) || - StringUtils.hasText(userManager.getManagercompany()) || - StringUtils.hasText(userManager.getManagerdepartment()) || - StringUtils.hasText(userManager.getOrganization()) || - StringUtils.hasText(userManager.getRole()) || - StringUtils.hasText(userManager.getUserName()) || - StringUtils.hasText(userManager.getAssistant()); - - System.out.println("📋 负责人认证信息检查结果: " + (hasAuthInfo ? "有认证信息" : "无认证信息")); - return hasAuthInfo; - } catch (Exception e) { - System.err.println("❌ 检查负责人认证信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一组织 - */ - private boolean hasSameOrganization(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameOrganization = StringUtils.hasText(userManager.getOrganization()) && - userManager.getOrganization().equals(authInfo.getOrganization()); - - System.out.println("🏢 组织匹配检查: " + userManager.getOrganization() + " vs " + authInfo.getOrganization() + " → " + sameOrganization); - return sameOrganization; - } catch (Exception e) { - System.err.println("❌ 检查组织信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一部门 - */ - private boolean hasSameDepartment(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameDepartment = StringUtils.hasText(userManager.getManagerdepartment()) && - userManager.getManagerdepartment().equals(authInfo.getManagerdepartment()); - - System.out.println("🏢 部门匹配检查: " + userManager.getManagerdepartment() + " vs " + authInfo.getManagerdepartment() + " → " + sameDepartment); - return sameDepartment; - } catch (Exception e) { - System.err.println("❌ 检查部门信息失败: " + e.getMessage()); - return false; - } - } - - - - /** - * 检查用户负责人权限 - 优化版本,数据库层面直接匹配 - */ - private boolean hasUserManagerPermission(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 检查用户负责人权限,用户ID: " + userId); - - // 🔥 优化:直接在数据库层面查询匹配的负责人记录,避免内存比较 - UsersManagements userManager = usersManagementsMapper.findByUserIdAndAuthInfo(userId, authInfo); - - // 🔥 优化:如果没有找到匹配的负责人记录,检查是否为公海池客户 - if (userManager == null) { - System.out.println("🔍 未找到匹配的负责人记录,检查客户等级..."); - - // 获取用户信息检查等级 - UserProductCartDTO userInfo = usersMapper.getUserBasicInfo(userId); - if (userInfo != null) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - boolean isPublicSea = publicSeaLevels.contains(userInfo.getLevel()); - - if (isPublicSea) { - System.out.println("✅ 公海池客户,允许查看"); - return true; - } - } - - System.out.println("❌ 非公海池客户且无匹配负责人,拒绝访问"); - return false; - } - - // 🔥 优化:数据库已经完成匹配,直接返回true - System.out.println("✅ 找到匹配的负责人记录,允许查看"); - System.out.println("📝 负责人信息: " + - "公司=" + userManager.getManagercompany() + - ", 部门=" + userManager.getManagerdepartment() + - ", 组织=" + userManager.getOrganization() + - ", 负责人=" + userManager.getUserName()); - - return true; - - } catch (Exception e) { - System.err.println("❌ 检查用户负责人权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 检查企业负责人权限 - */ - private boolean hasManagerPermission(EnterpriseInfoDTO enterpriseInfo, ManagerAuthInfo authInfo) { - if (enterpriseInfo.getManagers() == null) { - System.out.println("✅ 企业客户无负责人信息,允许查看"); - return true; - } - - return isManagerMatch(enterpriseInfo.getManagers(), authInfo); - } - - /** - * 检查负责人信息是否匹配(Managers)- 使用新字段 - */ - private boolean isManagerMatch(Managers manager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(manager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(manager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(manager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(manager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(manager.getUserName())); - - System.out.println("🔐 负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 检查负责人信息是否匹配(UsersManagements) - */ - private boolean isManagerMatch(UsersManagements userManager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(userManager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(userManager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(userManager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(userManager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(userManager.getUserName())); - - System.out.println("🔐 用户负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 根据企业ID查询客户信息(默认数据源)- 添加负责人过滤 - */ - public UnifiedCustomerDTO getCustomerById(String id, ManagerAuthInfo authInfo) { - EnterpriseInfoDTO enterpriseInfo = enterpriseService.getEnterpriseInfoById(id); - if (enterpriseInfo == null) { - return null; - } - - // 检查负责人权限 - if (!hasManagerPermission(enterpriseInfo, authInfo)) { - System.out.println("❌ 负责人权限不足,无法查看该客户"); - return null; - } - - return convertToUnifiedDTO(enterpriseInfo); - } - - // ==================== 私有方法 - 精确更新逻辑 ==================== - - /** - * 精确更新联系人信息 - */ - private void updateContactInfoPrecise(UnifiedCustomerDTO dto, String userId) { - if (dto.getTargetContactId() != null && !dto.getTargetContactId().trim().isEmpty()) { - // 精确更新特定联系人 - updateSpecificContact(dto, userId); - } else if (dto.getContacts() != null && !dto.getContacts().isEmpty()) { - // 更新第一个联系人(向后兼容) - updateFirstContact(dto, userId); - } else { - // 使用单个字段更新第一个联系人(向后兼容) - updateContactFromSingleFields(dto, userId); - } - } - - /** - * 精确更新购物车信息 - */ - private void updateCartItemInfoPrecise(UnifiedCustomerDTO dto, String userId) { - if (!"buyer".equals(dto.getType()) && !"both".equals(dto.getType())) { - return; - } - - if (dto.getTargetCartItemId() != null && !dto.getTargetCartItemId().trim().isEmpty()) { - // 精确更新特定购物车项 - updateSpecificCartItem(dto, userId); - } else if (dto.getCartItems() != null && !dto.getCartItems().isEmpty()) { - // 更新第一个购物车项(向后兼容) - updateFirstCartItem(dto, userId); - } else { - // 使用单个字段更新第一个购物车项(向后兼容) - updateCartItemFromSingleFields(dto, userId); - } - } - - /** - * 更新用户基本信息 - */ - private void updateUserBasicInfo(UnifiedCustomerDTO dto, UserProductCartDTO existingUser) { - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(existingUser.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - - // 只更新非空字段 - updateUser.setNickName(getUpdateValue(dto.getNickName(), existingUser.getNickName())); - updateUser.setType(dto.getType()); // 类型必须更新 - updateUser.setCompany(getUpdateValue(dto.getCompany(), existingUser.getCompany())); - updateUser.setRegion(getUpdateValue(dto.getRegion(), existingUser.getRegion())); - updateUser.setLevel(getUpdateValue(dto.getLevel(), existingUser.getLevel())); - updateUser.setDemand(getUpdateValue(dto.getDemand(), existingUser.getDemand())); - updateUser.setSpec(getUpdateValue(dto.getSpec(), existingUser.getSpec())); - // 优先使用前端传递的更新时间,如果没有则使用当前时间 - updateUser.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int rows = usersMapper.updateByPhone(updateUser); - System.out.println("更新用户基本信息影响行数: " + rows); - - if (rows == 0) { - throw new RuntimeException("用户基本信息更新失败"); - } - } - - /** - * 精确更新特定联系人 - */ - private void updateSpecificContact(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 精确更新特定联系人,contactId: " + dto.getTargetContactId()); - - UnifiedCustomerDTO.ContactInfo contactData = dto.getUpdateContactData(); - if (contactData == null) { - System.out.println("未提供联系人更新数据,跳过联系人更新"); - return; - } - - int contactsRows = usersMapper.updateSpecificContact( - userId, - dto.getTargetContactId(), - contactData.getWechat(), - contactData.getAccount(), - contactData.getAccountNumber(), - contactData.getBank(), - contactData.getAddress() - ); - System.out.println("更新特定联系人影响行数: " + contactsRows); - - if (contactsRows == 0) { - System.out.println("⚠️ 特定联系人更新失败,可能ID不存在"); - } - } - - /** - * 更新第一个联系人(向后兼容) - */ - private void updateFirstContact(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 更新第一个联系人(向后兼容)"); - UnifiedCustomerDTO.ContactInfo contact = dto.getContacts().get(0); - - int contactsRows = usersMapper.updateContactsByUserId( - userId, - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - System.out.println("更新第一个联系人影响行数: " + contactsRows); - } - - /** - * 从单个字段更新联系人(向后兼容) - */ - private void updateContactFromSingleFields(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 从单个字段更新联系人(向后兼容)"); - - int contactsRows = usersMapper.updateContactsByUserId( - userId, - dto.getWechat(), - dto.getAccount(), - dto.getAccountNumber(), - dto.getBank(), - dto.getAddress() - ); - System.out.println("更新联系人信息影响行数: " + contactsRows); - } - - /** - * 精确更新特定购物车项 - */ - private void updateSpecificCartItem(UnifiedCustomerDTO dto, String userId) { - System.out.println("🛒 精确更新特定购物车项,cartItemId: " + dto.getTargetCartItemId()); - - UnifiedCustomerDTO.CartItem cartItemData = dto.getUpdateCartItemData(); - if (cartItemData == null) { - System.out.println("未提供购物车项更新数据,跳过购物车项更新"); - return; - } - - int cartRows = usersMapper.updateSpecificCartItem( - userId, - dto.getTargetCartItemId(), - cartItemData.getProductId(), - cartItemData.getProductName(), - cartItemData.getSpecification(), - cartItemData.getQuantity(), - cartItemData.getGrossWeight(), - cartItemData.getYolk() - ); - System.out.println("更新特定购物车项影响行数: " + cartRows); - - if (cartRows == 0) { - System.out.println("⚠️ 特定购物车项更新失败,可能ID不存在"); - } - } - - /** - * 更新第一个购物车项(向后兼容) - */ - private void updateFirstCartItem(UnifiedCustomerDTO dto, String userId) { - System.out.println("🛒 更新第一个购物车项(向后兼容)"); - UnifiedCustomerDTO.CartItem cartItem = dto.getCartItems().get(0); - - String productId = getExistingProductId(userId); - int cartRows = usersMapper.updateCartItemByBuyerId( - userId, - productId, - cartItem.getProductName(), - cartItem.getSpecification(), - cartItem.getQuantity(), - cartItem.getGrossWeight(), - cartItem.getYolk() - ); - System.out.println("更新公海需求信息(购物车)影响行数: " + cartRows); - } - - /** - * 从单个字段更新购物车项(向后兼容) - */ - private void updateCartItemFromSingleFields(UnifiedCustomerDTO dto, String userId) { - if (!StringUtils.hasText(dto.getProductName())) { - return; - } - - System.out.println("🛒 从单个字段更新购物车信息"); - - String productId = getExistingProductId(userId); - int cartRows = usersMapper.updateCartItemByBuyerId( - userId, - productId, - dto.getProductName(), - dto.getSpecification(), - dto.getQuantity(), - dto.getGrossWeight(), - dto.getYolk() - ); - System.out.println("更新公海需求信息(购物车)影响行数: " + cartRows); - - if (cartRows == 0) { - System.out.println("⚠️ 公海需求信息(购物车)更新影响0行,可能需要插入新记录"); - } - } - - // ==================== 私有方法 - 辅助方法 ==================== - - /** - * 验证手机号 - */ - private void validatePhoneNumber(String phoneNumber) { - if (!StringUtils.hasText(phoneNumber)) { - throw new IllegalArgumentException("手机号不能为空"); - } - } - - /** - * 验证公司ID - */ - private void validateCompanyId(String companyId) { - if (!StringUtils.hasText(companyId)) { - throw new IllegalArgumentException("公司ID不能为空"); - } - } - - /** - * 验证销售员权限 - */ - private void validateSalesPermission(String type) { - System.out.println("🔐 ====== 开始权限校验 ======"); - System.out.println("🔐 当前类型: " + type); - System.out.println("🔐 类型比较 - buyer: " + "buyer".equals(type)); - System.out.println("🔐 类型比较 - both: " + "both".equals(type)); - System.out.println("🔐 类型类名: " + (type != null ? type.getClass().getName() : "null")); - - if (!"buyer".equals(type) && !"both".equals(type)) { - System.out.println("❌ 权限校验失败:销售员只能更新为buyer或both类型,当前类型: " + type); - System.out.println("❌ 类型长度: " + (type != null ? type.length() : "null")); - System.out.println("❌ 类型字符: " + (type != null ? Arrays.toString(type.toCharArray()) : "null")); - throw new IllegalArgumentException("销售员权限只能操作客户端类型客户和BOTH类型客户"); - } - System.out.println("✅ 权限校验通过"); - System.out.println("🔐 ====== 权限校验结束 ======"); - } - - /** - * 验证并获取用户信息 - */ - private UserProductCartDTO validateAndGetUser(String phoneNumber) { - try { - // 尝试通过手机号精确查询 - UserProductCartDTO user = usersMapper.selectByPhone(phoneNumber); - if (user == null) { - throw new RuntimeException("未找到手机号对应的客户:" + phoneNumber); - } - System.out.println("找到现有客户,用户ID: " + user.getUserId()); - return user; - } catch (org.apache.ibatis.exceptions.TooManyResultsException e) { - // 处理多个结果的情况 - 这是一个关键修复 - System.out.println("警告:通过手机号" + phoneNumber + "查询到多个客户,使用userId进行精确查询"); - // 由于在updateWechatCustomer方法中我们已经有userId,这里需要一个备用方案 - // 从更新的DTO中获取userId会更合适,但为了保持方法签名不变,我们做一个临时修复 - // 实际解决方案应该是修改updateWechatCustomer方法,传入userId进行精确查询 - throw new RuntimeException("查询到多个客户记录,请提供更精确的查询条件"); - } - } - - /** - * 获取更新值(优先使用新值,如果新值为空则使用原值) - */ - private String getUpdateValue(String newValue, String originalValue) { - return StringUtils.hasText(newValue) ? newValue : originalValue; - } - - /** - * 获取现有的产品ID - */ - private String getExistingProductId(String userId) { - List existingCartItems = usersMapper.getBuyerCartItems(userId); - return existingCartItems != null && !existingCartItems.isEmpty() ? - existingCartItems.get(0).getProductId() : "default_product_id"; - } - - /** - * 只更新wechat数据源(包含负责人信息生成) - */ - private boolean updateWechatDataSource(UnifiedCustomerDTO dto, UserProductCartDTO existingUser) { - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(existingUser.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - - // 只更新非空字段 - updateUser.setNickName(getUpdateValue(dto.getNickName(), existingUser.getNickName())); - updateUser.setType(dto.getType()); // 类型必须更新 - updateUser.setCompany(getUpdateValue(dto.getCompany(), existingUser.getCompany())); - updateUser.setRegion(getUpdateValue(dto.getRegion(), existingUser.getRegion())); - updateUser.setLevel(getUpdateValue(dto.getLevel(), existingUser.getLevel())); - updateUser.setDemand(getUpdateValue(dto.getDemand(), existingUser.getDemand())); - updateUser.setSpec(getUpdateValue(dto.getSpec(), existingUser.getSpec())); - // 优先使用前端传递的更新时间,如果没有则使用当前时间 - updateUser.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int rows = usersMapper.updateByPhone(updateUser); - System.out.println("更新用户基本信息影响行数: " + rows); - - if (rows == 0) { - throw new RuntimeException("用户基本信息更新失败"); - } - - // 更新联系人信息 - updateContactInfoPrecise(dto, existingUser.getUserId()); - - // 更新购物车信息 - updateCartItemInfoPrecise(dto, existingUser.getUserId()); - - return rows > 0; - } - - // ==================== 转换方法 ==================== - - /** - * 为公海池客户转换DTO的方法 - 支持多个联系人和购物车项 - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea(UserProductCartDTO userInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - dto.setId(userInfo.getUserId()); - dto.setPhoneNumber(userInfo.getPhoneNumber()); - dto.setNickName(userInfo.getNickName()); - dto.setType(userInfo.getType()); - dto.setCompany(getSafeString(userInfo.getCompany())); - dto.setRegion(getSafeString(userInfo.getRegion())); - dto.setLevel(getSafeString(userInfo.getLevel(), "公海池")); - dto.setDemand(getSafeString(userInfo.getDemand())); - dto.setSpec(getSafeString(userInfo.getSpec())); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - - // 设置多个联系人信息 - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - List contacts = new ArrayList<>(); - for (UserProductCartDTO.UsersContacts userContact : userInfo.getUsersContacts()) { - UnifiedCustomerDTO.ContactInfo contact = new UnifiedCustomerDTO.ContactInfo(); - contact.setContactId(getSafeString(userContact.getContactId())); - contact.setWechat(getSafeString(userContact.getWechat())); - contact.setAccount(getSafeString(userContact.getAccount())); - contact.setAccountNumber(getSafeString(userContact.getAccountNumber())); - contact.setBank(getSafeString(userContact.getBank())); - contact.setAddress(getSafeString(userContact.getAddress())); - contacts.add(contact); - } - dto.setContacts(contacts); - - // 向后兼容:设置第一个联系人到单个字段 - UserProductCartDTO.UsersContacts firstContact = userInfo.getUsersContacts().get(0); - dto.setWechat(firstContact.getWechat()); - dto.setAccount(firstContact.getAccount()); - dto.setAccountNumber(firstContact.getAccountNumber()); - dto.setBank(firstContact.getBank()); - dto.setAddress(firstContact.getAddress()); - } - - // 设置多个购物车项 - if (userInfo.getCartItems() != null && !userInfo.getCartItems().isEmpty()) { - List cartItems = new ArrayList<>(); - for (UserProductCartDTO.CartItem userCartItem : userInfo.getCartItems()) { - UnifiedCustomerDTO.CartItem cartItem = new UnifiedCustomerDTO.CartItem(); - cartItem.setCartItemId(getSafeString(userCartItem.getCartItemId())); - cartItem.setProductId(getSafeString(userCartItem.getProductId())); - cartItem.setProductName(getSafeString(userCartItem.getProductName())); - cartItem.setSpecification(getSafeString(userCartItem.getSpecification())); - cartItem.setQuantity(userCartItem.getQuantity() != null ? userCartItem.getQuantity() : 0); - cartItem.setGrossWeight(userCartItem.getGrossWeight() != null ? userCartItem.getGrossWeight() : ""); - cartItem.setYolk(getSafeString(userCartItem.getYolk())); - cartItems.add(cartItem); - } - dto.setCartItems(cartItems); - - // 向后兼容:设置第一个购物车项到单个字段 - UserProductCartDTO.CartItem firstCartItem = userInfo.getCartItems().get(0); - dto.setProductName(firstCartItem.getProductName()); - dto.setSpecification(firstCartItem.getSpecification()); - dto.setQuantity(firstCartItem.getQuantity()); - dto.setGrossWeight(firstCartItem.getGrossWeight()); - dto.setYolk(firstCartItem.getYolk()); - dto.setVariety(""); // 购物车没有品种字段 - } else { - setDefaultProductValues(dto); - } - - return dto; - } - - /** - * 将企业信息转换为UnifiedCustomerDTO - 使用新字段 - */ - private UnifiedCustomerDTO convertToUnifiedDTO(EnterpriseInfoDTO enterpriseInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - if (enterpriseInfo.getEnterprise() != null) { - dto.setId(enterpriseInfo.getEnterprise().getId()); - dto.setCompany(getSafeString(enterpriseInfo.getEnterprise().getCompany())); - dto.setRegion(getSafeString(enterpriseInfo.getEnterprise().getRegion())); - dto.setLevel(getSafeString(enterpriseInfo.getEnterprise().getLevel())); - dto.setType(getSafeString(enterpriseInfo.getEnterprise().getType())); - dto.setDemand(getSafeString(enterpriseInfo.getEnterprise().getDemand())); - dto.setSpec(getSafeString(enterpriseInfo.getEnterprise().getSpec())); - } - - if (enterpriseInfo.getContacts() != null) { - dto.setNickName(getSafeString(enterpriseInfo.getContacts().getNickName())); - dto.setPhoneNumber(getSafeString(enterpriseInfo.getContacts().getPhoneNumber())); - dto.setWechat(getSafeString(enterpriseInfo.getContacts().getWechat())); - dto.setAccount(getSafeString(enterpriseInfo.getContacts().getAccount())); - dto.setAccountNumber(getSafeString(enterpriseInfo.getContacts().getAccountNumber())); - dto.setBank(getSafeString(enterpriseInfo.getContacts().getBank())); - dto.setAddress(getSafeString(enterpriseInfo.getContacts().getAddress())); - dto.setCreated_at(enterpriseInfo.getContacts().getCreated_at()); - dto.setUpdated_at(enterpriseInfo.getContacts().getUpdated_at()); - } - - if (enterpriseInfo.getManagers() != null) { - // 使用新的负责人字段 - dto.setManagerId(getSafeString(enterpriseInfo.getManagers().getManagerId())); - dto.setManagercompany(getSafeString(enterpriseInfo.getManagers().getManagercompany())); - dto.setManagerdepartment(getSafeString(enterpriseInfo.getManagers().getManagerdepartment())); - dto.setOrganization(getSafeString(enterpriseInfo.getManagers().getOrganization())); - dto.setRole(getSafeString(enterpriseInfo.getManagers().getRole())); - dto.setUserName(getSafeString(enterpriseInfo.getManagers().getUserName())); - dto.setAssistant(getSafeString(enterpriseInfo.getManagers().getAssistant())); - } - - return dto; - } - - /** - * 设置默认产品值 - */ - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - dto.setCustomDetails(new Object[0]); - } - - /** - * 安全获取字符串(带默认值) - */ - private String getSafeString(String value) { - return value != null ? value : ""; - } - - /** - * 安全获取字符串(带自定义默认值) - */ - private String getSafeString(String value, String defaultValue) { - return value != null ? value : defaultValue; - } - - /** - * 根据ID查询wechat数据源客户信息 - */ - public UnifiedCustomerDTO getWechatCustomerById(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔍 开始根据用户ID查询wechat客户: " + userId); - - UserProductCartDTO userInfo = poolCustomerService.getPublicSeaCustomerInfo(userId); - if (userInfo == null) { - System.out.println("❌ 未找到用户ID对应的客户:" + userId); - return null; - } - - // 销售员权限校验 - if (!"buyer".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - System.out.println("❌ 该客户不在销售员权限范围内,类型: " + userInfo.getType()); - return null; - } - - // 负责人权限校验 - if (!hasPermissionToViewCustomer(userInfo, authInfo)) { - System.out.println("❌ 负责人权限不足,无法查看该客户"); - return null; - } - - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo); - dto.setDataSource("wechat"); - return dto; - - } catch (Exception e) { - System.err.println("❌ 查询wechat客户信息失败: " + e.getMessage()); - return null; - } - } - /** - * 检查默认数据源中是否存在指定ID的客户 - */ - public boolean checkDefaultCustomerExists(String customerId) { - try { - System.out.println("🔍 检查默认数据源客户是否存在,客户ID: " + customerId); - - if (customerId == null || customerId.trim().isEmpty()) { - System.out.println("❌ 客户ID为空,无法检查"); - return false; - } - - // 使用现有的selectEnterpriseInfoById方法检查存在性 - EnterpriseInfoDTO enterpriseInfo = enterpriseMapper.selectEnterpriseInfoById(customerId); - - boolean exists = enterpriseInfo != null && enterpriseInfo.getEnterprise() != null; - System.out.println("📊 默认数据源客户检查结果: " + (exists ? "✅ 存在" : "❌ 不存在")); - - if (exists) { - System.out.println("📝 客户信息: 公司=" + enterpriseInfo.getEnterprise().getCompany() + - ", 区域=" + enterpriseInfo.getEnterprise().getRegion()); - } - - return exists; - - } catch (Exception e) { - System.err.println("❌ 检查默认数据源客户存在性失败: " + e.getMessage()); - e.printStackTrace(); - return false; - } - } + boolean claimCustomer(String customerId, Login login); } \ No newline at end of file diff --git a/src/main/java/com/example/web/service/EnterpriseService.java b/src/main/java/com/example/web/service/EnterpriseService.java deleted file mode 100644 index 6ce6b92..0000000 --- a/src/main/java/com/example/web/service/EnterpriseService.java +++ /dev/null @@ -1,501 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Enterprise; -import com.example.web.entity.Contacts; -import com.example.web.entity.Managers; -import com.example.web.mapper.EnterpriseMapper; -import com.example.web.mapper.ContactsMapper; -import com.example.web.mapper.ManagersMapper; -import com.example.web.mapper.UsersMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -@Service// 标识为Spring服务层组件,用于处理业务逻辑 -public class EnterpriseService { - - @Autowired// 自动注入数据访问层(Mapper)对象,用于数据库操作 - private EnterpriseMapper enterpriseMapper; - - @Autowired - private ContactsMapper contactsMapper; - - @Autowired - private ManagersMapper managersMapper; - - @Autowired - private UsersMapper usersMapper; - - - - // 修改:检查电话号码是否重复(同时检查两个数据源) - public boolean isPhoneNumberDuplicate(String phoneNumber) { - // 1. 检查微信数据源中的电话号码是否重复 - boolean wechatDuplicate = false; - try { - UserProductCartDTO existingUser = usersMapper.selectByPhone(phoneNumber); - wechatDuplicate = existingUser != null; - if (wechatDuplicate) { - System.out.println("❌ 电话号码在微信数据源中已存在: " + phoneNumber); - } - } catch (Exception e) { - System.err.println("查询微信数据源电话号码失败: " + e.getMessage()); - } - - // 2. 检查默认数据源(userlogin)中的电话号码是否重复 - boolean defaultDuplicate = false; - try { - int count = contactsMapper.countByPhoneNumber(phoneNumber); - defaultDuplicate = count > 0; - if (defaultDuplicate) { - System.out.println("❌ 电话号码在默认数据源中已存在: " + phoneNumber); - } - } catch (Exception e) { - System.err.println("查询默认数据源电话号码失败: " + e.getMessage()); - } - - // 3. 返回最终结果:任意一个数据源中存在都算重复 - boolean isDuplicate = wechatDuplicate || defaultDuplicate; - System.out.println("📞 电话号码重复检查结果: " + phoneNumber + - " -> 微信数据源:" + wechatDuplicate + - ", 默认数据源:" + defaultDuplicate + - ", 最终结果:" + isDuplicate); - - return isDuplicate; - } - - private String convertFrontendTypeToDatabase(String frontendType) { - if (frontendType == null) { - return null; - } - switch (frontendType) { - case "供应端": - return "seller"; - case "客户端": - return "buyer"; - case "BOTH": - return "both"; // 改为小写 - default: - return frontendType; - } - } - - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": // 匹配小写的数据库存储 - return "BOTH"; - default: - return databaseType; - } - } - - - - // 新增客户:保存企业、联系人、负责人信息(默认数据源) - @Transactional(rollbackFor = Exception.class) - public boolean addCustomer(UnifiedCustomerDTO dto) { - System.out.println("===================================================="); - System.out.println("➕ 开始新增客户到默认数据源"); - System.out.println("===================================================="); - System.out.println("📋 客户信息: 手机=" + dto.getPhoneNumber() + - ", 公司=" + dto.getCompany() + - ", 类型=" + dto.getType() + - ", 等级=" + dto.getLevel()); - - // 1. 转换前端类型为数据库类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - System.out.println("🔄 类型转换: 前端=" + dto.getType() + " → 数据库=" + databaseType); - - // 2. 权限校验 - if (!"buyer".equals(dto.getType()) && !"both".equals(dto.getType())) { - System.out.println("❌ 权限校验失败: 销售端只能新增客户端类型和BOTH客户"); - throw new IllegalArgumentException("采购端权限只能新增客户端类型客户和BOTH类型客户"); - } - System.out.println("✅ 权限校验通过"); - - // 3. 等级校验 - if (!StringUtils.hasText(dto.getLevel())) { - System.out.println("❌ 等级校验失败: 客户等级不能为空"); - throw new IllegalArgumentException("客户等级不能为空"); - } - System.out.println("✅ 等级校验通过"); - - // 4. 检查电话号码是否重复 - System.out.println("🔍 检查电话号码重复性..."); - if (isPhoneNumberDuplicate(dto.getPhoneNumber())) { - System.out.println("❌ 电话号码重复: " + dto.getPhoneNumber()); - throw new IllegalArgumentException("电话号码已存在"); - } - System.out.println("✅ 电话号码检查通过"); - - // 5. 封装并保存企业信息 - System.out.println("💾 保存企业信息..."); - Enterprise enterprise = new Enterprise(); - enterprise.setId(dto.getId()); - enterprise.setCompany(dto.getCompany()); - enterprise.setRegion(dto.getRegion()); - enterprise.setLevel(dto.getLevel()); - enterprise.setType(dto.getType()); - enterprise.setDemand(dto.getDemand()); - enterprise.setSpec(dto.getSpec()); - - int enterpriseRows = enterpriseMapper.insertEnterprise(enterprise); - System.out.println("✅ 企业信息保存结果: " + enterpriseRows + " 行受影响"); - - // 6. 封装联系人信息 - System.out.println("💾 保存联系人信息..."); - Contacts contacts = new Contacts(); - String contactId = UUID.randomUUID().toString().replaceAll("-", ""); - contacts.setContact_id(contactId); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - contacts.setPhoneNumber(dto.getPhoneNumber()); - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - contacts.setCreated_at(dto.getCreated_at() != null ? dto.getCreated_at() : LocalDateTime.now()); - contacts.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int contactsRows = contactsMapper.insertContacts(contacts); - System.out.println("✅ 联系人信息保存结果: " + contactsRows + " 行受影响"); - - // 7. 封装负责人信息 - 使用前端传递的认证信息(更新为新表结构) - System.out.println("💾 保存负责人信息..."); - Managers managers = new Managers(); - managers.setId(dto.getId()); - managers.setManagerId(StringUtils.hasText(dto.getManagerId()) ? dto.getManagerId() : "未分配"); - managers.setManagercompany(StringUtils.hasText(dto.getManagercompany()) ? dto.getManagercompany() : "未分配"); - managers.setManagerdepartment(StringUtils.hasText(dto.getManagerdepartment()) ? dto.getManagerdepartment() : "未分配"); - managers.setOrganization(StringUtils.hasText(dto.getOrganization()) ? dto.getOrganization() : "未分配"); - managers.setRole(StringUtils.hasText(dto.getRole()) ? dto.getRole() : "未分配"); - managers.setRoot("3"); // 默认权限 - managers.setUserName(StringUtils.hasText(dto.getUserName()) ? dto.getUserName() : "未分配"); - managers.setAssistant(StringUtils.hasText(dto.getAssistant()) ? dto.getAssistant() : "无"); - managers.setCreated_at(LocalDateTime.now()); - managers.setUpdated_at(LocalDateTime.now()); - - int managersRows = managersMapper.insertManagers(managers); - System.out.println("✅ 负责人信息保存结果: " + managersRows + " 行受影响"); - - boolean success = enterpriseRows > 0 && contactsRows > 0 && managersRows > 0; - - if (success) { - System.out.println("🎉 新增客户成功,负责人信息已自动填充"); - // 记录负责人信息详情 - System.out.println("📝 负责人信息详情: " + - "负责人id=" + managers.getManagerId() + - "负责公司=" + managers.getManagercompany() + - ", 负责部门=" + managers.getManagerdepartment() + - ", 组织=" + managers.getOrganization() + - ", 角色=" + managers.getRole() + - ", 负责人=" + managers.getUserName() + - ", 协助人=" + managers.getAssistant()); - } else { - System.out.println("❌ 新增客户失败"); - } - - System.out.println("===================================================="); - - return success; - } - - /** - * 获取所有企业的完整信息(企业信息 + 联系人信息 + 负责人信息) - */ - public List getAllEnterpriseInfo() { - try { - return enterpriseMapper.selectAllEnterpriseInfo(); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取详细信息 - */ - public EnterpriseInfoDTO getEnterpriseInfoById(String id) { - try { - return enterpriseMapper.selectEnterpriseInfoById(id); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** - * 获取所有企业基本信息 - */ - public List getAllEnterprises() { - try { - return enterpriseMapper.selectAllEnterprises(); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取联系人信息 - */ - public List getContactsByEnterpriseId(String id) { - try { - return contactsMapper.selectContactsByEnterpriseId(id); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取负责人信息 - */ - public List getManagersByEnterpriseId(String id) { - try { - return managersMapper.selectManagersByEnterpriseId(id); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } - - - /** - * 搜索企业信息(根据企业名称、地区、类型等) - */ - public List searchEnterprises(String keyword) { - try { - // 这里可以扩展更复杂的搜索逻辑 - List allInfo = enterpriseMapper.selectAllEnterpriseInfo(); - if (keyword == null || keyword.trim().isEmpty()) { - return allInfo; - } - - List result = new ArrayList<>(); - for (EnterpriseInfoDTO info : allInfo) { - if (info.getEnterprise() != null) { - String company = info.getEnterprise().getCompany() != null ? info.getEnterprise().getCompany().toLowerCase() : ""; - String region = info.getEnterprise().getRegion() != null ? info.getEnterprise().getRegion().toLowerCase() : ""; - String type = info.getEnterprise().getType() != null ? info.getEnterprise().getType().toLowerCase() : ""; - - if (company.contains(keyword.toLowerCase()) || - region.contains(keyword.toLowerCase()) || - type.contains(keyword.toLowerCase())) { - result.add(info); - } - } - } - return result; - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 更新默认数据源客户信息(企业、联系人、负责人) - */ - @Transactional(rollbackFor = Exception.class) - public boolean updateDefaultCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - // 转换前端类型为数据库类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - - // 销售员权限:校验客户类型,只允许buyer和both - if (!"buyer".equals(dto.getType()) && !"both".equals(dto.getType())) { - throw new IllegalArgumentException("销售员权限只能更新为客户端类型客户"); - } - - // 1. 更新企业信息 - Enterprise enterprise = new Enterprise(); - enterprise.setId(dto.getId()); - enterprise.setCompany(dto.getCompany()); - enterprise.setRegion(dto.getRegion()); - enterprise.setLevel(dto.getLevel()); - enterprise.setType(dto.getType()); - enterprise.setDemand(dto.getDemand()); - enterprise.setSpec(dto.getSpec()); - int enterpriseRows = enterpriseMapper.updateEnterprise(enterprise); - - if (enterpriseRows <= 0) { - throw new RuntimeException("更新企业信息失败,企业ID: " + dto.getId()); - } - - // 2. 更新联系人信息 - 修复逻辑 - Contacts contacts = new Contacts(); - // 先根据企业ID查询原始联系人信息 - List originalContactsList = contactsMapper.selectContactsByEnterpriseId(dto.getId()); - if (originalContactsList != null && !originalContactsList.isEmpty()) { - Contacts originalContacts = originalContactsList.get(0); - contacts.setContact_id(originalContacts.getContact_id()); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - // 关键:使用原始电话号码,禁止修改 - contacts.setPhoneNumber(originalContacts.getPhoneNumber()); - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - - int contactsRows = contactsMapper.updateContacts(contacts); - if (contactsRows <= 0) { - throw new RuntimeException("更新联系人信息失败,联系人ID: " + originalContacts.getContact_id()); - } - } else { - // 如果没有找到联系人记录,创建新的联系人 - System.out.println("未找到现有联系人,创建新的联系人记录"); - contacts.setContact_id(UUID.randomUUID().toString().replaceAll("-", "")); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - contacts.setPhoneNumber(""); // 新创建的联系人电话号码为空 - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - contacts.setCreated_at(LocalDateTime.now()); - contacts.setUpdated_at(LocalDateTime.now()); - - int contactsRows = contactsMapper.insertContacts(contacts); - if (contactsRows <= 0) { - throw new RuntimeException("创建联系人信息失败"); - } - } - - // 🔥 修改:检查是否需要更新负责人信息 - boolean hasFrontendManagerInfo = StringUtils.hasText(dto.getManagercompany()) || - StringUtils.hasText(dto.getManagerdepartment()) || - StringUtils.hasText(dto.getOrganization()) || - StringUtils.hasText(dto.getRole()) || - StringUtils.hasText(dto.getUserName()) || - StringUtils.hasText(dto.getAssistant()); - - // 定义非公海池等级 - Set nonPublicSeaLevels = Set.of("important", "normal", "low-value", "logistics", "unclassified"); - boolean isNonPublicSeaCustomer = nonPublicSeaLevels.contains(dto.getLevel()); - - System.out.println("🎯 负责人信息更新检查: " + - "是否非公海池客户=" + isNonPublicSeaCustomer + - ", 前端是否提交负责人信息=" + hasFrontendManagerInfo); - - // 🔥 只有非公海池客户且前端提交了负责人信息时才更新 - if (isNonPublicSeaCustomer && hasFrontendManagerInfo) { - System.out.println("✅ 需要更新负责人信息"); - - Managers managers = new Managers(); - managers.setId(dto.getId()); - - System.out.println("✅ 前端提交了负责人信息,使用前端数据更新"); - // 使用前端提交的数据 - managers.setManagercompany(dto.getManagercompany()); - managers.setManagerdepartment(dto.getManagerdepartment()); - managers.setOrganization(dto.getOrganization()); - managers.setRole(dto.getRole()); - managers.setUserName(dto.getUserName()); - managers.setAssistant(dto.getAssistant()); - - managers.setUpdated_at(LocalDateTime.now()); - - int managersRows = managersMapper.updateManagers(managers); - if (managersRows <= 0) { - // 如果没有更新到记录,尝试插入 - System.out.println("未找到现有负责人记录,创建新的负责人记录"); - managers.setManagerId(authInfo.getManagerId()); - managers.setRoot("3"); - managers.setCreated_at(LocalDateTime.now()); - managersRows = managersMapper.insertManagers(managers); - if (managersRows <= 0) { - throw new RuntimeException("更新负责人信息失败"); - } - } - System.out.println("✅ 负责人信息更新成功"); - } else { - System.out.println("ℹ️ 无需更新负责人信息 - " + - (!isNonPublicSeaCustomer ? "客户不是非公海池客户" : "") + - (!hasFrontendManagerInfo ? "前端未提交负责人信息" : "")); - } - - return true; - } - - /** - * 更新wechat数据源的客户信息(用户和产品信息) - */ - public boolean updateWechatCustomer(UnifiedCustomerDTO dto) { - // 修复:确保类型转换正确 - String type = dto.getType(); - if ("BOTH".equals(type)) { - type = "both"; - dto.setType(type); - } else if ("客户端".equals(type)) { - type = "buyer"; - dto.setType(type); - } else if ("供应端".equals(type)) { - type = "seller"; - dto.setType(type); - } - - // 销售员权限:校验客户类型,只允许buyer和both - if (!"buyer".equals(dto.getType()) && !"both".equals(dto.getType())) { - throw new IllegalArgumentException("销售权限只能更新为供应端类型客户和BOTH类型客户"); - } - - // 1. 根据手机号查询wechat用户ID(关联用户与产品) - UserProductCartDTO user = usersMapper.selectByPhone(dto.getPhoneNumber()); - if (user == null) { - // 若该用户在wechat数据源中不存在,无需更新 - return true; - } - // 2. 更新用户基本信息 - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(user.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - updateUser.setNickName(dto.getNickName()); - updateUser.setType(dto.getType()); - updateUser.setUpdated_at(LocalDateTime.now()); - - int rows = usersMapper.updateByPhone(updateUser); - System.out.println("更新用户基本信息影响行数: " + rows); - - // 3. 如果有产品信息需要更新 - if (("buyer".equals(dto.getType()) || "both".equals(dto.getType())) && - dto.getProductName() != null && !dto.getProductName().trim().isEmpty()) { - - System.out.println("更新产品信息"); - int productRows = usersMapper.updateProductBySellerId( - user.getUserId(), - dto.getProductName(), - dto.getVariety(), - dto.getSpecification(), - dto.getQuantity(), - dto.getGrossWeight(), - dto.getYolk() - ); - System.out.println("更新产品信息影响行数: " + productRows); - } - - return rows > 0; - } -} diff --git a/src/main/java/com/example/web/service/FollowUpService.java b/src/main/java/com/example/web/service/FollowUpService.java deleted file mode 100644 index 826b83f..0000000 --- a/src/main/java/com/example/web/service/FollowUpService.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.example.web.service; - -import com.example.web.entity.Contacts; -import com.example.web.entity.Users; -import com.example.web.mapper.ContactsMapper; -import com.example.web.mapper.SupplyContactsMapper; -import com.example.web.mapper.SupplyUsersMapper; -import com.example.web.mapper.UsersMapper; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -public class FollowUpService { - - private final ContactsMapper contactsMapper; - private final UsersMapper usersMapper; - private final SupplyContactsMapper supplyContactsMapper; - private final SupplyUsersMapper supplyUsersMapper; - - public FollowUpService(ContactsMapper contactsMapper, UsersMapper usersMapper, SupplyContactsMapper supplyContactsMapper, SupplyUsersMapper supplyUsersMapper) { - this.contactsMapper = contactsMapper; - this.usersMapper = usersMapper; - this.supplyContactsMapper = supplyContactsMapper; - this.supplyUsersMapper = supplyUsersMapper; - } - - /** - * 根据电话号码查询跟进信息 - * @param phoneNumber 电话号码 - * @return 跟进信息 - */ - public String getFollowUpByPhone(String phoneNumber) { - try { - // 先尝试在contacts表中查询 - String followup = contactsMapper.getFollowUpByPhone(phoneNumber); - if (followup != null) { - return followup; - } - // 如果contacts表中没有,尝试在users表中查询 - return supplyUsersMapper.getFollowUpByPhone(phoneNumber); - } catch (Exception e) { - return ""; - } - } - - /** - * 保存跟进信息 - * @param phoneNumber 电话号码 - * @param followup 跟进信息 - * @return 是否成功 - */ - public boolean saveFollowUp(String phoneNumber, String followup) { - try { - // 先尝试在contacts表中保存 - if (contactsMapper.updateFollowUpByPhone(phoneNumber, followup) > 0) { - return true; - } - // 如果contacts表中没有,尝试在users表中保存 - return supplyUsersMapper.updateFollowUpByPhone(phoneNumber, followup) > 0; - } catch (Exception e) { - throw e; - } - } -} diff --git a/src/main/java/com/example/web/service/InformationTraService.java b/src/main/java/com/example/web/service/InformationTraService.java deleted file mode 100644 index 4c6f57d..0000000 --- a/src/main/java/com/example/web/service/InformationTraService.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Contacts; -import com.example.web.entity.InformationTra; -import com.example.web.mapper.*; -import com.example.web.config.DynamicDataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; - -@Service -public class InformationTraService { - - @Autowired - private InformationTraMapper informationTraMapper; - - @Autowired - private UsersMapper usersMapper; - - @Autowired - private ContactsMapper contactsMapper; - - /** - * 记录操作事件 - */ - public boolean recordOperationEvent(String phoneNumber, String customerName, String operationEvent, - String managerCompany, String managerDepartment, String organization, - String role, String userName, String assistant) { - // 保存原始数据源,以便在finally块中恢复 - String originalDataSource = DynamicDataSource.getCurrentDataSourceKey(); - try { - // 1. 从两个数据源查询客户信息 - String userId = null; - - // 查询wechat数据源的users表 - DynamicDataSource.setDataSourceKey("wechat"); - UserProductCartDTO wechatUser = usersMapper.selectByPhone(phoneNumber); - - if (wechatUser != null) { - userId = wechatUser.getUserId(); - System.out.println("ℹ️ 从wechat数据源获取到userId: " + userId); - } else { - System.out.println("ℹ️ 在wechat数据源中未找到客户"); - // 查询primary数据源的contacts表 - DynamicDataSource.setDataSourceKey("primary"); - Contacts contact = contactsMapper.selectByPhoneNumber(phoneNumber); - - if (contact != null) { - System.out.println("✅ 在primary数据源中找到客户: " + contact.getNickName()); - userId = contact.getId(); - System.out.println("ℹ️ 使用primary数据源的contact.id作为userId: " + userId); - } - } - - // 如果都没找到,返回失败 - if (userId == null) { - System.err.println("❌ 无法获取客户ID,操作记录失败"); - return false; - } - - // 2. 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - - // 3. 构造操作记录 - InformationTra informationTra = new InformationTra(); - informationTra.setTracompany(managerCompany); - informationTra.setTradepartment(managerDepartment); - informationTra.setTraorganization(organization); - informationTra.setTrarole(role); - informationTra.setTrauserName(userName); - informationTra.setTraassistant(assistant); - informationTra.setUserId(userId); - informationTra.setOperationEvent(operationEvent); - informationTra.setOperationTime(now); - informationTra.setCreatedAt(now); - informationTra.setUpdatedAt(now); - - // 4. 始终写入wechat数据源的informationtra表 - DynamicDataSource.setDataSourceKey("wechat"); - System.out.println("🔄 设置数据源为wechat,准备插入信息跟踪记录"); - int result = informationTraMapper.insertInformationTra(informationTra); - if (result > 0) { - System.out.println("✅ 插入信息跟踪记录成功,影响行数: " + result); - return true; - } else { - System.err.println("❌ 插入信息跟踪记录失败,影响行数: " + result); - return false; - } - } catch (Exception e) { - e.printStackTrace(); - System.err.println("❌ 操作记录异常: " + e.getMessage()); - return false; - } finally { - // 恢复原始数据源,避免线程池复用问题 - if (originalDataSource != null) { - DynamicDataSource.setDataSourceKey(originalDataSource); - } else { - DynamicDataSource.clearDataSourceKey(); - } - System.out.println("🔄 恢复数据源为原始值: " + (originalDataSource != null ? originalDataSource : "默认数据源")); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/LoginService.java b/src/main/java/com/example/web/service/LoginService.java index 59c7592..086fd21 100644 --- a/src/main/java/com/example/web/service/LoginService.java +++ b/src/main/java/com/example/web/service/LoginService.java @@ -1,259 +1,28 @@ package com.example.web.service; import com.example.web.entity.Login; -import com.example.web.entity.Rootdb; -import com.example.web.entity.UsersManagements; -import com.example.web.entity.Managers; -import com.example.web.mapper.LoginMapper; -import com.example.web.mapper.RootdbMapper; -import com.example.web.mapper.UsersManagementsMapper; -import com.example.web.mapper.SupplyUsersManagementsMapper; -import com.example.web.mapper.ManagersMapper; -import com.example.web.mapper.SupplyManagersMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import com.example.web.entity.Personnel; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Service -public class LoginService { - - @Autowired - private LoginMapper loginMapper; - - @Autowired - private RootdbMapper rootdbMapper; - - @Autowired - private UsersManagementsMapper usersManagementsMapper; // 销售端 usermanagements - - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; // 采购端 usermanagements - - @Autowired - private ManagersMapper managersMapper; // 销售端 managers - - @Autowired - private SupplyManagersMapper supplyManagersMapper; // 采购端 managers - - public Map authenticate(String projectName, String userName, String password) { - Map result = new HashMap<>(); - - try { - System.out.println("=== 开始认证过程 ==="); - System.out.println("工位名: " + projectName + ", 用户名: " + userName); - - // 1. 验证登录信息 - Login loginInfo = loginMapper.findByProjectNameAndUserName(projectName, userName); - System.out.println("登录信息查询结果: " + (loginInfo != null ? "成功" : "失败")); - - if (loginInfo == null) { - result.put("success", false); - result.put("message", "用户名或工位名不存在"); - result.put("errorType", "user"); - return result; - } - - // 2. 验证密码 - boolean passwordCorrect = loginInfo.getPassword().equals(password); - System.out.println("密码验证: " + (passwordCorrect ? "正确" : "错误")); - - if (!passwordCorrect) { - result.put("success", false); - result.put("message", "密码错误"); - result.put("errorType", "password"); - return result; - } - - // 3. 获取权限信息 - Rootdb rootInfo = rootdbMapper.findByProjectName(projectName); - System.out.println("权限信息查询结果: " + (rootInfo != null ? "成功" : "失败")); - System.out.println("权限等级: " + (rootInfo != null ? rootInfo.getRoot() : "无")); - - if (rootInfo == null) { - result.put("success", false); - result.put("message", "未找到该职位的权限信息"); - return result; - } - - // 4. 🔥 关键修改:使用 loginId 来查询负责人信息 - String loginId = String.valueOf(loginInfo.getId()); // 获取 login 表的 id - System.out.println("登录ID (loginId): " + loginId); - - boolean isSupplySide = isSupplySideProject(projectName); - System.out.println("🔄 系统识别: " + (isSupplySide ? "采购端" : "销售端")); - - UsersManagements userManagement = null; - boolean fromManagersTable = false; - - // 4.1 首先尝试从 managers 表查询(使用 loginId 作为 managerId) - List managersList; - if (isSupplySide) { - managersList = supplyManagersMapper.selectByUserNameAndManagerId(userName, loginId); - } else { - managersList = managersMapper.selectByUserNameAndManagerId(userName, loginId); - } - - if (managersList != null && !managersList.isEmpty()) { - // 从 managers 表找到数据 - Managers manager = managersList.get(0); - if (managersList.size() > 1) { - System.out.println("找到多个 managers 记录,数量: " + managersList.size()); - // 选择最新的记录 - manager = managersList.stream() - .sorted((m1, m2) -> { - if (m1.getUpdated_at() != null && m2.getUpdated_at() != null) { - return m2.getUpdated_at().compareTo(m1.getUpdated_at()); - } - return 0; - }) - .findFirst() - .orElse(managersList.get(0)); - } - - // 将 Managers 转换为 UsersManagements - userManagement = convertManagerToUserManagement(manager); - fromManagersTable = true; - System.out.println("✅ 从 managers 表获取用户管理信息"); - } else { - // 4.2 如果 managers 表没有数据,再从 usermanagements 表查询(使用 loginId 作为 managerId) - List userManagementsList; - if (isSupplySide) { - userManagementsList = supplyUsersManagementsMapper.findByUserNameAndManagerId(userName, loginId); - } else { - userManagementsList = usersManagementsMapper.findByUserNameAndManagerId(userName, loginId); - } - - if (userManagementsList != null && !userManagementsList.isEmpty()) { - if (userManagementsList.size() > 1) { - System.out.println("找到多个 usermanagements 记录,数量: " + userManagementsList.size()); - userManagement = userManagementsList.stream() - .sorted((u1, u2) -> { - if (u1.getUpdated_at() != null && u2.getUpdated_at() != null) { - return u2.getUpdated_at().compareTo(u1.getUpdated_at()); - } - return 0; - }) - .findFirst() - .orElse(userManagementsList.get(0)); - } else { - userManagement = userManagementsList.get(0); - } - System.out.println("✅ 从 usermanagements 表获取用户管理信息"); - } - } - - if (userManagement == null) { - result.put("success", false); - result.put("message", "未找到对应的负责人信息,请检查用户名和密码是否正确!"); - return result; - } - - // 打印用户管理信息详情 - System.out.println("用户管理信息详情:"); - System.out.println(" - 数据来源: " + (fromManagersTable ? "managers表" : "usermanagements表")); - System.out.println(" - managerId: " + userManagement.getManagerId()); - System.out.println(" - managercompany: " + userManagement.getManagercompany()); - System.out.println(" - managerdepartment: " + userManagement.getManagerdepartment()); - System.out.println(" - organization: " + userManagement.getOrganization()); - System.out.println(" - role: " + userManagement.getRole()); - System.out.println(" - userName: " + userManagement.getUserName()); - System.out.println(" - assistant: " + userManagement.getAssistant()); - - // 5. 生成token(包含端信息) - String token = generateToken(userName, projectName, isSupplySide); - System.out.println("生成的token: " + token); - - // 6. 构建返回结果 - result.put("success", true); - result.put("token", token); - result.put("root", rootInfo.getRoot()); - result.put("user", buildUserResponse(userManagement)); - result.put("isSupplySide", isSupplySide); - result.put("fromManagersTable", fromManagersTable); // 新增:标识数据来源 - result.put("loginId", loginId); // 返回 loginId - - // 返回完整的认证信息供前端使用 - Map authInfo = new HashMap<>(); - authInfo.put("managerId", userManagement.getManagerId() != null ? userManagement.getManagerId() : ""); - authInfo.put("company", userManagement.getManagercompany() != null ? userManagement.getManagercompany() : ""); - authInfo.put("department", userManagement.getManagerdepartment() != null ? userManagement.getManagerdepartment() : ""); - authInfo.put("organization", userManagement.getOrganization() != null ? userManagement.getOrganization() : ""); - authInfo.put("role", userManagement.getRole() != null ? userManagement.getRole() : ""); - authInfo.put("userName", userManagement.getUserName() != null ? userManagement.getUserName() : ""); - authInfo.put("assistant", userManagement.getAssistant() != null ? userManagement.getAssistant() : ""); - - result.put("authInfo", authInfo); - System.out.println("✅ 返回完整认证信息: " + authInfo); - - System.out.println("最终返回结果: " + result); - System.out.println("=== 认证过程结束 ==="); - - } catch (Exception e) { - System.err.println("认证过程中发生异常: " + e.getMessage()); - e.printStackTrace(); - result.put("success", false); - result.put("message", "登录过程中发生错误: " + e.getMessage()); - } - - return result; - } +/** + * @Description: 登录服务接口 + * @Author: + * @Date: 2025-12-17 + */ +public interface LoginService { /** - * 将 Managers 实体转换为 UsersManagements 实体 + * 验证用户登录信息 + * @param projectName 工位名 + * @param userName 用户名 + * @param password 密码 + * @return Login对象,如果验证成功则返回用户信息,否则返回null */ - private UsersManagements convertManagerToUserManagement(Managers manager) { - UsersManagements userManagement = new UsersManagements(); - userManagement.setId(manager.getManager_id()); - userManagement.setUserId(manager.getId()); // 使用企业id作为userId - userManagement.setManagerId(manager.getManagerId()); - userManagement.setManagercompany(manager.getManagercompany()); - userManagement.setManagerdepartment(manager.getManagerdepartment()); - userManagement.setOrganization(manager.getOrganization()); - userManagement.setRole(manager.getRole()); - userManagement.setRoot(manager.getRoot()); - userManagement.setCreated_at(manager.getCreated_at()); - userManagement.setUpdated_at(manager.getUpdated_at()); - userManagement.setUserName(manager.getUserName()); - userManagement.setAssistant(manager.getAssistant()); - return userManagement; - } + Login verifyLogin(String projectName, String userName, String password); /** - * 判断是否为采购端工位 + * 根据managerId获取员工详细信息 + * @param managerId 负责人ID + * @return Personnel对象,包含员工详细信息 */ - private boolean isSupplySideProject(String projectName) { - if (projectName == null) { - return false; - } - - String lowerProjectName = projectName.toLowerCase(); - return lowerProjectName.contains("supply") || - lowerProjectName.contains("purchase") || - lowerProjectName.contains("procurement") || - lowerProjectName.contains("采购"); - } - - /** - * 生成token,包含端信息 - */ - private String generateToken(String userName, String projectName, boolean isSupplySide) { - String side = isSupplySide ? "supply" : "sales"; - return System.currentTimeMillis() + "-" + userName + "-" + projectName + "-" + side; - } - - private Map buildUserResponse(UsersManagements userManagement) { - Map user = new HashMap<>(); - user.put("managerId", userManagement.getManagerId() != null ? userManagement.getManagerId() : ""); - user.put("managercompany", userManagement.getManagercompany() != null ? userManagement.getManagercompany() : ""); - user.put("managerdepartment", userManagement.getManagerdepartment() != null ? userManagement.getManagerdepartment() : ""); - user.put("organization", userManagement.getOrganization() != null ? userManagement.getOrganization() : ""); - user.put("role", userManagement.getRole() != null ? userManagement.getRole() : ""); - user.put("userName", userManagement.getUserName() != null ? userManagement.getUserName() : ""); - user.put("assistant", userManagement.getAssistant() != null ? userManagement.getAssistant() : ""); - System.out.println("构建的用户响应: " + user); - return user; - } + Personnel getPersonnelInfo(String managerId); } \ No newline at end of file diff --git a/src/main/java/com/example/web/service/NotificationService.java b/src/main/java/com/example/web/service/NotificationService.java new file mode 100644 index 0000000..8176040 --- /dev/null +++ b/src/main/java/com/example/web/service/NotificationService.java @@ -0,0 +1,48 @@ +package com.example.web.service; + +import com.example.web.dto.NotificationDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +/** + * WebSocket通知服务 + */ +@Service +public class NotificationService { + + @Autowired + private SimpMessagingTemplate messagingTemplate; + + /** + * 广播通知给所有用户 + */ + public void broadcastNotification(NotificationDTO notification) { + messagingTemplate.convertAndSend("/topic/notifications", notification); + } + + /** + * 发送通知给特定用户 + */ + public void sendNotificationToUser(String userId, NotificationDTO notification) { + messagingTemplate.convertAndSendToUser(userId, "/queue/notifications", notification); + } + + /** + * 发送客户数据更新通知 + */ + public void sendCustomerUpdateNotification(String customerId, String message) { + NotificationDTO notification = new NotificationDTO(); + notification.setType("CUSTOMER_UPDATE"); + notification.setTitle("客户数据更新"); + notification.setMessage(message); + notification.setCustomerId(customerId); + notification.setTimestamp(LocalDateTime.now(ZoneOffset.UTC)); + + // 广播给所有用户 + messagingTemplate.convertAndSend("/topic/customers/" + customerId, notification); + } +} diff --git a/src/main/java/com/example/web/service/PersonnelService.java b/src/main/java/com/example/web/service/PersonnelService.java new file mode 100644 index 0000000..88deaec --- /dev/null +++ b/src/main/java/com/example/web/service/PersonnelService.java @@ -0,0 +1,15 @@ +package com.example.web.service; + +import com.example.web.entity.Personnel; + +/** + * @Description: 员工信息服务接口 + */ +public interface PersonnelService { + /** + * 根据负责人ID获取员工信息 + * @param managerId 负责人ID + * @return Personnel对象 + */ + Personnel getPersonnelByManagerId(String managerId); +} diff --git a/src/main/java/com/example/web/service/PoolCustomerService.java b/src/main/java/com/example/web/service/PoolCustomerService.java deleted file mode 100644 index 6e43d52..0000000 --- a/src/main/java/com/example/web/service/PoolCustomerService.java +++ /dev/null @@ -1,818 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.UsersManagementsMapper; -import com.example.web.mapper.UsersMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class PoolCustomerService { - - @Autowired - private UsersMapper usersMapper; - @Autowired - private UsersManagementsMapper usersManagementsMapper; - - /** - * 公共方法:判断是否为公海池客户(供Controller调用) - */ - public boolean isPublicSeaCustomerPublic(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - return isPublicSeaCustomer(userInfo, authInfo); - } - - /** - * 根据手机号查询微信用户信息(销售端权限:只处理buyer和both类型)- 支持一对多 - */ - public UserProductCartDTO getWechatCustomerByPhone(String phoneNumber) { - if (!StringUtils.hasText(phoneNumber)) { - throw new IllegalArgumentException("手机号不能为空"); - } - - // 1. 根据手机号查询微信用户基本信息 - UserProductCartDTO userInfo = usersMapper.selectByPhone(phoneNumber); - if (userInfo == null) { - throw new RuntimeException("未找到手机号对应的微信用户:" + phoneNumber); - } - - System.out.println("获取到用户基础信息,用户ID: " + userInfo.getUserId() + - ", 类型: " + userInfo.getType() + - ", 公司: " + userInfo.getCompany() + - ", 需求: " + userInfo.getDemand() + - ", 规格: " + userInfo.getSpec()); - - // 2. 获取所有联系人信息(一对多) - try { - List contacts = usersMapper.getUserAllContacts(userInfo.getUserId()); - // 转换为UserProductCartDTO.UsersContacts格式以保持兼容 - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - // 设置contactId - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - userInfo.setUsersContacts(userContacts); - } else { - userInfo.setUsersContacts(Collections.emptyList()); - } - System.out.println("获取用户所有联系人信息,数量: " + (userInfo.getUsersContacts() != null ? userInfo.getUsersContacts().size() : 0)); - } catch (Exception e) { - System.err.println("获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - // 3. 获取所有购物车项信息(一对多) - if ("buyer".equals(userInfo.getType()) || "both".equals(userInfo.getType())) { - try { - List cartItems = usersMapper.getUserAllCartItems(userInfo.getUserId()); - // 转换为UserProductCartDTO.CartItem格式以保持兼容 - if (cartItems != null && !cartItems.isEmpty()) { - List userCartItems = cartItems.stream() - .map(item -> { - UserProductCartDTO.CartItem cartItem = new UserProductCartDTO.CartItem(); - cartItem.setCartItemId(item.getCartItemId()); - cartItem.setProductId(item.getProductId()); - cartItem.setProductName(item.getProductName()); - cartItem.setSpecification(item.getSpecification()); - cartItem.setQuantity(item.getQuantity()); - cartItem.setGrossWeight(item.getGrossWeight()); - cartItem.setYolk(item.getYolk()); - return cartItem; - }) - .collect(Collectors.toList()); - userInfo.setCartItems(userCartItems); - } else { - userInfo.setCartItems(Collections.emptyList()); - } - System.out.println("获取用户所有购物车项信息,数量: " + (userInfo.getCartItems() != null ? userInfo.getCartItems().size() : 0)); - } catch (Exception e) { - System.err.println("获取购物车信息失败: " + e.getMessage()); - userInfo.setCartItems(Collections.emptyList()); - } - userInfo.setProducts(Collections.emptyList()); - } - - return userInfo; - } - - /** - * 根据用户ID获取用户信息和相关产品/购物车数据 - */ - public UserProductCartDTO getCustomerInfo(String userId) { - if (!StringUtils.hasText(userId)) { - throw new IllegalArgumentException("用户ID不能为空"); - } - - // 1. 获取用户基本信息 - UserProductCartDTO userInfo = usersMapper.getUserBasicInfo(userId); - if (userInfo == null) { - throw new RuntimeException("用户不存在: " + userId); - } - - // 2. 根据用户类型查询不同的数据 - if ("seller".equals(userInfo.getType())) { - // 卖家:查询产品信息 - List products = usersMapper.getSellerProducts(userId); - userInfo.setProducts(products != null ? products : Collections.emptyList()); - userInfo.setCartItems(Collections.emptyList()); - } else { - // 买家:查询购物车信息 - List cartItems = usersMapper.getBuyerCartItems(userId); - userInfo.setCartItems(cartItems != null ? cartItems : Collections.emptyList()); - userInfo.setProducts(Collections.emptyList()); - } - - // 3. 获取联系人信息 - 安全处理 - try { - List contacts = usersMapper.getUserContacts(userId); - userInfo.setUsersContacts(contacts != null ? contacts : Collections.emptyList()); - } catch (Exception e) { - System.err.println("获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - return userInfo; - } - - /** - * 获取所有客户信息 - 使用数据库层面权限过滤(销售端版本,支持分页) - */ - public List getAllCustomers(ManagerAuthInfo authInfo) { - try { - System.out.println("===================================================="); - System.out.println("🚀 开始获取所有微信用户数据(数据库权限过滤,销售端)..."); - - // 移除固定的分页限制,获取所有数据 - // 注意:这里可以根据实际需要调整,或者改为支持传入分页参数的方法 - int limit = Integer.MAX_VALUE; // 获取所有数据 - int offset = 0; // 从第一条开始 - - // 1. 获取授权客户总数 - System.out.println("📊 查询授权客户总数..."); - int totalCount = usersMapper.getAuthorizedCustomersCount(authInfo); - System.out.println("✅ 授权客户总数: " + totalCount); - - // 2. 使用数据库层面权限过滤并分页 - System.out.println("📋 查询授权客户基础信息(分页查询)..."); - List authorizedUsers = usersMapper.getAuthorizedCustomers(authInfo, limit, offset); - - System.out.println("✅ 授权客户数据查询完成"); - System.out.println("📊 当前页获取到授权客户数据条数: " + (authorizedUsers != null ? authorizedUsers.size() : "null")); - // 统计通知状态为banold的用户数量 - long banoldCount = authorizedUsers != null ? authorizedUsers.stream().filter(user -> "banold".equals(user.getNotice())).count() : 0; - System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); - - List result = new ArrayList<>(); - - if (authorizedUsers != null && !authorizedUsers.isEmpty()) { - // 🔥 修改:收集所有用户ID用于批量查询 - List userIds = authorizedUsers.stream() - .map(UserProductCartDTO::getUserId) - .filter(Objects::nonNull) - .filter(userId -> !userId.trim().isEmpty()) - .distinct() - .collect(Collectors.toList()); - - System.out.println("🔍 需要批量查询的用户数量: " + userIds.size()); - - // 🔥 修改:批量查询所有相关数据 - Map managerMap = batchQueryManagers(userIds); - Map> contactsMap = batchQueryContacts(userIds); - Map> cartItemsMap = batchQueryCartItems(userIds); - - // 2. 为每个授权用户构建完整信息 - System.out.println("🔄 开始处理 " + authorizedUsers.size() + " 条授权用户数据..."); - - for (int i = 0; i < authorizedUsers.size(); i++) { - UserProductCartDTO user = authorizedUsers.get(i); - try { - // 🔥 修改:使用批量查询的数据构建完整用户信息 - UserProductCartDTO fullUserInfo = buildUserInfoFromBatchData(user, managerMap, contactsMap, cartItemsMap); - if (fullUserInfo != null) { - result.add(fullUserInfo); - // 打印前几个客户的详细信息 - if (i < 3) { - System.out.println("📝 授权客户样例 " + (i + 1) + ": " + - "ID=" + fullUserInfo.getUserId() + - ", 手机=" + fullUserInfo.getPhoneNumber() + - ", 公司=" + fullUserInfo.getCompany() + - ", 联系人数量=" + (fullUserInfo.getUsersContacts() != null ? fullUserInfo.getUsersContacts().size() : 0) + - ", 购物车数量=" + (fullUserInfo.getCartItems() != null ? fullUserInfo.getCartItems().size() : 0)); - } - } - } catch (Exception e) { - System.err.println("❌ 构建用户 " + user.getUserId() + " 的详细信息时出错: " + e.getMessage()); - } - } - } - - System.out.println("===================================================="); - System.out.println("🎉 数据获取完成(数据库权限过滤,销售端)"); - System.out.println("📊 返回记录数: " + result.size()); - System.out.println("===================================================="); - - return result; - } catch (Exception e) { - System.err.println("❌ 获取授权客户信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 检查是否有权限查看客户 - */ - private boolean hasPermissionToViewCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 使用新的公海池判断逻辑 - if (isPublicSeaCustomer(userInfo, authInfo)) { - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - - /** - * 判断是否为公海池客户 - 根据负责人信息中的认证字段是否为空判断 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - System.out.println("🔍 PoolCustomerService - 客户等级检查: " + userInfo.getLevel() + " → 是否公海池等级: " + isPublicSeaLevel); - - if (!isPublicSeaLevel) { - return false; - } - - // 根据不同类型的公海池使用不同判断逻辑 - String level = userInfo.getLevel(); - - if ("company-sea-pools".equals(level) || "公海池".equals(level)) { - // 公司公海池:必须没有负责人信息 - boolean result = !hasManagerAuthInfo(userInfo.getUserId()); - System.out.println("🏢 公司公海池检查结果: " + result); - return result; - } else if ("organization-sea-pools".equals(level)) { - // 组织公海池:必须有负责人信息且组织匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 组织公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameOrganization = hasSameOrganization(userInfo.getUserId(), authInfo); - System.out.println("🏢 组织公海池检查结果 - 有负责人: " + hasManager + ", 组织匹配: " + sameOrganization + " → 结果: " + sameOrganization); - return sameOrganization; - } else if ("department-sea-pools".equals(level)) { - // 部门公海池:必须有负责人信息且部门匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 部门公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameDepartment = hasSameDepartment(userInfo.getUserId(), authInfo); - System.out.println("🏢 部门公海池检查结果 - 有负责人: " + hasManager + ", 部门匹配: " + sameDepartment + " → 结果: " + sameDepartment); - return sameDepartment; - } - - return false; - } - - /** - * 检查是否有负责人认证信息 - */ - private boolean hasManagerAuthInfo(String userId) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - // 检查认证字段是否为空 - 只要有一个认证字段有值,就有负责人信息 - boolean hasAuthInfo = StringUtils.hasText(userManager.getManagerId()) || - StringUtils.hasText(userManager.getManagercompany()) || - StringUtils.hasText(userManager.getManagerdepartment()) || - StringUtils.hasText(userManager.getOrganization()) || - StringUtils.hasText(userManager.getRole()) || - StringUtils.hasText(userManager.getUserName()) || - StringUtils.hasText(userManager.getAssistant()); - - System.out.println("📋 负责人认证信息检查结果: " + (hasAuthInfo ? "有认证信息" : "无认证信息")); - return hasAuthInfo; - } catch (Exception e) { - System.err.println("❌ 检查负责人认证信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一组织 - */ - private boolean hasSameOrganization(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameOrganization = StringUtils.hasText(userManager.getOrganization()) && - userManager.getOrganization().equals(authInfo.getOrganization()); - - System.out.println("🏢 组织匹配检查: " + userManager.getOrganization() + " vs " + authInfo.getOrganization() + " → " + sameOrganization); - return sameOrganization; - } catch (Exception e) { - System.err.println("❌ 检查组织信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一部门 - */ - private boolean hasSameDepartment(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameDepartment = StringUtils.hasText(userManager.getManagerdepartment()) && - userManager.getManagerdepartment().equals(authInfo.getManagerdepartment()); - - System.out.println("🏢 部门匹配检查: " + userManager.getManagerdepartment() + " vs " + authInfo.getManagerdepartment() + " → " + sameDepartment); - return sameDepartment; - } catch (Exception e) { - System.err.println("❌ 检查部门信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查用户负责人权限 - 优化版本,数据库层面直接匹配 - */ - private boolean hasUserManagerPermission(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 检查用户负责人权限,用户ID: " + userId); - - // 🔥 优化:直接在数据库层面查询匹配的负责人记录,避免内存比较 - UsersManagements userManager = usersManagementsMapper.findByUserIdAndAuthInfo(userId, authInfo); - - // 🔥 优化:如果没有找到匹配的负责人记录,检查是否为公海池客户 - if (userManager == null) { - System.out.println("🔍 未找到匹配的负责人记录,检查客户等级..."); - - // 获取用户信息检查等级 - UserProductCartDTO userInfo = usersMapper.getUserBasicInfo(userId); - if (userInfo != null) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - boolean isPublicSea = publicSeaLevels.contains(userInfo.getLevel()); - - if (isPublicSea) { - System.out.println("✅ 公海池客户,允许查看"); - return true; - } - } - - System.out.println("❌ 非公海池客户且无匹配负责人,拒绝访问"); - return false; - } - - // 🔥 优化:数据库已经完成匹配,直接返回true - System.out.println("✅ 找到匹配的负责人记录,允许查看"); - System.out.println("📝 负责人信息: " + - "公司=" + userManager.getManagercompany() + - ", 部门=" + userManager.getManagerdepartment() + - ", 组织=" + userManager.getOrganization() + - ", 负责人=" + userManager.getUserName()); - - return true; - - } catch (Exception e) { - System.err.println("❌ 检查用户负责人权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 检查负责人信息是否匹配(UsersManagements) - */ - private boolean isManagerMatch(UsersManagements userManager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(userManager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(userManager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(userManager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(userManager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(userManager.getUserName())); - - System.out.println("🔐 用户负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - - /** - * 获取公海池客户完整信息 - 支持一对多(单个查询版本) - */ - public UserProductCartDTO getPublicSeaCustomerInfo(String userId) { - if (!StringUtils.hasText(userId)) { - System.out.println("⚠️ 用户ID为空"); - return null; - } - - // 1. 获取用户基本信息 - UserProductCartDTO userInfo = usersMapper.getUserBasicInfo(userId); - if (userInfo == null) { - System.out.println("⚠️ 用户不存在: " + userId); - return null; - } - - // 2. 如果通知状态为banold,则更新为old - if ("banold".equals(userInfo.getNotice())) { - System.out.println("🔄 更新通知状态, userId: " + userId + ", 从banold改为old"); - usersMapper.updateNotice(userId, "old"); - userInfo.setNotice("old"); - } - - // 销售端权限校验 - if (!"buyer".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - System.out.println("🚫 过滤掉非客户端客户: " + userId + " (类型: " + userInfo.getType() + ")"); - return null; - } - - // 🔥 恢复:原有的单个查询负责人信息逻辑 - try { - UsersManagements userManager = usersManagementsMapper.findByUserId(userId); - if (userManager != null) { - System.out.println("✅ 获取到负责人信息: " + - "负责人=" + userManager.getUserName() + - ", 组织=" + userManager.getOrganization() + - ", 部门=" + userManager.getManagerdepartment()); - } else { - System.out.println("⚠️ 未找到负责人信息"); - } - } catch (Exception e) { - System.err.println("❌ 获取负责人信息失败: " + e.getMessage()); - } - - // 2. 获取联系人信息 - 一对多 - try { - List contacts = usersMapper.getUserAllContacts(userId); - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - userInfo.setUsersContacts(userContacts); - } else { - userInfo.setUsersContacts(Collections.emptyList()); - } - } catch (Exception e) { - System.err.println("❌ 获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - // 3. 销售端:获取购物车信息(公海需求)- 一对多 - try { - List cartItems = usersMapper.getUserAllCartItems(userId); - System.out.println("🔍 查询到的购物车数据条数: " + (cartItems != null ? cartItems.size() : 0)); - - if (cartItems != null && !cartItems.isEmpty()) { - List userCartItems = cartItems.stream() - .map(item -> { - UserProductCartDTO.CartItem cartItem = new UserProductCartDTO.CartItem(); - cartItem.setCartItemId(item.getCartItemId()); - cartItem.setProductId(item.getProductId()); - cartItem.setProductName(item.getProductName()); - cartItem.setSpecification(item.getSpecification()); - cartItem.setQuantity(item.getQuantity()); - cartItem.setGrossWeight(item.getGrossWeight()); - cartItem.setYolk(item.getYolk()); - - // 调试日志 - System.out.println("📦 转换购物车项: " + - "ID=" + cartItem.getCartItemId() + - ", 产品=" + cartItem.getProductName() + - ", 规格=" + cartItem.getSpecification()); - - return cartItem; - }) - .collect(Collectors.toList()); - userInfo.setCartItems(userCartItems); - System.out.println("✅ 成功设置购物车数据,数量: " + userCartItems.size()); - } else { - userInfo.setCartItems(Collections.emptyList()); - System.out.println("⚠️ 购物车数据为空"); - } - userInfo.setProducts(Collections.emptyList()); // 销售端不使用产品信息 - } catch (Exception e) { - System.err.println("❌ 获取购物车信息失败: " + e.getMessage()); - e.printStackTrace(); - userInfo.setCartItems(Collections.emptyList()); - userInfo.setProducts(Collections.emptyList()); - } - - // 最终调试信息 - System.out.println("🎯 最终返回的用户数据: " + - "cartItems数量=" + (userInfo.getCartItems() != null ? userInfo.getCartItems().size() : "null") + - ", contacts数量=" + (userInfo.getUsersContacts() != null ? userInfo.getUsersContacts().size() : "null")); - - return userInfo; - } - - /** - * 获取所有客户信息 - 不进行负责人过滤,直接返回所有数据(销售端版本) - */ - public List getAllCustomersWithoutFilter() { - try { - System.out.println("===================================================="); - System.out.println("🚀 开始获取所有微信用户数据(无过滤,销售端)..."); - - // 1. 获取所有用户的基本信息 - System.out.println("📋 查询用户基础信息..."); - List allUsers = usersMapper.getAllUserBasicInfo(); - - System.out.println("✅ 基础用户数据查询完成"); - System.out.println("📊 获取到基础用户数据条数: " + (allUsers != null ? allUsers.size() : "null")); - // 统计通知状态为banold的用户数量 - long banoldCount = allUsers != null ? allUsers.stream().filter(user -> "banold".equals(user.getNotice())).count() : 0; - System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); - - List result = new ArrayList<>(); - - if (allUsers != null && !allUsers.isEmpty()) { - // 🔥 修改:收集所有用户ID用于批量查询 - List userIds = allUsers.stream() - .map(UserProductCartDTO::getUserId) - .filter(Objects::nonNull) - .filter(userId -> !userId.trim().isEmpty()) - .distinct() - .collect(Collectors.toList()); - - System.out.println("🔍 需要批量查询的用户数量: " + userIds.size()); - - // 🔥 修改:批量查询所有相关数据 - Map managerMap = batchQueryManagers(userIds); - Map> contactsMap = batchQueryContacts(userIds); - Map> cartItemsMap = batchQueryCartItems(userIds); - - // 2. 为每个用户构建完整信息 - System.out.println("🔄 开始处理 " + allUsers.size() + " 条用户数据..."); - - for (int i = 0; i < allUsers.size(); i++) { - UserProductCartDTO user = allUsers.get(i); - try { - // 销售端权限:只处理buyer和both类型 - if (!"buyer".equals(user.getType()) && !"both".equals(user.getType())) { - System.out.println("🚫 过滤掉非供应端客户: " + user.getUserId() + " (类型: " + user.getType() + ")"); - continue; - } - - // 🔥 修改:使用批量查询的数据构建完整用户信息 - UserProductCartDTO fullUserInfo = buildUserInfoFromBatchData(user, managerMap, contactsMap, cartItemsMap); - if (fullUserInfo != null) { - result.add(fullUserInfo); - // 打印前几个客户的详细信息 - if (i < 3) { - System.out.println("📝 客户样例 " + (i + 1) + ": " + - "ID=" + fullUserInfo.getUserId() + - ", 手机=" + fullUserInfo.getPhoneNumber() + - ", 公司=" + fullUserInfo.getCompany() + - ", 联系人数量=" + (fullUserInfo.getUsersContacts() != null ? fullUserInfo.getUsersContacts().size() : 0) + - ", 购物车数量=" + (fullUserInfo.getCartItems() != null ? fullUserInfo.getCartItems().size() : 0)); - } - } - } catch (Exception e) { - System.err.println("❌ 构建用户 " + user.getUserId() + " 的详细信息时出错: " + e.getMessage()); - } - } - } - - System.out.println("===================================================="); - System.out.println("🎉 数据获取完成(无过滤,销售端)"); - System.out.println("📊 返回记录数: " + result.size()); - System.out.println("===================================================="); - - return result; - } catch (Exception e) { - System.err.println("❌ 获取所有客户信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 1.批量查询负责人信息 - */ - private Map batchQueryManagers(List userIds) { - Map managerMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - List allManagers = usersManagementsMapper.findByUserIds(userIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询负责人信息失败: " + e.getMessage()); - } - } - return managerMap; - } - - /** - * 2.批量查询联系人信息 - */ - private Map> batchQueryContacts(List userIds) { - Map> contactsMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - List allContacts = usersMapper.getUserContactsByUserIds(userIds); - // 按用户ID分组 - for (UsersMapper.ContactInfo contact : allContacts) { - String userId = contact.getUserId(); - if (userId != null) { - contactsMap.computeIfAbsent(userId, k -> new ArrayList<>()).add(contact); - } - } - System.out.println("✅ 批量查询联系人信息完成,共获取 " + allContacts.size() + " 条记录,涉及 " + contactsMap.size() + " 个用户"); - } catch (Exception e) { - System.err.println("❌ 批量查询联系人信息失败: " + e.getMessage()); - } - } - return contactsMap; - } - - /** - * 3.批量查询购物车信息 - */ - private Map> batchQueryCartItems(List userIds) { - Map> cartItemsMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - List allCartItems = usersMapper.getCartItemsByUserIds(userIds); - // 按用户ID分组 - for (UsersMapper.CartItem cartItem : allCartItems) { - String userId = cartItem.getUserId(); - if (userId != null) { - cartItemsMap.computeIfAbsent(userId, k -> new ArrayList<>()).add(cartItem); - } - } - System.out.println("✅ 批量查询购物车信息完成,共获取 " + allCartItems.size() + " 条记录,涉及 " + cartItemsMap.size() + " 个用户"); - } catch (Exception e) { - System.err.println("❌ 批量查询购物车信息失败: " + e.getMessage()); - } - } - return cartItemsMap; - } - - /** - * 4.从批量查询的数据构建用户完整信息 - */ - private UserProductCartDTO buildUserInfoFromBatchData(UserProductCartDTO basicUserInfo, - Map managerMap, - Map> contactsMap, - Map> cartItemsMap) { - String userId = basicUserInfo.getUserId(); - - // 销售端权限校验 - if (!"buyer".equals(basicUserInfo.getType()) && !"both".equals(basicUserInfo.getType())) { - System.out.println("🚫 过滤掉非客户端客户: " + userId + " (类型: " + basicUserInfo.getType() + ")"); - return null; - } - - // 🔥 设置负责人信息(记录日志,但不设置到DTO中,因为UserProductCartDTO没有负责人字段) - try { - UsersManagements userManager = managerMap.get(userId); - if (userManager != null) { - System.out.println("✅ 从批量Map中获取到负责人信息: " + - "负责人=" + userManager.getUserName() + - ", 组织=" + userManager.getOrganization() + - ", 部门=" + userManager.getManagerdepartment()); - } else { - System.out.println("⚠️ 未在批量Map中找到负责人信息,用户ID: " + userId); - } - } catch (Exception e) { - System.err.println("❌ 从Map获取负责人信息失败: " + e.getMessage()); - } - - // 🔥 设置联系人信息 - 从批量查询的Map中获取 - try { - List contacts = contactsMap.get(userId); - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - basicUserInfo.setUsersContacts(userContacts); - System.out.println("✅ 成功设置联系人数据,数量: " + userContacts.size() + ",用户ID: " + userId); - } else { - basicUserInfo.setUsersContacts(Collections.emptyList()); - System.out.println("⚠️ 未找到联系人信息,用户ID: " + userId); - } - } catch (Exception e) { - System.err.println("❌ 设置联系人信息失败: " + e.getMessage()); - basicUserInfo.setUsersContacts(Collections.emptyList()); - } - - // 🔥 设置购物车信息 - 从批量查询的Map中获取 - try { - List cartItems = cartItemsMap.get(userId); - if (cartItems != null && !cartItems.isEmpty()) { - List userCartItems = cartItems.stream() - .map(item -> { - UserProductCartDTO.CartItem cartItem = new UserProductCartDTO.CartItem(); - cartItem.setCartItemId(item.getCartItemId()); - cartItem.setProductId(item.getProductId()); - cartItem.setProductName(item.getProductName()); - cartItem.setSpecification(item.getSpecification()); - cartItem.setQuantity(item.getQuantity()); - cartItem.setGrossWeight(item.getGrossWeight()); - cartItem.setYolk(item.getYolk()); - return cartItem; - }) - .collect(Collectors.toList()); - basicUserInfo.setCartItems(userCartItems); - System.out.println("✅ 成功设置购物车数据,数量: " + userCartItems.size() + ",用户ID: " + userId); - } else { - basicUserInfo.setCartItems(Collections.emptyList()); - System.out.println("⚠️ 购物车数据为空,用户ID: " + userId); - } - basicUserInfo.setProducts(Collections.emptyList()); // 销售端不使用产品信息 - } catch (Exception e) { - System.err.println("❌ 设置购物车信息失败: " + e.getMessage()); - basicUserInfo.setCartItems(Collections.emptyList()); - basicUserInfo.setProducts(Collections.emptyList()); - } - - return basicUserInfo; - } - - - - /** - * 只检查等级是否为公海池等级(不检查负责人信息) - */ - private boolean isPublicSeaLevel(String level) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - boolean isPublicSeaLevel = publicSeaLevels.contains(level); - System.out.println("🔍 等级检查: " + level + " → 是否公海池等级: " + isPublicSeaLevel); - - return isPublicSeaLevel; - } - - /** - * 销售端:获取客户的购物车信息(公海需求) - */ - public List getCustomerProducts(String phoneNumber) { - try { - UserProductCartDTO user = usersMapper.selectByPhone(phoneNumber); - if (user != null && ("buyer".equals(user.getType()) || "both".equals(user.getType()))) { - return usersMapper.getSellerProducts(user.getUserId()); - } - return new ArrayList<>(); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/RootService.java b/src/main/java/com/example/web/service/RootService.java deleted file mode 100644 index 830c76b..0000000 --- a/src/main/java/com/example/web/service/RootService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.web.service; - -import com.example.web.mapper.RootdbMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class RootService { - -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java b/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java deleted file mode 100644 index abc93cb..0000000 --- a/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.SupplyUsersMapper; -import com.example.web.mapper.SupplyUsersManagementsMapper; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import java.time.LocalDateTime; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class SupplyCustomerRecycleService { - - private static final Logger log = LoggerFactory.getLogger(SupplyCustomerRecycleService.class); - - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; - @Autowired - private SupplyUsersMapper supplyUsersMapper; - - // 从配置文件注入回流时间配置 - @Value("${app.recycle.unclassified-to-organization-days:30}") - private int unclassifiedToOrganizationDays; - - @Value("${app.recycle.organization-to-department-days:30}") - private int organizationToDepartmentDays; - - /** - * 客户回流定时任务 - 每天凌晨2点执行 - */ - @Scheduled(cron = "0 0 2 * * ?") - @Transactional(rollbackFor = Exception.class) - public void autoRecycleCustomers() { - log.info("🎯 开始执行客户回流任务..."); - log.info("📅 回流配置 - 未分级->组织公海池: {}天, 组织->部门公海池: {}天", - unclassifiedToOrganizationDays, organizationToDepartmentDays); - - try { - // 1. 未分级客户回流到组织公海池 - recycleUnclassifiedToOrganization(); - - // 2. 组织公海池客户回流到部门公海池 - recycleOrganizationToDepartment(); - - log.info("✅ 客户回流任务执行完成"); - } catch (Exception e) { - log.error("❌ 客户回流任务执行失败", e); - throw e; // 抛出异常确保事务回滚 - } - } - - /** - * 未分级客户回流到组织公海池 - 修复:保留负责人信息 - */ - private void recycleUnclassifiedToOrganization() { - log.info("🔄 开始处理未分级客户回流..."); - - LocalDateTime thresholdTime = LocalDateTime.now().minusDays(unclassifiedToOrganizationDays); - - // 查询超过指定天数未更新的未分级客户 - List unclassifiedCustomers = supplyUsersMapper.findUnclassifiedCustomersOlderThan(thresholdTime); - - log.info("📊 找到 {} 个需要回流的未分级客户 (阈值: {}天前)", - unclassifiedCustomers.size(), unclassifiedToOrganizationDays); - - int recycledCount = 0; - for (UserProductCartDTO customer : unclassifiedCustomers) { - try { - // 🔥 关键修改:先查询当前的负责人信息 - UsersManagements currentManager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); - - log.info("🔍 客户 {} 当前负责人信息: {}", customer.getUserId(), - currentManager != null ? currentManager.getUserName() : "无负责人"); - - // 更新客户等级为组织公海池 - boolean success = supplyUsersMapper.updateCustomerLevel( - customer.getUserId(), - "organization-sea-pools", - LocalDateTime.now() - ); - - if (success) { - // 🔥 关键修改:确保负责人信息保留 - if (currentManager != null) { - // 更新负责人信息的更新时间,但不改变负责人本身 - boolean managerUpdated = supplyUsersManagementsMapper.updateManagerUpdateTime( - customer.getUserId(), LocalDateTime.now()); - log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(), - managerUpdated ? "成功" : "失败"); - } - - recycledCount++; - log.info("🔄 客户 {} 从未分级回流到组织公海池, 负责人: {}", - customer.getUserId(), - currentManager != null ? currentManager.getUserName() : "无"); - } - } catch (Exception e) { - log.error("❌ 回流客户失败: {}", customer.getUserId(), e); - } - } - - log.info("✅ 未分级客户回流完成: {} 个客户已回流到组织公海池", recycledCount); - } - - /** - * 组织公海池客户回流到部门公海池 - 修复:保留负责人信息 - */ - private void recycleOrganizationToDepartment() { - log.info("🔄 开始处理组织公海池客户回流..."); - - LocalDateTime thresholdTime = LocalDateTime.now().minusDays(organizationToDepartmentDays); - - // 查询超过指定天数未更新的组织公海池客户 - List organizationCustomers = supplyUsersMapper.findOrganizationSeaPoolsCustomersOlderThan(thresholdTime); - - log.info("📊 找到 {} 个需要回流的组织公海池客户 (阈值: {}天前)", - organizationCustomers.size(), organizationToDepartmentDays); - - int recycledCount = 0; - for (UserProductCartDTO customer : organizationCustomers) { - try { - // 🔥 关键修改:先查询当前的负责人信息 - UsersManagements currentManager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); - - log.info("🔍 客户 {} 当前负责人信息: {}", customer.getUserId(), - currentManager != null ? currentManager.getUserName() : "无负责人"); - - // 更新客户等级为部门公海池 - boolean success = supplyUsersMapper.updateCustomerLevel( - customer.getUserId(), - "department-sea-pools", - LocalDateTime.now() - ); - - if (success) { - // 🔥 关键修改:确保负责人信息保留 - if (currentManager != null) { - // 更新负责人信息的更新时间,但不改变负责人本身 - boolean managerUpdated = supplyUsersManagementsMapper.updateManagerUpdateTime( - customer.getUserId(), LocalDateTime.now()); - log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(), - managerUpdated ? "成功" : "失败"); - } - - recycledCount++; - log.info("🔄 客户 {} 从组织公海池回流到部门公海池, 负责人: {}", - customer.getUserId(), - currentManager != null ? currentManager.getUserName() : "无"); - } - } catch (Exception e) { - log.error("❌ 回流客户失败: {}", customer.getUserId(), e); - } - } - - log.info("✅ 组织公海池客户回流完成: {} 个客户已回流到部门公海池", recycledCount); - } - - /** - * 手动触发回流任务(用于测试或手动执行) - */ - public void manualRecycle() { - log.info("🔧 手动触发客户回流任务..."); - autoRecycleCustomers(); - } - - /** - * 获取当前回流配置信息(用于调试或监控) - */ - public String getRecycleConfigInfo() { - return String.format("回流配置 - 未分级->组织公海池: %d天, 组织->部门公海池: %d天", - unclassifiedToOrganizationDays, organizationToDepartmentDays); - } - - /** - * 🔥 新增:获取回流客户完整信息(用于前端显示) - */ - public List getRecycledCustomersWithManagerInfo() { - log.info("🔍 获取回流客户完整信息(包含负责人信息)"); - - // 获取最近回流的客户(例如最近1天内回流的) - LocalDateTime sinceTime = LocalDateTime.now().minusDays(1); - List recycledCustomers = supplyUsersMapper.findRecentlyRecycledCustomers(sinceTime); - - // 为每个客户加载负责人信息 - for (UserProductCartDTO customer : recycledCustomers) { - UsersManagements manager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); - if (manager != null) { - // 将负责人信息设置到DTO中(需要扩展UserProductCartDTO或使用其他方式) - log.info("✅ 客户 {} 回流后负责人信息: {}", customer.getUserId(), manager.getUserName()); - } - } - - log.info("📊 获取到 {} 个回流客户的完整信息", recycledCustomers.size()); - return recycledCustomers; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/SupplyCustomerService.java b/src/main/java/com/example/web/service/SupplyCustomerService.java deleted file mode 100644 index f20a085..0000000 --- a/src/main/java/com/example/web/service/SupplyCustomerService.java +++ /dev/null @@ -1,1330 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Managers; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.*; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -@Service -@RequiredArgsConstructor -public class SupplyCustomerService { - - @Autowired - private SupplyContactsMapper supplyContactsMapper; - - @Autowired - private SupplyUsersMapper supplyUsersMapper; - - @Autowired - private SupplyEnterpriseMapper supplyEnterpriseMapper; - - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; - - @Autowired - private SupplyEnterpriseService supplyEnterpriseService; - - @Autowired - private SupplyPoolCustomerService supplyPoolCustomerService; - - // ==================== 精确更新方法 ==================== - - /** - * 精确更新基于电话号码的客户信息 - 支持精确修改特定联系人或产品项 - * 专门用于公海池客户更新,处理客户等级变化时的负责人信息更新 - */ - public boolean updatePhoneBasedCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - validatePhoneNumber(dto.getPhoneNumber()); - - System.out.println("🚀 [采购端] 开始精确更新公海池客户信息,手机号: " + dto.getPhoneNumber()); - - try { - // 1. 验证客户存在性 - UserProductCartDTO existingUser = validateAndGetUser(dto.getPhoneNumber()); - String userId = existingUser.getUserId(); - - // 🔥 关键修复:规范化类型 - String normalizedType = normalizeCustomerType(dto.getType()); - dto.setType(normalizedType); - - // 记录原始等级用于比较 - String originalLevel = existingUser.getLevel(); - String newLevel = dto.getLevel(); - - System.out.println("📊 客户等级变化检查 - 原始: " + originalLevel + ", 新: " + newLevel); - - // 🔥 修复:添加详细的类型转换日志 - System.out.println("🔄 开始类型转换,原始类型: " + dto.getType()); - - // 类型转换逻辑 - String originalType = dto.getType(); - String convertedType = convertCustomerType(originalType); - dto.setType(convertedType); - - System.out.println("🔄 类型转换完成: " + originalType + " → " + convertedType); - - // 2. 权限校验 - System.out.println("🔐 开始权限校验,当前类型: " + dto.getType()); - validatePurchasePermission(dto.getType()); - - // 3. 更新用户基本信息 - updateUserBasicInfo(dto, existingUser); - - // 4. 精确更新联系人信息 - updateContactInfoPrecise(dto, userId); - - // 5. 精确更新产品信息 - updateProductInfoPrecise(dto, userId); - - // 6. 检查是否需要生成/更新负责人信息(从公海池变为非公海池)- 传递authInfo - checkAndUpdateManagerInfo(originalLevel, newLevel, dto, userId, authInfo); - - System.out.println("✅ 公海池客户信息精确更新成功"); - return true; - - } catch (Exception e) { - System.err.println("❌ 精确更新公海池客户信息失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("更新公海池客户信息失败: " + e.getMessage(), e); - } - } - - /** - * 统一的客户类型转换方法 - 采购端 - */ - private String convertCustomerType(String originalType) { - if (originalType == null) { - System.out.println("⚠️ 客户类型为空,使用默认值 seller"); - return "seller"; - } - - switch (originalType.toUpperCase()) { - case "BOTH": - case "供应端&BOTH": - System.out.println("🔄 转换 BOTH 类型"); - return "both"; - case "客户端": - case "BUYER": - System.out.println("🔄 转换 buyer 类型"); - return "buyer"; - case "供应端": - case "SELLER": - System.out.println("🔄 转换 seller 类型"); - return "seller"; - default: - System.out.println("⚠️ 未知类型: " + originalType + ",使用原值"); - return originalType; - } - } - - private void checkAndUpdateManagerInfo(String originalLevel, String newLevel, - UnifiedCustomerDTO dto, String userId, ManagerAuthInfo authInfo) { - // 定义公海池和非公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - Set nonPublicSeaLevels = Set.of("important", "normal", "low-value", "logistics", "unclassified"); - - // 情况1:从公海池变为非公海池 - boolean isFromPublicSeaToNonPublic = publicSeaLevels.contains(originalLevel) && - nonPublicSeaLevels.contains(newLevel); - - // 情况2:已经是非公海池且前端提交了负责人信息 - boolean isNonPublicSeaWithManagerUpdate = nonPublicSeaLevels.contains(originalLevel) && - nonPublicSeaLevels.contains(newLevel) && - hasFrontendManagerInfo(dto); - - System.out.println("🎯 负责人信息更新检查: " + - "公海池→非公海池=" + isFromPublicSeaToNonPublic + - ", 非公海池更新负责人=" + isNonPublicSeaWithManagerUpdate); - - if (isFromPublicSeaToNonPublic || isNonPublicSeaWithManagerUpdate) { - System.out.println("🎯 需要处理负责人信息,数据来源: " + - (hasFrontendManagerInfo(dto) ? "前端提交" : "登录信息")); - - handleManagerRecord(userId, dto, authInfo, hasFrontendManagerInfo(dto)); - System.out.println("✅ 负责人信息处理成功"); - } else { - System.out.println("ℹ️ 无需处理负责人信息"); - System.out.println(" 原始等级: " + originalLevel + ", 新等级: " + newLevel); - System.out.println(" 前端提交负责人信息: " + hasFrontendManagerInfo(dto)); - } - } - - /** - * 检查前端是否提交了负责人信息 - */ - private boolean hasFrontendManagerInfo(UnifiedCustomerDTO dto) { - return StringUtils.hasText(dto.getManagercompany()) || - StringUtils.hasText(dto.getManagerdepartment()) || - StringUtils.hasText(dto.getOrganization()) || - StringUtils.hasText(dto.getRole()) || - StringUtils.hasText(dto.getUserName()) || - StringUtils.hasText(dto.getAssistant()); - } - - /** - * 处理负责人信息记录 - 更新或创建(支持前端数据和登录数据) - */ - private void handleManagerRecord(String userId, UnifiedCustomerDTO dto, ManagerAuthInfo authInfo, boolean useFrontendData) { - try { - System.out.println("🔍 开始处理负责人记录,用户ID: " + userId); - System.out.println("📝 数据来源: " + (useFrontendData ? "前端提交" : "登录信息")); - - // 检查是否已存在负责人记录 - UsersManagements existingManager = supplyUsersManagementsMapper.findByUserId(userId); - - if (existingManager != null) { - System.out.println("🔄 负责人记录已存在,进行更新"); - // 更新现有记录 - 根据数据来源选择 - updateExistingManagerRecord(existingManager, dto, authInfo, useFrontendData); - } else { - System.out.println("➕ 创建新的负责人记录"); - // 创建新记录 - 根据数据来源选择 - createNewManagerRecord(userId, dto, authInfo, useFrontendData); - } - - // 验证负责人信息是否成功处理 - UsersManagements verifiedManager = supplyUsersManagementsMapper.findByUserId(userId); - System.out.println("✅ 负责人信息验证: " + (verifiedManager != null ? "成功" : "失败")); - if (verifiedManager != null) { - System.out.println("📝 验证后的负责人信息: " + - "公司=" + verifiedManager.getManagercompany() + - ", 部门=" + verifiedManager.getManagerdepartment() + - ", 组织=" + verifiedManager.getOrganization() + - ", 角色=" + verifiedManager.getRole() + - ", 负责人=" + verifiedManager.getUserName() + - ", 协助人=" + verifiedManager.getAssistant()); - } - - } catch (Exception e) { - System.err.println("❌ 处理负责人记录失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("处理负责人记录失败: " + e.getMessage(), e); - } - } - - /** - * 处理负责人信息记录 - 更新或创建(仅使用登录用户信息) - */ - private void handleManagerRecord(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔍 [采购端] 开始处理负责人记录,用户ID: " + userId); - - // 检查是否已存在负责人记录 - UsersManagements existingManager = supplyUsersManagementsMapper.findByUserId(userId); - - if (existingManager != null) { - System.out.println("🔄 负责人记录已存在,进行更新"); - // 更新现有记录 - 使用当前登录用户信息 - updateExistingManagerRecord(existingManager, authInfo); - } else { - System.out.println("➕ 创建新的负责人记录"); - // 创建新记录 - 使用当前登录用户信息 - createNewManagerRecord(userId, authInfo); - } - - // 验证负责人信息是否成功处理 - UsersManagements verifiedManager = supplyUsersManagementsMapper.findByUserId(userId); - System.out.println("✅ 负责人信息验证: " + (verifiedManager != null ? "成功" : "失败")); - if (verifiedManager != null) { - System.out.println("📝 验证后的负责人信息: " + - "公司=" + verifiedManager.getManagercompany() + - ", 部门=" + verifiedManager.getManagerdepartment() + - ", 组织=" + verifiedManager.getOrganization() + - ", 角色=" + verifiedManager.getRole() + - ", 负责人=" + verifiedManager.getUserName() + - ", 协助人=" + verifiedManager.getAssistant()); - } - - } catch (Exception e) { - System.err.println("❌ 处理负责人记录失败: " + e.getMessage()); - e.printStackTrace(); - throw new RuntimeException("处理负责人记录失败: " + e.getMessage(), e); - } - } - - /** - * 更新现有的负责人记录 - 支持前端数据和登录数据 - */ - private void updateExistingManagerRecord(UsersManagements existingManager, UnifiedCustomerDTO dto, - ManagerAuthInfo authInfo, boolean useFrontendData) { - if (useFrontendData) { - // 使用前端提交的数据 - existingManager.setManagercompany(getSafeString(dto.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(dto.getManagerdepartment())); - existingManager.setOrganization(getSafeString(dto.getOrganization())); - existingManager.setRole(getSafeString(dto.getRole())); - existingManager.setUserName(getSafeString(dto.getUserName())); - existingManager.setAssistant(getSafeString(dto.getAssistant())); - } else { - // 使用当前登录用户信息 - existingManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - existingManager.setOrganization(getSafeString(authInfo.getOrganization())); - existingManager.setRole(getSafeString(authInfo.getRole())); - existingManager.setUserName(getSafeString(authInfo.getUserName())); - existingManager.setAssistant(getSafeString(authInfo.getAssistant())); - } - - // 确保managerId不为空 - if (existingManager.getManagerId() == null || existingManager.getManagerId().isEmpty()) { - existingManager.setManagerId(authInfo.getManagerId()); - } - - // 确保root不为空(采购端默认权限2) - if (existingManager.getRoot() == null || existingManager.getRoot().isEmpty()) { - existingManager.setRoot("2"); - } - - existingManager.setUpdated_at(LocalDateTime.now()); - - int rows = supplyUsersManagementsMapper.updateUsersManagements(existingManager); - System.out.println("✅ 更新负责人记录影响行数: " + rows); - } - - /** - * 创建新的负责人记录 - 支持前端数据和登录数据 - */ - private void createNewManagerRecord(String userId, UnifiedCustomerDTO dto, - ManagerAuthInfo authInfo, boolean useFrontendData) { - UsersManagements newManager = new UsersManagements(); - newManager.setUserId(userId); - - if (useFrontendData) { - // 使用前端提交的数据 - newManager.setManagercompany(getSafeString(dto.getManagercompany())); - newManager.setManagerdepartment(getSafeString(dto.getManagerdepartment())); - newManager.setOrganization(getSafeString(dto.getOrganization())); - newManager.setRole(getSafeString(dto.getRole())); - newManager.setUserName(getSafeString(dto.getUserName())); - newManager.setAssistant(getSafeString(dto.getAssistant())); - } else { - // 使用当前登录用户信息 - newManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - newManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - newManager.setOrganization(getSafeString(authInfo.getOrganization())); - newManager.setRole(getSafeString(authInfo.getRole())); - newManager.setUserName(getSafeString(authInfo.getUserName())); - newManager.setAssistant(getSafeString(authInfo.getAssistant())); - } - - newManager.setManagerId(getSafeString(authInfo.getManagerId())); - newManager.setRoot("2"); // 采购端默认权限 - - newManager.setCreated_at(LocalDateTime.now()); - newManager.setUpdated_at(LocalDateTime.now()); - - int rows = supplyUsersManagementsMapper.insertUsersManagements(newManager); - System.out.println("✅ 插入负责人记录影响行数: " + rows); - } - - /** - * 更新wechat数据源客户信息 - 重载方法,支持控制是否处理负责人信息 - */ - public boolean updateWechatCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo, boolean handleManagerInfo) { - validatePhoneNumber(dto.getPhoneNumber()); - - System.out.println("[采购端] 开始更新微信用户(wechat数据源),手机号: " + dto.getPhoneNumber()); - System.out.println("处理负责人信息: " + handleManagerInfo); - - UserProductCartDTO existingUser; - String userId = dto.getId(); // 优先使用DTO中的ID - - // 关键修复:优先使用用户ID进行精确查询,避免多结果问题 - if (userId != null && !userId.trim().isEmpty()) { - System.out.println("[采购端] 优先通过用户ID查询:" + userId); - try { - existingUser = supplyUsersMapper.selectByUserId(userId); - if (existingUser == null) { - throw new RuntimeException("未找到ID对应的客户:" + userId); - } - } catch (Exception e) { - System.out.println("[采购端] 通过ID查询失败,尝试通过手机号查询: " + e.getMessage()); - existingUser = validateAndGetUser(dto.getPhoneNumber()); - userId = existingUser.getUserId(); - } - } else { - // 如果没有提供ID,回退到通过手机号查询 - existingUser = validateAndGetUser(dto.getPhoneNumber()); - userId = existingUser.getUserId(); - } - - // 记录原始等级用于比较 - String originalLevel = existingUser.getLevel(); - String newLevel = dto.getLevel(); - - System.out.println("📊 客户等级变化检查 - 原始: " + originalLevel + ", 新: " + newLevel); - - // 🔥 修复:完善类型转换逻辑(增加规范化步骤) - String type = dto.getType(); - if (type != null) { - // 先规范化类型 - type = normalizeCustomerType(type); - switch (type) { - case "BOTH": - case "供应端&BOTH": - type = "both"; - break; - case "客户端": - case "buyer": - type = "buyer"; - break; - case "供应端": - case "seller": - type = "seller"; - break; - default: - // 保持原值 - break; - } - dto.setType(type); - System.out.println("🔄 类型转换结果: " + dto.getType() + " → " + type); - } else { - System.out.println("⚠️ 客户类型为空,使用默认值"); - dto.setType("seller"); // 采购端默认设为seller - } - - validatePurchasePermission(type); - - // 更新用户基本信息 - boolean success = updateWechatDataSource(dto, existingUser); - - // 根据参数决定是否处理负责人信息 - if (success && handleManagerInfo) { - checkAndUpdateManagerInfo(originalLevel, newLevel, dto, userId, authInfo); - } - - // 对于非公海池客户更新,不处理负责人信息 - return success; - } - - /** - * 更新现有的负责人记录 - 使用当前登录用户信息(采购端) - */ - private void updateExistingManagerRecord(UsersManagements existingManager, ManagerAuthInfo authInfo) { - // 使用当前登录用户的认证信息填充 - existingManager.setManagerId(getSafeString(authInfo.getManagerId())); - existingManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - existingManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - existingManager.setOrganization(getSafeString(authInfo.getOrganization())); - existingManager.setRole(getSafeString(authInfo.getRole())); - existingManager.setUserName(getSafeString(authInfo.getUserName())); - existingManager.setAssistant(getSafeString(authInfo.getAssistant())); - - // 确保managerId不为空 - if (existingManager.getManagerId() == null || existingManager.getManagerId().isEmpty()) { - existingManager.setManagerId(authInfo.getManagerId()); - } - - // 确保root不为空(采购端默认权限2) - if (existingManager.getRoot() == null || existingManager.getRoot().isEmpty()) { - existingManager.setRoot("2"); - } - - existingManager.setUpdated_at(LocalDateTime.now()); - - int rows = supplyUsersManagementsMapper.updateUsersManagements(existingManager); - System.out.println("✅ 更新负责人记录影响行数: " + rows); - } - - /** - * 创建新的负责人记录 - 使用当前登录用户信息(采购端) - */ - private void createNewManagerRecord(String userId, ManagerAuthInfo authInfo) { - UsersManagements newManager = new UsersManagements(); - newManager.setUserId(userId); - - // 使用当前登录用户的认证信息填充 - newManager.setManagerId(getSafeString(authInfo.getManagerId())); - newManager.setManagercompany(getSafeString(authInfo.getManagercompany())); - newManager.setManagerdepartment(getSafeString(authInfo.getManagerdepartment())); - newManager.setOrganization(getSafeString(authInfo.getOrganization())); - newManager.setRole(getSafeString(authInfo.getRole())); - newManager.setRoot("2"); // 采购端默认权限 - newManager.setUserName(getSafeString(authInfo.getUserName())); - newManager.setAssistant(getSafeString(authInfo.getAssistant())); - - newManager.setCreated_at(LocalDateTime.now()); - newManager.setUpdated_at(LocalDateTime.now()); - - int rows = supplyUsersManagementsMapper.insertUsersManagements(newManager); - System.out.println("✅ 插入负责人记录影响行数: " + rows); - } - - /** - * 更新默认数据源客户信息 - 修复版本(增加类型规范化) - */ - public boolean updateDefaultCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - validateCompanyId(dto.getId()); - - // 🔥 关键修复:规范化类型(适配采购端) - String normalizedType = normalizeCustomerType(dto.getType()); - dto.setType(normalizedType); - - validatePurchasePermission(dto.getType()); - - return supplyEnterpriseService.updateDefaultCustomer(dto, authInfo); - } - - // ==================== 查询方法 ==================== - - /** - * 根据手机号查询客户 - 采购员权限 + 负责人过滤 - */ - public UnifiedCustomerDTO getCustomerByPhone(String phoneNumber, ManagerAuthInfo authInfo) { - validatePhoneNumber(phoneNumber); - - System.out.println("🔍 [采购端] 开始根据手机号查询客户: " + phoneNumber); - - UserProductCartDTO userInfo = supplyPoolCustomerService.getWechatCustomerByPhone(phoneNumber); - if (userInfo == null) { - throw new RuntimeException("未找到手机号对应的客户:" + phoneNumber); - } - - // 采购员权限校验 - if (!"seller".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - throw new RuntimeException("该客户不在采购员权限范围内,类型: " + userInfo.getType()); - } - - // 负责人权限校验 - 添加对公海池客户的特殊处理 - if (!hasPermissionToViewCustomer(userInfo, authInfo)) { - System.out.println("❌ 负责人权限不足,无法查看该客户"); - throw new RuntimeException("您没有权限查看该客户信息"); - } - - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo); - dto.setDataSource("wechat"); - return dto; - } - - /** - * 检查是否有权限查看客户(统一权限检查方法) - */ - private boolean hasPermissionToViewCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 使用新的公海池判断逻辑 - if (isPublicSeaCustomer(userInfo, authInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - - /** - * 检查是否有权限查看微信客户 - */ - public boolean hasPermissionToViewWechatCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 公海池客户对所有人可见 - if (isPublicSeaCustomer(userInfo, authInfo)) { - System.out.println("✅ 公海池客户,无需负责人权限验证"); - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - - /** - * 判断是否为公海池客户 - 根据认证字段是否有值判断 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - System.out.println("🔍 SupplyCustomerService - 客户等级检查: " + userInfo.getLevel() + " → 是否公海池等级: " + isPublicSeaLevel); - - if (!isPublicSeaLevel) { - return false; - } - - // 根据不同类型的公海池使用不同判断逻辑 - String level = userInfo.getLevel(); - - if ("company-sea-pools".equals(level) || "公海池".equals(level)) { - // 公司公海池:必须没有负责人信息 - boolean result = !hasManagerAuthInfo(userInfo.getUserId()); - System.out.println("🏢 公司公海池检查结果: " + result); - return result; - } else if ("organization-sea-pools".equals(level)) { - // 组织公海池:必须有负责人信息且组织匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 组织公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameOrganization = hasSameOrganization(userInfo.getUserId(), authInfo); - System.out.println("🏢 组织公海池检查结果 - 有负责人: " + hasManager + ", 组织匹配: " + sameOrganization + " → 结果: " + sameOrganization); - return sameOrganization; - } else if ("department-sea-pools".equals(level)) { - // 部门公海池:必须有负责人信息且部门匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 部门公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameDepartment = hasSameDepartment(userInfo.getUserId(), authInfo); - System.out.println("🏢 部门公海池检查结果 - 有负责人: " + hasManager + ", 部门匹配: " + sameDepartment + " → 结果: " + sameDepartment); - return sameDepartment; - } - - return false; - } - - /** - * 检查是否有负责人认证信息 - */ - private boolean hasManagerAuthInfo(String userId) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - // 检查认证字段是否为空 - 只要有一个认证字段有值,就有负责人信息 - boolean hasAuthInfo = StringUtils.hasText(userManager.getManagerId()) || - StringUtils.hasText(userManager.getManagercompany()) || - StringUtils.hasText(userManager.getManagerdepartment()) || - StringUtils.hasText(userManager.getOrganization()) || - StringUtils.hasText(userManager.getRole()) || - StringUtils.hasText(userManager.getUserName()) || - StringUtils.hasText(userManager.getAssistant()); - - System.out.println("📋 负责人认证信息检查结果: " + (hasAuthInfo ? "有认证信息" : "无认证信息")); - return hasAuthInfo; - } catch (Exception e) { - System.err.println("❌ 检查负责人认证信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一组织 - */ - private boolean hasSameOrganization(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameOrganization = StringUtils.hasText(userManager.getOrganization()) && - userManager.getOrganization().equals(authInfo.getOrganization()); - - System.out.println("🏢 组织匹配检查: " + userManager.getOrganization() + " vs " + authInfo.getOrganization() + " → " + sameOrganization); - return sameOrganization; - } catch (Exception e) { - System.err.println("❌ 检查组织信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一部门 - */ - private boolean hasSameDepartment(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameDepartment = StringUtils.hasText(userManager.getManagerdepartment()) && - userManager.getManagerdepartment().equals(authInfo.getManagerdepartment()); - - System.out.println("🏢 部门匹配检查: " + userManager.getManagerdepartment() + " vs " + authInfo.getManagerdepartment() + " → " + sameDepartment); - return sameDepartment; - } catch (Exception e) { - System.err.println("❌ 检查部门信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查用户负责人权限 - 优化版本,数据库层面直接匹配 - */ - private boolean hasUserManagerPermission(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 检查用户负责人权限,用户ID: " + userId); - - // 🔥 优化:直接在数据库层面查询匹配的负责人记录,避免内存比较 - UsersManagements userManager = supplyUsersManagementsMapper.findByUserIdAndAuthInfo(userId, authInfo); - - // 🔥 优化:如果没有找到匹配的负责人记录,检查是否为公海池客户 - if (userManager == null) { - System.out.println("🔍 未找到匹配的负责人记录,检查客户等级..."); - - // 获取用户信息检查等级 - UserProductCartDTO userInfo = supplyUsersMapper.getUserBasicInfo(userId); - if (userInfo != null) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - boolean isPublicSea = publicSeaLevels.contains(userInfo.getLevel()); - - if (isPublicSea) { - System.out.println("✅ 公海池客户,允许查看"); - return true; - } - } - - System.out.println("❌ 非公海池客户且无匹配负责人,拒绝访问"); - return false; - } - - // 🔥 优化:数据库已经完成匹配,直接返回true - System.out.println("✅ 找到匹配的负责人记录,允许查看"); - System.out.println("📝 负责人信息: " + - "公司=" + userManager.getManagercompany() + - ", 部门=" + userManager.getManagerdepartment() + - ", 组织=" + userManager.getOrganization() + - ", 负责人=" + userManager.getUserName()); - - return true; - - } catch (Exception e) { - System.err.println("❌ 检查用户负责人权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 检查企业负责人权限 - */ - private boolean hasManagerPermission(EnterpriseInfoDTO enterpriseInfo, ManagerAuthInfo authInfo) { - if (enterpriseInfo.getManagers() == null) { - System.out.println("✅ 企业客户无负责人信息,允许查看"); - return true; - } - - return isManagerMatch(enterpriseInfo.getManagers(), authInfo); - } - - /** - * 检查负责人信息是否匹配(Managers)- 使用新字段 - */ - private boolean isManagerMatch(Managers manager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(manager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(manager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(manager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(manager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(manager.getUserName())); - - System.out.println("🔐 负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 检查负责人信息是否匹配(UsersManagements) - */ - private boolean isManagerMatch(UsersManagements userManager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(userManager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(userManager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(userManager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(userManager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(userManager.getUserName())); - - System.out.println("🔐 用户负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 根据企业ID查询客户信息(默认数据源)- 添加负责人过滤 - */ - public UnifiedCustomerDTO getCustomerById(String id, ManagerAuthInfo authInfo) { - System.out.println("🔍 [采购端-Service] 根据ID查询客户: " + id); - - EnterpriseInfoDTO enterpriseInfo = supplyEnterpriseService.getEnterpriseInfoById(id); - if (enterpriseInfo == null) { - System.out.println("❌ [采购端-Service] 未找到企业信息,ID: " + id); - return null; - } - - // 检查负责人权限 - if (!hasManagerPermission(enterpriseInfo, authInfo)) { - System.out.println("❌ 负责人权限不足,无法查看该客户"); - return null; - } - - return convertToUnifiedDTO(enterpriseInfo); - } - - // ==================== 私有方法 - 精确更新逻辑 ==================== - - /** - * 精确更新联系人信息 - */ - private void updateContactInfoPrecise(UnifiedCustomerDTO dto, String userId) { - if (dto.getTargetContactId() != null && !dto.getTargetContactId().trim().isEmpty()) { - // 精确更新特定联系人 - updateSpecificContact(dto, userId); - } else if (dto.getContacts() != null && !dto.getContacts().isEmpty()) { - // 更新第一个联系人(向后兼容) - updateFirstContact(dto, userId); - } else { - // 使用单个字段更新第一个联系人(向后兼容) - updateContactFromSingleFields(dto, userId); - } - } - - /** - * 精确更新产品信息 - */ - private void updateProductInfoPrecise(UnifiedCustomerDTO dto, String userId) { - if (!"seller".equals(dto.getType()) && !"both".equals(dto.getType())) { - return; - } - - if (dto.getTargetProductItemId() != null && !dto.getTargetProductItemId().trim().isEmpty()) { - // 精确更新特定产品项 - updateSpecificProductItem(dto, userId); - } else if (dto.getProductItems() != null && !dto.getProductItems().isEmpty()) { - // 更新第一个产品项(向后兼容) - updateFirstProductItem(dto, userId); - } else { - // 使用单个字段更新第一个产品项(向后兼容) - updateProductItemFromSingleFields(dto, userId); - } - } - - /** - * 更新用户基本信息 - */ - private void updateUserBasicInfo(UnifiedCustomerDTO dto, UserProductCartDTO existingUser) { - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(existingUser.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - - // 只更新非空字段 - updateUser.setNickName(getUpdateValue(dto.getNickName(), existingUser.getNickName())); - updateUser.setType(dto.getType()); // 类型必须更新 - updateUser.setCompany(getUpdateValue(dto.getCompany(), existingUser.getCompany())); - updateUser.setRegion(getUpdateValue(dto.getRegion(), existingUser.getRegion())); - updateUser.setLevel(getUpdateValue(dto.getLevel(), existingUser.getLevel())); - updateUser.setDemand(getUpdateValue(dto.getDemand(), existingUser.getDemand())); - updateUser.setSpec(getUpdateValue(dto.getSpec(), existingUser.getSpec())); - // 优先使用前端传递的更新时间,如果没有则使用当前时间 - updateUser.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int rows = supplyUsersMapper.updateByPhone(updateUser); - System.out.println("更新用户基本信息影响行数: " + rows); - - if (rows == 0) { - throw new RuntimeException("用户基本信息更新失败"); - } - } - - /** - * 精确更新特定联系人 - */ - private void updateSpecificContact(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 [采购端] 精确更新特定联系人,contactId: " + dto.getTargetContactId()); - - UnifiedCustomerDTO.ContactInfo contactData = dto.getUpdateContactData(); - if (contactData == null) { - System.out.println("未提供联系人更新数据,跳过联系人更新"); - return; - } - - int contactsRows = supplyUsersMapper.updateSpecificContact( - userId, - dto.getTargetContactId(), - contactData.getWechat(), - contactData.getAccount(), - contactData.getAccountNumber(), - contactData.getBank(), - contactData.getAddress() - ); - System.out.println("更新特定联系人影响行数: " + contactsRows); - - if (contactsRows == 0) { - System.out.println("⚠️ 特定联系人更新失败,可能ID不存在"); - } - } - - /** - * 更新第一个联系人(向后兼容) - */ - private void updateFirstContact(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 [采购端] 更新第一个联系人(向后兼容)"); - UnifiedCustomerDTO.ContactInfo contact = dto.getContacts().get(0); - - int contactsRows = supplyUsersMapper.updateContactsByUserId( - userId, - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - System.out.println("更新第一个联系人影响行数: " + contactsRows); - } - - /** - * 从单个字段更新联系人(向后兼容) - */ - private void updateContactFromSingleFields(UnifiedCustomerDTO dto, String userId) { - System.out.println("📞 [采购端] 从单个字段更新联系人(向后兼容)"); - - int contactsRows = supplyUsersMapper.updateContactsByUserId( - userId, - dto.getWechat(), - dto.getAccount(), - dto.getAccountNumber(), - dto.getBank(), - dto.getAddress() - ); - System.out.println("更新联系人信息影响行数: " + contactsRows); - } - - /** - * 精确更新特定产品项 - */ - private void updateSpecificProductItem(UnifiedCustomerDTO dto, String userId) { - System.out.println("📦 [采购端] 精确更新特定产品项,targetProductItemId: " + dto.getTargetProductItemId()); - - UnifiedCustomerDTO.ProductItem productItemData = dto.getUpdateProductItemData(); - if (productItemData == null) { - System.out.println("❌ 未提供产品项更新数据,跳过产品项更新"); - return; - } - - // 确保使用targetProductItemId - String productId = dto.getTargetProductItemId(); - if (productId == null || productId.trim().isEmpty()) { - System.out.println("❌ targetProductItemId为空,无法更新"); - return; - } - - int productRows = supplyUsersMapper.updateSpecificProduct( - userId, - productId, - productItemData.getProductName(), - productItemData.getVariety(), - productItemData.getSpecification(), - productItemData.getQuantity(), - productItemData.getGrossWeight(), - productItemData.getYolk() - ); - System.out.println("✅ 更新特定产品项影响行数: " + productRows); - - if (productRows == 0) { - System.out.println("⚠️ 特定产品项更新失败,可能ID不存在"); - } - } - - /** - * 更新第一个产品项(向后兼容) - */ - private void updateFirstProductItem(UnifiedCustomerDTO dto, String userId) { - System.out.println("📦 [采购端] 更新第一个产品项(向后兼容)"); - UnifiedCustomerDTO.ProductItem productItem = dto.getProductItems().get(0); - - String productId = getExistingProductId(userId); - int productRows = supplyUsersMapper.updateProductBySellerId( - userId, - productId, - productItem.getProductName(), - productItem.getSpecification(), - productItem.getQuantity(), - productItem.getGrossWeight(), - productItem.getYolk() - ); - System.out.println("更新产品信息影响行数: " + productRows); - } - - /** - * 从单个字段更新产品项(向后兼容) - */ - private void updateProductItemFromSingleFields(UnifiedCustomerDTO dto, String userId) { - if (!StringUtils.hasText(dto.getProductName())) { - return; - } - - System.out.println("📦 [采购端] 从单个字段更新产品信息"); - - String productId = getExistingProductId(userId); - int productRows = supplyUsersMapper.updateProductBySellerId( - userId, - productId, - dto.getProductName(), - dto.getSpecification(), - dto.getQuantity(), - dto.getGrossWeight(), - dto.getYolk() - ); - System.out.println("更新产品信息影响行数: " + productRows); - - if (productRows == 0) { - System.out.println("⚠️ 产品信息更新影响0行,可能需要插入新记录"); - } - } - - // ==================== 私有方法 - 辅助方法 ==================== - - /** - * 验证手机号 - */ - private void validatePhoneNumber(String phoneNumber) { - if (!StringUtils.hasText(phoneNumber)) { - throw new IllegalArgumentException("手机号不能为空"); - } - } - - /** - * 验证公司ID - */ - private void validateCompanyId(String companyId) { - if (!StringUtils.hasText(companyId)) { - throw new IllegalArgumentException("公司ID不能为空"); - } - } - - /** - * 验证采购员权限 - 修复版本(支持大小写不敏感) - */ - private void validatePurchasePermission(String type) { - System.out.println("🔐 ====== [采购端] 开始权限校验 ======"); - - // 🔥 关键修复:规范化类型(转换为小写) - String normalizedType = normalizeCustomerType(type); - - System.out.println("🔐 原始类型: " + type); - System.out.println("🔐 规范化后类型: " + normalizedType); - System.out.println("🔐 类型比较 - seller: " + "seller".equals(normalizedType)); - System.out.println("🔐 类型比较 - both: " + "both".equals(normalizedType)); - System.out.println("🔐 类型类名: " + (type != null ? type.getClass().getName() : "null")); - - if (!"seller".equals(normalizedType) && !"both".equals(normalizedType)) { - System.out.println("❌ 权限校验失败:采购员只能更新为seller或both类型,当前类型: " + type + " -> " + normalizedType); - System.out.println("❌ 类型长度: " + (type != null ? type.length() : "null")); - System.out.println("❌ 类型字符: " + (type != null ? Arrays.toString(type.toCharArray()) : "null")); - throw new IllegalArgumentException("采购员权限只能操作供应端类型客户和BOTH类型客户"); - } - System.out.println("✅ 权限校验通过"); - System.out.println("🔐 ====== 权限校验结束 ======"); - } - - /** - * 规范化客户类型(支持大小写不敏感)- 采购端适配 - */ - private String normalizeCustomerType(String type) { - if (type == null) { - return null; - } - - // 转换为小写进行比较 - String lowerType = type.toLowerCase(); - - switch (lowerType) { - case "both": - case "seller": - case "buyer": - return lowerType; - case "供应端": - return "seller"; - case "客户端": - return "buyer"; - case "供应端&both": - return "both"; - default: - return type; // 返回原值 - } - } - - /** - * 验证并获取用户信息 - */ - private UserProductCartDTO validateAndGetUser(String phoneNumber) { - try { - // 尝试通过手机号精确查询 - UserProductCartDTO user = supplyUsersMapper.selectByPhone(phoneNumber); - if (user == null) { - throw new RuntimeException("未找到手机号对应的客户:" + phoneNumber); - } - System.out.println("找到现有客户,用户ID: " + user.getUserId()); - return user; - } catch (org.apache.ibatis.exceptions.TooManyResultsException e) { - // 处理多个结果的情况 - System.out.println("[采购端] 警告:通过手机号" + phoneNumber + "查询到多个客户"); - throw new RuntimeException("查询到多个客户记录,请提供更精确的查询条件"); - } - } - - /** - * 获取更新值(优先使用新值,如果新值为空则使用原值) - */ - private String getUpdateValue(String newValue, String originalValue) { - return StringUtils.hasText(newValue) ? newValue : originalValue; - } - - /** - * 获取现有的产品ID - */ - private String getExistingProductId(String userId) { - List existingProducts = supplyUsersMapper.getSellerProducts(userId); - return existingProducts != null && !existingProducts.isEmpty() ? - existingProducts.get(0).getProductId() : "default_product_id"; - } - - /** - * 只更新wechat数据源(包含负责人信息生成) - */ - private boolean updateWechatDataSource(UnifiedCustomerDTO dto, UserProductCartDTO existingUser) { - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(existingUser.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - - // 只更新非空字段 - updateUser.setNickName(getUpdateValue(dto.getNickName(), existingUser.getNickName())); - updateUser.setType(dto.getType()); // 类型必须更新 - updateUser.setCompany(getUpdateValue(dto.getCompany(), existingUser.getCompany())); - updateUser.setRegion(getUpdateValue(dto.getRegion(), existingUser.getRegion())); - updateUser.setLevel(getUpdateValue(dto.getLevel(), existingUser.getLevel())); - updateUser.setDemand(getUpdateValue(dto.getDemand(), existingUser.getDemand())); - updateUser.setSpec(getUpdateValue(dto.getSpec(), existingUser.getSpec())); - // 优先使用前端传递的更新时间,如果没有则使用当前时间 - updateUser.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int rows = supplyUsersMapper.updateByPhone(updateUser); - System.out.println("更新用户基本信息影响行数: " + rows); - - if (rows == 0) { - throw new RuntimeException("用户基本信息更新失败"); - } - - // 更新联系人信息 - updateContactInfoPrecise(dto, existingUser.getUserId()); - - // 更新产品信息 - updateProductInfoPrecise(dto, existingUser.getUserId()); - - return rows > 0; - } - - // ==================== 转换方法 ==================== - - /** - * 为公海池客户转换DTO的方法 - 支持多个联系人和产品项 - */ - private UnifiedCustomerDTO convertToUnifiedDTOForPublicSea(UserProductCartDTO userInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - dto.setId(userInfo.getUserId()); - dto.setPhoneNumber(userInfo.getPhoneNumber()); - dto.setNickName(userInfo.getNickName()); - dto.setType(userInfo.getType()); - dto.setCompany(getSafeString(userInfo.getCompany())); - dto.setRegion(getSafeString(userInfo.getRegion())); - dto.setLevel(getSafeString(userInfo.getLevel(), "公海池")); - dto.setDemand(getSafeString(userInfo.getDemand())); - dto.setSpec(getSafeString(userInfo.getSpec())); - dto.setCreated_at(userInfo.getCreated_at()); - dto.setUpdated_at(userInfo.getUpdated_at()); - - // 设置多个联系人信息 - if (userInfo.getUsersContacts() != null && !userInfo.getUsersContacts().isEmpty()) { - List contacts = new ArrayList<>(); - for (UserProductCartDTO.UsersContacts userContact : userInfo.getUsersContacts()) { - UnifiedCustomerDTO.ContactInfo contact = new UnifiedCustomerDTO.ContactInfo(); - contact.setContactId(getSafeString(userContact.getContactId())); - contact.setWechat(getSafeString(userContact.getWechat())); - contact.setAccount(getSafeString(userContact.getAccount())); - contact.setAccountNumber(getSafeString(userContact.getAccountNumber())); - contact.setBank(getSafeString(userContact.getBank())); - contact.setAddress(getSafeString(userContact.getAddress())); - contacts.add(contact); - } - dto.setContacts(contacts); - - // 向后兼容:设置第一个联系人到单个字段 - UserProductCartDTO.UsersContacts firstContact = userInfo.getUsersContacts().get(0); - dto.setWechat(firstContact.getWechat()); - dto.setAccount(firstContact.getAccount()); - dto.setAccountNumber(firstContact.getAccountNumber()); - dto.setBank(firstContact.getBank()); - dto.setAddress(firstContact.getAddress()); - } - - // 设置多个产品项 - if (userInfo.getProducts() != null && !userInfo.getProducts().isEmpty()) { - List productItems = new ArrayList<>(); - for (UserProductCartDTO.ProductInfo userProduct : userInfo.getProducts()) { - UnifiedCustomerDTO.ProductItem productItem = new UnifiedCustomerDTO.ProductItem(); - productItem.setProductId(getSafeString(userProduct.getProductId())); - productItem.setProductName(getSafeString(userProduct.getProductName())); - productItem.setVariety(getSafeString(userProduct.getVariety())); - productItem.setSpecification(getSafeString(userProduct.getSpecification())); - productItem.setQuantity(userProduct.getQuantity() != null ? userProduct.getQuantity() : 0); - productItem.setGrossWeight(userProduct.getGrossWeight() != null ? userProduct.getGrossWeight() : ""); - productItem.setYolk(getSafeString(userProduct.getYolk())); - productItems.add(productItem); - } - dto.setProductItems(productItems); - - // 向后兼容:设置第一个产品项到单个字段 - UserProductCartDTO.ProductInfo firstProduct = userInfo.getProducts().get(0); - dto.setProductName(firstProduct.getProductName()); - dto.setVariety(firstProduct.getVariety()); - dto.setSpecification(firstProduct.getSpecification()); - dto.setQuantity(firstProduct.getQuantity()); - dto.setGrossWeight(firstProduct.getGrossWeight()); - dto.setYolk(firstProduct.getYolk()); - } else { - setDefaultProductValues(dto); - } - - return dto; - } - - /** - * 将企业信息转换为UnifiedCustomerDTO - 使用新字段 - */ - private UnifiedCustomerDTO convertToUnifiedDTO(EnterpriseInfoDTO enterpriseInfo) { - UnifiedCustomerDTO dto = new UnifiedCustomerDTO(); - - if (enterpriseInfo.getEnterprise() != null) { - dto.setId(enterpriseInfo.getEnterprise().getId()); - dto.setCompany(getSafeString(enterpriseInfo.getEnterprise().getCompany())); - dto.setRegion(getSafeString(enterpriseInfo.getEnterprise().getRegion())); - dto.setLevel(getSafeString(enterpriseInfo.getEnterprise().getLevel())); - dto.setType(getSafeString(enterpriseInfo.getEnterprise().getType())); - dto.setDemand(getSafeString(enterpriseInfo.getEnterprise().getDemand())); - dto.setSpec(getSafeString(enterpriseInfo.getEnterprise().getSpec())); - } - - if (enterpriseInfo.getContacts() != null) { - dto.setNickName(getSafeString(enterpriseInfo.getContacts().getNickName())); - dto.setPhoneNumber(getSafeString(enterpriseInfo.getContacts().getPhoneNumber())); - dto.setWechat(getSafeString(enterpriseInfo.getContacts().getWechat())); - dto.setAccount(getSafeString(enterpriseInfo.getContacts().getAccount())); - dto.setAccountNumber(getSafeString(enterpriseInfo.getContacts().getAccountNumber())); - dto.setBank(getSafeString(enterpriseInfo.getContacts().getBank())); - dto.setAddress(getSafeString(enterpriseInfo.getContacts().getAddress())); - dto.setCreated_at(enterpriseInfo.getContacts().getCreated_at()); - dto.setUpdated_at(enterpriseInfo.getContacts().getUpdated_at()); - } - - if (enterpriseInfo.getManagers() != null) { - // 使用新的负责人字段 - dto.setManagerId(getSafeString(enterpriseInfo.getManagers().getManagerId())); - dto.setManagercompany(getSafeString(enterpriseInfo.getManagers().getManagercompany())); - dto.setManagerdepartment(getSafeString(enterpriseInfo.getManagers().getManagerdepartment())); - dto.setOrganization(getSafeString(enterpriseInfo.getManagers().getOrganization())); - dto.setRole(getSafeString(enterpriseInfo.getManagers().getRole())); - dto.setUserName(getSafeString(enterpriseInfo.getManagers().getUserName())); - dto.setAssistant(getSafeString(enterpriseInfo.getManagers().getAssistant())); - } - - return dto; - } - - /** - * 设置默认产品值 - */ - private void setDefaultProductValues(UnifiedCustomerDTO dto) { - dto.setProductName(""); - dto.setVariety(""); - dto.setSpecification(""); - dto.setQuantity(0); - dto.setGrossWeight(""); - dto.setYolk(""); - dto.setCustomDetails(new Object[0]); - } - - /** - * 安全获取字符串(带默认值) - */ - private String getSafeString(String value) { - return value != null ? value : ""; - } - - /** - * 安全获取字符串(带自定义默认值) - */ - private String getSafeString(String value, String defaultValue) { - return value != null ? value : defaultValue; - } - - /** - * 根据ID查询wechat数据源客户信息 - */ - public UnifiedCustomerDTO getWechatCustomerById(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔍 [采购端] 开始根据用户ID查询wechat客户: " + userId); - - UserProductCartDTO userInfo = supplyPoolCustomerService.getPublicSeaCustomerInfo(userId); - if (userInfo == null) { - System.out.println("❌ 未找到用户ID对应的客户:" + userId); - return null; - } - - // 采购员权限校验 - if (!"seller".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - System.out.println("❌ 该客户不在采购员权限范围内,类型: " + userInfo.getType()); - return null; - } - - // 负责人权限校验 - if (!hasPermissionToViewCustomer(userInfo, authInfo)) { - System.out.println("❌ 负责人权限不足,无法查看该客户"); - return null; - } - - UnifiedCustomerDTO dto = convertToUnifiedDTOForPublicSea(userInfo); - dto.setDataSource("wechat"); - return dto; - - } catch (Exception e) { - System.err.println("❌ 查询wechat客户信息失败: " + e.getMessage()); - return null; - } - } - /** - * 检查默认数据源中是否存在指定ID的客户 - */ - public boolean checkDefaultCustomerExists(String customerId) { - try { - System.out.println("🔍 检查默认数据源客户是否存在,客户ID: " + customerId); - - if (customerId == null || customerId.trim().isEmpty()) { - System.out.println("❌ 客户ID为空,无法检查"); - return false; - } - - // 使用现有的selectEnterpriseInfoById方法检查存在性 - EnterpriseInfoDTO enterpriseInfo = supplyEnterpriseMapper.selectEnterpriseInfoById(customerId); - - boolean exists = enterpriseInfo != null && enterpriseInfo.getEnterprise() != null; - System.out.println("📊 默认数据源客户检查结果: " + (exists ? "✅ 存在" : "❌ 不存在")); - - if (exists) { - System.out.println("📝 客户信息: 公司=" + enterpriseInfo.getEnterprise().getCompany() + - ", 区域=" + enterpriseInfo.getEnterprise().getRegion()); - } - - return exists; - - } catch (Exception e) { - System.err.println("❌ 检查默认数据源客户存在性失败: " + e.getMessage()); - e.printStackTrace(); - return false; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/SupplyEnterpriseService.java b/src/main/java/com/example/web/service/SupplyEnterpriseService.java deleted file mode 100644 index f63c3a3..0000000 --- a/src/main/java/com/example/web/service/SupplyEnterpriseService.java +++ /dev/null @@ -1,515 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.EnterpriseInfoDTO; -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UnifiedCustomerDTO; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.Contacts; -import com.example.web.entity.Enterprise; -import com.example.web.entity.Managers; -import com.example.web.mapper.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -@Service -public class SupplyEnterpriseService { - - @Autowired - private SupplyEnterpriseMapper supplyenterpriseMapper; - - @Autowired - private SupplyContactsMapper supplycontactsMapper; - - @Autowired - private SupplyManagersMapper supplymanagersMapper; - - @Autowired - private SupplyUsersMapper supplyusersMapper; - - @Autowired - private SupplyPoolCustomerService supplypoolCustomerService; - - - // 修改:检查电话号码是否重复(同时检查两个数据源) - public boolean isPhoneNumberDuplicate(String phoneNumber) { - // 1. 检查微信数据源中的电话号码是否重复 - boolean wechatDuplicate = false; - try { - UserProductCartDTO existingUser = supplyusersMapper.selectByPhone(phoneNumber); - wechatDuplicate = existingUser != null; - if (wechatDuplicate) { - System.out.println("❌ [采购端] 电话号码在微信数据源中已存在: " + phoneNumber); - } - } catch (Exception e) { - System.err.println("[采购端] 查询微信数据源电话号码失败: " + e.getMessage()); - } - - // 2. 检查默认数据源(userlogin)中的电话号码是否重复 - boolean defaultDuplicate = false; - try { - int count = supplycontactsMapper.countByPhoneNumber(phoneNumber); - defaultDuplicate = count > 0; - if (defaultDuplicate) { - System.out.println("❌ [采购端] 电话号码在默认数据源中已存在: " + phoneNumber); - } - } catch (Exception e) { - System.err.println("[采购端] 查询默认数据源电话号码失败: " + e.getMessage()); - } - - // 3. 返回最终结果:任意一个数据源中存在都算重复 - boolean isDuplicate = wechatDuplicate || defaultDuplicate; - System.out.println("📞 [采购端] 电话号码重复检查结果: " + phoneNumber + - " -> 微信数据源:" + wechatDuplicate + - ", 默认数据源:" + defaultDuplicate + - ", 最终结果:" + isDuplicate); - - return isDuplicate; - } - - // 类型转换方法(保持与销售端一致) - private String convertFrontendTypeToDatabase(String frontendType) { - if (frontendType == null) { - return null; - } - switch (frontendType) { - case "供应端": - return "seller"; - case "客户端": - return "buyer"; - case "BOTH": - return "both"; // 改为小写 - default: - return frontendType; - } - } - - private String convertDatabaseTypeToFrontend(String databaseType) { - if (databaseType == null) { - return null; - } - switch (databaseType) { - case "seller": - return "供应端"; - case "buyer": - return "客户端"; - case "both": // 匹配小写的数据库存储 - return "BOTH"; - default: - return databaseType; - } - } - - - - // 新增客户:保存企业、联系人、负责人信息(默认数据源) - @Transactional(rollbackFor = Exception.class) - public boolean addCustomer(UnifiedCustomerDTO dto) { - System.out.println("===================================================="); - System.out.println("➕ [采购端] 开始新增客户到默认数据源"); - System.out.println("===================================================="); - System.out.println("📋 客户信息: 手机=" + dto.getPhoneNumber() + - ", 公司=" + dto.getCompany() + - ", 类型=" + dto.getType() + - ", 等级=" + dto.getLevel()); - - // 1. 转换前端类型为数据库类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - System.out.println("🔄 [采购端] 类型转换: 前端=" + dto.getType() + " → 数据库=" + databaseType); - - // 2. 权限校验(采购端:仅允许seller/both) - if (!"seller".equals(dto.getType()) && !"both".equals(dto.getType())) { - System.out.println("❌ [采购端] 权限校验失败: 采购端只能新增供应端类型客户和BOTH类型客户"); - throw new IllegalArgumentException("采购端权限只能新增供应端类型客户和BOTH类型客户"); - } - System.out.println("✅ [采购端] 权限校验通过"); - - // 3. 等级校验 - if (!StringUtils.hasText(dto.getLevel())) { - System.out.println("❌ [采购端] 等级校验失败: 客户等级不能为空"); - throw new IllegalArgumentException("客户等级不能为空"); - } - System.out.println("✅ [采购端] 等级校验通过"); - - // 4. 检查电话号码是否重复 - System.out.println("🔍 [采购端] 检查电话号码重复性..."); - if (isPhoneNumberDuplicate(dto.getPhoneNumber())) { - System.out.println("❌ [采购端] 电话号码重复: " + dto.getPhoneNumber()); - throw new IllegalArgumentException("电话号码已存在"); - } - System.out.println("✅ [采购端] 电话号码检查通过"); - - // 5. 封装并保存企业信息 - System.out.println("💾 [采购端] 保存企业信息..."); - Enterprise enterprise = new Enterprise(); - enterprise.setId(dto.getId()); - enterprise.setCompany(dto.getCompany()); - enterprise.setRegion(dto.getRegion()); - enterprise.setLevel(dto.getLevel()); - enterprise.setType(dto.getType()); - enterprise.setDemand(dto.getDemand()); - enterprise.setSpec(dto.getSpec()); - - int enterpriseRows = supplyenterpriseMapper.insertEnterprise(enterprise); - System.out.println("✅ [采购端] 企业信息保存结果: " + enterpriseRows + " 行受影响"); - - // 6. 封装联系人信息 - System.out.println("💾 [采购端] 保存联系人信息..."); - Contacts contacts = new Contacts(); - String contactId = UUID.randomUUID().toString().replaceAll("-", ""); - contacts.setContact_id(contactId); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - contacts.setPhoneNumber(dto.getPhoneNumber()); - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - contacts.setCreated_at(dto.getCreated_at() != null ? dto.getCreated_at() : LocalDateTime.now()); - contacts.setUpdated_at(dto.getUpdated_at() != null ? dto.getUpdated_at() : LocalDateTime.now()); - - int contactsRows = supplycontactsMapper.insertContacts(contacts); - System.out.println("✅ [采购端] 联系人信息保存结果: " + contactsRows + " 行受影响"); - - // 7. 封装负责人信息 - 使用前端传递的认证信息(更新为新表结构) - System.out.println("💾 [采购端] 保存负责人信息..."); - Managers managers = new Managers(); - managers.setId(dto.getId()); - managers.setManagerId(StringUtils.hasText(dto.getManagerId()) ? dto.getManagerId() : "未分配"); - managers.setManagercompany(StringUtils.hasText(dto.getManagercompany()) ? dto.getManagercompany() : "未分配"); - managers.setManagerdepartment(StringUtils.hasText(dto.getManagerdepartment()) ? dto.getManagerdepartment() : "未分配"); - managers.setOrganization(StringUtils.hasText(dto.getOrganization()) ? dto.getOrganization() : "未分配"); - managers.setRole(StringUtils.hasText(dto.getRole()) ? dto.getRole() : "未分配"); - managers.setRoot("2"); // 采购端默认权限 - managers.setUserName(StringUtils.hasText(dto.getUserName()) ? dto.getUserName() : "未分配"); - managers.setAssistant(StringUtils.hasText(dto.getAssistant()) ? dto.getAssistant() : "无"); - managers.setCreated_at(LocalDateTime.now()); - managers.setUpdated_at(LocalDateTime.now()); - - int managersRows = supplymanagersMapper.insertManagers(managers); - System.out.println("✅ [采购端] 负责人信息保存结果: " + managersRows + " 行受影响"); - - boolean success = enterpriseRows > 0 && contactsRows > 0 && managersRows > 0; - - if (success) { - System.out.println("🎉 [采购端] 新增客户成功,负责人信息已自动填充"); - // 记录负责人信息详情 - System.out.println("📝 [采购端] 负责人信息详情: " + - "负责人id=" + managers.getManagerId() + - "负责公司=" + managers.getManagercompany() + - ", 负责部门=" + managers.getManagerdepartment() + - ", 组织=" + managers.getOrganization() + - ", 角色=" + managers.getRole() + - ", 负责人=" + managers.getUserName() + - ", 协助人=" + managers.getAssistant()); - } else { - System.out.println("❌ [采购端] 新增客户失败"); - } - - System.out.println("===================================================="); - - return success; - } - - - /** - * 获取所有企业的完整信息(企业信息 + 联系人信息 + 负责人信息) - */ - public List getAllEnterpriseInfo() { - try { - return supplyenterpriseMapper.selectAllEnterpriseInfo(); - } catch (Exception e) { - System.err.println("[采购端] 获取所有企业信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取详细信息 - */ - public EnterpriseInfoDTO getEnterpriseInfoById(String id) { - try { - System.out.println("🔍 [采购端] 根据企业ID查询信息: " + id); - return supplyenterpriseMapper.selectEnterpriseInfoById(id); - } catch (Exception e) { - System.err.println("[采购端] 根据企业ID查询信息失败: " + e.getMessage()); - e.printStackTrace(); - return null; - } - } - - /** - * 获取所有企业基本信息 - */ - public List getAllEnterprises() { - try { - return supplyenterpriseMapper.selectAllEnterprises(); - } catch (Exception e) { - System.err.println("[采购端] 获取所有企业基本信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取联系人信息 - */ - public List getContactsByEnterpriseId(String id) { - try { - return supplycontactsMapper.selectContactsByEnterpriseId(id); - } catch (Exception e) { - System.err.println("[采购端] 根据企业ID获取联系人信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 根据企业ID获取负责人信息 - */ - public List getManagersByEnterpriseId(String id) { - try { - return supplymanagersMapper.selectManagersByEnterpriseId(id); - } catch (Exception e) { - System.err.println("[采购端] 根据企业ID获取负责人信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 搜索企业信息(根据企业名称、地区、类型等) - */ - public List searchEnterprises(String keyword) { - try { - System.out.println("🔍 [采购端] 搜索企业信息,关键词: " + keyword); - // 这里可以扩展更复杂的搜索逻辑 - List allInfo = supplyenterpriseMapper.selectAllEnterpriseInfo(); - if (keyword == null || keyword.trim().isEmpty()) { - return allInfo; - } - - List result = new ArrayList<>(); - for (EnterpriseInfoDTO info : allInfo) { - if (info.getEnterprise() != null) { - String company = info.getEnterprise().getCompany() != null ? info.getEnterprise().getCompany().toLowerCase() : ""; - String region = info.getEnterprise().getRegion() != null ? info.getEnterprise().getRegion().toLowerCase() : ""; - String type = info.getEnterprise().getType() != null ? info.getEnterprise().getType().toLowerCase() : ""; - - if (company.contains(keyword.toLowerCase()) || - region.contains(keyword.toLowerCase()) || - type.contains(keyword.toLowerCase())) { - result.add(info); - } - } - } - return result; - } catch (Exception e) { - System.err.println("[采购端] 搜索企业信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 更新默认数据源客户信息(企业、联系人、负责人)- 同步销售端,增加ManagerAuthInfo参数 - */ - @Transactional(rollbackFor = Exception.class) - public boolean updateDefaultCustomer(UnifiedCustomerDTO dto, ManagerAuthInfo authInfo) { - // 转换前端类型为数据库类型 - String databaseType = convertFrontendTypeToDatabase(dto.getType()); - dto.setType(databaseType); - - // 采购员权限:校验客户类型,只允许seller和both - if (!"seller".equals(dto.getType()) && !"both".equals(dto.getType())) { - throw new IllegalArgumentException("采购员权限只能更新为供应端类型客户和BOTH类型客户"); - } - - // 1. 更新企业信息 - Enterprise enterprise = new Enterprise(); - enterprise.setId(dto.getId()); - enterprise.setCompany(dto.getCompany()); - enterprise.setRegion(dto.getRegion()); - enterprise.setLevel(dto.getLevel()); - enterprise.setType(dto.getType()); - enterprise.setDemand(dto.getDemand()); - enterprise.setSpec(dto.getSpec()); - int enterpriseRows = supplyenterpriseMapper.updateEnterprise(enterprise); - - if (enterpriseRows <= 0) { - throw new RuntimeException("更新企业信息失败,企业ID: " + dto.getId()); - } - - // 2. 更新联系人信息 - 修复逻辑(与销售端一致) - Contacts contacts = new Contacts(); - // 先根据企业ID查询原始联系人信息 - List originalContactsList = supplycontactsMapper.selectContactsByEnterpriseId(dto.getId()); - if (originalContactsList != null && !originalContactsList.isEmpty()) { - Contacts originalContacts = originalContactsList.get(0); - contacts.setContact_id(originalContacts.getContact_id()); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - // 关键:使用原始电话号码,禁止修改 - contacts.setPhoneNumber(originalContacts.getPhoneNumber()); - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - - int contactsRows = supplycontactsMapper.updateContacts(contacts); - if (contactsRows <= 0) { - throw new RuntimeException("更新联系人信息失败,联系人ID: " + originalContacts.getContact_id()); - } - } else { - // 如果没有找到联系人记录,创建新的联系人 - System.out.println("[采购端] 未找到现有联系人,创建新的联系人记录"); - contacts.setContact_id(UUID.randomUUID().toString().replaceAll("-", "")); - contacts.setId(dto.getId()); - contacts.setNickName(dto.getNickName()); - contacts.setPhoneNumber(""); // 新创建的联系人电话号码为空 - contacts.setWechat(dto.getWechat()); - contacts.setAccount(dto.getAccount()); - contacts.setAccountNumber(dto.getAccountNumber()); - contacts.setBank(dto.getBank()); - contacts.setAddress(dto.getAddress()); - contacts.setCreated_at(LocalDateTime.now()); - contacts.setUpdated_at(LocalDateTime.now()); - - int contactsRows = supplycontactsMapper.insertContacts(contacts); - if (contactsRows <= 0) { - throw new RuntimeException("创建联系人信息失败"); - } - } - - // 3. 更新负责人信息 - 只有非公海池客户且前端提交了负责人信息时才更新 - // 定义公海池和非公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - Set nonPublicSeaLevels = Set.of("important", "normal", "low-value", "logistics", "unclassified"); - - // 检查是否是非公海池客户且前端提交了负责人信息 - boolean isNonPublicSeaCustomer = nonPublicSeaLevels.contains(dto.getLevel()); - boolean hasFrontendManagerInfo = StringUtils.hasText(dto.getManagercompany()) || - StringUtils.hasText(dto.getManagerdepartment()) || - StringUtils.hasText(dto.getOrganization()) || - StringUtils.hasText(dto.getRole()) || - StringUtils.hasText(dto.getUserName()) || - StringUtils.hasText(dto.getAssistant()); - - System.out.println("🎯 [采购端] 默认数据源负责人更新检查: " + - "客户等级=" + dto.getLevel() + - ", 是否非公海池=" + isNonPublicSeaCustomer + - ", 前端提交负责人信息=" + hasFrontendManagerInfo); - - // 只有非公海池客户且前端提交了负责人信息时才更新 - if (isNonPublicSeaCustomer && hasFrontendManagerInfo) { - System.out.println("✅ [采购端] 更新默认数据源负责人信息"); - - Managers managers = new Managers(); - managers.setId(dto.getId()); - - // 使用前端提交的数据 - managers.setManagercompany(dto.getManagercompany()); - managers.setManagerdepartment(dto.getManagerdepartment()); - managers.setOrganization(dto.getOrganization()); - managers.setRole(dto.getRole()); - managers.setUserName(dto.getUserName()); - managers.setAssistant(dto.getAssistant()); - - managers.setUpdated_at(LocalDateTime.now()); - - int managersRows = supplymanagersMapper.updateManagers(managers); - if (managersRows <= 0) { - // 如果没有更新到记录,尝试插入 - System.out.println("[采购端] 未找到现有负责人记录,创建新的负责人记录"); - managers.setManagerId(authInfo.getManagerId()); - managers.setRoot("2"); // 采购端默认权限 - managers.setCreated_at(LocalDateTime.now()); - managersRows = supplymanagersMapper.insertManagers(managers); - if (managersRows <= 0) { - throw new RuntimeException("更新负责人信息失败"); - } - } - - System.out.println("✅ [采购端] 默认数据源负责人信息更新完成,影响行数: " + managersRows); - } else { - System.out.println("ℹ️ [采购端] 跳过默认数据源负责人信息更新"); - if (!isNonPublicSeaCustomer) { - System.out.println(" 原因: 客户是公海池客户,等级=" + dto.getLevel()); - } else if (!hasFrontendManagerInfo) { - System.out.println(" 原因: 前端未提交负责人信息"); - } - } - - return true; - } - - /** - * 更新wechat数据源的客户信息(用户和产品信息) - */ - public boolean updateWechatCustomer(UnifiedCustomerDTO dto) { - // 修复:确保类型转换正确 - String type = dto.getType(); - if ("BOTH".equals(type)) { - type = "both"; - dto.setType(type); - } else if ("客户端".equals(type)) { - type = "buyer"; - dto.setType(type); - } else if ("供应端".equals(type)) { - type = "seller"; - dto.setType(type); - } - - // 采购员权限:校验客户类型,只允许seller和both - if (!"seller".equals(dto.getType()) && !"both".equals(dto.getType())) { - throw new IllegalArgumentException("采购权限只能更新为供应端类型客户和BOTH类型客户"); - } - - // 1. 根据手机号查询wechat用户ID(关联用户与产品) - UserProductCartDTO user = supplyusersMapper.selectByPhone(dto.getPhoneNumber()); - if (user == null) { - // 若该用户在wechat数据源中不存在,无需更新 - return true; - } - // 2. 更新用户基本信息 - UserProductCartDTO updateUser = new UserProductCartDTO(); - updateUser.setUserId(user.getUserId()); - updateUser.setPhoneNumber(dto.getPhoneNumber()); - updateUser.setNickName(dto.getNickName()); - updateUser.setType(dto.getType()); - updateUser.setUpdated_at(LocalDateTime.now()); - - int rows = supplyusersMapper.updateByPhone(updateUser); - System.out.println("[采购端] 更新用户基本信息影响行数: " + rows); - - // 3. 如果有产品信息需要更新 - if (("seller".equals(dto.getType()) || "both".equals(dto.getType())) && - dto.getProductName() != null && !dto.getProductName().trim().isEmpty()) { - - System.out.println("[采购端] 更新产品信息"); - int productRows = supplyusersMapper.updateProductBySellerId( - user.getUserId(), - dto.getProductName(), - dto.getVariety(), - dto.getSpecification(), - dto.getQuantity(), - dto.getGrossWeight(), - dto.getYolk() - ); - System.out.println("[采购端] 更新产品信息影响行数: " + productRows); - } - - return rows > 0; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/SupplyPoolCustomerService.java b/src/main/java/com/example/web/service/SupplyPoolCustomerService.java deleted file mode 100644 index 5e66d37..0000000 --- a/src/main/java/com/example/web/service/SupplyPoolCustomerService.java +++ /dev/null @@ -1,816 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.ManagerAuthInfo; -import com.example.web.dto.UserProductCartDTO; -import com.example.web.entity.UsersManagements; -import com.example.web.mapper.SupplyUsersManagementsMapper; -import com.example.web.mapper.SupplyUsersMapper; -import com.example.web.mapper.UsersManagementsMapper; -import com.example.web.mapper.UsersMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class SupplyPoolCustomerService { - - @Autowired - private SupplyUsersMapper supplyusersMapper; - @Autowired - private SupplyUsersManagementsMapper supplyUsersManagementsMapper; - - /** - * 根据手机号查询微信用户信息(采购端权限:只处理seller和both类型)- 支持一对多 - */ - public UserProductCartDTO getWechatCustomerByPhone(String phoneNumber) { - if (!StringUtils.hasText(phoneNumber)) { - throw new IllegalArgumentException("手机号不能为空"); - } - - // 1. 根据手机号查询微信用户基本信息 - UserProductCartDTO userInfo = supplyusersMapper.selectByPhone(phoneNumber); - if (userInfo == null) { - throw new RuntimeException("未找到手机号对应的微信用户:" + phoneNumber); - } - - System.out.println("🔍 获取到用户基础信息,用户ID: " + userInfo.getUserId() + - ", 类型: " + userInfo.getType() + - ", 公司: " + userInfo.getCompany() + - ", 需求: " + userInfo.getDemand() + - ", 规格: " + userInfo.getSpec()); - - // 采购端权限校验:只处理seller和both类型 - if (!"seller".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - System.out.println("❌ 权限校验失败: 采购端只能处理供应端和BOTH类型客户"); - throw new IllegalArgumentException("采购端权限只能处理供应端和BOTH类型客户"); - } - - // 2. 获取所有联系人信息(一对多) - try { - List contacts = supplyusersMapper.getUserAllContacts(userInfo.getUserId()); - // 转换为UserProductCartDTO.UsersContacts格式以保持兼容 - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - // 设置contactId - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - userInfo.setUsersContacts(userContacts); - } else { - userInfo.setUsersContacts(Collections.emptyList()); - } - System.out.println("✅ 获取用户所有联系人信息,数量: " + (userInfo.getUsersContacts() != null ? userInfo.getUsersContacts().size() : 0)); - } catch (Exception e) { - System.err.println("❌ 获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - // 3. 采购端:获取所有产品项信息(一对多)- 公海需求 - if ("seller".equals(userInfo.getType()) || "both".equals(userInfo.getType())) { - try { - List products = supplyusersMapper.getUserAllProducts(userInfo.getUserId()); - // 转换为UserProductCartDTO.ProductInfo格式以保持兼容 - if (products != null && !products.isEmpty()) { - List userProducts = products.stream() - .map(item -> { - UserProductCartDTO.ProductInfo product = new UserProductCartDTO.ProductInfo(); - product.setProductId(item.getProductId()); - product.setProductName(item.getProductName()); - product.setVariety(item.getVariety()); - product.setSpecification(item.getSpecification()); - product.setQuantity(item.getQuantity()); - product.setGrossWeight(item.getGrossWeight()); - product.setYolk(item.getYolk()); - return product; - }) - .collect(Collectors.toList()); - userInfo.setProducts(userProducts); - } else { - userInfo.setProducts(Collections.emptyList()); - } - System.out.println("✅ 获取用户所有产品项信息,数量: " + (userInfo.getProducts() != null ? userInfo.getProducts().size() : 0)); - } catch (Exception e) { - System.err.println("❌ 获取产品信息失败: " + e.getMessage()); - userInfo.setProducts(Collections.emptyList()); - } - userInfo.setCartItems(Collections.emptyList()); // 采购端不使用购物车信息 - } - - return userInfo; - } - - /** - * 根据用户ID获取用户信息和相关产品数据(采购端版本) - */ - public UserProductCartDTO getCustomerInfo(String userId) { - if (!StringUtils.hasText(userId)) { - throw new IllegalArgumentException("用户ID不能为空"); - } - - // 1. 获取用户基本信息 - UserProductCartDTO userInfo = supplyusersMapper.getUserBasicInfo(userId); - if (userInfo == null) { - throw new RuntimeException("用户不存在: " + userId); - } - - // 采购端权限校验 - if (!"seller".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - throw new IllegalArgumentException("采购端权限只能查看供应端和BOTH类型客户"); - } - - // 2. 采购端:查询产品信息(公海需求) - List products = supplyusersMapper.getSellerProducts(userId); - userInfo.setProducts(products != null ? products : Collections.emptyList()); - userInfo.setCartItems(Collections.emptyList()); // 采购端不使用购物车 - - // 3. 获取联系人信息 - 安全处理 - try { - List contacts = supplyusersMapper.getUserContacts(userId); - userInfo.setUsersContacts(contacts != null ? contacts : Collections.emptyList()); - } catch (Exception e) { - System.err.println("❌ 获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - return userInfo; - } - - /** - * 获取所有客户信息 - 使用数据库层面权限过滤(采购端版本)- 优化版(支持分页) - */ - public List getAllCustomers(ManagerAuthInfo authInfo) { - try { - System.out.println("===================================================="); - System.out.println("🚀 开始获取所有微信用户数据(数据库权限过滤,采购端)..."); - System.out.println("🔐 负责人过滤条件: " + - "公司=" + authInfo.getManagercompany() + - ", 部门=" + authInfo.getManagerdepartment()); - - // 移除固定的分页限制,获取所有数据 - int limit = Integer.MAX_VALUE; // 获取所有数据 - int offset = 0; // 从第一条开始 - - // 1. 获取授权客户总数 - System.out.println("📊 查询授权客户总数..."); - int totalCount = supplyusersMapper.getAuthorizedCustomersCount(authInfo); - System.out.println("✅ 授权客户总数: " + totalCount); - - // 2. 使用数据库层面权限过滤并分页 - System.out.println("📋 查询授权客户基础信息(分页查询)..."); - List authorizedUsers = supplyusersMapper.getAuthorizedCustomers(authInfo, limit, offset); - - System.out.println("✅ 授权客户数据查询完成"); - System.out.println("📊 当前页获取到授权客户数据条数: " + (authorizedUsers != null ? authorizedUsers.size() : "null")); - // 统计通知状态为banold的授权客户数量 - if (authorizedUsers != null) { - long banoldCount = authorizedUsers.stream().filter(user -> "banold".equals(user.getNotice())).count(); - System.out.println("📊 通知状态为banold的授权客户数量: " + banoldCount); - } - - List result = new ArrayList<>(); - - if (authorizedUsers != null && !authorizedUsers.isEmpty()) { - // 🔥 新增:收集所有用户ID用于批量查询 - List userIds = authorizedUsers.stream() - .map(UserProductCartDTO::getUserId) - .filter(Objects::nonNull) - .filter(userId -> !userId.trim().isEmpty()) - .distinct() - .collect(Collectors.toList()); - - System.out.println("🔍 需要批量查询的授权用户数量: " + userIds.size()); - - // 🔥 新增:批量查询所有相关数据 - Map managerMap = batchQueryManagers(userIds); - Map> contactsMap = batchQueryContacts(userIds); - Map> productsMap = batchQueryProducts(userIds); - - // 2. 为每个授权用户构建完整信息(使用批量数据) - System.out.println("🔄 开始处理 " + authorizedUsers.size() + " 条授权用户数据..."); - - for (int i = 0; i < authorizedUsers.size(); i++) { - UserProductCartDTO user = authorizedUsers.get(i); - try { - // 🎯 关键修改:使用批量查询的数据构建完整用户信息 - UserProductCartDTO fullUserInfo = buildSupplyUserInfoFromBatchData(user, managerMap, contactsMap, productsMap); - if (fullUserInfo != null) { - // 数据库已经过滤了权限,这里直接添加 - result.add(fullUserInfo); - - // 打印前几个客户的详细信息 - if (i < 3) { - System.out.println("📝 授权客户样例 " + (i + 1) + ": " + - "ID=" + fullUserInfo.getUserId() + - ", 手机=" + fullUserInfo.getPhoneNumber() + - ", 公司=" + fullUserInfo.getCompany() + - ", 类型=" + fullUserInfo.getType() + - ", 联系人数量=" + (fullUserInfo.getUsersContacts() != null ? fullUserInfo.getUsersContacts().size() : 0) + - ", 产品数量=" + (fullUserInfo.getProducts() != null ? fullUserInfo.getProducts().size() : 0) + - ", 是否公海池=" + isPublicSeaCustomer(fullUserInfo, authInfo)); - } - } - } catch (Exception e) { - System.err.println("❌ 构建用户 " + user.getUserId() + " 的详细信息时出错: " + e.getMessage()); - } - } - } - - System.out.println("===================================================="); - System.out.println("🎉 数据获取完成(数据库权限过滤,采购端)"); - System.out.println("📊 返回记录数: " + result.size()); - System.out.println("===================================================="); - - return result; - } catch (Exception e) { - System.err.println("❌ 获取授权客户信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 检查是否有权限查看客户 - */ - private boolean hasPermissionToViewCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 公海池客户使用特殊权限检查 - if (isPublicSeaCustomer(userInfo, authInfo)) { - return true; - } - - // 非公海池客户需要检查负责人权限 - return hasUserManagerPermission(userInfo.getUserId(), authInfo); - } - - /** - * 判断是否为公海池客户 - 根据不同类型使用不同逻辑 - */ - private boolean isPublicSeaCustomer(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - // 检查等级是否为公海池 - boolean isPublicSeaLevel = publicSeaLevels.contains(userInfo.getLevel()); - System.out.println("🔍 客户等级检查: " + userInfo.getLevel() + " → 是否公海池等级: " + isPublicSeaLevel); - - if (!isPublicSeaLevel) { - return false; - } - - // 根据不同类型的公海池使用不同判断逻辑 - String level = userInfo.getLevel(); - - if ("company-sea-pools".equals(level) || "公海池".equals(level)) { - // 公司公海池:必须没有负责人信息 - boolean result = !hasManagerAuthInfo(userInfo.getUserId()); - System.out.println("🏢 公司公海池检查结果: " + result); - return result; - } else if ("organization-sea-pools".equals(level)) { - // 组织公海池:必须有负责人信息且组织匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 组织公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameOrganization = hasSameOrganization(userInfo.getUserId(), authInfo); - System.out.println("🏢 组织公海池检查结果 - 有负责人: " + hasManager + ", 组织匹配: " + sameOrganization + " → 结果: " + sameOrganization); - return sameOrganization; - } else if ("department-sea-pools".equals(level)) { - // 部门公海池:必须有负责人信息且部门匹配 - boolean hasManager = hasManagerAuthInfo(userInfo.getUserId()); - if (!hasManager) { - System.out.println("🏢 部门公海池:无负责人信息,不允许查看"); - return false; - } - boolean sameDepartment = hasSameDepartment(userInfo.getUserId(), authInfo); - System.out.println("🏢 部门公海池检查结果 - 有负责人: " + hasManager + ", 部门匹配: " + sameDepartment + " → 结果: " + sameDepartment); - return sameDepartment; - } - - return false; - } - - /** - * 公共方法:判断是否为公海池客户(供Controller调用) - */ - public boolean isPublicSeaCustomerPublic(UserProductCartDTO userInfo, ManagerAuthInfo authInfo) { - return isPublicSeaCustomer(userInfo, authInfo); - } - - /** - * 检查是否有负责人认证信息 - */ - private boolean hasManagerAuthInfo(String userId) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - // 检查认证字段是否为空 - 只要有一个认证字段有值,就有负责人信息 - boolean hasAuthInfo = StringUtils.hasText(userManager.getManagerId()) || - StringUtils.hasText(userManager.getManagercompany()) || - StringUtils.hasText(userManager.getManagerdepartment()) || - StringUtils.hasText(userManager.getOrganization()) || - StringUtils.hasText(userManager.getRole()) || - StringUtils.hasText(userManager.getUserName()) || - StringUtils.hasText(userManager.getAssistant()); - - System.out.println("📋 负责人认证信息检查结果: " + (hasAuthInfo ? "有认证信息" : "无认证信息")); - return hasAuthInfo; - } catch (Exception e) { - System.err.println("❌ 检查负责人认证信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一组织 - */ - private boolean hasSameOrganization(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameOrganization = StringUtils.hasText(userManager.getOrganization()) && - userManager.getOrganization().equals(authInfo.getOrganization()); - - System.out.println("🏢 组织匹配检查: " + userManager.getOrganization() + " vs " + authInfo.getOrganization() + " → " + sameOrganization); - return sameOrganization; - } catch (Exception e) { - System.err.println("❌ 检查组织信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查是否同一部门 - */ - private boolean hasSameDepartment(String userId, ManagerAuthInfo authInfo) { - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager == null) { - return false; - } - - boolean sameDepartment = StringUtils.hasText(userManager.getManagerdepartment()) && - userManager.getManagerdepartment().equals(authInfo.getManagerdepartment()); - - System.out.println("🏢 部门匹配检查: " + userManager.getManagerdepartment() + " vs " + authInfo.getManagerdepartment() + " → " + sameDepartment); - return sameDepartment; - } catch (Exception e) { - System.err.println("❌ 检查部门信息失败: " + e.getMessage()); - return false; - } - } - - /** - * 检查用户负责人权限 - 优化版本,数据库层面直接匹配 - */ - private boolean hasUserManagerPermission(String userId, ManagerAuthInfo authInfo) { - try { - System.out.println("🔐 检查用户负责人权限,用户ID: " + userId); - - // 🔥 优化:直接在数据库层面查询匹配的负责人记录,避免内存比较 - UsersManagements userManager = supplyUsersManagementsMapper.findByUserIdAndAuthInfo(userId, authInfo); - - // 🔥 优化:如果没有找到匹配的负责人记录,检查是否为公海池客户 - if (userManager == null) { - System.out.println("🔍 未找到匹配的负责人记录,检查客户等级..."); - - // 获取用户信息检查等级 - UserProductCartDTO userInfo = supplyusersMapper.getUserBasicInfo(userId); - if (userInfo != null) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - boolean isPublicSea = publicSeaLevels.contains(userInfo.getLevel()); - - if (isPublicSea) { - System.out.println("✅ 公海池客户,允许查看"); - return true; - } - } - - System.out.println("❌ 非公海池客户且无匹配负责人,拒绝访问"); - return false; - } - - // 🔥 优化:数据库已经完成匹配,直接返回true - System.out.println("✅ 找到匹配的负责人记录,允许查看"); - System.out.println("📝 负责人信息: " + - "公司=" + userManager.getManagercompany() + - ", 部门=" + userManager.getManagerdepartment() + - ", 组织=" + userManager.getOrganization() + - ", 负责人=" + userManager.getUserName()); - - return true; - - } catch (Exception e) { - System.err.println("❌ 检查用户负责人权限失败: " + e.getMessage()); - // 发生异常时,出于安全考虑返回false - return false; - } - } - - /** - * 检查负责人信息是否匹配(UsersManagements) - */ - private boolean isManagerMatch(UsersManagements userManager, ManagerAuthInfo authInfo) { - boolean match = - (authInfo.getManagerId() == null || authInfo.getManagerId().equals(userManager.getManagerId())) && - (authInfo.getManagercompany() == null || authInfo.getManagercompany().equals(userManager.getManagercompany())) && - (authInfo.getManagerdepartment() == null || authInfo.getManagerdepartment().equals(userManager.getManagerdepartment())) && - (authInfo.getOrganization() == null || authInfo.getOrganization().equals(userManager.getOrganization())) && - (authInfo.getRole() == null || authInfo.getRole().equals(userManager.getRole())) && - (authInfo.getUserName() == null || authInfo.getUserName().equals(userManager.getUserName())); - - System.out.println("🔐 用户负责人权限检查: " + (match ? "✅ 匹配" : "❌ 不匹配")); - return match; - } - - /** - * 获取公海池客户完整信息 - 支持一对多(采购端版本) - */ - public UserProductCartDTO getPublicSeaCustomerInfo(String userId) { - if (!StringUtils.hasText(userId)) { - System.out.println("⚠️ 用户ID为空"); - return null; - } - - // 1. 获取用户基本信息 - UserProductCartDTO userInfo = supplyusersMapper.getUserBasicInfo(userId); - if (userInfo == null) { - System.out.println("⚠️ 用户不存在: " + userId); - return null; // 返回null而不是抛出异常 - } - - // 采购端权限校验 - if (!"seller".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { - System.out.println("🚫 过滤掉非供应端客户: " + userId + " (类型: " + userInfo.getType() + ")"); - return null; // 返回null而不是抛出异常 - } - - // 如果通知状态为banold,则更新为old - if ("banold".equals(userInfo.getNotice())) { - System.out.println("🔄 更新通知状态: " + userId + " 从banold改为old"); - supplyusersMapper.updateNotice(userId, "old"); - userInfo.setNotice("old"); - } -// 🔥 新增:查询负责人信息 - try { - UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); - if (userManager != null) { - System.out.println("✅ 获取到负责人信息: " + - "负责人=" + userManager.getUserName() + - ", 组织=" + userManager.getOrganization() + - ", 部门=" + userManager.getManagerdepartment()); - - // 将负责人信息设置到DTO中(需要扩展UserProductCartDTO或使用其他方式) - // 这里可以创建一个新的字段来存储负责人信息,或者使用现有的扩展机制 - // 暂时记录日志,后续需要DTO支持负责人字段 - } else { - System.out.println("⚠️ 未找到负责人信息"); - } - } catch (Exception e) { - System.err.println("❌ 获取负责人信息失败: " + e.getMessage()); - } - // 2. 获取联系人信息 - 一对多 - try { - List contacts = supplyusersMapper.getUserAllContacts(userId); - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - userInfo.setUsersContacts(userContacts); - } else { - userInfo.setUsersContacts(Collections.emptyList()); - } - } catch (Exception e) { - System.err.println("❌ 获取用户联系人信息失败: " + e.getMessage()); - userInfo.setUsersContacts(Collections.emptyList()); - } - - // 3. 采购端:获取产品信息(公海需求)- 一对多 - try { - List products = supplyusersMapper.getUserAllProducts(userId); - System.out.println("🔍 查询到的产品数据条数: " + (products != null ? products.size() : 0)); - - if (products != null && !products.isEmpty()) { - List userProducts = products.stream() - .map(item -> { - UserProductCartDTO.ProductInfo product = new UserProductCartDTO.ProductInfo(); - product.setProductId(item.getProductId()); - product.setProductName(item.getProductName()); - product.setVariety(item.getVariety()); - product.setSpecification(item.getSpecification()); - product.setQuantity(item.getQuantity()); - product.setGrossWeight(item.getGrossWeight()); - product.setYolk(item.getYolk()); - - // 调试日志 - System.out.println("📦 转换产品项: " + - "ID=" + product.getProductId() + - ", 产品=" + product.getProductName() + - ", 规格=" + product.getSpecification()); - - return product; - }) - .collect(Collectors.toList()); - userInfo.setProducts(userProducts); - System.out.println("✅ 成功设置产品数据,数量: " + userProducts.size()); - } else { - userInfo.setProducts(Collections.emptyList()); - System.out.println("⚠️ 产品数据为空"); - } - userInfo.setCartItems(Collections.emptyList()); // 采购端不使用购物车信息 - } catch (Exception e) { - System.err.println("❌ 获取产品信息失败: " + e.getMessage()); - e.printStackTrace(); - userInfo.setProducts(Collections.emptyList()); - userInfo.setCartItems(Collections.emptyList()); - } - - // 最终调试信息 - System.out.println("🎯 最终返回的用户数据: " + - "products数量=" + (userInfo.getProducts() != null ? userInfo.getProducts().size() : "null") + - ", contacts数量=" + (userInfo.getUsersContacts() != null ? userInfo.getUsersContacts().size() : "null")); - - return userInfo; - } - - /** - * 获取所有客户信息 - 不进行负责人过滤,直接返回所有数据(采购端版本 - 优化版) - */ - public List getAllCustomersWithoutFilter() { - try { - System.out.println("===================================================="); - System.out.println("🚀 开始获取所有微信用户数据(无过滤,采购端)..."); - - // 1. 获取所有用户的基本信息(采购端:只获取seller和both类型) - System.out.println("📋 查询用户基础信息..."); - List allUsers = supplyusersMapper.getAllUserBasicInfo(); - - System.out.println("✅ 基础用户数据查询完成"); - System.out.println("📊 获取到基础用户数据条数: " + (allUsers != null ? allUsers.size() : "null")); - // 统计通知状态为banold的用户数量 - if (allUsers != null) { - long banoldCount = allUsers.stream().filter(user -> "banold".equals(user.getNotice())).count(); - System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); - } - - List result = new ArrayList<>(); - - if (allUsers != null && !allUsers.isEmpty()) { - // 🔥 修改:收集所有用户ID用于批量查询 - List userIds = allUsers.stream() - .map(UserProductCartDTO::getUserId) - .filter(Objects::nonNull) - .filter(userId -> !userId.trim().isEmpty()) - .distinct() - .collect(Collectors.toList()); - - System.out.println("🔍 需要批量查询的用户数量: " + userIds.size()); - - // 🔥 修改:批量查询所有相关数据(采购端需要产品信息) - Map managerMap = batchQueryManagers(userIds); - Map> contactsMap = batchQueryContacts(userIds); - Map> productsMap = batchQueryProducts(userIds); // 采购端需要产品信息 - - // 2. 为每个用户构建完整信息 - System.out.println("🔄 开始处理 " + allUsers.size() + " 条用户数据..."); - - for (int i = 0; i < allUsers.size(); i++) { - UserProductCartDTO user = allUsers.get(i); - try { - // 采购端权限:只处理seller和both类型 - if (!"seller".equals(user.getType()) && !"both".equals(user.getType())) { - System.out.println("🚫 过滤掉非供应端客户: " + user.getUserId() + " (类型: " + user.getType() + ")"); - continue; - } - - // 🔥 修改:使用批量查询的数据构建完整用户信息(采购端版本) - UserProductCartDTO fullUserInfo = buildSupplyUserInfoFromBatchData(user, managerMap, contactsMap, productsMap); - if (fullUserInfo != null) { - result.add(fullUserInfo); - // 打印前几个客户的详细信息 - if (i < 3) { - System.out.println("📝 采购端客户样例 " + (i + 1) + ": " + - "ID=" + fullUserInfo.getUserId() + - ", 手机=" + fullUserInfo.getPhoneNumber() + - ", 公司=" + fullUserInfo.getCompany() + - ", 类型=" + fullUserInfo.getType() + - ", 联系人数量=" + (fullUserInfo.getUsersContacts() != null ? fullUserInfo.getUsersContacts().size() : 0) + - ", 产品数量=" + (fullUserInfo.getProducts() != null ? fullUserInfo.getProducts().size() : 0)); - } - } - } catch (Exception e) { - System.err.println("❌ 构建用户 " + user.getUserId() + " 的详细信息时出错: " + e.getMessage()); - } - } - } - - System.out.println("===================================================="); - System.out.println("🎉 数据获取完成(无过滤,采购端)"); - System.out.println("📊 返回记录数: " + result.size()); - System.out.println("===================================================="); - - return result; - } catch (Exception e) { - System.err.println("❌ 获取所有客户信息失败: " + e.getMessage()); - e.printStackTrace(); - return new ArrayList<>(); - } - } - - /** - * 1.批量查询负责人信息(与销售端复用) - */ - private Map batchQueryManagers(List userIds) { - Map managerMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - // 🔥 注意:采购端可能需要使用不同的Mapper - List allManagers = supplyUsersManagementsMapper.findByUserIds(userIds); - for (UsersManagements manager : allManagers) { - if (manager.getUserId() != null) { - managerMap.put(manager.getUserId(), manager); - } - } - System.out.println("✅ 采购端批量查询负责人信息完成,共获取 " + allManagers.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 采购端批量查询负责人信息失败: " + e.getMessage()); - } - } - return managerMap; - } - - /** - * 2.批量查询联系人信息(与销售端复用) - */ - private Map> batchQueryContacts(List userIds) { - Map> contactsMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - // 🔥 注意:采购端需要使用采购端的Mapper - List allContacts = supplyusersMapper.getUserContactsByUserIds(userIds); - for (UsersMapper.ContactInfo contact : allContacts) { - String userId = contact.getUserId(); - if (userId != null) { - contactsMap.computeIfAbsent(userId, k -> new ArrayList<>()).add(contact); - } - } - System.out.println("✅ 采购端批量查询联系人信息完成,共获取 " + allContacts.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 采购端批量查询联系人信息失败: " + e.getMessage()); - } - } - return contactsMap; - } - - /** - * 3.批量查询产品信息(采购端专用) - */ - private Map> batchQueryProducts(List userIds) { - Map> productsMap = new HashMap<>(); - if (userIds != null && !userIds.isEmpty()) { - try { - List allProducts = supplyusersMapper.getSellerProductsByUserIds(userIds); - for (UserProductCartDTO.ProductInfo product : allProducts) { - String userId = product.getSellerId(); - if (userId != null) { - productsMap.computeIfAbsent(userId, k -> new ArrayList<>()).add(product); - } - } - System.out.println("✅ 批量查询产品信息完成,共获取 " + allProducts.size() + " 条记录"); - } catch (Exception e) { - System.err.println("❌ 批量查询产品信息失败: " + e.getMessage()); - } - } - return productsMap; - } - - /** - * 4.从批量查询的数据构建采购端用户完整信息(采购端专用) - */ - private UserProductCartDTO buildSupplyUserInfoFromBatchData(UserProductCartDTO basicUserInfo, - Map managerMap, - Map> contactsMap, - Map> productsMap) { - String userId = basicUserInfo.getUserId(); - - // 采购端权限校验 - if (!"seller".equals(basicUserInfo.getType()) && !"both".equals(basicUserInfo.getType())) { - System.out.println("🚫 过滤掉非供应端客户: " + userId + " (类型: " + basicUserInfo.getType() + ")"); - return null; - } - - // 设置负责人信息 - try { - UsersManagements userManager = managerMap.get(userId); - if (userManager != null) { - System.out.println("✅ 从批量Map中获取到负责人信息: " + - "负责人=" + userManager.getUserName() + - ", 组织=" + userManager.getOrganization() + - ", 部门=" + userManager.getManagerdepartment()); - } - } catch (Exception e) { - System.err.println("❌ 从Map获取负责人信息失败: " + e.getMessage()); - } - - // 设置联系人信息 - try { - List contacts = contactsMap.get(userId); - if (contacts != null && !contacts.isEmpty()) { - List userContacts = contacts.stream() - .map(contact -> { - UserProductCartDTO.UsersContacts userContact = new UserProductCartDTO.UsersContacts( - contact.getWechat(), - contact.getAccount(), - contact.getAccountNumber(), - contact.getBank(), - contact.getAddress() - ); - userContact.setContactId(contact.getContactId()); - return userContact; - }) - .collect(Collectors.toList()); - basicUserInfo.setUsersContacts(userContacts); - } else { - basicUserInfo.setUsersContacts(Collections.emptyList()); - } - } catch (Exception e) { - System.err.println("❌ 设置联系人信息失败: " + e.getMessage()); - basicUserInfo.setUsersContacts(Collections.emptyList()); - } - - // 设置产品信息(采购端关键) - try { - List products = productsMap.get(userId); - if (products != null && !products.isEmpty()) { - basicUserInfo.setProducts(products); - } else { - basicUserInfo.setProducts(Collections.emptyList()); - } - basicUserInfo.setCartItems(Collections.emptyList()); // 采购端不使用购物车信息 - } catch (Exception e) { - System.err.println("❌ 设置产品信息失败: " + e.getMessage()); - basicUserInfo.setProducts(Collections.emptyList()); - basicUserInfo.setCartItems(Collections.emptyList()); - } - - return basicUserInfo; - } - - - /** - * 只检查等级是否为公海池等级(不检查负责人信息) - */ - private boolean isPublicSeaLevel(String level) { - // 定义公海池等级 - Set publicSeaLevels = Set.of("company-sea-pools", "organization-sea-pools", "department-sea-pools", "公海池"); - - boolean isPublicSeaLevel = publicSeaLevels.contains(level); - System.out.println("🔍 等级检查: " + level + " → 是否公海池等级: " + isPublicSeaLevel); - - return isPublicSeaLevel; - } - - /** - * 采购端:获取客户的产品信息(公海需求) - */ - public List getCustomerProducts(String phoneNumber) { - try { - UserProductCartDTO user = supplyusersMapper.selectByPhone(phoneNumber); - if (user != null && ("seller".equals(user.getType()) || "both".equals(user.getType()))) { - return supplyusersMapper.getSellerProducts(user.getUserId()); - } - return new ArrayList<>(); - } catch (Exception e) { - e.printStackTrace(); - return new ArrayList<>(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/SupplyUserService.java b/src/main/java/com/example/web/service/SupplyUserService.java deleted file mode 100644 index 7ef59a1..0000000 --- a/src/main/java/com/example/web/service/SupplyUserService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.web.service; - -import org.springframework.stereotype.Service; - -@Service -public class SupplyUserService { - -} diff --git a/src/main/java/com/example/web/service/UserService.java b/src/main/java/com/example/web/service/UserService.java deleted file mode 100644 index 4545a6d..0000000 --- a/src/main/java/com/example/web/service/UserService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.web.service; - -import com.example.web.dto.UserProductCartDTO; -import com.example.web.mapper.UsersMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class UserService { - -} diff --git a/src/main/java/com/example/web/service/impl/CustomerServiceImpl.java b/src/main/java/com/example/web/service/impl/CustomerServiceImpl.java new file mode 100644 index 0000000..7c77ec4 --- /dev/null +++ b/src/main/java/com/example/web/service/impl/CustomerServiceImpl.java @@ -0,0 +1,1708 @@ +package com.example.web.service.impl; + +import com.example.web.entity.Contacts; +import com.example.web.entity.CustomerData; +import com.example.web.entity.Enterprise; +import com.example.web.entity.Favorites; +import com.example.web.entity.Login; +import com.example.web.entity.Managers; +import com.example.web.entity.InformationTra; +import com.example.web.entity.Products; +import com.example.web.entity.Users; +import com.example.web.entity.UsersContacts; +import com.example.web.entity.UsersManagements; +import com.example.web.mapper.CustomerMapper; +import com.example.web.mapper.InformationTraMapper; +import com.example.web.mapper.WechatCustomerMapper; +import com.example.web.service.CustomerService; +import com.example.web.utils.CustomerTraceUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + +/** + * @Description: 客户数据服务实现类 + */ +@Service +public class CustomerServiceImpl implements CustomerService { + + @Autowired + private CustomerMapper customerMapper; + + @Autowired + private WechatCustomerMapper wechatCustomerMapper; + + @Autowired + private InformationTraMapper informationTraMapper; + + @Autowired + private CustomerTraceUtil customerTraceUtil; + + @Override + public List getAllCustomers() { + List allCustomers = new ArrayList<>(); + + // 获取primary数据源的客户数据 + List primaryCustomers = getPrimaryCustomers(); + System.out.println("DEBUG: getPrimaryCustomers returned: " + primaryCustomers.size() + " records"); + allCustomers.addAll(primaryCustomers); + + // 获取wechat数据源的客户数据 + List wechatCustomers = getWechatCustomers(); + System.out.println("DEBUG: getWechatCustomers returned: " + wechatCustomers.size() + " records"); + allCustomers.addAll(wechatCustomers); + + System.out.println("DEBUG: getAllCustomers total: " + allCustomers.size() + " records"); + return allCustomers; + } + + @Override + public boolean followupCustomer(String phoneNumber, String followupContent, String dataSource, Login login) { + try { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + System.out.println("DEBUG: 开始跟进客户,电话号码: " + phoneNumber + ", 跟进内容: " + followupContent); + + // 1. 尝试从primary数据源查找客户,添加连接重试机制 + Contacts contacts = null; + int retryCount = 0; + int maxRetries = 3; + long retryDelay = 1000; // 1秒 + + while (retryCount < maxRetries) { + try { + contacts = customerMapper.getContactsByPhoneNumber(phoneNumber); + break; // 获取成功,退出重试循环 + } catch (Exception e) { + retryCount++; + System.out.println("DEBUG: 第" + retryCount + "次尝试获取primary数据源连接失败,异常信息: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; // 达到最大重试次数,抛出异常 + } + // 等待一段时间后重试 + Thread.sleep(retryDelay); + retryDelay *= 2; // 指数退避 + } + } + + if (contacts != null) { + System.out.println("DEBUG: 在primary数据源中找到客户"); + // 保存原始数据用于操作记录 + String originalData = "{\"followup\": \"" + (contacts.getFollowup() == null ? "" : contacts.getFollowup()) + "\", \"followup_at\": \"" + (contacts.getFollowup_at() == null ? "" : contacts.getFollowup_at().toString()) + "\"}"; + + // 更新跟进信息和时间 + contacts.setFollowup(followupContent); + contacts.setFollowup_at(now); + contacts.setUpdated_at(now); + + int result = customerMapper.updateContacts(contacts); + System.out.println("DEBUG: 更新primary数据源联系人结果: " + result); + + // 跟进后将客户状态更新为未分级 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise != null) { + enterprise.setLevel("unclassified"); + customerMapper.updateEnterprise(enterprise); + } + + // 保存操作记录 + if (result > 0) { + String modifiedData = "{\"followup\": \"" + followupContent + "\", \"followup_at\": \"" + now.toString() + "\"}"; + String changedFields = "[\"followup\", \"followup_at\"]"; + saveOperationRecord(contacts.getId(), login, "跟进客户", originalData, modifiedData, changedFields); + + // 记录客户跟进操作 + customerTraceUtil.recordCustomerFollowup(contacts.getId(), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData, modifiedData, changedFields); + } + return result > 0; + } + + System.out.println("DEBUG: 在primary数据源中未找到客户,尝试从wechat数据源查找"); + + // 2. 尝试从wechat数据源查找客户,添加连接重试机制 + Users user = null; + retryCount = 0; + retryDelay = 1000; // 1秒 + + while (retryCount < maxRetries) { + try { + user = wechatCustomerMapper.getUsersByPhoneNumber(phoneNumber); + break; // 获取成功,退出重试循环 + } catch (Exception e) { + retryCount++; + System.out.println("DEBUG: 第" + retryCount + "次尝试获取wechat数据源连接失败,异常信息: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; // 达到最大重试次数,抛出异常 + } + // 等待一段时间后重试 + Thread.sleep(retryDelay); + retryDelay *= 2; // 指数退避 + } + } + + if (user != null) { + System.out.println("DEBUG: 在wechat数据源中找到客户"); + // 保存原始数据用于操作记录 + String originalData = "{\"followup\": \"" + (user.getFollowup() == null ? "" : user.getFollowup()) + "\", \"followup_at\": \"" + (user.getFollowup_at() == null ? "" : user.getFollowup_at().toString()) + "\"}"; + + // 更新跟进信息、时间和状态 + user.setFollowup(followupContent); + user.setFollowup_at(now); + user.setUpdated_at(now); + // 跟进后将客户状态更新为未分级 + user.setLevel("unclassified"); + + int result = wechatCustomerMapper.updateUsers(user); + System.out.println("DEBUG: 更新wechat数据源用户结果: " + result); + + // 保存操作记录 + if (result > 0) { + String modifiedData = "{\"followup\": \"" + followupContent + "\", \"followup_at\": \"" + now.toString() + "\"}"; + String changedFields = "[\"followup\", \"followup_at\"]"; + saveOperationRecord(String.valueOf(user.getUserId()), login, "跟进客户", originalData, modifiedData, changedFields); + + // 记录客户跟进操作 + customerTraceUtil.recordCustomerFollowup(String.valueOf(user.getUserId()), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData, modifiedData, changedFields); + } + return result > 0; + } + + System.out.println("DEBUG: 在两个数据源中都未找到客户信息"); + return false; + } catch (InterruptedException e) { + System.out.println("DEBUG: 跟进客户过程中线程被中断,异常信息: " + e.getMessage()); + Thread.currentThread().interrupt(); + throw new RuntimeException("跟进客户失败: 线程中断"); + } catch (Exception e) { + System.out.println("DEBUG: 跟进客户失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("跟进客户失败: " + e.getMessage()); + } + } + + @Override + public boolean saveOperationRecord(String userId, Login login, String operationEvent, String originalData, String modifiedData, String changedFields) { + try { + // 创建信息跟踪记录 + InformationTra informationTra = new InformationTra(); + informationTra.setUserId(userId); + informationTra.setTracompany(login.getManagercompany()); + informationTra.setTradepartment(login.getManagerdepartment()); + informationTra.setTraorganization(login.getOrganization()); + informationTra.setTrarole(login.getProjectName()); + informationTra.setTrauserName(login.getUserName()); + informationTra.setOperationEvent(operationEvent); + informationTra.setOperationTime(LocalDateTime.now()); + informationTra.setCreatedAt(LocalDateTime.now()); + informationTra.setUpdatedAt(LocalDateTime.now()); + informationTra.setOriginalData(originalData); + informationTra.setModifiedData(modifiedData); + informationTra.setChangedFields(changedFields); + + // 保存到数据库 + int result = informationTraMapper.insertInformationTra(informationTra); + System.out.println("DEBUG: 保存操作记录,用户ID: " + userId + ", 操作人: " + login.getUserName() + ", 操作事件: " + operationEvent + ", 结果: " + result); + return result > 0; + } catch (Exception e) { + System.out.println("DEBUG: 保存操作记录失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + @Override + public boolean recordCustomerView(String userId, Login login) { + try { + System.out.println("DEBUG: 记录客户查看操作,客户ID: " + userId + ", 操作人: " + login.getUserName()); + + // 保存操作记录 + return saveOperationRecord(userId, login, "查看客户详情", "", "", ""); + } catch (Exception e) { + System.out.println("DEBUG: 记录客户查看操作失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + @Override + public boolean claimCustomer(String customerId, Login login) { + try { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + System.out.println("DEBUG: 开始认领客户,客户ID: " + customerId); + + // 1. 尝试从primary数据源查找客户 + Contacts contacts = null; + int retryCount = 0; + int maxRetries = 3; + long retryDelay = 1000; // 1秒 + + while (retryCount < maxRetries) { + try { + contacts = customerMapper.getContactsById(customerId); + break; // 获取成功,退出重试循环 + } catch (Exception e) { + retryCount++; + System.out.println("DEBUG: 第" + retryCount + "次尝试获取primary数据源连接失败,异常信息: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; // 达到最大重试次数,抛出异常 + } + // 等待一段时间后重试 + Thread.sleep(retryDelay); + retryDelay *= 2; // 指数退避 + } + } + + if (contacts != null) { + System.out.println("DEBUG: 在primary数据源中找到客户"); + + // 获取企业信息和负责人信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + Managers managers = customerMapper.getManagerByContactId(contacts.getId()); + + // 保存原始数据用于操作记录 + StringBuilder originalData = new StringBuilder("{"); + if (enterprise != null) { + originalData.append("\"level\": \"" + (enterprise.getLevel() == null ? "" : enterprise.getLevel()) + "\","); + } + if (managers != null) { + originalData.append("\"managercompany\": \"" + (managers.getManagercompany() == null ? "" : managers.getManagercompany()) + "\","); + originalData.append("\"managerdepartment\": \"" + (managers.getManagerdepartment() == null ? "" : managers.getManagerdepartment()) + "\","); + originalData.append("\"organization\": \"" + (managers.getOrganization() == null ? "" : managers.getOrganization()) + "\","); + originalData.append("\"userName\": \"" + (managers.getUserName() == null ? "" : managers.getUserName()) + "\","); + } + // 移除末尾逗号 + if (originalData.length() > 1 && originalData.charAt(originalData.length() - 1) == ',') { + originalData.setLength(originalData.length() - 1); + } + originalData.append("}"); + + // 更新企业等级为未分级 + String originalLevel = null; + if (enterprise != null) { + originalLevel = enterprise.getLevel(); + enterprise.setLevel("unclassified"); + customerMapper.updateEnterprise(enterprise); + } + + // 更新负责人信息 + String originalManagerInfo = ""; + if (managers != null) { + originalManagerInfo = managers.getManagercompany() + "," + managers.getManagerdepartment() + "," + managers.getOrganization() + "," + managers.getUserName(); + managers.setManagercompany(login.getManagercompany()); + managers.setManagerdepartment(login.getManagerdepartment()); + managers.setOrganization(login.getOrganization()); + managers.setUserName(login.getUserName()); + customerMapper.updateManagers(managers); + } else { + managers = new Managers(); + managers.setId(contacts.getId()); + managers.setManagercompany(login.getManagercompany()); + managers.setManagerdepartment(login.getManagerdepartment()); + managers.setOrganization(login.getOrganization()); + managers.setUserName(login.getUserName()); + managers.setRole(login.getProjectName()); + managers.setCreated_at(now); + managers.setUpdated_at(now); + customerMapper.insertManagers(managers); + } + + // 构建修改后的数据 + StringBuilder modifiedData = new StringBuilder("{"); + modifiedData.append("\"level\": \"unclassified\","); + modifiedData.append("\"managercompany\": \"" + login.getManagercompany() + "\","); + modifiedData.append("\"managerdepartment\": \"" + login.getManagerdepartment() + "\","); + modifiedData.append("\"organization\": \"" + login.getOrganization() + "\","); + modifiedData.append("\"userName\": \"" + login.getUserName() + "\""); + modifiedData.append("}"); + + // 保存操作记录 + String changedFields = "[\"level\", \"managercompany\", \"managerdepartment\", \"organization\", \"userName\"]"; + saveOperationRecord(contacts.getId(), login, "认领客户", originalData.toString(), modifiedData.toString(), changedFields); + + // 记录客户认领操作 + customerTraceUtil.recordCustomerFollowup(contacts.getId(), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData.toString(), modifiedData.toString(), changedFields); + + return true; + } + + System.out.println("DEBUG: 在primary数据源中未找到客户,尝试从wechat数据源查找"); + + // 2. 尝试从wechat数据源查找客户 + Users user = null; + retryCount = 0; + retryDelay = 1000; // 1秒 + + while (retryCount < maxRetries) { + try { + user = wechatCustomerMapper.getUsersByUserId(customerId); + break; // 获取成功,退出重试循环 + } catch (Exception e) { + retryCount++; + System.out.println("DEBUG: 第" + retryCount + "次尝试获取wechat数据源连接失败,异常信息: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; // 达到最大重试次数,抛出异常 + } + // 等待一段时间后重试 + Thread.sleep(retryDelay); + retryDelay *= 2; // 指数退避 + } + } + + if (user != null) { + System.out.println("DEBUG: 在wechat数据源中找到客户"); + + // 获取负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(user.getUserId()); + + // 保存原始数据用于操作记录 + StringBuilder originalData = new StringBuilder("{"); + originalData.append("\"level\": \"" + (user.getLevel() == null ? "" : user.getLevel()) + "\","); + if (managements != null) { + originalData.append("\"managercompany\": \"" + (managements.getManagercompany() == null ? "" : managements.getManagercompany()) + "\","); + originalData.append("\"managerdepartment\": \"" + (managements.getManagerdepartment() == null ? "" : managements.getManagerdepartment()) + "\","); + originalData.append("\"organization\": \"" + (managements.getOrganization() == null ? "" : managements.getOrganization()) + "\","); + originalData.append("\"userName\": \"" + (managements.getUserName() == null ? "" : managements.getUserName()) + "\","); + } + // 移除末尾逗号 + if (originalData.length() > 1 && originalData.charAt(originalData.length() - 1) == ',') { + originalData.setLength(originalData.length() - 1); + } + originalData.append("}"); + + // 更新用户等级为未分级 + user.setLevel("unclassified"); + user.setUpdated_at(now); + + // 更新负责人信息 + if (managements == null) { + managements = new UsersManagements(); + managements.setUserId(user.getUserId()); + } + managements.setManagercompany(login.getManagercompany()); + managements.setManagerdepartment(login.getManagerdepartment()); + managements.setOrganization(login.getOrganization()); + managements.setUserName(login.getUserName()); + managements.setRole(login.getProjectName()); + + int result = wechatCustomerMapper.updateUsers(user); + + // 保存或更新负责人信息 + int managerResult = wechatCustomerMapper.getManagementsByUserId(user.getUserId()) == null + ? wechatCustomerMapper.updateUsersManagements(managements) + : wechatCustomerMapper.updateUsersManagements(managements); + + System.out.println("DEBUG: 更新wechat数据源用户结果: " + result + ", 更新负责人结果: " + managerResult); + + // 保存操作记录 + if (result > 0 || managerResult > 0) { + StringBuilder modifiedData = new StringBuilder("{"); + modifiedData.append("\"level\": \"unclassified\","); + modifiedData.append("\"managercompany\": \"" + login.getManagercompany() + "\","); + modifiedData.append("\"managerdepartment\": \"" + login.getManagerdepartment() + "\","); + modifiedData.append("\"organization\": \"" + login.getOrganization() + "\","); + modifiedData.append("\"userName\": \"" + login.getUserName() + "\""); + modifiedData.append("}"); + + String changedFields = "[\"level\", \"managercompany\", \"managerdepartment\", \"organization\", \"userName\"]"; + saveOperationRecord(String.valueOf(user.getUserId()), login, "认领客户", originalData.toString(), modifiedData.toString(), changedFields); + + // 记录客户认领操作 + customerTraceUtil.recordCustomerFollowup(String.valueOf(user.getUserId()), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData.toString(), modifiedData.toString(), changedFields); + } + + return result > 0; + } + + System.out.println("DEBUG: 在两个数据源中都未找到客户信息"); + return false; + } catch (InterruptedException e) { + System.out.println("DEBUG: 认领客户过程中线程被中断,异常信息: " + e.getMessage()); + Thread.currentThread().interrupt(); + throw new RuntimeException("认领客户失败: 线程中断"); + } catch (Exception e) { + System.out.println("DEBUG: 认领客户失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("认领客户失败: " + e.getMessage()); + } + } + + @Override + public List getDepartmentSeaPool(String role, Login login) { + // 移除重复解码,前端已解码 + System.out.println("DEBUG: getDepartmentSeaPool called with role: " + role + ", login: " + login); + List departmentSeaPool = new ArrayList<>(); + + // 获取primary数据源的部门公海池数据 + List primaryData = getPrimaryDepartmentSeaPool(role, login); + System.out.println("DEBUG: getPrimaryDepartmentSeaPool returned: " + primaryData.size() + " records"); + departmentSeaPool.addAll(primaryData); + + // 获取wechat数据源的部门公海池数据 + List wechatData = getWechatDepartmentSeaPool(role, login); + System.out.println("DEBUG: getWechatDepartmentSeaPool returned: " + wechatData.size() + " records"); + departmentSeaPool.addAll(wechatData); + + System.out.println("DEBUG: Total departmentSeaPool returned: " + departmentSeaPool.size() + " records"); + return departmentSeaPool; + } + + @Override + public List getOrganizationSeaPool(String role, Login login) { + // 移除重复解码,前端已解码 + System.out.println("DEBUG: getOrganizationSeaPool called with role: " + role + ", login: " + login); + List organizationSeaPool = new ArrayList<>(); + + // 获取primary数据源的组织公海池数据 + List primaryData = getPrimaryOrganizationSeaPool(role, login); + System.out.println("DEBUG: getPrimaryOrganizationSeaPool returned: " + primaryData.size() + " records"); + organizationSeaPool.addAll(primaryData); + + // 获取wechat数据源的组织公海池数据 + List wechatData = getWechatOrganizationSeaPool(role, login); + System.out.println("DEBUG: getWechatOrganizationSeaPool returned: " + wechatData.size() + " records"); + organizationSeaPool.addAll(wechatData); + + System.out.println("DEBUG: Total organizationSeaPool returned: " + organizationSeaPool.size() + " records"); + return organizationSeaPool; + } + + @Override + public List getCustomersByRole(String role, Login login) { + List filteredCustomers = new ArrayList<>(); + + System.out.println("DEBUG: getCustomersByRole called with role: " + role + ", login: " + login); + System.out.println("DEBUG: Login info - userName: " + login.getUserName() + ", company: " + login.getManagercompany() + ", department: " + login.getManagerdepartment() + ", organization: " + login.getOrganization()); + + // 获取primary数据源的角色数据 + List primaryData = getPrimaryCustomersByRole(role, login); + System.out.println("DEBUG: getPrimaryCustomersByRole returned: " + primaryData.size() + " records"); + filteredCustomers.addAll(primaryData); + + // 获取wechat数据源的角色数据 + List wechatData = getWechatCustomersByRole(role, login); + System.out.println("DEBUG: getWechatCustomersByRole returned: " + wechatData.size() + " records"); + filteredCustomers.addAll(wechatData); + + System.out.println("DEBUG: Total customers after filtering: " + filteredCustomers.size()); + return filteredCustomers; + } + + /** + * 获取primary数据源的角色数据 + * @param role 角色 + * @param login 登录信息 + * @return primary数据源的角色数据 + */ + private List getPrimaryCustomersByRole(String role, Login login) { + List roleCustomers = new ArrayList<>(); + + // 直接从数据库获取符合条件的联系人信息 + List contactsList = customerMapper.getCustomersByRole( + role, login.getUserName(), login.getManagercompany(), + login.getManagerdepartment(), login.getOrganization()); + + for (Contacts contacts : contactsList) { + CustomerData customerData = new CustomerData(); + + // 设置联系人基本信息 + customerData.setId(contacts.getId()); + customerData.setNickName(contacts.getNickName()); + customerData.setPhoneNumber(contacts.getPhoneNumber()); + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + customerData.setFollowup(contacts.getFollowup()); + customerData.setCreated_at(contacts.getCreated_at()); + customerData.setUpdated_at(contacts.getUpdated_at()); + + // 获取并设置企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise != null) { + customerData.setCompany(enterprise.getCompany()); + customerData.setRegion(enterprise.getRegion()); + customerData.setLevel(enterprise.getLevel()); + customerData.setType(enterprise.getType()); + customerData.setDemand(enterprise.getDemand()); + customerData.setSpec(enterprise.getSpec()); + } + + // 获取并设置负责人信息 + Managers managers = customerMapper.getManagerByContactId(contacts.getId()); + if (managers != null) { + customerData.setManagercompany(managers.getManagercompany()); + customerData.setManagerdepartment(managers.getManagerdepartment()); + customerData.setOrganization(managers.getOrganization()); + customerData.setProjectName(managers.getRole()); + customerData.setRole(managers.getRole()); + customerData.setUserName(managers.getUserName()); + customerData.setAssistant(managers.getAssistant()); + } + + // 设置收藏产品信息 + customerData.setFavorites(new ArrayList<>()); + + roleCustomers.add(customerData); + } + + return roleCustomers; + } + + /** + * 获取wechat数据源的角色数据 + * @param role 角色 + * @param login 登录信息 + * @return wechat数据源的角色数据 + */ + private List getWechatCustomersByRole(String role, Login login) { + List roleCustomers = new ArrayList<>(); + + // 直接从数据库获取符合条件的用户信息 + List usersList = wechatCustomerMapper.getCustomersByRole( + role, login.getUserName(), login.getManagercompany(), + login.getManagerdepartment(), login.getOrganization()); + + for (Users user : usersList) { + // 跳过type为manager的用户 + if ("manager".equals(user.getType())) { + continue; + } + + CustomerData customerData = new CustomerData(); + + // 设置用户基本信息 + customerData.setId(user.getUserId()); + customerData.setNickName(user.getNickName()); + customerData.setPhoneNumber(user.getPhoneNumber()); + customerData.setType(user.getType()); + customerData.setCompany(user.getCompany()); + customerData.setRegion(user.getRegion()); + customerData.setLevel(user.getLevel()); + customerData.setDemand(user.getDemand()); + customerData.setSpec(user.getSpec()); + customerData.setFollowup(user.getFollowup()); + customerData.setNotice(user.getNotice()); + customerData.setFollowup_at(user.getFollowup_at()); + customerData.setCreated_at(user.getCreated_at()); + customerData.setUpdated_at(user.getUpdated_at()); + + // 获取并设置联系人信息 + UsersContacts contacts = wechatCustomerMapper.getContactsByUserId(user.getUserId()); + if (contacts != null) { + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + } + + // 获取并设置负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(user.getUserId()); + if (managements != null) { + customerData.setManagercompany(managements.getManagercompany()); + customerData.setManagerdepartment(managements.getManagerdepartment()); + customerData.setOrganization(managements.getOrganization()); + customerData.setProjectName(managements.getRole()); + customerData.setRole(managements.getRole()); + customerData.setUserName(managements.getUserName()); + customerData.setAssistant(managements.getAssistant()); + } + + // 获取并设置收藏产品信息 + customerData.setFavorites(getProductFavorites(user.getPhoneNumber())); + + roleCustomers.add(customerData); + } + + return roleCustomers; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean addCustomer(Map customerData) { + try { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + + // 1. 插入企业信息 + Enterprise enterprise = new Enterprise(); + enterprise.setId((String) customerData.get("id")); + enterprise.setCompany((String) customerData.get("company")); + enterprise.setRegion((String) customerData.get("region")); + enterprise.setLevel((String) customerData.get("level")); + enterprise.setType((String) customerData.get("type")); + enterprise.setDemand((String) customerData.get("demand")); + enterprise.setSpec((String) customerData.get("spec")); + customerMapper.insertEnterprise(enterprise); + + // 2. 插入联系人信息 + Contacts contacts = new Contacts(); + contacts.setContact_id((String) customerData.get("contact_id")); + contacts.setId((String) customerData.get("id")); + contacts.setNickName((String) customerData.get("nickName")); + contacts.setPhoneNumber((String) customerData.get("phoneNumber")); + contacts.setWechat((String) customerData.get("wechat")); + contacts.setAccount((String) customerData.get("account")); + contacts.setAccountNumber((String) customerData.get("accountNumber")); + contacts.setBank((String) customerData.get("bank")); + contacts.setAddress((String) customerData.get("address")); + contacts.setFollowup((String) customerData.get("followup")); + contacts.setCreated_at(now); + contacts.setUpdated_at(now); + customerMapper.insertContacts(contacts); + + // 3. 插入负责人信息 + Managers managers = new Managers(); + // manager_id是自增主键,不需要手动设置,数据库会自动生成 + managers.setId((String) customerData.get("id")); + managers.setManagerId((String) customerData.get("managerId")); + managers.setManagercompany((String) customerData.get("managercompany")); + managers.setManagerdepartment((String) customerData.get("managerdepartment")); + managers.setOrganization((String) customerData.get("organization")); + managers.setRole((String) customerData.get("role")); + managers.setRoot("normal"); // 默认权限 + managers.setCreated_at(now); + managers.setUpdated_at(now); + managers.setUserName((String) customerData.get("userName")); + managers.setAssistant((String) customerData.get("assistant")); + customerMapper.insertManagers(managers); + + return true; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("添加客户失败: " + e.getMessage()); + } + } + + @Override + public boolean updateCustomer(Map customerData, Login login) { + try { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + + // 获取电话号码作为唯一标识 + String phoneNumber = (String) customerData.get("phoneNumber"); + if (phoneNumber == null || phoneNumber.isEmpty()) { + System.out.println("DEBUG: 电话号码为空,无法更新客户信息"); + return false; + } + + System.out.println("DEBUG: 开始更新客户信息,电话号码: " + phoneNumber); + System.out.println("DEBUG: 客户数据: " + customerData); + + // 1. 尝试从primary数据源更新,添加连接重试机制 + Contacts existingContacts = null; + int retryCount = 0; + int maxRetries = 3; + long retryDelay = 1000; // 1秒 + + while (retryCount < maxRetries) { + try { + existingContacts = customerMapper.getContactsByPhoneNumber(phoneNumber); + break; // 获取成功,退出重试循环 + } catch (Exception e) { + retryCount++; + System.out.println("DEBUG: 第" + retryCount + "次尝试获取primary数据源连接失败,异常信息: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; // 达到最大重试次数,抛出异常 + } + // 等待一段时间后重试 + Thread.sleep(retryDelay); + retryDelay *= 2; // 指数退避 + } + } + + if (existingContacts != null) { + System.out.println("DEBUG: 在primary数据源中找到联系人信息,contactId: " + existingContacts.getContact_id()); + + // 获取企业信息和负责人信息 + Enterprise existingEnterprise = customerMapper.getEnterpriseByContactId(existingContacts.getId()); + Managers existingManagers = customerMapper.getManagerByContactId(existingContacts.getId()); + + // 保存原始数据快照 + // 保存Contacts表原始数据 + String originalContactNickName = existingContacts.getNickName(); + String originalContactWechat = existingContacts.getWechat(); + String originalContactAccount = existingContacts.getAccount(); + String originalContactAccountNumber = existingContacts.getAccountNumber(); + String originalContactBank = existingContacts.getBank(); + String originalContactAddress = existingContacts.getAddress(); + String originalContactFollowup = existingContacts.getFollowup(); + LocalDateTime originalContactFollowupAt = existingContacts.getFollowup_at(); + + // 保存Enterprise表原始数据 + String originalEnterpriseCompany = (existingEnterprise != null ? existingEnterprise.getCompany() : null); + String originalEnterpriseRegion = (existingEnterprise != null ? existingEnterprise.getRegion() : null); + String originalEnterpriseLevel = (existingEnterprise != null ? existingEnterprise.getLevel() : null); + String originalEnterpriseType = (existingEnterprise != null ? existingEnterprise.getType() : null); + String originalEnterpriseDemand = (existingEnterprise != null ? existingEnterprise.getDemand() : null); + String originalEnterpriseSpec = (existingEnterprise != null ? existingEnterprise.getSpec() : null); + + // 1.1 更新primary数据源中的数据 + boolean primaryResult = updatePrimaryCustomer(existingContacts, customerData, now); + System.out.println("DEBUG: primary数据源更新结果: " + primaryResult); + + // 获取更新后的企业信息和负责人信息 + Enterprise updatedEnterprise = customerMapper.getEnterpriseByContactId(existingContacts.getId()); + Managers updatedManagers = customerMapper.getManagerByContactId(existingContacts.getId()); + + // 构建完整的原始数据JSON + StringBuilder originalDataBuilder = new StringBuilder("{"); + originalDataBuilder.append("\"nickName\": \"" + (originalContactNickName == null ? "" : originalContactNickName) + "\","); + originalDataBuilder.append("\"wechat\": \"" + (originalContactWechat == null ? "" : originalContactWechat) + "\","); + originalDataBuilder.append("\"account\": \"" + (originalContactAccount == null ? "" : originalContactAccount) + "\","); + originalDataBuilder.append("\"accountNumber\": \"" + (originalContactAccountNumber == null ? "" : originalContactAccountNumber) + "\","); + originalDataBuilder.append("\"bank\": \"" + (originalContactBank == null ? "" : originalContactBank) + "\","); + originalDataBuilder.append("\"address\": \"" + (originalContactAddress == null ? "" : originalContactAddress) + "\","); + originalDataBuilder.append("\"followup\": \"" + (originalContactFollowup == null ? "" : originalContactFollowup) + "\","); + originalDataBuilder.append("\"followup_at\": \"" + (originalContactFollowupAt == null ? "" : originalContactFollowupAt.toString()) + "\","); + originalDataBuilder.append("\"company\": \"" + (originalEnterpriseCompany == null ? "" : originalEnterpriseCompany) + "\","); + originalDataBuilder.append("\"region\": \"" + (originalEnterpriseRegion == null ? "" : originalEnterpriseRegion) + "\","); + originalDataBuilder.append("\"level\": \"" + (originalEnterpriseLevel == null ? "" : originalEnterpriseLevel) + "\","); + originalDataBuilder.append("\"type\": \"" + (originalEnterpriseType == null ? "" : originalEnterpriseType) + "\","); + originalDataBuilder.append("\"demand\": \"" + (originalEnterpriseDemand == null ? "" : originalEnterpriseDemand) + "\","); + originalDataBuilder.append("\"spec\": \"" + (originalEnterpriseSpec == null ? "" : originalEnterpriseSpec) + "\""); + originalDataBuilder.append("}"); + String originalData = originalDataBuilder.toString(); + + // 构建完整的修改后数据JSON + StringBuilder modifiedDataBuilder = new StringBuilder("{"); + modifiedDataBuilder.append("\"nickName\": \"" + (existingContacts.getNickName() == null ? "" : existingContacts.getNickName()) + "\","); + modifiedDataBuilder.append("\"wechat\": \"" + (existingContacts.getWechat() == null ? "" : existingContacts.getWechat()) + "\","); + modifiedDataBuilder.append("\"account\": \"" + (existingContacts.getAccount() == null ? "" : existingContacts.getAccount()) + "\","); + modifiedDataBuilder.append("\"accountNumber\": \"" + (existingContacts.getAccountNumber() == null ? "" : existingContacts.getAccountNumber()) + "\","); + modifiedDataBuilder.append("\"bank\": \"" + (existingContacts.getBank() == null ? "" : existingContacts.getBank()) + "\","); + modifiedDataBuilder.append("\"address\": \"" + (existingContacts.getAddress() == null ? "" : existingContacts.getAddress()) + "\","); + modifiedDataBuilder.append("\"followup\": \"" + (existingContacts.getFollowup() == null ? "" : existingContacts.getFollowup()) + "\","); + modifiedDataBuilder.append("\"followup_at\": \"" + (existingContacts.getFollowup_at() == null ? "" : existingContacts.getFollowup_at().toString()) + "\","); + modifiedDataBuilder.append("\"company\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getCompany() == null ? "" : updatedEnterprise.getCompany()) : "") + "\","); + modifiedDataBuilder.append("\"region\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getRegion() == null ? "" : updatedEnterprise.getRegion()) : "") + "\","); + modifiedDataBuilder.append("\"level\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getLevel() == null ? "" : updatedEnterprise.getLevel()) : "") + "\","); + modifiedDataBuilder.append("\"type\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getType() == null ? "" : updatedEnterprise.getType()) : "") + "\","); + modifiedDataBuilder.append("\"demand\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getDemand() == null ? "" : updatedEnterprise.getDemand()) : "") + "\","); + modifiedDataBuilder.append("\"spec\": \"" + (updatedEnterprise != null ? (updatedEnterprise.getSpec() == null ? "" : updatedEnterprise.getSpec()) : "") + "\""); + modifiedDataBuilder.append("}"); + String modifiedData = modifiedDataBuilder.toString(); + + // 确定实际变更的字段 + StringBuilder changedFieldsBuilder = new StringBuilder("["); + boolean hasChanged = false; + + // 比较Contacts表字段 + if (!equals(originalContactNickName, existingContacts.getNickName())) { + changedFieldsBuilder.append("\"nickName\", "); + hasChanged = true; + } + if (!equals(originalContactWechat, existingContacts.getWechat())) { + changedFieldsBuilder.append("\"wechat\", "); + hasChanged = true; + } + if (!equals(originalContactAccount, existingContacts.getAccount())) { + changedFieldsBuilder.append("\"account\", "); + hasChanged = true; + } + if (!equals(originalContactAccountNumber, existingContacts.getAccountNumber())) { + changedFieldsBuilder.append("\"accountNumber\", "); + hasChanged = true; + } + if (!equals(originalContactBank, existingContacts.getBank())) { + changedFieldsBuilder.append("\"bank\", "); + hasChanged = true; + } + if (!equals(originalContactAddress, existingContacts.getAddress())) { + changedFieldsBuilder.append("\"address\", "); + hasChanged = true; + } + if (!equals(originalContactFollowup, existingContacts.getFollowup())) { + changedFieldsBuilder.append("\"followup\", "); + hasChanged = true; + } + if (!equals(originalContactFollowupAt, existingContacts.getFollowup_at())) { + changedFieldsBuilder.append("\"followup_at\", "); + hasChanged = true; + } + + // 比较Enterprise表字段 + if (!equals(originalEnterpriseCompany, (updatedEnterprise != null ? updatedEnterprise.getCompany() : null))) { + changedFieldsBuilder.append("\"company\", "); + hasChanged = true; + } + if (!equals(originalEnterpriseRegion, (updatedEnterprise != null ? updatedEnterprise.getRegion() : null))) { + changedFieldsBuilder.append("\"region\", "); + hasChanged = true; + } + if (!equals(originalEnterpriseLevel, (updatedEnterprise != null ? updatedEnterprise.getLevel() : null))) { + changedFieldsBuilder.append("\"level\", "); + hasChanged = true; + } + if (!equals(originalEnterpriseType, (updatedEnterprise != null ? updatedEnterprise.getType() : null))) { + changedFieldsBuilder.append("\"type\", "); + hasChanged = true; + } + if (!equals(originalEnterpriseDemand, (updatedEnterprise != null ? updatedEnterprise.getDemand() : null))) { + changedFieldsBuilder.append("\"demand\", "); + hasChanged = true; + } + if (!equals(originalEnterpriseSpec, (updatedEnterprise != null ? updatedEnterprise.getSpec() : null))) { + changedFieldsBuilder.append("\"spec\", "); + hasChanged = true; + } + + // 移除末尾的逗号和空格 + String changedFields; + if (hasChanged) { + changedFields = changedFieldsBuilder.substring(0, changedFieldsBuilder.length() - 2) + "]"; + } else { + changedFields = "[]"; + } + + // 记录客户编辑操作 + customerTraceUtil.recordCustomerEdit(existingContacts.getId(), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData, modifiedData, changedFields); + + return primaryResult; + } + + System.out.println("DEBUG: 在primary数据源中未找到联系人信息,尝试从wechat数据源更新"); + + // 2. 尝试从wechat数据源更新,添加异常处理 + try { + Users existingUser = wechatCustomerMapper.getUsersByPhoneNumber(phoneNumber); + if (existingUser != null) { + System.out.println("DEBUG: 在wechat数据源中找到用户信息,userId: " + existingUser.getUserId()); + + // 获取联系人信息和负责人信息 + UsersContacts existingWechatContacts = wechatCustomerMapper.getContactsByUserId(existingUser.getUserId()); + UsersManagements existingManagements = wechatCustomerMapper.getManagementsByUserId(existingUser.getUserId()); + + // 保存原始数据快照 + // 保存Users表原始数据 + String originalUserNickName = existingUser.getNickName(); + String originalUserCompany = existingUser.getCompany(); + String originalUserRegion = existingUser.getRegion(); + String originalUserLevel = existingUser.getLevel(); + String originalUserDemand = existingUser.getDemand(); + String originalUserSpec = existingUser.getSpec(); + String originalUserFollowup = existingUser.getFollowup(); + String originalUserNotice = existingUser.getNotice(); + LocalDateTime originalUserFollowupAt = existingUser.getFollowup_at(); + + // 保存UsersContacts表原始数据 + String originalContactWechat = (existingWechatContacts != null ? existingWechatContacts.getWechat() : null); + String originalContactAccount = (existingWechatContacts != null ? existingWechatContacts.getAccount() : null); + String originalContactAccountNumber = (existingWechatContacts != null ? existingWechatContacts.getAccountNumber() : null); + String originalContactBank = (existingWechatContacts != null ? existingWechatContacts.getBank() : null); + String originalContactAddress = (existingWechatContacts != null ? existingWechatContacts.getAddress() : null); + + // 2.1 更新wechat数据源中的数据 + boolean wechatResult = updateWechatCustomer(existingUser, customerData, now); + System.out.println("DEBUG: wechat数据源更新结果: " + wechatResult); + + // 获取更新后的联系人信息和负责人信息 + UsersContacts updatedContacts = wechatCustomerMapper.getContactsByUserId(existingUser.getUserId()); + UsersManagements updatedManagements = wechatCustomerMapper.getManagementsByUserId(existingUser.getUserId()); + + // 构建完整的原始数据JSON + StringBuilder originalDataBuilder = new StringBuilder("{"); + originalDataBuilder.append("\"nickName\": \"" + (originalUserNickName == null ? "" : originalUserNickName) + "\","); + originalDataBuilder.append("\"company\": \"" + (originalUserCompany == null ? "" : originalUserCompany) + "\","); + originalDataBuilder.append("\"region\": \"" + (originalUserRegion == null ? "" : originalUserRegion) + "\","); + originalDataBuilder.append("\"level\": \"" + (originalUserLevel == null ? "" : originalUserLevel) + "\","); + originalDataBuilder.append("\"demand\": \"" + (originalUserDemand == null ? "" : originalUserDemand) + "\","); + originalDataBuilder.append("\"spec\": \"" + (originalUserSpec == null ? "" : originalUserSpec) + "\","); + originalDataBuilder.append("\"followup\": \"" + (originalUserFollowup == null ? "" : originalUserFollowup) + "\","); + originalDataBuilder.append("\"notice\": \"" + (originalUserNotice == null ? "" : originalUserNotice) + "\","); + originalDataBuilder.append("\"followup_at\": \"" + (originalUserFollowupAt == null ? "" : originalUserFollowupAt.toString()) + "\","); + originalDataBuilder.append("\"wechat\": \"" + (originalContactWechat == null ? "" : originalContactWechat) + "\","); + originalDataBuilder.append("\"account\": \"" + (originalContactAccount == null ? "" : originalContactAccount) + "\","); + originalDataBuilder.append("\"accountNumber\": \"" + (originalContactAccountNumber == null ? "" : originalContactAccountNumber) + "\","); + originalDataBuilder.append("\"bank\": \"" + (originalContactBank == null ? "" : originalContactBank) + "\","); + originalDataBuilder.append("\"address\": \"" + (originalContactAddress == null ? "" : originalContactAddress) + "\""); + originalDataBuilder.append("}"); + String originalData = originalDataBuilder.toString(); + + // 构建完整的修改后数据JSON + StringBuilder modifiedDataBuilder = new StringBuilder("{"); + modifiedDataBuilder.append("\"nickName\": \"" + (existingUser.getNickName() == null ? "" : existingUser.getNickName()) + "\","); + modifiedDataBuilder.append("\"company\": \"" + (existingUser.getCompany() == null ? "" : existingUser.getCompany()) + "\","); + modifiedDataBuilder.append("\"region\": \"" + (existingUser.getRegion() == null ? "" : existingUser.getRegion()) + "\","); + modifiedDataBuilder.append("\"level\": \"" + (existingUser.getLevel() == null ? "" : existingUser.getLevel()) + "\","); + modifiedDataBuilder.append("\"demand\": \"" + (existingUser.getDemand() == null ? "" : existingUser.getDemand()) + "\","); + modifiedDataBuilder.append("\"spec\": \"" + (existingUser.getSpec() == null ? "" : existingUser.getSpec()) + "\","); + modifiedDataBuilder.append("\"followup\": \"" + (existingUser.getFollowup() == null ? "" : existingUser.getFollowup()) + "\","); + modifiedDataBuilder.append("\"notice\": \"" + (existingUser.getNotice() == null ? "" : existingUser.getNotice()) + "\","); + modifiedDataBuilder.append("\"followup_at\": \"" + (existingUser.getFollowup_at() == null ? "" : existingUser.getFollowup_at().toString()) + "\","); + modifiedDataBuilder.append("\"wechat\": \"" + (updatedContacts != null ? (updatedContacts.getWechat() == null ? "" : updatedContacts.getWechat()) : "") + "\","); + modifiedDataBuilder.append("\"account\": \"" + (updatedContacts != null ? (updatedContacts.getAccount() == null ? "" : updatedContacts.getAccount()) : "") + "\","); + modifiedDataBuilder.append("\"accountNumber\": \"" + (updatedContacts != null ? (updatedContacts.getAccountNumber() == null ? "" : updatedContacts.getAccountNumber()) : "") + "\","); + modifiedDataBuilder.append("\"bank\": \"" + (updatedContacts != null ? (updatedContacts.getBank() == null ? "" : updatedContacts.getBank()) : "") + "\","); + modifiedDataBuilder.append("\"address\": \"" + (updatedContacts != null ? (updatedContacts.getAddress() == null ? "" : updatedContacts.getAddress()) : "") + "\""); + modifiedDataBuilder.append("}"); + String modifiedData = modifiedDataBuilder.toString(); + + // 确定实际变更的字段 + StringBuilder changedFieldsBuilder = new StringBuilder("["); + boolean hasChanged = false; + + // 比较Users表字段 + if (!equals(originalUserNickName, existingUser.getNickName())) { + changedFieldsBuilder.append("\"nickName\", "); + hasChanged = true; + } + if (!equals(originalUserCompany, existingUser.getCompany())) { + changedFieldsBuilder.append("\"company\", "); + hasChanged = true; + } + if (!equals(originalUserRegion, existingUser.getRegion())) { + changedFieldsBuilder.append("\"region\", "); + hasChanged = true; + } + if (!equals(originalUserLevel, existingUser.getLevel())) { + changedFieldsBuilder.append("\"level\", "); + hasChanged = true; + } + if (!equals(originalUserDemand, existingUser.getDemand())) { + changedFieldsBuilder.append("\"demand\", "); + hasChanged = true; + } + if (!equals(originalUserSpec, existingUser.getSpec())) { + changedFieldsBuilder.append("\"spec\", "); + hasChanged = true; + } + if (!equals(originalUserFollowup, existingUser.getFollowup())) { + changedFieldsBuilder.append("\"followup\", "); + hasChanged = true; + } + if (!equals(originalUserNotice, existingUser.getNotice())) { + changedFieldsBuilder.append("\"notice\", "); + hasChanged = true; + } + if (!equals(originalUserFollowupAt, existingUser.getFollowup_at())) { + changedFieldsBuilder.append("\"followup_at\", "); + hasChanged = true; + } + + // 比较UsersContacts表字段 + if (!equals(originalContactWechat, (updatedContacts != null ? updatedContacts.getWechat() : null))) { + changedFieldsBuilder.append("\"wechat\", "); + hasChanged = true; + } + if (!equals(originalContactAccount, (updatedContacts != null ? updatedContacts.getAccount() : null))) { + changedFieldsBuilder.append("\"account\", "); + hasChanged = true; + } + if (!equals(originalContactAccountNumber, (updatedContacts != null ? updatedContacts.getAccountNumber() : null))) { + changedFieldsBuilder.append("\"accountNumber\", "); + hasChanged = true; + } + if (!equals(originalContactBank, (updatedContacts != null ? updatedContacts.getBank() : null))) { + changedFieldsBuilder.append("\"bank\", "); + hasChanged = true; + } + if (!equals(originalContactAddress, (updatedContacts != null ? updatedContacts.getAddress() : null))) { + changedFieldsBuilder.append("\"address\", "); + hasChanged = true; + } + + // 移除末尾的逗号和空格 + String changedFields; + if (hasChanged) { + changedFields = changedFieldsBuilder.substring(0, changedFieldsBuilder.length() - 2) + "]"; + } else { + changedFields = "[]"; + } + + // 记录客户编辑操作 + customerTraceUtil.recordCustomerEdit(String.valueOf(existingUser.getUserId()), login.getManagercompany(), login.getManagerdepartment(), login.getOrganization(), login.getProjectName(), login.getUserName(), originalData, modifiedData, changedFields); + + return wechatResult; + } + } catch (Exception e) { + System.out.println("DEBUG: 从wechat数据源查询用户信息失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + // 忽略wechat数据源查询失败的异常,继续执行 + } + + System.out.println("DEBUG: 在两个数据源中都未找到客户信息,无法更新"); + // 3. 两个数据源中都没有找到,返回false + return false; + } catch (InterruptedException e) { + System.out.println("DEBUG: 更新客户过程中线程被中断,异常信息: " + e.getMessage()); + Thread.currentThread().interrupt(); + throw new RuntimeException("更新客户失败: 线程中断"); + } catch (Exception e) { + System.out.println("DEBUG: 更新客户失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("更新客户失败: " + e.getMessage()); + } + } + + /** + * 更新primary数据源中的客户信息 + */ + private boolean updatePrimaryCustomer(Contacts existingContacts, Map customerData, LocalDateTime now) { + try { + String contactId = existingContacts.getContact_id(); + String enterpriseId = existingContacts.getId(); + System.out.println("DEBUG: 开始更新primary数据源中的客户信息,contactId: " + contactId + ", enterpriseId: " + enterpriseId); + + // 只更新customerData中存在的字段,避免将现有字段设为null + // 更新联系人信息 + if (customerData.containsKey("nickName")) { + existingContacts.setNickName((String) customerData.get("nickName")); + } + if (customerData.containsKey("wechat")) { + existingContacts.setWechat((String) customerData.get("wechat")); + } + if (customerData.containsKey("account")) { + existingContacts.setAccount((String) customerData.get("account")); + } + if (customerData.containsKey("accountNumber")) { + existingContacts.setAccountNumber((String) customerData.get("accountNumber")); + } + if (customerData.containsKey("bank")) { + existingContacts.setBank((String) customerData.get("bank")); + } + if (customerData.containsKey("address")) { + existingContacts.setAddress((String) customerData.get("address")); + } + existingContacts.setUpdated_at(now); + int contactsUpdateResult = customerMapper.updateContacts(existingContacts); + System.out.println("DEBUG: 更新联系人信息结果: " + contactsUpdateResult); + + // 更新企业信息 + Enterprise enterprise = new Enterprise(); + enterprise.setId(enterpriseId); + if (customerData.containsKey("company")) { + enterprise.setCompany((String) customerData.get("company")); + } + if (customerData.containsKey("region")) { + enterprise.setRegion((String) customerData.get("region")); + } + if (customerData.containsKey("level")) { + enterprise.setLevel((String) customerData.get("level")); + } + if (customerData.containsKey("type")) { + enterprise.setType((String) customerData.get("type")); + } + if (customerData.containsKey("demand")) { + enterprise.setDemand((String) customerData.get("demand")); + } + if (customerData.containsKey("spec")) { + enterprise.setSpec((String) customerData.get("spec")); + } + int enterpriseUpdateResult = customerMapper.updateEnterprise(enterprise); + System.out.println("DEBUG: 更新企业信息结果: " + enterpriseUpdateResult); + + // 更新负责人信息 + Managers managers = new Managers(); + managers.setId(enterpriseId); + if (customerData.containsKey("managercompany")) { + managers.setManagercompany((String) customerData.get("managercompany")); + } + if (customerData.containsKey("managerdepartment")) { + managers.setManagerdepartment((String) customerData.get("managerdepartment")); + } + if (customerData.containsKey("organization")) { + managers.setOrganization((String) customerData.get("organization")); + } + if (customerData.containsKey("projectName")) { + managers.setRole((String) customerData.get("projectName")); + } + if (customerData.containsKey("userName")) { + managers.setUserName((String) customerData.get("userName")); + } + if (customerData.containsKey("assistant")) { + managers.setAssistant((String) customerData.get("assistant")); + } + managers.setUpdated_at(now); + int managersUpdateResult = customerMapper.updateManagers(managers); + System.out.println("DEBUG: 更新负责人信息结果: " + managersUpdateResult); + + System.out.println("DEBUG: 更新primary数据源客户成功"); + return true; + } catch (Exception e) { + System.out.println("DEBUG: 更新primary数据源客户失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("更新primary数据源客户失败: " + e.getMessage()); + } + } + + /** + * 更新wechat数据源中的客户信息 + */ + private boolean updateWechatCustomer(Users existingUser, Map customerData, LocalDateTime now) { + try { + String userId = existingUser.getUserId(); + System.out.println("DEBUG: 开始更新wechat数据源中的客户信息,userId: " + userId); + + // 只更新customerData中存在的字段,避免将现有字段设为null + if (customerData.containsKey("nickName")) { + existingUser.setNickName((String) customerData.get("nickName")); + } + if (customerData.containsKey("company")) { + existingUser.setCompany((String) customerData.get("company")); + } + if (customerData.containsKey("region")) { + existingUser.setRegion((String) customerData.get("region")); + } + if (customerData.containsKey("level")) { + existingUser.setLevel((String) customerData.get("level")); + } + if (customerData.containsKey("demand")) { + existingUser.setDemand((String) customerData.get("demand")); + } + if (customerData.containsKey("notice")) { + existingUser.setNotice((String) customerData.get("notice")); + } + existingUser.setUpdated_at(now); + int usersUpdateResult = wechatCustomerMapper.updateUsers(existingUser); + System.out.println("DEBUG: 更新用户信息结果: " + usersUpdateResult); + + // 获取或创建联系人信息 + UsersContacts contacts = wechatCustomerMapper.getContactsByUserId(userId); + System.out.println("DEBUG: 获取联系人信息结果: " + (contacts != null ? "找到" : "未找到")); + + if (contacts != null) { + // 更新联系人信息 + contacts.setWechat((String) customerData.get("wechat")); + contacts.setAccount((String) customerData.get("account")); + contacts.setAccountNumber((String) customerData.get("accountNumber")); + contacts.setBank((String) customerData.get("bank")); + contacts.setAddress((String) customerData.get("address")); + contacts.setUpdated_at(now); + int contactsUpdateResult = wechatCustomerMapper.updateUsersContacts(contacts); + System.out.println("DEBUG: 更新联系人信息结果: " + contactsUpdateResult); + } + + // 获取或创建负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(userId); + System.out.println("DEBUG: 获取负责人信息结果: " + (managements != null ? "找到" : "未找到")); + + if (managements != null) { + // 更新负责人信息 + managements.setManagercompany((String) customerData.get("managercompany")); + managements.setManagerdepartment((String) customerData.get("managerdepartment")); + managements.setOrganization((String) customerData.get("organization")); + managements.setRole((String) customerData.get("projectName")); + managements.setUserName((String) customerData.get("userName")); + managements.setAssistant((String) customerData.get("assistant")); + managements.setUpdated_at(now); + int managementsUpdateResult = wechatCustomerMapper.updateUsersManagements(managements); + System.out.println("DEBUG: 更新负责人信息结果: " + managementsUpdateResult); + } + + System.out.println("DEBUG: 更新wechat数据源客户成功"); + return true; + } catch (Exception e) { + System.out.println("DEBUG: 更新wechat数据源客户失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("更新wechat数据源客户失败: " + e.getMessage()); + } + } + + /** + * 获取primary数据源的客户数据 + * @return primary数据源的客户数据列表 + */ + private List getPrimaryCustomers() { + List primaryCustomers = new ArrayList<>(); + + // 获取所有联系人信息 + List contactsList = customerMapper.getAllContacts(); + + for (Contacts contacts : contactsList) { + CustomerData customerData = new CustomerData(); + + // 设置联系人基本信息 + customerData.setId(contacts.getId()); // 设置客户ID + customerData.setNickName(contacts.getNickName()); + customerData.setPhoneNumber(contacts.getPhoneNumber()); + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + customerData.setFollowup(contacts.getFollowup()); + customerData.setCreated_at(contacts.getCreated_at()); + customerData.setUpdated_at(contacts.getUpdated_at()); + + // 获取并设置企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise != null) { + customerData.setCompany(enterprise.getCompany()); + customerData.setRegion(enterprise.getRegion()); + // 明确设置部门公海池的level值,与wechat数据保持一致 + customerData.setLevel("department-sea-pools"); + customerData.setType(enterprise.getType()); + customerData.setDemand(enterprise.getDemand()); + customerData.setSpec(enterprise.getSpec()); + } + + // 获取并设置负责人信息 + Managers managers = customerMapper.getManagerByContactId(contacts.getId()); + if (managers != null) { + customerData.setManagercompany(managers.getManagercompany()); + customerData.setManagerdepartment(managers.getManagerdepartment()); + customerData.setOrganization(managers.getOrganization()); + customerData.setProjectName(managers.getRole()); // 使用实际的role字段 + customerData.setRole(managers.getRole()); // 同时设置role字段 + customerData.setUserName(managers.getUserName()); + customerData.setAssistant(managers.getAssistant()); + } + + // 设置收藏产品信息(primary数据源暂时没有收藏功能) + customerData.setFavorites(new ArrayList<>()); + + primaryCustomers.add(customerData); + } + + return primaryCustomers; + } + + /** + * 获取wechat数据源的客户数据 + * @return wechat数据源的客户数据列表 + */ + private List getWechatCustomers() { + List wechatCustomers = new ArrayList<>(); + + // 获取所有用户信息 + List usersList = wechatCustomerMapper.getAllUsers(); + + for (Users user : usersList) { + // 跳过type为manager的用户 + if ("manager".equals(user.getType())) { + continue; + } + + CustomerData customerData = new CustomerData(); + + // 设置用户基本信息 + customerData.setId(user.getUserId()); // 设置客户ID + customerData.setNickName(user.getNickName()); + customerData.setPhoneNumber(user.getPhoneNumber()); + customerData.setType(user.getType()); + customerData.setCompany(user.getCompany()); + customerData.setRegion(user.getRegion()); + customerData.setLevel(user.getLevel()); + customerData.setDemand(user.getDemand()); + customerData.setSpec(user.getSpec()); + customerData.setFollowup(user.getFollowup()); + customerData.setNotice(user.getNotice()); + customerData.setFollowup_at(user.getFollowup_at()); + customerData.setCreated_at(user.getCreated_at()); + customerData.setUpdated_at(user.getUpdated_at()); + + // 获取并设置联系人信息 + UsersContacts contacts = wechatCustomerMapper.getContactsByUserId(user.getUserId()); + if (contacts != null) { + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + } + + // 获取并设置负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(user.getUserId()); // 使用user.getUserId()获取关联字段 + if (managements != null) { + customerData.setManagercompany(managements.getManagercompany()); + customerData.setManagerdepartment(managements.getManagerdepartment()); + customerData.setOrganization(managements.getOrganization()); + customerData.setProjectName(managements.getRole()); // 使用role字段作为职位信息 + customerData.setRole(managements.getRole()); // 同时设置role字段 + customerData.setUserName(managements.getUserName()); + customerData.setAssistant(managements.getAssistant()); + } + + // 获取并设置收藏产品信息 + customerData.setFavorites(getProductFavorites(user.getPhoneNumber())); + + wechatCustomers.add(customerData); + } + + return wechatCustomers; + } + + /** + * 比较两个对象是否相等,处理null情况 + * @param obj1 第一个对象 + * @param obj2 第二个对象 + * @return 是否相等 + */ + private boolean equals(Object obj1, Object obj2) { + if (obj1 == null && obj2 == null) { + return true; + } + if (obj1 == null || obj2 == null) { + return false; + } + return obj1.equals(obj2); + } + + /** + * URL解码工具方法 + * @param encodedStr URL编码的字符串 + * @return 解码后的字符串 + */ + private String urlDecode(String encodedStr) { + if (encodedStr == null) { + return null; + } + try { + return URLDecoder.decode(encodedStr, StandardCharsets.UTF_8.name()); + } catch (Exception e) { + // 如果解码失败,返回原始字符串 + return encodedStr; + } + } + + /** + * 获取用户收藏的产品信息 + * @param userPhone 用户手机号 + * @return 产品收藏列表 + */ + private List getProductFavorites(String userPhone) { + List productFavorites = new ArrayList<>(); + + // 获取收藏的产品ID列表 + List favoritesList = wechatCustomerMapper.getFavoritesByUserPhone(userPhone); + + for (Favorites favorite : favoritesList) { + // 获取产品信息 + Products product = wechatCustomerMapper.getProductById(favorite.getProductId()); + if (product != null) { + CustomerData.ProductFavorite productFavorite = new CustomerData.ProductFavorite(); + productFavorite.setProductName(product.getProductName()); + productFavorite.setPrice(product.getPrice()); + productFavorite.setQuantity(String.valueOf(product.getQuantity())); + productFavorite.setGrossWeight(product.getGrossWeight()); + productFavorite.setYolk(product.getYolk()); + productFavorite.setFavoriteDate(favorite.getDate()); + productFavorites.add(productFavorite); + } + } + + return productFavorites; + } + + /** + * 获取primary数据源的部门公海池数据 + * @param login 用户登录信息 + * @return primary数据源的部门公海池数据 + */ + private List getPrimaryDepartmentSeaPool(String role, Login login) { + List departmentSeaPool = new ArrayList<>(); + + // 获取部门公海池的联系人信息 + List contactsList = customerMapper.getDepartmentSeaPoolContacts( + role, login.getManagercompany(), login.getManagerdepartment()); + + for (Contacts contacts : contactsList) { + CustomerData customerData = new CustomerData(); + // 设置联系人基本信息 + customerData.setId(contacts.getId()); // 设置客户ID + customerData.setNickName(contacts.getNickName()); + customerData.setPhoneNumber(contacts.getPhoneNumber()); + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + customerData.setFollowup(contacts.getFollowup()); + customerData.setCreated_at(contacts.getCreated_at()); + customerData.setUpdated_at(contacts.getUpdated_at()); + + // 获取并设置企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise != null) { + customerData.setCompany(enterprise.getCompany()); + customerData.setRegion(enterprise.getRegion()); + // 统一设置部门公海池的level值 + customerData.setLevel("department-sea-pools"); + customerData.setType(enterprise.getType()); + customerData.setDemand(enterprise.getDemand()); + customerData.setSpec(enterprise.getSpec()); + } + + // 获取并设置负责人信息 + Managers managers = customerMapper.getManagerByContactId(contacts.getId()); + if (managers != null) { + customerData.setManagercompany(managers.getManagercompany()); + customerData.setManagerdepartment(managers.getManagerdepartment()); + customerData.setOrganization(managers.getOrganization()); + customerData.setProjectName(managers.getRole()); // 使用实际的role字段 + customerData.setRole(managers.getRole()); // 同时设置role字段 + customerData.setUserName(managers.getUserName()); + customerData.setAssistant(managers.getAssistant()); + } else { + // 如果没有负责人信息,使用登录用户的公司和部门信息 + customerData.setManagercompany(login.getManagercompany()); + customerData.setManagerdepartment(login.getManagerdepartment()); + customerData.setOrganization("无"); + customerData.setProjectName("无"); + customerData.setRole("无"); + customerData.setUserName("无"); + customerData.setAssistant("无"); + } + + // 设置收藏产品信息 + customerData.setFavorites(new ArrayList<>()); + + departmentSeaPool.add(customerData); + } + + return departmentSeaPool; + } + + /** + * 获取wechat数据源的部门公海池数据 + * @param login 用户登录信息 + * @return wechat数据源的部门公海池数据 + */ + private List getWechatDepartmentSeaPool(String role, Login login) { + List departmentSeaPool = new ArrayList<>(); + + // 添加日志输出 + System.out.println("DEBUG: getWechatDepartmentSeaPool - role: " + role); + System.out.println("DEBUG: getWechatDepartmentSeaPool - managercompany: " + login.getManagercompany()); + System.out.println("DEBUG: getWechatDepartmentSeaPool - managerdepartment: " + login.getManagerdepartment()); + + // 获取部门公海池的用户信息 + List usersList = wechatCustomerMapper.getDepartmentSeaPoolUsers( + role, login.getManagercompany(), login.getManagerdepartment()); + + System.out.println("DEBUG: getWechatDepartmentSeaPool - usersList size: " + (usersList != null ? usersList.size() : 0)); + System.out.println("DEBUG: getWechatDepartmentSeaPool - usersList: " + usersList); + + for (Users user : usersList) { + // 跳过type为manager的用户 + if ("manager".equals(user.getType())) { + continue; + } + + CustomerData customerData = new CustomerData(); + + // 设置用户基本信息 + customerData.setId(user.getUserId()); // 设置客户ID + customerData.setNickName(user.getNickName()); + customerData.setPhoneNumber(user.getPhoneNumber()); + customerData.setType(user.getType()); + customerData.setCompany(user.getCompany()); + customerData.setRegion(user.getRegion()); + // 明确设置部门公海池的level值 + customerData.setLevel("department-sea-pools"); + customerData.setDemand(user.getDemand()); + customerData.setFollowup(user.getFollowup()); + customerData.setNotice(user.getNotice()); + customerData.setFollowup_at(user.getFollowup_at()); + customerData.setCreated_at(user.getCreated_at()); + customerData.setUpdated_at(user.getUpdated_at()); + + // 获取并设置联系人信息 + UsersContacts contacts = wechatCustomerMapper.getContactsByUserId(user.getUserId()); + if (contacts != null) { + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + } + + // 获取并设置负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(user.getUserId()); // 使用user.getUserId()获取关联字段 + if (managements != null) { + customerData.setManagercompany(managements.getManagercompany()); + customerData.setManagerdepartment(managements.getManagerdepartment()); + customerData.setOrganization(managements.getOrganization()); + customerData.setProjectName(managements.getRole()); // 使用role字段作为职位信息 + customerData.setRole(managements.getRole()); // 同时设置role字段 + customerData.setUserName(managements.getUserName()); + customerData.setAssistant(managements.getAssistant()); + } else { + // 如果没有负责人信息,使用登录用户的公司和部门信息 + customerData.setManagercompany(login.getManagercompany()); + customerData.setManagerdepartment(login.getManagerdepartment()); + customerData.setOrganization("无"); + customerData.setProjectName("无"); + customerData.setRole("无"); + customerData.setUserName("无"); + customerData.setAssistant("无"); + } + + // 获取并设置收藏产品信息 + customerData.setFavorites(getProductFavorites(user.getPhoneNumber())); + + departmentSeaPool.add(customerData); + } + + return departmentSeaPool; + } + + /** + * 获取primary数据源的组织公海池数据 + * @param login 用户登录信息 + * @return primary数据源的组织公海池数据 + */ + private List getPrimaryOrganizationSeaPool(String role, Login login) { + List organizationSeaPool = new ArrayList<>(); + + // 获取组织公海池的联系人信息 + List contactsList = customerMapper.getOrganizationSeaPoolContacts( + role, login.getManagercompany(), login.getManagerdepartment(), login.getOrganization()); + + for (Contacts contacts : contactsList) { + CustomerData customerData = new CustomerData(); + + // 设置联系人基本信息 + customerData.setId(contacts.getId()); // 设置客户ID + customerData.setNickName(contacts.getNickName()); + customerData.setPhoneNumber(contacts.getPhoneNumber()); + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + customerData.setFollowup(contacts.getFollowup()); + customerData.setCreated_at(contacts.getCreated_at()); + customerData.setUpdated_at(contacts.getUpdated_at()); + + // 获取并设置企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise != null) { + customerData.setCompany(enterprise.getCompany()); + customerData.setRegion(enterprise.getRegion()); + // 统一设置组织公海池的level值 + customerData.setLevel("organization-sea-pools"); + customerData.setType(enterprise.getType()); + customerData.setDemand(enterprise.getDemand()); + } + + // 获取并设置负责人信息 + Managers managers = customerMapper.getManagerByContactId(contacts.getId()); + if (managers != null) { + customerData.setManagercompany(managers.getManagercompany()); + customerData.setManagerdepartment(managers.getManagerdepartment()); + customerData.setOrganization(managers.getOrganization()); + customerData.setProjectName(managers.getRole()); // 使用实际的role字段 + customerData.setRole(managers.getRole()); // 同时设置role字段 + customerData.setUserName(managers.getUserName()); + customerData.setAssistant(managers.getAssistant()); + } else { + // 如果没有负责人信息,使用登录用户的公司、部门和组织信息 + customerData.setManagercompany(login.getManagercompany()); + customerData.setManagerdepartment(login.getManagerdepartment()); + customerData.setOrganization(login.getOrganization()); + customerData.setProjectName("无"); + customerData.setRole("无"); + customerData.setUserName("无"); + customerData.setAssistant("无"); + } + + // 设置收藏产品信息 + customerData.setFavorites(new ArrayList<>()); + + organizationSeaPool.add(customerData); + } + + return organizationSeaPool; + } + + /** + * 获取wechat数据源的组织公海池数据 + * @param login 用户登录信息 + * @return wechat数据源的组织公海池数据 + */ + private List getWechatOrganizationSeaPool(String role, Login login) { + List organizationSeaPool = new ArrayList<>(); + + // 添加日志输出 + System.out.println("DEBUG: getWechatOrganizationSeaPool - role: " + role); + System.out.println("DEBUG: getWechatOrganizationSeaPool - managercompany: " + login.getManagercompany()); + System.out.println("DEBUG: getWechatOrganizationSeaPool - managerdepartment: " + login.getManagerdepartment()); + System.out.println("DEBUG: getWechatOrganizationSeaPool - organization: " + login.getOrganization()); + + // 获取组织公海池的用户信息 + List usersList = wechatCustomerMapper.getOrganizationSeaPoolUsers( + role, login.getManagercompany(), login.getManagerdepartment(), login.getOrganization()); + + System.out.println("DEBUG: getWechatOrganizationSeaPool - usersList size: " + (usersList != null ? usersList.size() : 0)); + System.out.println("DEBUG: getWechatOrganizationSeaPool - usersList: " + usersList); + + for (Users user : usersList) { + // 跳过type为manager的用户 + if ("manager".equals(user.getType())) { + continue; + } + + CustomerData customerData = new CustomerData(); + + // 设置用户基本信息 + customerData.setId(user.getUserId()); // 设置客户ID + customerData.setNickName(user.getNickName()); + customerData.setPhoneNumber(user.getPhoneNumber()); + customerData.setType(user.getType()); + customerData.setCompany(user.getCompany()); + customerData.setRegion(user.getRegion()); + // 明确设置组织公海池的level值 + customerData.setLevel("organization-sea-pools"); + customerData.setDemand(user.getDemand()); + customerData.setFollowup(user.getFollowup()); + customerData.setNotice(user.getNotice()); + customerData.setFollowup_at(user.getFollowup_at()); + customerData.setCreated_at(user.getCreated_at()); + customerData.setUpdated_at(user.getUpdated_at()); + + // 获取并设置联系人信息 + UsersContacts contacts = wechatCustomerMapper.getContactsByUserId(user.getUserId()); + if (contacts == null) { + // 如果通过userId没有找到联系人信息,尝试通过电话号码获取 + contacts = wechatCustomerMapper.getContactsByPhoneNumber(user.getPhoneNumber()); + } + if (contacts != null) { + customerData.setWechat(contacts.getWechat()); + customerData.setAccount(contacts.getAccount()); + customerData.setAccountNumber(contacts.getAccountNumber()); + customerData.setBank(contacts.getBank()); + customerData.setAddress(contacts.getAddress()); + } + + // 获取并设置负责人信息 + UsersManagements managements = wechatCustomerMapper.getManagementsByUserId(user.getUserId()); + if (managements != null) { + customerData.setManagercompany(managements.getManagercompany()); + customerData.setManagerdepartment(managements.getManagerdepartment()); + customerData.setOrganization(managements.getOrganization()); + customerData.setProjectName(managements.getRole()); // 使用role字段作为职位信息 + customerData.setRole(managements.getRole()); // 同时设置role字段 + customerData.setUserName(managements.getUserName()); + customerData.setAssistant(managements.getAssistant()); + } else { + // 如果没有负责人信息,使用登录用户的公司、部门和组织信息 + customerData.setManagercompany(login.getManagercompany()); + customerData.setManagerdepartment(login.getManagerdepartment()); + customerData.setOrganization(login.getOrganization()); + customerData.setProjectName("无"); + customerData.setRole("无"); + customerData.setUserName("无"); + customerData.setAssistant("无"); + } + + // 获取并设置收藏产品信息 + customerData.setFavorites(getProductFavorites(user.getPhoneNumber())); + + organizationSeaPool.add(customerData); + } + + return organizationSeaPool; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/impl/LoginServiceImpl.java b/src/main/java/com/example/web/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..f9649ea --- /dev/null +++ b/src/main/java/com/example/web/service/impl/LoginServiceImpl.java @@ -0,0 +1,63 @@ +package com.example.web.service.impl; + +import com.example.web.entity.Login; +import com.example.web.entity.Personnel; +import com.example.web.mapper.LoginMapper; +import com.example.web.mapper.PersonnelMapper; +import com.example.web.service.LoginService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @Description: 登录服务实现类 + * @Author: + * @Date: 2025-12-17 + */ +@Service +public class LoginServiceImpl implements LoginService { + + @Autowired + private LoginMapper loginMapper; + + @Autowired + private PersonnelMapper personnelMapper; + + /** + * 验证用户登录信息 + * @param projectName 工位名 + * @param userName 用户名 + * @param password 密码 + * @return Login对象,如果验证成功则返回用户信息,否则返回null + */ + @Override + public Login verifyLogin(String projectName, String userName, String password) { + // 根据用户名和工位名查询用户 + Login login = loginMapper.selectByUserNameAndProjectName(userName, projectName); + + // 如果用户存在且密码正确,则返回用户信息 + if (login != null && login.getPassword().equals(password)) { + // 从Personnel表中获取负责人的公司和部门信息 + Personnel personnel = getPersonnelInfo(login.getManagerId()); + if (personnel != null) { + login.setManagercompany(personnel.getManagercompany()); + login.setManagerdepartment(personnel.getManagerdepartment()); + login.setOrganization(personnel.getOrganization()); + } + return login; + } + + // 否则返回null表示验证失败 + return null; + } + + /** + * 根据managerId获取员工详细信息 + * @param managerId 负责人ID + * @return Personnel对象,包含员工详细信息 + */ + @Override + public Personnel getPersonnelInfo(String managerId) { + // 根据managerId查询员工详细信息 + return personnelMapper.selectByManagerId(managerId); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/service/impl/PersonnelServiceImpl.java b/src/main/java/com/example/web/service/impl/PersonnelServiceImpl.java new file mode 100644 index 0000000..be1f904 --- /dev/null +++ b/src/main/java/com/example/web/service/impl/PersonnelServiceImpl.java @@ -0,0 +1,27 @@ +package com.example.web.service.impl; + +import com.example.web.entity.Personnel; +import com.example.web.mapper.PersonnelMapper; +import com.example.web.service.PersonnelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @Description: 员工信息服务实现类 + */ +@Service +public class PersonnelServiceImpl implements PersonnelService { + + @Autowired + private PersonnelMapper personnelMapper; + + /** + * 根据负责人ID获取员工信息 + * @param managerId 负责人ID + * @return Personnel对象 + */ + @Override + public Personnel getPersonnelByManagerId(String managerId) { + return personnelMapper.selectByManagerId(managerId); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/web/task/CustomerStatusTask.java b/src/main/java/com/example/web/task/CustomerStatusTask.java new file mode 100644 index 0000000..ca335bb --- /dev/null +++ b/src/main/java/com/example/web/task/CustomerStatusTask.java @@ -0,0 +1,138 @@ +package com.example.web.task; + +import com.example.web.entity.Contacts; +import com.example.web.entity.Enterprise; +import com.example.web.entity.Users; +import com.example.web.mapper.CustomerMapper; +import com.example.web.mapper.WechatCustomerMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @Description: 客户状态流转定时任务 + */ +@Component +public class CustomerStatusTask { + + @Autowired + private CustomerMapper customerMapper; + + @Autowired + private WechatCustomerMapper wechatCustomerMapper; + + /** + * 每分钟执行一次客户状态流转处理 + */ + @Scheduled(cron = "0 * * */5 * ?") + public void processCustomerStatus() { + System.out.println("DEBUG: 开始执行客户状态流转定时任务,当前时间: " + LocalDateTime.now()); + + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + + // 计算3天前和6天前的时间 + LocalDateTime threeDaysAgo = now.minusDays(3); + LocalDateTime sixDaysAgo = now.minusDays(6); + + // 处理primary数据源的客户 + processPrimaryCustomers(threeDaysAgo, sixDaysAgo, now); + + // 处理wechat数据源的客户 + processWechatCustomers(threeDaysAgo, sixDaysAgo, now); + + System.out.println("DEBUG: 客户状态流转定时任务执行完成"); + } + + /** + * 处理primary数据源的客户状态流转 + * @param threeDaysAgo 3天前的时间 + * @param sixDaysAgo 6天前的时间 + * @param now 当前时间 + */ + private void processPrimaryCustomers(LocalDateTime threeDaysAgo, LocalDateTime sixDaysAgo, LocalDateTime now) { + try { + System.out.println("DEBUG: 开始处理primary数据源的客户状态流转"); + + // 获取所有联系人信息 + List contactsList = customerMapper.getAllContacts(); + + for (Contacts contacts : contactsList) { + // 获取企业信息 + Enterprise enterprise = customerMapper.getEnterpriseByContactId(contacts.getId()); + if (enterprise == null) { + continue; + } + + String currentLevel = enterprise.getLevel(); + LocalDateTime followupAt = contacts.getFollowup_at(); + + // 第一次筛选:查找 followup_at ≤ 3天前的客户,当前状态为"未分级" → 变更为"组织公海池客户" + if ("unclassified".equals(currentLevel) && followupAt != null && followupAt.isBefore(threeDaysAgo)) { + enterprise.setLevel("organization-sea-pools"); + customerMapper.updateEnterprise(enterprise); + System.out.println("DEBUG: primary数据源客户ID: " + contacts.getId() + " 从 未分级 变更为 组织公海池客户"); + } + // 第二次筛选:查找 followup_at ≤ 6天前的客户,当前状态为"组织公海池客户" → 变更为"部门公海池" + else if ("organization-sea-pools".equals(currentLevel) && followupAt != null && followupAt.isBefore(sixDaysAgo)) { + enterprise.setLevel("department-sea-pools"); + customerMapper.updateEnterprise(enterprise); + System.out.println("DEBUG: primary数据源客户ID: " + contacts.getId() + " 从 组织公海池客户 变更为 部门公海池"); + } + } + + System.out.println("DEBUG: primary数据源的客户状态流转处理完成"); + } catch (Exception e) { + System.out.println("DEBUG: 处理primary数据源的客户状态流转失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 处理wechat数据源的客户状态流转 + * @param threeDaysAgo 3天前的时间 + * @param sixDaysAgo 6天前的时间 + * @param now 当前时间 + */ + private void processWechatCustomers(LocalDateTime threeDaysAgo, LocalDateTime sixDaysAgo, LocalDateTime now) { + try { + System.out.println("DEBUG: 开始处理wechat数据源的客户状态流转"); + + // 获取所有用户信息 + List usersList = wechatCustomerMapper.getAllUsers(); + + for (Users user : usersList) { + // 跳过type为manager的用户 + if ("manager".equals(user.getType())) { + continue; + } + + String currentLevel = user.getLevel(); + LocalDateTime followupAt = user.getFollowup_at(); + + // 第一次筛选:查找 followup_at ≤ 3天前的客户,当前状态为"未分级" → 变更为"组织公海池客户" + if ("unclassified".equals(currentLevel) && followupAt != null && followupAt.isBefore(threeDaysAgo)) { + user.setLevel("organization-sea-pools"); + user.setUpdated_at(now); + wechatCustomerMapper.updateUsers(user); + System.out.println("DEBUG: wechat数据源客户ID: " + user.getUserId() + " 从 未分级 变更为 组织公海池客户"); + } + // 第二次筛选:查找 followup_at ≤ 6天前的客户,当前状态为"组织公海池客户" → 变更为"部门公海池" + else if ("organization-sea-pools".equals(currentLevel) && followupAt != null && followupAt.isBefore(sixDaysAgo)) { + user.setLevel("department-sea-pools"); + user.setUpdated_at(now); + wechatCustomerMapper.updateUsers(user); + System.out.println("DEBUG: wechat数据源客户ID: " + user.getUserId() + " 从 组织公海池客户 变更为 部门公海池"); + } + } + + System.out.println("DEBUG: wechat数据源的客户状态流转处理完成"); + } catch (Exception e) { + System.out.println("DEBUG: 处理wechat数据源的客户状态流转失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/example/web/utils/CustomerTraceUtil.java b/src/main/java/com/example/web/utils/CustomerTraceUtil.java new file mode 100644 index 0000000..ecb84b8 --- /dev/null +++ b/src/main/java/com/example/web/utils/CustomerTraceUtil.java @@ -0,0 +1,121 @@ +package com.example.web.utils; + +import com.example.web.entity.InformationTra; +import com.example.web.mapper.InformationTraMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @Description: 客户踪迹追踪工具类 + */ +@Component +public class CustomerTraceUtil { + + @Autowired + private InformationTraMapper informationTraMapper; + + /** + * 记录客户操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param traassistant 协助人 + * @param operationEvent 操作事件 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerOperation(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String traassistant, String operationEvent, + String originalData, String modifiedData, String changedFields) { + try { + // 创建信息跟踪记录 + InformationTra informationTra = new InformationTra(); + informationTra.setUserId(userId); + informationTra.setTracompany(tracompany); + informationTra.setTradepartment(tradepartment); + informationTra.setTraorganization(traorganization); + informationTra.setTrarole(trarole); + informationTra.setTrauserName(trauserName); + informationTra.setTraassistant(traassistant); + informationTra.setOperationEvent(operationEvent); + informationTra.setOperationTime(LocalDateTime.now()); + informationTra.setCreatedAt(LocalDateTime.now()); + informationTra.setUpdatedAt(LocalDateTime.now()); + informationTra.setOriginalData(originalData); + informationTra.setModifiedData(modifiedData); + informationTra.setChangedFields(changedFields); + + // 保存到数据库 + int result = informationTraMapper.insertInformationTra(informationTra); + System.out.println("DEBUG: 记录客户操作,用户ID: " + userId + ", 操作人: " + trauserName + ", 操作事件: " + operationEvent + ", 结果: " + result); + return result > 0; + } catch (Exception e) { + System.out.println("DEBUG: 记录客户操作失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + /** + * 记录客户查看详情操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @return 是否记录成功 + */ + public boolean recordCustomerView(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "查看客户详情", null, null, null); + } + + /** + * 记录客户编辑操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerEdit(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String originalData, String modifiedData, + String changedFields) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "编辑客户信息", originalData, modifiedData, changedFields); + } + + /** + * 记录客户跟进操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerFollowup(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String originalData, String modifiedData, + String changedFields) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "跟进客户", originalData, modifiedData, changedFields); + } +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7e4eaa7..4f96ade 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,32 +1,79 @@ spring: + main: + allow-bean-definition-overriding: true datasource: # userlogin数据库 primary: - jdbc-url: jdbc:mysql://1.95.162.61:3306/userlogin?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + jdbc-url: jdbc:mysql://1.95.162.61:3306/userlogin?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&maxReconnects=10&allowPublicKeyRetrieval=true username: root password: schl@2025 driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connection-timeout: 120000 + max-lifetime: 3600000 + maximum-pool-size: 15 + minimum-idle: 8 + validation-timeout: 5000 + test-while-idle: true + test-on-borrow: true + test-on-return: true + connection-test-query: SELECT 1 + initialization-fail-timeout: -1 + keepalive-time: 300000 + leak-detection-threshold: 30000 # wechat_app数据库 wechat: - jdbc-url: jdbc:mysql://1.95.162.61:3306/wechat_app?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + jdbc-url: jdbc:mysql://1.95.162.61:3306/wechat_app?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&maxReconnects=10&allowPublicKeyRetrieval=true username: root password: schl@2025 driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connection-timeout: 120000 + max-lifetime: 3600000 + maximum-pool-size: 20 + minimum-idle: 10 + validation-timeout: 5000 + test-while-idle: true + test-on-borrow: true + test-on-return: true + connection-test-query: SELECT 1 + initialization-fail-timeout: -1 + keepalive-time: 300000 + leak-detection-threshold: 30000 # 应用配置 app: recycle: # 未分级客户回流到组织公海池的天数阈值 - unclassified-to-organization-days: 30 + unclassified-to-organization-days: 3 # 组织公海池客户回流到部门公海池的天数阈值 - organization-to-department-days: 30 + organization-to-department-days: 3 + +# Spring Boot Actuator配置 +management: + endpoints: + web: + exposure: + include: health,info,metrics + endpoint: + health: + show-details: always + health: + datasource: + enabled: true server: - port: 8081 + port: 8080 servlet: context-path: /DL - # 在Tomcat中部署时,端口由Tomcat配置决定,这里不需要指定 - # address属性在Tomcat部署中不生效,由容器控制 + encoding: + charset: UTF-8 + enabled: true + force: true + tomcat: + uri-encoding: UTF-8 + # 在Tomcat中部署时,端口由Tomcat配置决定,这里不需要指定 + # address属性在Tomcat部署中不生效,由容器控制 mybatis: type-aliases-package: com.example.web.entity @@ -36,10 +83,13 @@ mybatis: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl call-setters-on-nulls: true jdbc-type-for-null: null + map-underscore-to-camel-case: true logging: level: - com.example.web.mapper: DEBUG - com.example.web.config: DEBUG - com.example.web.aspect: DEBUG + com.example.web.mapper: TRACE + com.example.web.config: TRACE + com.example.web.aspect: TRACE + org.apache.ibatis: TRACE + org.mybatis.spring: TRACE diff --git a/src/main/resources/mapper/Cart_itemsMapper.xml b/src/main/resources/mapper/Cart_itemsMapper.xml deleted file mode 100644 index 9d1b5c0..0000000 --- a/src/main/resources/mapper/Cart_itemsMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/CustomerMapper.xml b/src/main/resources/mapper/CustomerMapper.xml new file mode 100644 index 0000000..8951f5b --- /dev/null +++ b/src/main/resources/mapper/CustomerMapper.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO enterprise (id, company, region, level, type, demand, spec) + VALUES (#{id}, #{company}, #{region}, #{level}, #{type}, #{demand}, #{spec}) + + + + + INSERT INTO contacts (contact_id, id, nickName, phoneNumber, wechat, account, accountNumber, bank, address, followup, created_at, updated_at) + VALUES (#{contact_id}, #{id}, #{nickName}, #{phoneNumber}, #{wechat}, #{account}, #{accountNumber}, #{bank}, #{address}, #{followup}, #{created_at}, #{updated_at}) + + + + + INSERT INTO managers (id, managerId, managercompany, managerdepartment, organization, role, root, created_at, updated_at, userName, assistant) + VALUES (#{id}, #{managerId}, #{managercompany}, #{managerdepartment}, #{organization}, #{role}, #{root}, #{created_at}, #{updated_at}, #{userName}, #{assistant}) + + + + + + + + + + + + + + UPDATE contacts + SET nickName = #{nickName}, wechat = #{wechat}, account = #{account}, + accountNumber = #{accountNumber}, bank = #{bank}, address = #{address}, + updated_at = #{updated_at} + WHERE contact_id = #{contact_id} + + + + + UPDATE enterprise + SET company = #{company}, region = #{region}, level = #{level}, + type = #{type}, demand = #{demand}, spec = #{spec} + WHERE id = #{id} + + + + + UPDATE managers + SET managercompany = #{managercompany}, managerdepartment = #{managerdepartment}, + organization = #{organization}, role = #{role}, userName = #{userName}, + assistant = #{assistant}, updated_at = #{updated_at} + WHERE id = #{id} + + \ No newline at end of file diff --git a/src/main/resources/mapper/InformationTraMapper.xml b/src/main/resources/mapper/InformationTraMapper.xml index adf8e24..6e3bc49 100644 --- a/src/main/resources/mapper/InformationTraMapper.xml +++ b/src/main/resources/mapper/InformationTraMapper.xml @@ -1,35 +1,28 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + + - INSERT INTO informationtra ( - tracompany, tradepartment, traorganization, trarole, - trauserName, traassistant, userId, operationEvent, - operationTime, created_at, updated_at - ) VALUES ( - #{tracompany}, #{tradepartment}, #{traorganization}, #{trarole}, - #{trauserName}, #{traassistant}, #{userId}, #{operationEvent}, - #{operationTime}, #{createdAt}, #{updatedAt} - ) + INSERT INTO informationtra (tracompany, tradepartment, traorganization, trarole, trauserName, traassistant, userId, operationEvent, operationTime, created_at, updated_at, originalData, modifiedData, changedFields) + VALUES (#{tracompany}, #{tradepartment}, #{traorganization}, #{trarole}, #{trauserName}, #{traassistant}, #{userId}, #{operationEvent}, #{operationTime}, #{createdAt}, #{updatedAt}, #{originalData}, #{modifiedData}, #{changedFields}) - - - \ No newline at end of file + diff --git a/src/main/resources/mapper/LoginMapper.xml b/src/main/resources/mapper/LoginMapper.xml index 7831443..4bb8587 100644 --- a/src/main/resources/mapper/LoginMapper.xml +++ b/src/main/resources/mapper/LoginMapper.xml @@ -1,34 +1,16 @@ - + - - - - - - + + + + + + - - - + SELECT userName, projectName, password, managerId FROM login + WHERE userName = #{userName} AND projectName = #{projectName} - \ No newline at end of file diff --git a/src/main/resources/mapper/PersonnelMapper.xml b/src/main/resources/mapper/PersonnelMapper.xml new file mode 100644 index 0000000..ae3d354 --- /dev/null +++ b/src/main/resources/mapper/PersonnelMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ProductsMapper.xml b/src/main/resources/mapper/ProductsMapper.xml deleted file mode 100644 index 5fba03e..0000000 --- a/src/main/resources/mapper/ProductsMapper.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/RootdbMapper.xml b/src/main/resources/mapper/RootdbMapper.xml deleted file mode 100644 index 208ff92..0000000 --- a/src/main/resources/mapper/RootdbMapper.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyCart_itemsMapper.xml b/src/main/resources/mapper/SupplyCart_itemsMapper.xml deleted file mode 100644 index 8cff072..0000000 --- a/src/main/resources/mapper/SupplyCart_itemsMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyContactsMapper.xml b/src/main/resources/mapper/SupplyContactsMapper.xml deleted file mode 100644 index e65578a..0000000 --- a/src/main/resources/mapper/SupplyContactsMapper.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO contacts ( - contact_id, - id, nickName, phoneNumber, wechat, account, accountNumber, bank, address,created_at,updated_at - ) VALUES ( - #{contact_id}, - #{id}, #{nickName}, #{phoneNumber}, #{wechat}, #{account}, #{accountNumber}, #{bank}, #{address}, #{created_at}, #{updated_at} - ) - - - - - - - - - - UPDATE contacts - SET - id = #{id}, - nickName = #{nickName}, - wechat = #{wechat}, - account = #{account}, - accountNumber = #{accountNumber}, - bank = #{bank}, - address = #{address} - WHERE contact_id = #{contact_id} - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyEnterpriseMapper.xml b/src/main/resources/mapper/SupplyEnterpriseMapper.xml deleted file mode 100644 index 5a37588..0000000 --- a/src/main/resources/mapper/SupplyEnterpriseMapper.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO enterprise ( - id, company, region, level, type, demand, spec - ) VALUES ( - #{id}, #{company}, #{region}, #{level}, #{type}, #{demand}, #{spec} - ) - - - - UPDATE enterprise - SET - company = #{company}, - region = #{region}, - level = #{level}, - type = #{type}, - demand = #{demand}, - spec = #{spec} - WHERE id = #{id} - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyManagersMapper.xml b/src/main/resources/mapper/SupplyManagersMapper.xml deleted file mode 100644 index 50a586f..0000000 --- a/src/main/resources/mapper/SupplyManagersMapper.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO managers ( - id, managerId, managercompany, managerdepartment, - organization, role, root, created_at, updated_at, - userName, assistant - ) VALUES ( - #{id}, #{managerId}, #{managercompany}, #{managerdepartment}, - #{organization}, #{role}, #{root}, #{created_at}, #{updated_at}, - #{userName}, #{assistant} - ) - - - - - UPDATE managers - SET - managercompany = #{managercompany}, - managerdepartment = #{managerdepartment}, - organization = #{organization}, - role = #{role}, - userName = #{userName}, - assistant = #{assistant}, - updated_at = #{updated_at} - WHERE id = #{id} - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyProductsMapper.xml b/src/main/resources/mapper/SupplyProductsMapper.xml deleted file mode 100644 index 81cafd6..0000000 --- a/src/main/resources/mapper/SupplyProductsMapper.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyUsersManagementsMapper.xml b/src/main/resources/mapper/SupplyUsersManagementsMapper.xml deleted file mode 100644 index 5ee40b1..0000000 --- a/src/main/resources/mapper/SupplyUsersManagementsMapper.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO usermanagements ( - userId, managerId, managercompany, managerdepartment, - organization, role, root, created_at, updated_at, - userName, assistant - ) VALUES ( - #{userId}, #{managerId}, #{managercompany}, #{managerdepartment}, - #{organization}, #{role}, #{root}, #{created_at}, #{updated_at}, - #{userName}, #{assistant} - ) - - - - - UPDATE usermanagements - SET managerId = #{managerId}, - managercompany = #{managercompany}, - managerdepartment = #{managerdepartment}, - organization = #{organization}, - role = #{role}, - root = #{root}, - updated_at = #{updated_at}, - userName = #{userName}, - assistant = #{assistant} - WHERE id = #{id} - - - - - UPDATE users_managements - SET updated_at = #{updatedAt} - WHERE user_id = #{userId} - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/SupplyUsersMapper.xml b/src/main/resources/mapper/SupplyUsersMapper.xml deleted file mode 100644 index bee7220..0000000 --- a/src/main/resources/mapper/SupplyUsersMapper.xml +++ /dev/null @@ -1,709 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE products - SET - productName = #{product.productName}, - specification = #{product.specification}, - yolk = #{product.yolk}, - quantity = #{product.quantity}, - variety = #{product.variety}, - grossWeight = #{product.grossWeight}, - price = #{product.price}, - updated_at = NOW() - WHERE - sellerId = #{sellerId} - AND productId = #{productId} - - - - - UPDATE users - SET - - nickName = #{nickName}, - - - type = #{type}, - - - company = #{company}, - - - region = #{region}, - - - level = #{level}, - - - demand = #{demand}, - - - spec = #{spec}, - - updated_at = #{updated_at} - WHERE phoneNumber = #{phoneNumber} - - - - - UPDATE products - SET - - productName = #{productName}, - - - variety = #{variety}, - - - specification = #{specification}, - - - quantity = #{quantity}, - - - grossWeight = #{grossWeight}, - - - yolk = #{yolk}, - - updated_at = NOW() - WHERE sellerId = #{sellerId} - - - - - INSERT INTO products ( - productId, - sellerId, - productName, - variety, - specification, - quantity, - grossWeight, - yolk, - price, - created_at, - updated_at - ) VALUES ( - COALESCE(#{productId}, UUID()), - #{sellerId}, - #{productName}, - #{variety}, - #{specification}, - #{quantity}, - #{grossWeight}, - #{yolk}, - #{price}, - NOW(), - NOW() - ) - ON DUPLICATE KEY UPDATE - productName = VALUES(productName), - variety = VALUES(variety), - specification = VALUES(specification), - quantity = VALUES(quantity), - grossWeight = VALUES(grossWeight), - yolk = VALUES(yolk), - price = VALUES(price), - updated_at = NOW() - - - - - - - - UPDATE contacts - SET - - wechat = #{wechat}, - - - account = #{account}, - - - accountNumber = #{accountNumber}, - - - bank = #{bank}, - - - address = #{address}, - - updated_at = NOW() - WHERE userId = #{userId} - LIMIT 1 - - - - - INSERT INTO contacts (id, userId, wechat, account, accountNumber, bank, address, updated_at) - VALUES ( - COALESCE(#{contactId}, UUID()), - #{userId}, - #{wechat}, - #{account}, - #{accountNumber}, - #{bank}, - #{address}, - NOW() - ) - ON DUPLICATE KEY UPDATE - wechat = VALUES(wechat), - account = VALUES(account), - accountNumber = VALUES(accountNumber), - bank = VALUES(bank), - address = VALUES(address), - updated_at = NOW() - - - - - UPDATE contacts - SET - - wechat = #{wechat}, - - - account = #{account}, - - - accountNumber = #{accountNumber}, - - - bank = #{bank}, - - - address = #{address}, - - updated_at = NOW() - WHERE userId = #{userId} - AND id = #{contactId} - - - - - UPDATE products - SET - - productName = #{productName}, - - - variety = #{variety}, - - - specification = #{specification}, - - - quantity = #{quantity}, - - - grossWeight = #{grossWeight}, - - - yolk = #{yolk}, - - updated_at = NOW() - WHERE sellerId = #{sellerId} - AND productId = #{productId} - - - - - - - - - - - - - - - - - - - - - UPDATE products - SET - productName = #{productName}, - variety = #{variety}, - specification = #{specification}, - quantity = #{quantity}, - grossWeight = #{grossWeight}, - yolk = #{yolk}, - updated_at = NOW() - WHERE productId = #{productId} - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/UsersManagementsMapper.xml b/src/main/resources/mapper/UsersManagementsMapper.xml deleted file mode 100644 index 4a1fa29..0000000 --- a/src/main/resources/mapper/UsersManagementsMapper.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERT INTO usermanagements ( - userId, managerId, managercompany, managerdepartment, - organization, role, root, created_at, updated_at, - userName, assistant - ) VALUES ( - #{userId}, #{managerId}, #{managercompany}, #{managerdepartment}, - #{organization}, #{role}, #{root}, #{created_at}, #{updated_at}, - #{userName}, #{assistant} - ) - - - - - UPDATE usermanagements - SET managerId = #{managerId}, - managercompany = #{managercompany}, - managerdepartment = #{managerdepartment}, - organization = #{organization}, - role = #{role}, - root = #{root}, - updated_at = #{updated_at}, - userName = #{userName}, - assistant = #{assistant} - WHERE id = #{id} - - - - - UPDATE users_managements - SET updated_at = #{updatedAt} - WHERE user_id = #{userId} - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/UsersMapper.xml b/src/main/resources/mapper/UsersMapper.xml deleted file mode 100644 index ec196e9..0000000 --- a/src/main/resources/mapper/UsersMapper.xml +++ /dev/null @@ -1,722 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE products - SET - productName = #{product.productName}, - specification = #{product.specification}, - yolk = #{product.yolk}, - quantity = #{product.quantity}, - variety = #{product.variety}, - grossWeight = #{product.grossWeight}, - updated_at = NOW() - WHERE - sellerId = #{sellerId} - AND productId = #{productId} - - - - - UPDATE users - SET - - nickName = #{nickName}, - - - type = #{type}, - - - company = #{company}, - - - region = #{region}, - - - level = #{level}, - - - demand = #{demand}, - - - spec = #{spec}, - - updated_at = #{updated_at} - WHERE phoneNumber = #{phoneNumber} - - - - - UPDATE products - SET - - productName = #{productName}, - - - variety = #{variety}, - - - specification = #{specification}, - - - quantity = #{quantity}, - - - grossWeight = #{grossWeight}, - - - yolk = #{yolk}, - - updated_at = NOW() - WHERE sellerId = #{sellerId} - - - - - UPDATE cart_items - SET - productName = #{productName}, - specification = #{specification}, - quantity = #{quantity}, - grossWeight = #{grossWeight}, - yolk = #{yolk}, - added_at = NOW() - WHERE userId = #{buyerId} - AND productId = #{productId} - - - - - - - - UPDATE contacts - SET - - wechat = #{wechat}, - - - account = #{account}, - - - accountNumber = #{accountNumber}, - - - bank = #{bank}, - - - address = #{address}, - - updated_at = NOW() - WHERE userId = #{userId} - LIMIT 1 - - - - - INSERT INTO contacts (id, userId, wechat, account, accountNumber, bank, address, updated_at) - VALUES ( - COALESCE(#{contactId}, UUID()), - #{userId}, - #{wechat}, - #{account}, - #{accountNumber}, - #{bank}, - #{address}, - NOW() - ) - ON DUPLICATE KEY UPDATE - wechat = VALUES(wechat), - account = VALUES(account), - accountNumber = VALUES(accountNumber), - bank = VALUES(bank), - address = VALUES(address), - updated_at = NOW() - - - - - INSERT INTO cart_items (id, userId, productId, productName, specification, quantity, grossWeight, yolk, added_at) - VALUES ( - COALESCE(#{cartItemId}, UUID()), - #{userId}, - #{productId}, - #{productName}, - #{specification}, - #{quantity}, - #{grossWeight}, - #{yolk}, - NOW() - ) - ON DUPLICATE KEY UPDATE - productName = VALUES(productName), - specification = VALUES(specification), - quantity = VALUES(quantity), - grossWeight = VALUES(grossWeight), - yolk = VALUES(yolk), - added_at = NOW() - - - - - - - - - - - UPDATE contacts - SET - - wechat = #{wechat}, - - - account = #{account}, - - - accountNumber = #{accountNumber}, - - - bank = #{bank}, - - - address = #{address}, - - updated_at = NOW() - WHERE userId = #{userId} - AND id = #{contactId} - - - - - UPDATE cart_items - SET - - productId = #{productId}, - - - productName = #{productName}, - - - specification = #{specification}, - - - quantity = #{quantity}, - - - grossWeight = #{grossWeight}, - - - yolk = #{yolk}, - - added_at = NOW() - WHERE userId = #{userId} - AND id = #{cartItemId} - - - - - - - - - - - - - - - - - - - - - - UPDATE products - SET - productName = #{productName}, - variety = #{variety}, - specification = #{specification}, - quantity = #{quantity}, - grossWeight = #{grossWeight}, - yolk = #{yolk}, - updated_at = NOW() - WHERE productId = #{productId} - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/WechatCustomerMapper.xml b/src/main/resources/mapper/WechatCustomerMapper.xml new file mode 100644 index 0000000..2b04799 --- /dev/null +++ b/src/main/resources/mapper/WechatCustomerMapper.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE users + SET nickName = #{nickName}, company = #{company}, region = #{region}, + level = #{level}, demand = #{demand}, followup = #{followup}, + notice = #{notice}, followup_at = #{followup_at}, updated_at = #{updated_at} + WHERE userId = #{userId} + + + + + + + + UPDATE contacts + SET wechat = #{wechat}, account = #{account}, + accountNumber = #{accountNumber}, bank = #{bank}, address = #{address}, + updated_at = #{updated_at} + WHERE userId = #{userId} + + + + + UPDATE usermanagements + SET managercompany = #{managercompany}, managerdepartment = #{managerdepartment}, + organization = #{organization}, role = #{role}, + userName = #{userName}, assistant = #{assistant}, + updated_at = #{updated_at} + WHERE userId = #{userId} + + \ No newline at end of file diff --git a/src/main/resources/static/loginmm.html b/src/main/resources/static/loginmm.html index 5a72bbd..136fccf 100644 --- a/src/main/resources/static/loginmm.html +++ b/src/main/resources/static/loginmm.html @@ -584,51 +584,26 @@ } // 保存认证信息 - localStorage.setItem('authToken', response.token); - localStorage.setItem('currentUser', JSON.stringify(response.user)); + localStorage.setItem('authToken', response.token || ''); + localStorage.setItem('currentUser', JSON.stringify(response.userInfo)); - // 根据角色跳转到不同的页面,并传递用户信息 - const root = response.root; + // 根据职位跳转到不同的页面,并传递用户信息 + const userInfo = response.userInfo; const userParams = new URLSearchParams({ - managerId:encodeURIComponent(response.user.managerId), - managercompany:encodeURIComponent(response.user.managercompany), - managerdepartment:encodeURIComponent(response.user.managerdepartment), - organization:encodeURIComponent(response.user.organization), - role: encodeURIComponent(response.user.role),//角色 - userName: encodeURIComponent(response.user.userName),//用户名 - assistant:encodeURIComponent(response.user.assistant),//助理 - token: response.token//认证信息 + managercompany: encodeURIComponent(userInfo.managercompany), + managerdepartment: encodeURIComponent(userInfo.managerdepartment), + organization: encodeURIComponent(userInfo.organization), + projectName: encodeURIComponent(userInfo.projectName), + userName: encodeURIComponent(userInfo.name) }).toString(); - if (root === 1) { - // 总经理跳转到 - window.location.href = `mainapp(2).html?${userParams}`; - } - else if (root === 2) { - // 采购员跳转 - // 销售员跳转 - console.log('负责人id',response.user.managerId); - console.log('所属部门', response.user.managerdepartment); - console.log('所属公司', response.user.managercompany); - console.log('所属组织', response.user.organization); - console.log('角色', response.user.role); - console.log('用户名', response.user.userName); - console.log('助理', response.user.assistant); - window.location.href = `mainapp-supplys.html?${userParams}`; - } - else if (root === 3) { - // 销售员跳转 - console.log('负责人id',response.user.managerId); - console.log('所属部门', response.user.managerdepartment); - console.log('所属公司', response.user.managercompany); - console.log('所属组织', response.user.organization); - console.log('角色', response.user.role); - console.log('用户名', response.user.userName); - console.log('助理', response.user.assistant); - window.location.href = `mainapp-sells.html?${userParams}`; + if (userInfo.projectName === "采购员") { + window.location.href = `supply.html?${userParams}`; + } else if (userInfo.projectName === "销售员") { + window.location.href = `sells.html?${userParams}`; } else { - // 未知角色,显示错误或跳转到默认页面 - showModal('登录失败', '未知用户角色,请联系管理员'); + // 未知职位,显示错误 + showModal('登录失败', '未知职位,请联系管理员'); } } else { // 登录失败 diff --git a/src/main/resources/static/mainapp-sells.html b/src/main/resources/static/mainapp-sells.html deleted file mode 100644 index 913271e..0000000 --- a/src/main/resources/static/mainapp-sells.html +++ /dev/null @@ -1,14531 +0,0 @@ - - - - - - - - 客户关系管理系统 - - - - - - - - -
-
-
- -
加载中...
-
-
欢迎,祝您有个愉快的一天
-
Welcome, hope you have a nice day
-
-
- - - - - -
- - - - -
-
- - -
-
- -
0
-
总客户数
-
-
- -
0
-
活跃客户
-
-
- -
0%
-
客户留存率
-
-
- -
¥0
-
本月销售额
-
-
- -
- -
-
-

- - 最近客户 -

- - - - - - - - - - - - - - - - - - -
客户名称联系人联系方式最后订单状态操作
暂无客户数据
-
-
-
- - -
-
-
- - -
- - - - - - - - - -
-
- - -
-
时间筛选:
-
-
- 动态筛选 -
-
动态筛选
-
自定义筛选
-
-
- -
- 今天 -
-
今天
-
昨天
-
前天
-
大前天
-
一周内
-
一个月内
-
-
- - - - - - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
客户公司客户地区基本需求规格联系人电话创建时间修改时间操作
暂无重要客户数据
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-

客户跟进管理

- - - -
- - - - - - - - - - - - - - - - -
跟进详情联系人电话日期操作
暂无跟进记录
-
- - -
-
- - -
-
-

数据分析

-

数据分析功能即将上线,敬请期待。

-
-
- -
-
-

日程安排

-

日程安排功能即将上线,敬请期待。

-
-
- -
-
-

系统设置

-

系统设置功能即将上线,敬请期待。

-
-
-
- - - - - -
-
-

添加附加联系人信息

- - - - - - - -
-
- - - - - -
- 数据已刷新 -
- - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/mainapp-supplys.html b/src/main/resources/static/mainapp-supplys.html deleted file mode 100644 index 52bd4dd..0000000 --- a/src/main/resources/static/mainapp-supplys.html +++ /dev/null @@ -1,14391 +0,0 @@ - - - - - - - - 供应关系管理系统 - - - - - - - - -
-
-
- -
加载中...
-
-
欢迎,祝您有个愉快的一天
-
Welcome, hope you have a nice day
-
-
- - - - - -
- - - - -
-
- - -
-
- -
0
-
总客户数
-
-
- -
0
-
活跃客户
-
-
- -
0%
-
客户留存率
-
-
- -
¥0
-
本月销售额
-
-
- -
- -
-
-

- - 最近客户 -

- - - - - - - - - - - - - - - - - - -
客户名称联系人联系方式最后订单状态操作
暂无客户数据
-
-
-
- - -
-
-
- - -
- - - - - - - - - -
-
- - -
-
时间筛选:
-
-
- 动态筛选 -
-
动态筛选
-
自定义筛选
-
-
- -
- 今天 -
-
今天
-
昨天
-
前天
-
大前天
-
一周内
-
一个月内
-
-
- - - - - - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
客户公司客户地区基本需求规格联系人电话创建时间修改时间操作
暂无重要客户数据
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-

客户跟进管理

- - - -
- - - - - - - - - - - - - - - - -
跟进详情联系人电话日期操作
暂无跟进记录
-
- - -
-
- - -
-
-

数据分析

-

数据分析功能即将上线,敬请期待。

-
-
- -
-
-

日程安排

-

日程安排功能即将上线,敬请期待。

-
-
- -
-
-

系统设置

-

系统设置功能即将上线,敬请期待。

-
-
-
- - - - - -
-
-

添加附加联系人信息

- - - - - - - -
-
- - - - - -
- 数据已刷新 -
- - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/sells.html b/src/main/resources/static/sells.html new file mode 100644 index 0000000..1c9e2d1 --- /dev/null +++ b/src/main/resources/static/sells.html @@ -0,0 +1,7328 @@ + + + + + + + 客户关系管理系统 + + + + + + + + + + +
+
+
加载中...
+
+ + + +
+
+
+ +
加载中...
+ +
+ + +
+
+
欢迎,祝您有个愉快的一天
+
Welcome, hope you have a nice day
+
+
+ + +
+ + + + +
+
+ + +
+
+ +
0
+
总客户数
+
+
+ +
0
+
活跃客户
+
+
+ +
0%
+
客户留存率
+
+
+ +
¥0
+
本月销售额
+
+
+ +
+ +
+
+

+ + 最近客户 +

+ + + + + + + + + + + + + + + + + + +
客户名称联系人联系方式最后订单状态操作
暂无客户数据
+
+
+
+ + +
+
+
+ + + +
+ + +
+ +
+ + + + +
+ +
+ + + + + + + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
客户公司客户地区基本需求规格联系人电话创建时间修改时间操作
暂无重要客户数据
+
+ + +
+
+ + +
+
+

客户跟进管理

+ + + +
+ + + + + + + + + + + + + + + + +
跟进详情联系人电话日期操作
暂无跟进记录
+
+ + +
+
+ + +
+
+

数据分析

+

数据分析功能即将上线,敬请期待。

+
+
+ +
+
+

日程安排

+

日程安排功能即将上线,敬请期待。

+
+
+ +
+
+

系统设置

+

系统设置功能即将上线,敬请期待。

+
+
+
+ + + + + + + + +
+
+

添加附加联系人信息

+ + + + + + + +
+
+ + + + + + + + + + + + + + + +
+ + +
+
+

新客户通知

+ +
+
+
暂无新客户通知
+
+
+ + + + + + \ No newline at end of file diff --git a/src/main/resources/static/supply.html b/src/main/resources/static/supply.html new file mode 100644 index 0000000..a8e71ab --- /dev/null +++ b/src/main/resources/static/supply.html @@ -0,0 +1,7336 @@ + + + + + + + 客户关系管理系统 + + + + + + + + + + +
+
+
加载中...
+
+ + + +
+
+
+ +
加载中...
+ +
+ + +
+
+
欢迎,祝您有个愉快的一天
+
Welcome, hope you have a nice day
+
+
+ + +
+ + + + +
+
+ + +
+
+ +
0
+
总客户数
+
+
+ +
0
+
活跃客户
+
+
+ +
0%
+
客户留存率
+
+
+ +
¥0
+
本月销售额
+
+
+ +
+ +
+
+

+ + 最近客户 +

+ + + + + + + + + + + + + + + + + + +
客户名称联系人联系方式最后订单状态操作
暂无客户数据
+
+
+
+ + +
+
+
+ + + +
+ + +
+ +
+ + + + +
+ +
+ + + + + + + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
客户公司客户地区基本需求规格联系人电话创建时间修改时间操作
暂无重要客户数据
+
+ + +
+
+ + +
+
+

客户跟进管理

+ + + +
+ + + + + + + + + + + + + + + + +
跟进详情联系人电话日期操作
暂无跟进记录
+
+ + +
+
+ + +
+
+

数据分析

+

数据分析功能即将上线,敬请期待。

+
+
+ +
+
+

日程安排

+

日程安排功能即将上线,敬请期待。

+
+
+ +
+
+

系统设置

+

系统设置功能即将上线,敬请期待。

+
+
+
+ + + + + + + + +
+
+

添加附加联系人信息

+ + + + + + + +
+
+ + + + + + + + + + + + +
+ + +
+
+

新客户通知

+ +
+
+
暂无新客户通知
+
+
+ + + + + + \ No newline at end of file diff --git a/src/main/utils/CustomerTraceUtil.java b/src/main/utils/CustomerTraceUtil.java new file mode 100644 index 0000000..ecb84b8 --- /dev/null +++ b/src/main/utils/CustomerTraceUtil.java @@ -0,0 +1,121 @@ +package com.example.web.utils; + +import com.example.web.entity.InformationTra; +import com.example.web.mapper.InformationTraMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @Description: 客户踪迹追踪工具类 + */ +@Component +public class CustomerTraceUtil { + + @Autowired + private InformationTraMapper informationTraMapper; + + /** + * 记录客户操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param traassistant 协助人 + * @param operationEvent 操作事件 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerOperation(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String traassistant, String operationEvent, + String originalData, String modifiedData, String changedFields) { + try { + // 创建信息跟踪记录 + InformationTra informationTra = new InformationTra(); + informationTra.setUserId(userId); + informationTra.setTracompany(tracompany); + informationTra.setTradepartment(tradepartment); + informationTra.setTraorganization(traorganization); + informationTra.setTrarole(trarole); + informationTra.setTrauserName(trauserName); + informationTra.setTraassistant(traassistant); + informationTra.setOperationEvent(operationEvent); + informationTra.setOperationTime(LocalDateTime.now()); + informationTra.setCreatedAt(LocalDateTime.now()); + informationTra.setUpdatedAt(LocalDateTime.now()); + informationTra.setOriginalData(originalData); + informationTra.setModifiedData(modifiedData); + informationTra.setChangedFields(changedFields); + + // 保存到数据库 + int result = informationTraMapper.insertInformationTra(informationTra); + System.out.println("DEBUG: 记录客户操作,用户ID: " + userId + ", 操作人: " + trauserName + ", 操作事件: " + operationEvent + ", 结果: " + result); + return result > 0; + } catch (Exception e) { + System.out.println("DEBUG: 记录客户操作失败,异常信息: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + /** + * 记录客户查看详情操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @return 是否记录成功 + */ + public boolean recordCustomerView(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "查看客户详情", null, null, null); + } + + /** + * 记录客户编辑操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerEdit(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String originalData, String modifiedData, + String changedFields) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "编辑客户信息", originalData, modifiedData, changedFields); + } + + /** + * 记录客户跟进操作 + * @param userId 客户ID + * @param tracompany 负责人公司 + * @param tradepartment 负责人部门 + * @param traorganization 负责人组织 + * @param trarole 负责人角色 + * @param trauserName 负责人姓名 + * @param originalData 原始数据 + * @param modifiedData 修改后数据 + * @param changedFields 变更字段 + * @return 是否记录成功 + */ + public boolean recordCustomerFollowup(String userId, String tracompany, String tradepartment, String traorganization, + String trarole, String trauserName, String originalData, String modifiedData, + String changedFields) { + return recordCustomerOperation(userId, tracompany, tradepartment, traorganization, trarole, trauserName, + null, "跟进客户", originalData, modifiedData, changedFields); + } +}