package com.xly.web;
import com.fasterxml.jackson.databind.JsonNode;
import com.xly.service.ErpClient;
import com.xly.service.OpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 写操作确认端点(**确定性、不经过 LLM**)—— 人在环写入闭环的执行侧。
*
*
用户在对话框点【确认】-> {@code /confirm} 才真正调 ERP 执行;点【取消】-> {@code /cancel}。
* v1 为同步执行(update 很快):直接调 ERP 表单更新接口,回写 ai_op_queue 状态并返回结果。
*/
@RestController
@RequestMapping("/api/agent/op")
public class OpController {
private static final Logger log = LoggerFactory.getLogger(OpController.class);
private final OpService ops;
private final ErpClient erp;
public OpController(OpService ops, ErpClient erp) {
this.ops = ops;
this.erp = erp;
}
/** 会话里最近一条待确认操作(前端每轮结束后轮询,用于渲染确认卡片)。 */
@GetMapping("/pending")
public Map pending(@RequestParam("conversationId") String conversationId) {
Map op = ops.pending(conversationId);
return op == null ? Map.of() : op;
}
/** 确认执行:调 ERP 更新,回写状态。 */
@PostMapping("/{id}/confirm")
public Map confirm(@PathVariable("id") String id) {
Map op = ops.get(id);
if (op == null) {
return result("failed", "找不到该操作", null);
}
if (!"draft".equals(String.valueOf(op.get("sStatus")))) {
return result(String.valueOf(op.get("sStatus")), "该操作已处理过(" + op.get("sStatus") + ")", op);
}
try {
JsonNode r = erp.updateForm(
str(op.get("sTargetModuleId")), str(op.get("sTargetTable")), str(op.get("sTargetBillId")),
str(op.get("sField")), str(op.get("sNewValue")));
int code = r.path("code").asInt(0);
if (code == 1) {
ops.setStatus(id, "executed", "操作成功");
return result("executed", "已修改:" + op.get("sDescription"), op);
}
String msg = r.path("msg").asText("执行失败");
ops.setStatus(id, "failed", msg);
return result("failed", msg, op);
} catch (Exception e) {
log.warn("confirm op {} failed", id, e);
ops.setStatus(id, "failed", e.getMessage());
return result("failed", "执行异常:" + e.getMessage(), op);
}
}
/** 取消。 */
@PostMapping("/{id}/cancel")
public Map cancel(@PathVariable("id") String id) {
Map op = ops.get(id);
if (op != null && "draft".equals(String.valueOf(op.get("sStatus")))) {
ops.setStatus(id, "cancelled", "用户取消");
}
return result("cancelled", "已取消", op);
}
private Map result(String status, String msg, Map op) {
Map m = new LinkedHashMap<>();
m.put("status", status);
m.put("msg", msg);
if (op != null) {
m.put("opId", op.get("sId"));
m.put("description", op.get("sDescription"));
}
return m;
}
private static String str(Object o) {
return o == null ? null : o.toString();
}
}