|
|
@@ -6,6 +6,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|
6
|
6
|
import org.springframework.stereotype.Service;
|
|
7
|
7
|
|
|
8
|
8
|
import java.time.LocalDate;
|
|
|
9
|
+import java.time.LocalDateTime;
|
|
9
|
10
|
import java.time.YearMonth;
|
|
10
|
11
|
import java.time.format.DateTimeFormatter;
|
|
11
|
12
|
import java.util.*;
|
|
|
@@ -31,9 +32,17 @@ public class PatrolAppService {
|
|
31
|
32
|
LocalDate today = LocalDate.now();
|
|
32
|
33
|
LocalDate monthStart = today.withDayOfMonth(1);
|
|
33
|
34
|
|
|
|
35
|
+ // 验证用户存在
|
|
|
36
|
+ Long userExists = jdbc.queryForObject(
|
|
|
37
|
+ "SELECT COUNT(*) FROM sys_user WHERE id = ?",
|
|
|
38
|
+ Long.class, userId);
|
|
|
39
|
+ if (userExists == null || userExists == 0) {
|
|
|
40
|
+ throw new IllegalArgumentException("用户不存在: " + userId);
|
|
|
41
|
+ }
|
|
|
42
|
+
|
|
34
|
43
|
long todayTasks = countQuery(
|
|
35
|
|
- "SELECT COUNT(*) FROM patrol_task WHERE assignee_id = ? AND task_date = ?",
|
|
36
|
|
- userId, today);
|
|
|
44
|
+ "SELECT COUNT(*) FROM patrol_task WHERE assignee_id = ? AND task_date = CURRENT_DATE",
|
|
|
45
|
+ userId);
|
|
37
|
46
|
|
|
38
|
47
|
long pendingWorkOrders = countQuery(
|
|
39
|
48
|
"SELECT COUNT(*) FROM patrol_work_order WHERE assignee_id = ? AND status IN ('assigned','processing')",
|
|
|
@@ -57,6 +66,7 @@ public class PatrolAppService {
|
|
57
|
66
|
overview.put("monthCompletedCount", monthCompleted);
|
|
58
|
67
|
overview.put("monthDistance", monthDistance != null ? Math.round(monthDistance * 100.0) / 100.0 : 0.0);
|
|
59
|
68
|
overview.put("monthIssueCount", monthIssues);
|
|
|
69
|
+ overview.put("lastUpdated", LocalDateTime.now());
|
|
60
|
70
|
return overview;
|
|
61
|
71
|
}
|
|
62
|
72
|
|
|
|
@@ -243,43 +253,79 @@ public class PatrolAppService {
|
|
243
|
253
|
String voiceUrl, Double lng, Double lat) {
|
|
244
|
254
|
log.info("APP问题上报: taskId={}, type={}, desc={}", taskId, issueType, description);
|
|
245
|
255
|
|
|
246
|
|
- String problemNo = "PAT-" + System.currentTimeMillis();
|
|
|
256
|
+ // 参数校验
|
|
|
257
|
+ if (taskId == null) {
|
|
|
258
|
+ throw new IllegalArgumentException("任务ID不能为空");
|
|
|
259
|
+ }
|
|
|
260
|
+ if (issueType == null || issueType.trim().isEmpty()) {
|
|
|
261
|
+ throw new IllegalArgumentException("问题类型不能为空");
|
|
|
262
|
+ }
|
|
|
263
|
+ if (description == null || description.trim().isEmpty()) {
|
|
|
264
|
+ throw new IllegalArgumentException("问题描述不能为空");
|
|
|
265
|
+ }
|
|
|
266
|
+ if (description.length() > 1000) {
|
|
|
267
|
+ throw new IllegalArgumentException("问题描述不能超过1000字符");
|
|
|
268
|
+ }
|
|
247
|
269
|
|
|
248
|
|
- // 1. 创建巡检问题记录
|
|
249
|
|
- jdbc.update(
|
|
250
|
|
- "INSERT INTO patrol_problem (problem_no, task_id, device_id, reporter_id, " +
|
|
251
|
|
- " issue_type, description, photo_urls, voice_url, gps_lng, gps_lat, status, created_at) " +
|
|
252
|
|
- "SELECT ?, ?, ?, assignee_id, ?, ?, ?::jsonb, ?, ?, ?, 'reported', NOW() " +
|
|
253
|
|
- "FROM patrol_task WHERE id = ?",
|
|
254
|
|
- problemNo, taskId, deviceId,
|
|
255
|
|
- issueType, description,
|
|
256
|
|
- photoUrls != null ? photoUrls.toString() : "[]",
|
|
257
|
|
- voiceUrl, lng, lat, taskId);
|
|
258
|
|
-
|
|
259
|
|
- // 2. 自动创建工单
|
|
260
|
|
- String orderNo = "PWO-" + System.currentTimeMillis();
|
|
261
|
|
- jdbc.update(
|
|
262
|
|
- "INSERT INTO patrol_work_order (order_no, task_id, issue_type, description, severity, " +
|
|
263
|
|
- " location, lng, lat, status, created_at) " +
|
|
264
|
|
- "VALUES (?, ?, ?, ?, 'medium', ?, ?, ?, 'pending', NOW())",
|
|
265
|
|
- orderNo, taskId, issueType, description,
|
|
266
|
|
- description.length() > 50 ? description.substring(0, 50) : description,
|
|
267
|
|
- lng, lat);
|
|
268
|
|
-
|
|
269
|
|
- // 3. 关联工单到问题
|
|
270
|
|
- jdbc.update(
|
|
271
|
|
- "UPDATE patrol_problem SET work_order_id = (SELECT id FROM patrol_work_order WHERE order_no = ? LIMIT 1) " +
|
|
272
|
|
- "WHERE problem_no = ?",
|
|
273
|
|
- orderNo, problemNo);
|
|
|
270
|
+ // 验证任务存在且属于该用户
|
|
|
271
|
+ Long taskExists = jdbc.queryForObject(
|
|
|
272
|
+ "SELECT COUNT(*) FROM patrol_task WHERE id = ? AND assignee_id = ? AND status != 'completed'",
|
|
|
273
|
+ Long.class, taskId, userId);
|
|
|
274
|
+ if (taskExists == null || taskExists == 0) {
|
|
|
275
|
+ throw new IllegalArgumentException("任务不存在或已完成/不属于该用户");
|
|
|
276
|
+ }
|
|
274
|
277
|
|
|
275
|
|
- Map<String, Object> result = new LinkedHashMap<>();
|
|
276
|
|
- result.put("problemNo", problemNo);
|
|
277
|
|
- result.put("orderNo", orderNo);
|
|
278
|
|
- result.put("issueType", issueType);
|
|
279
|
|
- result.put("reported", true);
|
|
280
|
|
- result.put("photoCount", photoUrls != null ? photoUrls.size() : 0);
|
|
281
|
|
- result.put("hasVoice", voiceUrl != null && !voiceUrl.isEmpty());
|
|
282
|
|
- return result;
|
|
|
278
|
+ String problemNo = "PAT-" + System.currentTimeMillis();
|
|
|
279
|
+
|
|
|
280
|
+ try {
|
|
|
281
|
+ // 1. 创建巡检问题记录
|
|
|
282
|
+ jdbc.update(
|
|
|
283
|
+ "INSERT INTO patrol_problem (problem_no, task_id, device_id, reporter_id, " +
|
|
|
284
|
+ " issue_type, description, photo_urls, voice_url, gps_lng, gps_lat, status, created_at) " +
|
|
|
285
|
+ "SELECT ?, ?, ?, assignee_id, ?, ?, ?::jsonb, ?, ?, ?, 'reported', NOW() " +
|
|
|
286
|
+ "FROM patrol_task WHERE id = ?",
|
|
|
287
|
+ problemNo, taskId, deviceId,
|
|
|
288
|
+ issueType, description,
|
|
|
289
|
+ photoUrls != null ? photoUrls.toString() : "[]",
|
|
|
290
|
+ voiceUrl, lng, lat, taskId);
|
|
|
291
|
+
|
|
|
292
|
+ // 2. 自动创建工单
|
|
|
293
|
+ String orderNo = "PWO-" + System.currentTimeMillis();
|
|
|
294
|
+ jdbc.update(
|
|
|
295
|
+ "INSERT INTO patrol_work_order (order_no, task_id, issue_type, description, severity, " +
|
|
|
296
|
+ " location, lng, lat, status, created_at) " +
|
|
|
297
|
+ "VALUES (?, ?, ?, ?, 'medium', ?, ?, ?, 'pending', NOW())",
|
|
|
298
|
+ orderNo, taskId, issueType, description,
|
|
|
299
|
+ description.length() > 50 ? description.substring(0, 50) : description,
|
|
|
300
|
+ lng, lat);
|
|
|
301
|
+
|
|
|
302
|
+ // 3. 关联工单到问题
|
|
|
303
|
+ jdbc.update(
|
|
|
304
|
+ "UPDATE patrol_problem SET work_order_id = (SELECT id FROM patrol_work_order WHERE order_no = ? LIMIT 1) " +
|
|
|
305
|
+ "WHERE problem_no = ?",
|
|
|
306
|
+ orderNo, problemNo);
|
|
|
307
|
+
|
|
|
308
|
+ // 4. 更新巡逻任务状态为"有异常"
|
|
|
309
|
+ jdbc.update(
|
|
|
310
|
+ "UPDATE patrol_task SET status = 'with_issues', updated_at = NOW() WHERE id = ?",
|
|
|
311
|
+ taskId);
|
|
|
312
|
+
|
|
|
313
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
314
|
+ result.put("problemNo", problemNo);
|
|
|
315
|
+ result.put("orderNo", orderNo);
|
|
|
316
|
+ result.put("issueType", issueType);
|
|
|
317
|
+ result.put("description", description);
|
|
|
318
|
+ result.put("reported", true);
|
|
|
319
|
+ result.put("photoCount", photoUrls != null ? photoUrls.size() : 0);
|
|
|
320
|
+ result.put("hasVoice", voiceUrl != null && !voiceUrl.isEmpty());
|
|
|
321
|
+ result.put("gpsLocation", lng != null && lat != null ? String.format("%.6f,%.6f", lng, lat) : null);
|
|
|
322
|
+ result.put("reportedAt", LocalDateTime.now());
|
|
|
323
|
+ return result;
|
|
|
324
|
+
|
|
|
325
|
+ } catch (Exception e) {
|
|
|
326
|
+ log.error("上报问题失败: taskId={}, error={}", taskId, e.getMessage(), e);
|
|
|
327
|
+ throw new RuntimeException("上报问题失败: " + e.getMessage());
|
|
|
328
|
+ }
|
|
283
|
329
|
}
|
|
284
|
330
|
|
|
285
|
331
|
// ========== PAT-28 个人中心 ==========
|