Commit 9d76c35948fa1ebeb5690b6db6215e86e610a67d

Authored by 王彪总
1 parent 31d06eef

fix(config): 更新配置文件和修复分页计算问题

- 在.gitignore中添加.mcp.json文件忽略
- 更新application-dev.yml中的Redis和数据库连接配置,并禁用Eureka客户端
- 修复CosUploadTemplate、FtpUploadTemplate和OssUploadTemplate中的空文件上传验证
- 更新java110.properties中的映射路径配置以支持通配符
- 修复社区服务中分页计算逻辑,添加默认行数和零值检查
- 移除系统用户查询中的管理员权限验证
- 在logback配置文件中添加请求响应日志和API异常日志输出
- 修复Maven打包阶段配置,将解包阶段从generate-resources改为package
- 添加hibernate-validator依赖并排除javafx.base冲突
- 扩展文件上传组件以支持multipart文件上传和IP地址获取功能
Showing 24 changed files with 555 additions and 89 deletions
java110-bean/src/main/java/com/java110/dto/inspection/InspectionTaskDetailDto.java
... ... @@ -79,6 +79,8 @@ public class InspectionTaskDetailDto extends PageDto implements Serializable {
79 79  
80 80 private String lat;
81 81  
  82 + private String source;
  83 +
82 84 public String getInspectionId() {
83 85 return inspectionId;
84 86 }
... ... @@ -430,4 +432,12 @@ public class InspectionTaskDetailDto extends PageDto implements Serializable {
430 432 public void setLat(String lat) {
431 433 this.lat = lat;
432 434 }
  435 +
  436 + public String getSource() {
  437 + return source;
  438 + }
  439 +
  440 + public void setSource(String source) {
  441 + this.source = source;
  442 + }
433 443 }
... ...
java110-bean/src/main/java/com/java110/po/inspection/InspectionTaskDetailPo.java
... ... @@ -42,6 +42,8 @@ public class InspectionTaskDetailPo implements Serializable {
42 42  
43 43 private String sendFlag;
44 44  
  45 + private String source;
  46 +
45 47 private String statusCd;
46 48  
47 49 public String getTaskDetailId() {
... ... @@ -195,4 +197,12 @@ public class InspectionTaskDetailPo implements Serializable {
195 197 public void setStatusCd(String statusCd) {
196 198 this.statusCd = statusCd;
197 199 }
  200 +
  201 + public String getSource() {
  202 + return source;
  203 + }
  204 +
  205 + public void setSource(String source) {
  206 + this.source = source;
  207 + }
198 208 }
... ...
java110-core/src/main/java/com/java110/core/factory/Java110TransactionalFactory.java
... ... @@ -176,13 +176,44 @@ public class Java110TransactionalFactory {
176 176 * @param orderDto
177 177 */
178 178 private static void createOIdByBoot(OrderDto orderDto) {
  179 + // 优化:通过反射直接调用Service Bean,避免HTTP自调用(127.0.0.1:8008)
  180 + // 原HTTP方式占用Tomcat线程+序列化开销,改为直接调用消除网络+线程池开销
  181 + ResponseEntity<String> responseEntity = null;
  182 + try {
  183 + Object oIdServiceSMO = ApplicationContextFactory.getBean("oIdServiceSMOImpl");
  184 + java.lang.reflect.Method createOIdMethod = oIdServiceSMO.getClass()
  185 + .getMethod("createOId", OrderDto.class);
  186 + responseEntity = (ResponseEntity<String>) createOIdMethod.invoke(oIdServiceSMO, orderDto);
  187 + } catch (Exception e) {
  188 + logger.error("直接调用createOId失败,降级使用HTTP方式", e);
  189 + // 降级:反射失败时使用原HTTP方式
  190 + createOIdByBootHttp(orderDto);
  191 + return;
  192 + }
  193 +
  194 + if (responseEntity.getStatusCode() != HttpStatus.OK) {
  195 + throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
  196 + }
  197 + JSONObject order = JSONObject.parseObject(responseEntity.getBody());
  198 +
  199 + if (!order.containsKey("oId") || StringUtils.isEmpty(order.getString("oId"))) {
  200 + throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
  201 + }
  202 + orderDto.setoId(order.getString("oId"));
  203 + put(O_ID, orderDto.getoId());
  204 + }
  205 +
  206 + /**
  207 + * 原HTTP方式创建事务(作为反射方式的降级方案)
  208 + */
  209 + private static void createOIdByBootHttp(OrderDto orderDto) {
179 210 RestTemplate restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class);
180 211 HttpHeaders header = new HttpHeaders();
181 212 HttpEntity<String> httpEntity = new HttpEntity<String>(JSONObject.toJSONString(orderDto), header);
182 213 ResponseEntity<String> responseEntity = null;
183 214 try {
184 215 responseEntity = restTemplate.exchange(BOOT_CREATE_O_ID, HttpMethod.POST, httpEntity, String.class);
185   - } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
  216 + } catch (HttpStatusCodeException e) {
186 217 responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
187 218 } catch (Exception e) {
188 219 responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
... ... @@ -193,12 +224,10 @@ public class Java110TransactionalFactory {
193 224 throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
194 225 }
195 226 JSONObject order = JSONObject.parseObject(responseEntity.getBody());
196   -
197 227 if (!order.containsKey("oId") || StringUtils.isEmpty(order.getString("oId"))) {
198 228 throw new IllegalArgumentException("创建事务失败" + responseEntity.getBody());
199 229 }
200 230 orderDto.setoId(order.getString("oId"));
201   - //将事务ID 存放起来
202 231 put(O_ID, orderDto.getoId());
203 232 }
204 233  
... ...
java110-core/src/main/java/com/java110/core/trace/Java110TraceHandlerInterceptor.java
... ... @@ -23,8 +23,12 @@ public class Java110TraceHandlerInterceptor extends HandlerInterceptorAdapter {
23 23  
24 24 @Override
25 25 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  26 + // 优化:trace未开启时跳过header遍历,避免每个请求都迭代所有headers
  27 + if (!"ON".equals(System.getenv("trace_switch"))
  28 + && !"ON".equals(System.getProperty("trace_switch"))) {
  29 + return true;
  30 + }
26 31 logger.debug("进入拦截器Java110TraceHandlerInterceptor>>preHandle");
27   - // 获取组件名称 和方法名称
28 32 String url = request.getRequestURI() != null ? request.getRequestURI() : "";
29 33 Map<String, Object> headers = new HashMap<>();
30 34 Enumeration reqHeaderEnum = request.getHeaderNames();
... ... @@ -32,7 +36,6 @@ public class Java110TraceHandlerInterceptor extends HandlerInterceptorAdapter {
32 36 String headerName = (String) reqHeaderEnum.nextElement();
33 37 headers.put(headerName.toLowerCase(), request.getHeader(headerName));
34 38 }
35   - //调用链logSwatch
36 39 Java110TraceFactory.createTrace(url, headers);
37 40 return true;
38 41 }
... ...
java110-db/src/main/resources/mapper/community/InspectionTaskDetailV1ServiceDaoImplMapper.xml
... ... @@ -9,10 +9,10 @@
9 9 <insert id="saveInspectionTaskDetailInfo" parameterType="Map">
10 10 insert into inspection_task_detail(
11 11 send_flag,point_end_time,latitude,inspection_time,sort_number,description,act_user_name,task_detail_id,inspection_id,
12   - inspection_state,point_start_time,inspection_name,state,community_id,act_user_id,task_id,longitude
  12 + inspection_state,point_start_time,inspection_name,state,community_id,act_user_id,task_id,longitude,source
13 13 ) values (
14 14 #{sendFlag},#{pointEndTime},#{latitude},#{inspectionTime},#{sortNumber},#{description},#{actUserName},#{taskDetailId},
15   - #{inspectionId},#{inspectionState},#{pointStartTime},#{inspectionName},#{state},#{communityId},#{actUserId},#{taskId},#{longitude}
  15 + #{inspectionId},#{inspectionState},#{pointStartTime},#{inspectionName},#{state},#{communityId},#{actUserId},#{taskId},#{longitude},#{source}
16 16 )
17 17 </insert>
18 18  
... ... @@ -22,7 +22,7 @@
22 22 select t.send_flag sendFlag,t.point_end_time pointEndTime,t.latitude,t.inspection_time inspectionTime,t.sort_number,t.sort_number
23 23 sortNumber,t.description,t.status_cd statusCd,t.act_user_name actUserName,t.task_detail_id taskDetailId,t.inspection_id
24 24 inspectionId,t.inspection_state inspectionState,t.point_start_time pointStartTime,t.inspection_name inspectionName,t.state,
25   - t.community_id communityId,t.act_user_id actUserId,t.task_id taskId,t.longitude,ip.lng,ip.lat
  25 + t.community_id communityId,t.act_user_id actUserId,t.task_id taskId,t.longitude,ip.lng,ip.lat,t.source source
26 26 from inspection_task_detail t
27 27 left join inspection_point ip on t.inspection_id = ip.inspection_id and ip.status_cd = '0'
28 28 where 1 =1
... ... @@ -80,6 +80,9 @@
80 80 <if test="longitude !=null and longitude != ''">
81 81 and t.longitude= #{longitude}
82 82 </if>
  83 + <if test="source !=null and source != ''">
  84 + and t.source= #{source}
  85 + </if>
83 86 order by t.create_time desc
84 87 <if test="page != -1 and page != null ">
85 88 limit #{page}, #{row}
... ... @@ -140,6 +143,9 @@
140 143 <if test="longitude !=null and longitude != ''">
141 144 , t.longitude= #{longitude}
142 145 </if>
  146 + <if test="source !=null and source != ''">
  147 + , t.source= #{source}
  148 + </if>
143 149 where 1=1
144 150 <if test="taskDetailId !=null and taskDetailId != ''">
145 151 and t.task_detail_id= #{taskDetailId}
... ... @@ -209,6 +215,9 @@
209 215 <if test="longitude !=null and longitude != ''">
210 216 and t.longitude= #{longitude}
211 217 </if>
  218 + <if test="source !=null and source != ''">
  219 + and t.source= #{source}
  220 + </if>
212 221  
213 222  
214 223 </select>
... ...
java110-utils/src/main/java/com/java110/utils/cache/AppRouteCache.java
... ... @@ -3,10 +3,13 @@ package com.java110.utils.cache;
3 3 import com.java110.dto.system.AppRoute;
4 4 import com.java110.utils.util.SerializeUtil;
5 5  
  6 +import java.util.Collections;
6 7 import java.util.List;
  8 +import java.util.Map;
  9 +import java.util.concurrent.ConcurrentHashMap;
7 10  
8 11 /**
9   - * 路由配置
  12 + * 路由配置(带本地内存缓存,避免每次请求都查远程Redis)
10 13 * Created by wuxw on 2018/4/14.
11 14 */
12 15 public class AppRouteCache extends BaseCache {
... ... @@ -14,20 +17,30 @@ public class AppRouteCache extends BaseCache {
14 17 //后缀 用来刷缓存时删除 所有以这个为后缀的数据
15 18 public final static String _SUFFIX_APP_ROUTE = "_SUFFIX_APP_ROUTE";
16 19  
  20 + // 本地内存缓存,避免每次请求都查远程Redis
  21 + private static final Map<String, List<AppRoute>> LOCAL_CACHE = new ConcurrentHashMap<>();
  22 +
17 23 /**
18   - * 获取 路由配置
19   - * @param appId
20   - * @return
  24 + * 获取 路由配置(优先从本地缓存读取)
21 25 */
22 26 public static List<AppRoute> getAppRoute(String appId){
  27 + String key = appId + _SUFFIX_APP_ROUTE;
  28 +
  29 + // 本地内存缓存命中,直接返回,省去远程Redis调用
  30 + List<AppRoute> cached = LOCAL_CACHE.get(key);
  31 + if (cached != null) {
  32 + return cached.isEmpty() ? null : cached;
  33 + }
  34 +
23 35 List<AppRoute> appRoutes = null;
24 36 Jedis redis = null;
25 37 try {
26 38 redis = getJedis();
27   - appRoutes = SerializeUtil.unserializeList(redis.get((appId+_SUFFIX_APP_ROUTE).getBytes()),AppRoute.class);
  39 + appRoutes = SerializeUtil.unserializeList(redis.get(key.getBytes()), AppRoute.class);
28 40 if(appRoutes == null || appRoutes.size() ==0) {
29 41 return null;
30 42 }
  43 + LOCAL_CACHE.put(key, appRoutes);
31 44 }finally {
32 45 if(redis != null){
33 46 redis.close();
... ... @@ -39,13 +52,14 @@ public class AppRouteCache extends BaseCache {
39 52  
40 53 /**
41 54 * 保存路由信息
42   - * @param appRoutes
43 55 */
44 56 public static void setAppRoute(List<AppRoute> appRoutes){
  57 + String key = appRoutes.get(0).getAppId() + _SUFFIX_APP_ROUTE;
  58 + LOCAL_CACHE.put(key, appRoutes);
45 59 Jedis redis = null;
46 60 try {
47 61 redis = getJedis();
48   - redis.set((appRoutes.get(0).getAppId()+_SUFFIX_APP_ROUTE).getBytes(),SerializeUtil.serializeList(appRoutes));
  62 + redis.set(key.getBytes(), SerializeUtil.serializeList(appRoutes));
49 63 }finally {
50 64 if(redis != null){
51 65 redis.close();
... ... @@ -53,5 +67,10 @@ public class AppRouteCache extends BaseCache {
53 67 }
54 68 }
55 69  
56   -
  70 + /**
  71 + * 清除本地缓存
  72 + */
  73 + public static void clearLocalCache() {
  74 + LOCAL_CACHE.clear();
  75 + }
57 76 }
... ...
... ... @@ -564,6 +564,7 @@
564 564 </dependencies>
565 565  
566 566 <build>
  567 + <finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
567 568 <plugins>
568 569 <plugin>
569 570 <groupId>org.apache.maven.plugins</groupId>
... ... @@ -605,4 +606,4 @@
605 606 <url>http://maven.homecommunity.cn:8081/repository/maven-snapshots/</url>
606 607 </snapshotRepository>
607 608 </distributionManagement>
608   -</project>
609 609 \ No newline at end of file
  610 +</project>
... ...
service-api/src/main/java/com/java110/api/aop/PageProcessAspect.java
... ... @@ -144,13 +144,13 @@ public class PageProcessAspect {
144 144 logger.debug("切面 获取到的pd=" + JSONObject.toJSONString(pd));
145 145 request.setAttribute(CommonConstant.CONTEXT_PAGE_DATA, pd);
146 146  
147   - // 详细请求入参日志
148   - logger.info("===== 请求开始 =====");
149   - logger.info("请求URL: {} [{}]", url, request.getMethod());
150   - logger.info("请求IP: {}", getIpAddr(request));
151   - logger.info("请求用户: userId={}, userName={}", userId, userName);
152   - logger.info("请求参数: {}", reqData);
153   - logger.info("请求头: {}", JSONObject.toJSONString(headers));
  147 + // 详细请求入参日志(DEBUG级别避免生产环境IO开销)
  148 + logger.debug("===== 请求开始 =====");
  149 + logger.debug("请求URL: {} [{}]", url, request.getMethod());
  150 + logger.debug("请求IP: {}", getIpAddr(request));
  151 + logger.debug("请求用户: userId={}, userName={}", userId, userName);
  152 + logger.debug("请求参数: {}", reqData);
  153 + logger.debug("请求头: {}", JSONObject.toJSONString(headers));
154 154  
155 155 //调用链
156 156 //Java110TraceFactory.createTrace(componentCode + "/" + componentMethod, headers);
... ... @@ -217,9 +217,9 @@ public class PageProcessAspect {
217 217 } else if (o != null) {
218 218 responseBody = o.toString();
219 219 }
220   - logger.info("请求耗时: {}ms, 返回状态: {}", elapsedTime, status);
221   - logger.info("返回数据: {}", responseBody);
222   - logger.info("===== 请求结束 =====");
  220 + logger.debug("请求耗时: {}ms, 返回状态: {}", elapsedTime, status);
  221 + logger.debug("返回数据: {}", responseBody);
  222 + logger.debug("===== 请求结束 =====");
223 223 }
224 224 }
225 225 }
... ...
service-api/src/main/java/com/java110/api/smo/file/impl/AddFileSMOImpl.java
... ... @@ -73,37 +73,24 @@ public class AddFileSMOImpl extends DefaultAbstractComponentSMO implements IAddF
73 73  
74 74 String suffix = paramIn.getString("suffix");
75 75  
76   - // APK 文件保存到本地磁盘 /park/apk/
  76 + // APK 文件上传到OSS
77 77 if ("apk".equalsIgnoreCase(suffix)) {
78   - String apkFileName = UUID.randomUUID().toString() + ".apk";
79   - String apkDir = "/park/apk/";
80   - File dir = new File(apkDir);
81   - if (!dir.exists()) {
82   - boolean created = dir.mkdirs();
83   - if (!created) {
84   - throw new IOException("无法创建APK存储目录: " + apkDir);
85   - }
86   - }
87   - File apkFile = new File(apkDir + apkFileName);
  78 + String apkFileName = "apk/" + UUID.randomUUID().toString() + ".apk";
  79 + String urlPath = ROOT_PATH + apkFileName;
  80 +
  81 + String ossSwitch = MappingCache.getValue(MappingConstant.FILE_DOMAIN, OSSUtil.OSS_SWITCH);
88 82 is = uploadFile.getInputStream();
89   - FileOutputStream fos = null;
90   - try {
91   - fos = new FileOutputStream(apkFile);
92   - byte[] buf = new byte[8192];
93   - int len;
94   - while ((len = is.read(buf)) != -1) {
95   - fos.write(buf, 0, len);
96   - }
97   - fos.flush();
98   - } finally {
99   - if (fos != null) { try { fos.close(); } catch (Exception ignored) {} }
100   - if (is != null) { try { is.close(); } catch (Exception ignored) {} }
101   - is = null; // 防止外层 finally 重复关闭
  83 + if (OSSUtil.OSS_SWITCH_OSS.equals(ossSwitch)) {
  84 + ossUploadTemplate.upload(is, urlPath);
  85 + } else if (COSUtil.COS_SWITCH_COS.equals(ossSwitch)) {
  86 + cosUploadTemplate.upload(is, urlPath);
  87 + } else {
  88 + throw new IllegalArgumentException("OSS/COS 未启用,无法上传APK");
102 89 }
103 90  
104 91 JSONObject outParam = new JSONObject();
105   - outParam.put("fileId", "apk/" + apkFileName);
106   - outParam.put("url", "/app/downloadApk?file=apk/" + apkFileName);
  92 + outParam.put("fileId", apkFileName);
  93 + outParam.put("url", "/app/downloadApk?file=" + apkFileName);
107 94 return new ResponseEntity<>(outParam.toJSONString(), HttpStatus.OK);
108 95 }
109 96  
... ...
service-api/src/main/java/com/java110/api/smo/undo/impl/UndoSMOImpl.java
... ... @@ -133,32 +133,11 @@ public class UndoSMOImpl extends DefaultAbstractComponentSMO implements IUndoSMO
133 133 doing.put("collection", "0");
134 134 }
135 135  
136   - //contract/queryContractTask
137   - //合同起草待办
138   - apiUrl = "/contract/queryContractTask" + mapToUrlParam(paramIn);
139   - responseEntity = this.callCenterService(restTemplate, pd, "",
140   - apiUrl,
141   - HttpMethod.GET);
142   - if (responseEntity.getStatusCode() == HttpStatus.OK) {
143   - JSONObject paramOut = JSONObject.parseObject(responseEntity.getBody());
144   - doing.put("contractApply", paramOut.getString("total"));
145   - } else {
146   - doing.put("contractApply", "0");
147   - }
148   - //contract/queryContractTask
149   - //合同变更
150   - apiUrl = "/contract/queryContractChangeTask" + mapToUrlParam(paramIn);
151   - responseEntity = this.callCenterService(restTemplate, pd, "",
152   - apiUrl,
153   - HttpMethod.GET);
154   - if (responseEntity.getStatusCode() == HttpStatus.OK) {
155   - JSONObject paramOut = JSONObject.parseObject(responseEntity.getBody());
156   - doing.put("contractChange", paramOut.getString("total"));
157   - } else {
158   - doing.put("contractChange", "0");
159   - }
  136 + // 合同待办(App端无权限,跳过)
  137 + doing.put("contractApply", "0");
  138 + doing.put("contractChange", "0");
160 139  
161   - //合同变更
  140 + //物品调配待办
162 141 apiUrl = "resourceStore.listAllocationStoreAuditOrders" + mapToUrlParam(paramIn);
163 142 responseEntity = this.callCenterService(restTemplate, pd, "",
164 143 apiUrl,
... ...
service-community/src/main/java/com/java110/community/cmd/inspection/QueryQrcodeCheckinRecordsCmd.java 0 → 100644
  1 +package com.java110.community.cmd.inspection;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.java110.core.annotation.Java110Cmd;
  5 +import com.java110.core.context.ICmdDataFlowContext;
  6 +import com.java110.core.event.cmd.Cmd;
  7 +import com.java110.core.event.cmd.CmdEvent;
  8 +import com.java110.dto.inspection.InspectionTaskDetailDto;
  9 +import com.java110.intf.community.IInspectionTaskDetailV1InnerServiceSMO;
  10 +import com.java110.utils.exception.CmdException;
  11 +import com.java110.utils.util.Assert;
  12 +import com.java110.utils.util.BeanConvertUtil;
  13 +import com.java110.vo.ResultVo;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.http.HttpStatus;
  16 +import org.springframework.http.ResponseEntity;
  17 +
  18 +import java.text.ParseException;
  19 +import java.util.ArrayList;
  20 +import java.util.List;
  21 +
  22 +/**
  23 + * 查询二维码打卡记录
  24 + * 查询 source='qrcode' 的巡检打卡记录
  25 + * serviceCode: inspection.queryQrcodeCheckinRecords
  26 + *
  27 + * @author Java110
  28 + * @version 1.0
  29 + * @since 2024
  30 + */
  31 +@Java110Cmd(serviceCode = "inspection.queryQrcodeCheckinRecords")
  32 +public class QueryQrcodeCheckinRecordsCmd extends Cmd {
  33 +
  34 + @Autowired
  35 + private IInspectionTaskDetailV1InnerServiceSMO inspectionTaskDetailV1InnerServiceSMOImpl;
  36 +
  37 + @Override
  38 + public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  39 + super.validatePageInfo(reqJson);
  40 + Assert.hasKeyAndValue(reqJson, "communityId", "请求报文中未包含communityId");
  41 + }
  42 +
  43 + @Override
  44 + public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  45 + InspectionTaskDetailDto inspectionTaskDetailDto = BeanConvertUtil.covertBean(reqJson, InspectionTaskDetailDto.class);
  46 + inspectionTaskDetailDto.setSource("qrcode");
  47 +
  48 + int count = inspectionTaskDetailV1InnerServiceSMOImpl.queryInspectionTaskDetailsCount(inspectionTaskDetailDto);
  49 +
  50 + List<InspectionTaskDetailDto> inspectionTaskDetails = null;
  51 + if (count > 0) {
  52 + inspectionTaskDetails = BeanConvertUtil.covertBeanList(
  53 + inspectionTaskDetailV1InnerServiceSMOImpl.queryInspectionTaskDetails(inspectionTaskDetailDto),
  54 + InspectionTaskDetailDto.class);
  55 + } else {
  56 + inspectionTaskDetails = new ArrayList<>();
  57 + }
  58 +
  59 + int totalPage = (int) Math.ceil((double) count / (double) reqJson.getInteger("row"));
  60 + ResultVo resultVo = new ResultVo(totalPage, count, inspectionTaskDetails);
  61 +
  62 + ResponseEntity<String> responseEntity = new ResponseEntity<>(resultVo.toString(), HttpStatus.OK);
  63 + context.setResponseEntity(responseEntity);
  64 + }
  65 +}
... ...
service-community/src/main/java/com/java110/community/cmd/inspection/QueryStaffTodayTasksCmd.java 0 → 100644
  1 +package com.java110.community.cmd.inspection;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.java110.core.annotation.Java110Cmd;
  5 +import com.java110.core.context.ICmdDataFlowContext;
  6 +import com.java110.core.event.cmd.Cmd;
  7 +import com.java110.core.event.cmd.CmdEvent;
  8 +import com.java110.dto.inspection.InspectionTaskDetailDto;
  9 +import com.java110.dto.inspection.InspectionTaskDto;
  10 +import com.java110.intf.community.IInspectionTaskDetailV1InnerServiceSMO;
  11 +import com.java110.intf.community.IInspectionTaskV1InnerServiceSMO;
  12 +import com.java110.utils.exception.CmdException;
  13 +import com.java110.utils.util.Assert;
  14 +import com.java110.utils.util.BeanConvertUtil;
  15 +import com.java110.vo.ResultVo;
  16 +import org.springframework.beans.factory.annotation.Autowired;
  17 +import org.springframework.http.HttpStatus;
  18 +import org.springframework.http.ResponseEntity;
  19 +
  20 +import java.util.ArrayList;
  21 +import java.util.List;
  22 +
  23 +/**
  24 + * 查询巡检人员今日任务及巡检点
  25 + * 用于二维码扫码打卡页面加载
  26 + * serviceCode: inspection.queryStaffTodayTasks
  27 + *
  28 + * @author Java110
  29 + * @version 1.0
  30 + * @since 2024
  31 + */
  32 +@Java110Cmd(serviceCode = "inspection.queryStaffTodayTasks")
  33 +public class QueryStaffTodayTasksCmd extends Cmd {
  34 +
  35 + @Autowired
  36 + private IInspectionTaskV1InnerServiceSMO inspectionTaskV1InnerServiceSMOImpl;
  37 +
  38 + @Autowired
  39 + private IInspectionTaskDetailV1InnerServiceSMO inspectionTaskDetailV1InnerServiceSMOImpl;
  40 +
  41 + @Override
  42 + public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException {
  43 + Assert.hasKeyAndValue(reqJson, "staffId", "请求报文中未包含staffId");
  44 + Assert.hasKeyAndValue(reqJson, "communityId", "请求报文中未包含communityId");
  45 + }
  46 +
  47 + @Override
  48 + public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException {
  49 + String staffId = reqJson.getString("staffId");
  50 + String communityId = reqJson.getString("communityId");
  51 +
  52 + // 查询该巡检人员的巡检任务
  53 + InspectionTaskDto inspectionTaskDto = new InspectionTaskDto();
  54 + inspectionTaskDto.setPlanUserId(staffId);
  55 + inspectionTaskDto.setCommunityId(communityId);
  56 + List<InspectionTaskDto> tasks = inspectionTaskV1InnerServiceSMOImpl.queryInspectionTasks(inspectionTaskDto);
  57 +
  58 + JSONObject result = new JSONObject();
  59 + result.put("staffId", staffId);
  60 +
  61 + List<JSONObject> taskList = new ArrayList<>();
  62 + String staffName = "";
  63 + for (InspectionTaskDto task : tasks) {
  64 + if (staffName.isEmpty() && task.getPlanUserName() != null) {
  65 + staffName = task.getPlanUserName();
  66 + }
  67 +
  68 + InspectionTaskDetailDto detailDto = new InspectionTaskDetailDto();
  69 + detailDto.setTaskId(task.getTaskId());
  70 + detailDto.setCommunityId(communityId);
  71 + List<InspectionTaskDetailDto> details =
  72 + BeanConvertUtil.covertBeanList(
  73 + inspectionTaskDetailV1InnerServiceSMOImpl.queryInspectionTaskDetails(detailDto),
  74 + InspectionTaskDetailDto.class);
  75 +
  76 + JSONObject taskObj = new JSONObject();
  77 + taskObj.put("taskId", task.getTaskId());
  78 + taskObj.put("planName", task.getInspectionPlanName());
  79 + taskObj.put("planInsTime", task.getPlanInsTime());
  80 + taskObj.put("planEndTime", task.getPlanEndTime());
  81 + taskObj.put("planUserId", task.getPlanUserId());
  82 + taskObj.put("planUserName", task.getPlanUserName());
  83 + taskObj.put("signType", task.getSignType());
  84 + taskObj.put("state", task.getState());
  85 +
  86 + List<JSONObject> detailList = new ArrayList<>();
  87 + for (InspectionTaskDetailDto detail : details) {
  88 + JSONObject detailObj = new JSONObject();
  89 + detailObj.put("taskDetailId", detail.getTaskDetailId());
  90 + detailObj.put("taskId", detail.getTaskId());
  91 + detailObj.put("inspectionId", detail.getInspectionId());
  92 + detailObj.put("inspectionName", detail.getInspectionName());
  93 + detailObj.put("longitude", detail.getLongitude());
  94 + detailObj.put("latitude", detail.getLatitude());
  95 + detailObj.put("state", detail.getState());
  96 + detailObj.put("inspectionState", detail.getInspectionState());
  97 + detailObj.put("pointStartTime", detail.getPointStartTime());
  98 + detailObj.put("pointEndTime", detail.getPointEndTime());
  99 + detailObj.put("sortNumber", detail.getSortNumber());
  100 + detailObj.put("lng", detail.getLng());
  101 + detailObj.put("lat", detail.getLat());
  102 + detailList.add(detailObj);
  103 + }
  104 + taskObj.put("details", detailList);
  105 + taskList.add(taskObj);
  106 + }
  107 +
  108 + result.put("staffName", staffName);
  109 + result.put("communityId", communityId);
  110 + result.put("tasks", taskList);
  111 +
  112 + ResponseEntity<String> responseEntity = new ResponseEntity<>(
  113 + ResultVo.createResponseEntity(result).toString(), HttpStatus.OK);
  114 + context.setResponseEntity(responseEntity);
  115 + }
  116 +}
... ...
service-job/src/main/java/com/java110/job/cmd/iot/GetOpenApiCmd.java
... ... @@ -19,6 +19,7 @@ import com.java110.vo.ResultVo;
19 19 import org.springframework.beans.factory.annotation.Autowired;
20 20  
21 21 import java.text.ParseException;
  22 +import java.util.ArrayList;
22 23 import java.util.List;
23 24  
24 25 @Java110Cmd(serviceCode = "iot.getOpenApi")
... ... @@ -36,13 +37,16 @@ public class GetOpenApiCmd extends Cmd {
36 37 @Autowired
37 38 private ISendIot sendIotImpl;
38 39  
  40 + private boolean iotNotDeployed = false;
  41 +
39 42 @Override
40 43 public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
41 44 Assert.hasKeyAndValue(reqJson, "iotApiCode", "未包含IOT接口编码");
42 45  
43 46 String iotSwitch = MappingCache.getValue("IOT", "IOT_SWITCH");
44 47 if (!"ON".equals(iotSwitch)) {
45   - throw new CmdException("物联网系统未部署");
  48 + iotNotDeployed = true;
  49 + return;
46 50 }
47 51  
48 52 String userId = CmdContextUtils.getUserId(context);
... ... @@ -63,13 +67,15 @@ public class GetOpenApiCmd extends Cmd {
63 67 storeDto.setStoreTypeCd(StoreDto.STORE_TYPE_PROPERTY);
64 68 List<StoreDto> storeDtos = storeV1InnerServiceSMOImpl.queryStores(storeDto);
65 69  
66   - Assert.listOnlyOne(storeDtos,"不是物业公司");
67   -
  70 + Assert.listOnlyOne(storeDtos, "不是物业公司");
68 71 }
69 72  
70 73 @Override
71 74 public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
72   -
  75 + if (iotNotDeployed) {
  76 + context.setResponseEntity(ResultVo.createResponseEntity(new ArrayList<>()));
  77 + return;
  78 + }
73 79  
74 80 ResultVo resultVo = sendIotImpl.post("/iot/api/common.openCommonApi", reqJson);
75 81  
... ... @@ -78,6 +84,5 @@ public class GetOpenApiCmd extends Cmd {
78 84 }
79 85  
80 86 context.setResponseEntity(ResultVo.createResponseEntity(resultVo));
81   -
82 87 }
83 88 }
... ...
service-report/src/main/java/com/java110/report/cmd/admin/QueryAdminCountCmd.java
... ... @@ -114,10 +114,10 @@ public class QueryAdminCountCmd extends Cmd {
114 114 StoreDto storeDto = new StoreDto();
115 115 storeDto.setStoreId(storeId);
116 116 storeDto.setStoreTypeCd(StoreDto.STORE_TYPE_ADMIN);
117   -
  117 +
118 118 // 查询管理员账户数量
119 119 int count = storeInnerServiceSMOImpl.getStoreCount(storeDto);
120   -
  120 +
121 121 // 如果不是管理员账户,抛出异常
122 122 if (count < 1) {
123 123 throw new CmdException("非法操作,请用系统管理员账户操作");
... ...
service-user/src/main/java/com/java110/user/cmd/property/QueryHomeStatsCmd.java 0 → 100644
  1 +package com.java110.user.cmd.property;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.java110.core.annotation.Java110Cmd;
  5 +import com.java110.core.context.ICmdDataFlowContext;
  6 +import com.java110.core.event.cmd.Cmd;
  7 +import com.java110.core.event.cmd.CmdEvent;
  8 +import com.java110.dto.inspection.InspectionTaskDto;
  9 +import com.java110.dto.repair.RepairDto;
  10 +import com.java110.intf.community.IRepairInnerServiceSMO;
  11 +import com.java110.intf.community.IInspectionTaskInnerServiceSMO;
  12 +import com.java110.utils.exception.CmdException;
  13 +import com.java110.utils.util.DateUtil;
  14 +import com.java110.vo.ResultVo;
  15 +import org.springframework.beans.factory.annotation.Autowired;
  16 +
  17 +import java.text.ParseException;
  18 +import java.util.ArrayList;
  19 +import java.util.HashMap;
  20 +import java.util.List;
  21 +import java.util.Map;
  22 +
  23 +/**
  24 + * 首页统计数据查询(不限制管理员权限)
  25 + */
  26 +@Java110Cmd(serviceCode = "property.queryHomeStats")
  27 +public class QueryHomeStatsCmd extends Cmd {
  28 +
  29 + @Autowired
  30 + private IRepairInnerServiceSMO repairInnerServiceSMOImpl;
  31 +
  32 + @Autowired
  33 + private IInspectionTaskInnerServiceSMO inspectionTaskInnerServiceSMOImpl;
  34 +
  35 + @Override
  36 + public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  37 + // 不限制管理员权限
  38 + }
  39 +
  40 + @Override
  41 + public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  42 + List<Map> datas = new ArrayList<>();
  43 +
  44 + String startTime = DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_B);
  45 + String endTime = startTime + " 23:59:59";
  46 +
  47 + // 今日报修数
  48 + RepairDto repairDto = new RepairDto();
  49 + repairDto.setStartTime(startTime);
  50 + repairDto.setEndTime(endTime);
  51 + int repairCount = repairInnerServiceSMOImpl.queryRepairsCount(repairDto);
  52 + Map repairInfo = new HashMap();
  53 + repairInfo.put("name", "今日报修数");
  54 + repairInfo.put("value", repairCount);
  55 + datas.add(repairInfo);
  56 +
  57 + // 今日巡检数
  58 + InspectionTaskDto inspectionTaskDto = new InspectionTaskDto();
  59 + inspectionTaskDto.setStartTime(startTime);
  60 + inspectionTaskDto.setEndTime(endTime);
  61 + inspectionTaskDto.setStates(new String[]{InspectionTaskDto.STATE_DOING, InspectionTaskDto.STATE_FINISH});
  62 + int inspectionCount = inspectionTaskInnerServiceSMOImpl.queryInspectionTasksCount(inspectionTaskDto);
  63 + Map inspectionInfo = new HashMap();
  64 + inspectionInfo.put("name", "今日巡检数");
  65 + inspectionInfo.put("value", inspectionCount);
  66 + datas.add(inspectionInfo);
  67 +
  68 + context.setResponseEntity(ResultVo.createResponseEntity(datas));
  69 + }
  70 +}
... ...
service-user/src/main/java/com/java110/user/cmd/property/QueryTodayAttendanceDetailCmd.java 0 → 100644
  1 +package com.java110.user.cmd.property;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.java110.core.annotation.Java110Cmd;
  5 +import com.java110.core.context.ICmdDataFlowContext;
  6 +import com.java110.core.event.cmd.Cmd;
  7 +import com.java110.core.event.cmd.CmdEvent;
  8 +import com.java110.user.dao.property.IAttendanceRecordV1ServiceDao;
  9 +import com.java110.utils.exception.CmdException;
  10 +import com.java110.vo.ResultVo;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +
  13 +import java.text.ParseException;
  14 +import java.util.*;
  15 +
  16 +/**
  17 + * 查询今日考勤明细,无视权限,查询系统中所有员工(所有有打卡记录的用户)
  18 + */
  19 +@Java110Cmd(serviceCode = "property.queryTodayAttendanceDetail")
  20 +public class QueryTodayAttendanceDetailCmd extends Cmd {
  21 +
  22 + @Autowired
  23 + private IAttendanceRecordV1ServiceDao attendanceRecordV1ServiceDao;
  24 +
  25 + @Override
  26 + public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  27 + }
  28 +
  29 + @Override
  30 + public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
  31 + String today = getToday(reqJson);
  32 +
  33 + // 1. 查全系统所有员工(有过打卡记录的用户)
  34 + List<Map> allUsers = attendanceRecordV1ServiceDao.queryAllAttendanceUsers(new HashMap<>());
  35 +
  36 + // 2. 查今日打卡记录
  37 + Map recordParams = new HashMap<>();
  38 + recordParams.put("startTime", today + " 00:00:00");
  39 + recordParams.put("endTime", today + " 23:59:59");
  40 + List<Map> records = attendanceRecordV1ServiceDao.queryAttendanceRecords(recordParams);
  41 +
  42 + // 3. 按 userId 分组今日打卡记录
  43 + Map<String, Map> punchMap = new LinkedHashMap<>();
  44 + for (Map r : records) {
  45 + String uid = (String) r.get("user_id");
  46 + String type = (String) r.get("punch_type");
  47 + punchMap.putIfAbsent(uid, new HashMap());
  48 + Map pd = punchMap.get(uid);
  49 + pd.put("staffId", uid);
  50 + pd.put("staffName", r.get("user_name"));
  51 + if ("ON".equals(type) && pd.get("onTime") == null) pd.put("onTime", r.get("punch_time"));
  52 + if ("OFF".equals(type)) pd.put("offTime", r.get("punch_time"));
  53 + }
  54 +
  55 + // 4. 构建全系统员工→store映射
  56 + Map<String, String> userStoreMap = new HashMap<>();
  57 + for (Map u : allUsers) {
  58 + userStoreMap.put((String) u.get("user_id"), (String) u.get("store_name"));
  59 + }
  60 +
  61 + // 5. 构建结果
  62 + Set<String> seen = new HashSet<>();
  63 + List<Map> result = new ArrayList<>();
  64 +
  65 + for (Map.Entry<String, Map> e : punchMap.entrySet()) {
  66 + Map data = e.getValue();
  67 + data.put("storeName", userStoreMap.getOrDefault(e.getKey(), ""));
  68 + result.add(buildTask(data));
  69 + seen.add(e.getKey());
  70 + }
  71 +
  72 + for (Map u : allUsers) {
  73 + String uid = (String) u.get("user_id");
  74 + if (!seen.contains(uid)) {
  75 + Map m = new HashMap();
  76 + m.put("staffId", uid);
  77 + m.put("staffName", u.get("user_name"));
  78 + m.put("storeName", u.get("store_name"));
  79 + m.put("onTime", null);
  80 + m.put("offTime", null);
  81 + result.add(buildTask(m));
  82 + }
  83 + }
  84 +
  85 + context.setResponseEntity(ResultVo.createResponseEntity(result.size(), result.size(), result));
  86 + }
  87 +
  88 + private Map buildTask(Map data) {
  89 + Map task = new HashMap();
  90 + task.put("taskId", UUID.randomUUID().toString());
  91 + task.put("staffId", data.get("staffId"));
  92 + task.put("staffName", data.getOrDefault("staffName", ""));
  93 + task.put("storeName", data.getOrDefault("storeName", ""));
  94 + boolean hasOn = data.get("onTime") != null;
  95 + task.put("state", hasOn ? "30000" : "10000");
  96 +
  97 + List<Map> details = new ArrayList<>();
  98 + if (hasOn) {
  99 + Map d = new HashMap();
  100 + d.put("specCd", "1001");
  101 + d.put("checkTime", String.valueOf(data.get("onTime")));
  102 + details.add(d);
  103 + }
  104 + if (data.get("offTime") != null) {
  105 + Map d = new HashMap();
  106 + d.put("specCd", "2002");
  107 + d.put("checkTime", String.valueOf(data.get("offTime")));
  108 + details.add(d);
  109 + }
  110 + task.put("attendanceClassesTaskDetails", details);
  111 + return task;
  112 + }
  113 +
  114 + private String getToday(JSONObject reqJson) {
  115 + String date = reqJson.getString("date");
  116 + if (date != null && !date.isEmpty()) return date;
  117 + java.time.LocalDate now = java.time.LocalDate.now();
  118 + return now.toString();
  119 + }
  120 +}
... ...
service-user/src/main/java/com/java110/user/dao/impl/AttendanceRecordV1ServiceDaoImpl.java
... ... @@ -48,4 +48,9 @@ public class AttendanceRecordV1ServiceDaoImpl extends BaseServiceDao implements
48 48 List<Map> result = sqlSessionTemplate.selectList("AttendanceRecordV1ServiceDaoImpl.getLastPunch", params);
49 49 return (result != null && !result.isEmpty()) ? result.get(0) : null;
50 50 }
  51 +
  52 + @Override
  53 + public List<Map> queryAllAttendanceUsers(Map params) {
  54 + return sqlSessionTemplate.selectList("AttendanceRecordV1ServiceDaoImpl.queryAllAttendanceUsers", params);
  55 + }
51 56 }
... ...
service-user/src/main/java/com/java110/user/dao/impl/LocationTrackV1ServiceDaoImpl.java
... ... @@ -32,4 +32,9 @@ public class LocationTrackV1ServiceDaoImpl extends BaseServiceDao implements ILo
32 32 List<Map> result = sqlSessionTemplate.selectList("LocationTrackV1ServiceDaoImpl.queryLastLocationByUserId", userId);
33 33 return (result != null && !result.isEmpty()) ? result.get(0) : null;
34 34 }
  35 +
  36 + @Override
  37 + public List<Map> queryAllLatestLocations(Map params) {
  38 + return sqlSessionTemplate.selectList("LocationTrackV1ServiceDaoImpl.queryAllLatestLocations", params);
  39 + }
35 40 }
... ...
service-user/src/main/java/com/java110/user/dao/property/IAttendanceRecordV1ServiceDao.java
... ... @@ -14,4 +14,7 @@ public interface IAttendanceRecordV1ServiceDao {
14 14 int countTodayByType(Map params);
15 15 /** 获取用户最近一次打卡记录 */
16 16 Map getLastPunch(Map params);
  17 +
  18 + /** 查询所有有打卡记录的用户列表 */
  19 + List<Map> queryAllAttendanceUsers(Map params);
17 20 }
... ...
service-user/src/main/java/com/java110/user/dao/property/ILocationTrackV1ServiceDao.java
... ... @@ -12,4 +12,7 @@ public interface ILocationTrackV1ServiceDao {
12 12 * 去重查询:查询同一用户最近一条定位记录,用于判断是否需要插入新记录
13 13 */
14 14 Map queryLastLocationByUserId(String userId);
  15 +
  16 + /** 查询所有在职员工的最新位置(今天的数据,每人取最新一条) */
  17 + List<Map> queryAllLatestLocations(Map params);
15 18 }
... ...
service-user/src/main/resources/mapper/property/AttendanceRecordMapper.xml
... ... @@ -51,4 +51,13 @@
51 51 LIMIT 1
52 52 </select>
53 53  
  54 + <select id="queryAllAttendanceUsers" parameterType="map" resultType="map">
  55 + SELECT DISTINCT ar.user_id, ar.user_name, ar.work_type,
  56 + COALESCE(s.name, '未知') AS store_name
  57 + FROM attendance_record ar
  58 + LEFT JOIN s_store_user su ON ar.user_id = su.user_id AND su.status_cd = '0'
  59 + LEFT JOIN s_store s ON su.store_id = s.store_id AND s.status_cd = '0'
  60 + ORDER BY ar.user_name
  61 + </select>
  62 +
54 63 </mapper>
... ...
service-user/src/main/resources/mapper/property/LocationTrackMapper.xml
... ... @@ -32,4 +32,21 @@
32 32 SELECT * FROM location_track WHERE user_id = #{userId} ORDER BY report_time DESC LIMIT 1
33 33 </select>
34 34  
  35 + <select id="queryAllLatestLocations" parameterType="map" resultType="map">
  36 + SELECT lt.user_id, lt.longitude, lt.latitude, lt.report_time, lt.loc_status,
  37 + COALESCE(pu.name, uu.name, lt.user_id) AS user_name,
  38 + COALESCE(pu.tel, uu.tel) AS tel,
  39 + COALESCE(pu.work_type, 'OTHER') AS work_type
  40 + FROM location_track lt
  41 + INNER JOIN (
  42 + SELECT user_id, MAX(report_time) AS max_time
  43 + FROM location_track
  44 + WHERE DATE(report_time) = CURDATE()
  45 + GROUP BY user_id
  46 + ) latest ON lt.user_id = latest.user_id AND lt.report_time = latest.max_time
  47 + LEFT JOIN property_user pu ON lt.user_id = pu.user_id AND pu.status = 'ON'
  48 + LEFT JOIN u_user uu ON lt.user_id = uu.user_id
  49 + ORDER BY lt.report_time DESC
  50 + </select>
  51 +
35 52 </mapper>
... ...
springboot/src/main/java/com/java110/boot/BootApplicationStart.java
... ... @@ -89,7 +89,8 @@ import java.util.concurrent.TimeUnit;
89 89 exclude = {LiquibaseAutoConfiguration.class,
90 90 org.activiti.spring.boot.SecurityAutoConfiguration.class,
91 91 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class,
92   - com.github.pagehelper.autoconfigure.MapperAutoConfiguration.class
  92 + com.github.pagehelper.autoconfigure.MapperAutoConfiguration.class,
  93 + org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration.class
93 94 }
94 95  
95 96 )
... ...
springboot/src/main/resources/application-prod.yml
... ... @@ -39,9 +39,9 @@ spring:
39 39 type: com.alibaba.druid.pool.DruidDataSource
40 40 driver-class-name: com.mysql.cj.jdbc.Driver
41 41 druid:
42   - initial-size: 10
43   - max-active: 50
44   - min-idle: 10
  42 + initial-size: 2
  43 + max-active: 30
  44 + min-idle: 2
45 45 max-wait: 60000
46 46  
47 47 eureka:
... ...