151 lines
7.3 KiB
Java
151 lines
7.3 KiB
Java
package com.example.demo.consult;
|
||
|
||
import com.example.demo.common.AppDefaultsProperties;
|
||
import org.springframework.http.ResponseEntity;
|
||
import org.springframework.jdbc.core.JdbcTemplate;
|
||
import org.springframework.web.bind.annotation.*;
|
||
|
||
import java.util.*;
|
||
|
||
@RestController
|
||
@RequestMapping("/api/consults")
|
||
public class ConsultController {
|
||
|
||
private final JdbcTemplate jdbcTemplate;
|
||
private final AppDefaultsProperties defaults;
|
||
|
||
public ConsultController(JdbcTemplate jdbcTemplate, AppDefaultsProperties defaults) {
|
||
this.jdbcTemplate = jdbcTemplate;
|
||
this.defaults = defaults;
|
||
}
|
||
|
||
@PostMapping
|
||
public ResponseEntity<?> create(@RequestHeader(name = "X-Shop-Id", required = false) Long shopId,
|
||
@RequestHeader(name = "X-User-Id", required = false) Long userId,
|
||
@RequestBody Map<String, Object> body) {
|
||
Long sid = (shopId == null ? defaults.getShopId() : shopId);
|
||
Long uid = (userId == null ? defaults.getUserId() : userId);
|
||
if (body == null) body = new HashMap<>();
|
||
String topic = ""; // 主题字段已废弃
|
||
String message = Optional.ofNullable(body.get("message")).map(String::valueOf).orElse(null);
|
||
if (message == null || message.isBlank()) {
|
||
return ResponseEntity.badRequest().body(Map.of("message", "message required"));
|
||
}
|
||
jdbcTemplate.update("INSERT INTO consults (shop_id,user_id,topic,message,status,created_at,updated_at) VALUES (?,?,?,?, 'open', NOW(), NOW())",
|
||
sid, uid, topic, message);
|
||
Long id = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
||
Map<String,Object> resp = new HashMap<>();
|
||
resp.put("id", id);
|
||
return ResponseEntity.ok(resp);
|
||
}
|
||
|
||
@GetMapping("/latest")
|
||
public ResponseEntity<?> latest(@RequestHeader(name = "X-Shop-Id", required = false) Long shopId,
|
||
@RequestHeader(name = "X-User-Id", required = false) Long userId) {
|
||
Long sid = (shopId == null ? defaults.getShopId() : shopId);
|
||
Long uid = (userId == null ? defaults.getUserId() : userId);
|
||
List<Map<String, Object>> list = jdbcTemplate.query(
|
||
"SELECT id, topic, message, status, created_at FROM consults WHERE shop_id=? AND user_id=? ORDER BY id DESC LIMIT 1",
|
||
ps -> { ps.setLong(1, sid); ps.setLong(2, uid); },
|
||
(rs, i) -> {
|
||
Map<String,Object> m = new LinkedHashMap<>();
|
||
m.put("id", rs.getLong("id"));
|
||
m.put("topic", rs.getString("topic"));
|
||
m.put("message", rs.getString("message"));
|
||
m.put("status", rs.getString("status"));
|
||
m.put("createdAt", rs.getTimestamp("created_at"));
|
||
return m;
|
||
}
|
||
);
|
||
if (list.isEmpty()) {
|
||
return ResponseEntity.ok(Collections.emptyMap());
|
||
}
|
||
Map<String,Object> latest = list.get(0);
|
||
Object idObj = latest.get("id");
|
||
Long consultId = (idObj instanceof Number) ? ((Number) idObj).longValue() : Long.valueOf(String.valueOf(idObj));
|
||
Map<String,Object> reply = jdbcTemplate.query(
|
||
"SELECT content, created_at FROM consult_replies WHERE consult_id=? ORDER BY id DESC LIMIT 1",
|
||
rs -> {
|
||
if (rs.next()) {
|
||
Map<String,Object> r = new HashMap<>();
|
||
r.put("content", rs.getString("content"));
|
||
r.put("createdAt", rs.getTimestamp("created_at"));
|
||
return r;
|
||
}
|
||
return null;
|
||
}, consultId
|
||
);
|
||
latest.put("replied", Objects.equals("resolved", String.valueOf(latest.get("status"))));
|
||
if (reply != null) {
|
||
latest.put("latestReply", reply.get("content"));
|
||
latest.put("latestReplyAt", reply.get("createdAt"));
|
||
}
|
||
return ResponseEntity.ok(latest);
|
||
}
|
||
|
||
// 兼容:GET /api/consults 等同于 /api/consults/latest
|
||
@GetMapping
|
||
public ResponseEntity<?> latestAlias(@RequestHeader(name = "X-Shop-Id", required = false) Long shopId,
|
||
@RequestHeader(name = "X-User-Id", required = false) Long userId) {
|
||
return latest(shopId, userId);
|
||
}
|
||
|
||
// 用户确认已读:查看过管理员回复后,将状态回到 open
|
||
@PutMapping("/{id}/ack")
|
||
public ResponseEntity<?> ack(@PathVariable("id") Long id,
|
||
@RequestHeader(name = "X-User-Id", required = false) Long userId) {
|
||
// 若该咨询属于该用户,则把状态改回 open(仅在当前为 resolved 时)
|
||
int updated = jdbcTemplate.update(
|
||
"UPDATE consults SET status='open', updated_at=NOW() WHERE id=? AND user_id=? AND status='resolved'",
|
||
id, (userId == null ? defaults.getUserId() : userId));
|
||
Map<String,Object> body = new java.util.HashMap<>();
|
||
body.put("updated", updated);
|
||
return ResponseEntity.ok(body);
|
||
}
|
||
|
||
@GetMapping("/{id}")
|
||
public ResponseEntity<?> detail(@PathVariable("id") Long id,
|
||
@RequestHeader(name = "X-User-Id", required = false) Long userId) {
|
||
Map<String,Object> consult = jdbcTemplate.query(
|
||
"SELECT id, shop_id AS shopId, user_id AS userId, topic, message, status, created_at FROM consults WHERE id=?",
|
||
rs -> {
|
||
if (rs.next()) {
|
||
Map<String,Object> m = new LinkedHashMap<>();
|
||
m.put("id", rs.getLong("id"));
|
||
m.put("shopId", rs.getLong("shopId"));
|
||
m.put("userId", rs.getLong("userId"));
|
||
m.put("topic", rs.getString("topic"));
|
||
m.put("message", rs.getString("message"));
|
||
m.put("status", rs.getString("status"));
|
||
m.put("createdAt", rs.getTimestamp("created_at"));
|
||
return m;
|
||
}
|
||
return null;
|
||
}, id);
|
||
if (consult == null) return ResponseEntity.notFound().build();
|
||
if (userId != null) {
|
||
Object ownerObj = consult.get("userId");
|
||
Long ownerId = (ownerObj instanceof Number) ? ((Number) ownerObj).longValue() : Long.valueOf(String.valueOf(ownerObj));
|
||
if (!Objects.equals(ownerId, userId)) {
|
||
return ResponseEntity.status(403).body(Map.of("message", "forbidden"));
|
||
}
|
||
}
|
||
List<Map<String,Object>> replies = jdbcTemplate.query(
|
||
"SELECT id, user_id AS userId, content, created_at FROM consult_replies WHERE consult_id=? ORDER BY id ASC",
|
||
(rs, i) -> {
|
||
Map<String,Object> r = new LinkedHashMap<>();
|
||
r.put("id", rs.getLong("id"));
|
||
r.put("userId", rs.getLong("userId"));
|
||
r.put("content", rs.getString("content"));
|
||
r.put("createdAt", rs.getTimestamp("created_at"));
|
||
return r;
|
||
}, id);
|
||
Map<String,Object> body = new LinkedHashMap<>();
|
||
body.putAll(consult);
|
||
body.put("replies", replies);
|
||
return ResponseEntity.ok(body);
|
||
}
|
||
}
|
||
|
||
|