+45
@@ -164,6 +164,51 @@ public class InquiryAgentController {
|
|||||||
return Result.OK(out);
|
return Result.OK(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("开始事件异常等待(不改六态)")
|
||||||
|
@PostMapping("/ticket/startEventWait")
|
||||||
|
public Result<Map<String, Object>> startEventWait(@RequestBody Map<String, Object> body,
|
||||||
|
HttpServletRequest http) {
|
||||||
|
if (!authed(http)) {
|
||||||
|
return Result.error(401, "unauthorized");
|
||||||
|
}
|
||||||
|
return Result.OK(workOrderService.startEventWait(
|
||||||
|
firstStr(body, "workOrderNo", "work_order_no"),
|
||||||
|
firstStr(body, "waitKind", "wait_kind")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("清空事件异常等待(不改六态、不清摘要)")
|
||||||
|
@PostMapping("/ticket/clearEventWait")
|
||||||
|
public Result<Map<String, Object>> clearEventWait(@RequestBody Map<String, Object> body,
|
||||||
|
HttpServletRequest http) {
|
||||||
|
if (!authed(http)) {
|
||||||
|
return Result.error(401, "unauthorized");
|
||||||
|
}
|
||||||
|
return Result.OK(workOrderService.clearEventWait(firstStr(body, "workOrderNo", "work_order_no")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("列出未告警的事件异常等待(Worker 巡检)")
|
||||||
|
@PostMapping("/ticket/listEventWaits")
|
||||||
|
public Result<java.util.List<Map<String, Object>>> listEventWaits(
|
||||||
|
@RequestBody(required = false) Map<String, Object> body,
|
||||||
|
HttpServletRequest http) {
|
||||||
|
if (!authed(http)) {
|
||||||
|
return Result.error(401, "unauthorized");
|
||||||
|
}
|
||||||
|
return Result.OK(workOrderService.listEventWaits());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("记下事件异常摘要并标记已告警(不改六态)")
|
||||||
|
@PostMapping("/ticket/recordEventException")
|
||||||
|
public Result<Map<String, Object>> recordEventException(@RequestBody Map<String, Object> body,
|
||||||
|
HttpServletRequest http) {
|
||||||
|
if (!authed(http)) {
|
||||||
|
return Result.error(401, "unauthorized");
|
||||||
|
}
|
||||||
|
return Result.OK(workOrderService.recordEventException(
|
||||||
|
firstStr(body, "workOrderNo", "work_order_no"),
|
||||||
|
firstStr(body, "eventException", "event_exception")));
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation("智能体续办读单(只读,校验发起人)")
|
@ApiOperation("智能体续办读单(只读,校验发起人)")
|
||||||
@PostMapping("/ticket/get")
|
@PostMapping("/ticket/get")
|
||||||
public Result<Map<String, Object>> get(@RequestBody Map<String, Object> body,
|
public Result<Map<String, Object>> get(@RequestBody Map<String, Object> body,
|
||||||
|
|||||||
+4
-1
@@ -24,7 +24,7 @@ import java.util.Map;
|
|||||||
* <p>
|
* <p>
|
||||||
* 只提供全量列表与改小时数;无 add/delete,维度由 SQL 种子固定。
|
* 只提供全量列表与改小时数;无 add/delete,维度由 SQL 种子固定。
|
||||||
* 每条有唯一 timeoutCode(如 sea_sales),智能体单码调用;roleCode 仅为角色维度可重复。
|
* 每条有唯一 timeoutCode(如 sea_sales),智能体单码调用;roleCode 仅为角色维度可重复。
|
||||||
* 本接口供管理后台使用;工单超时判定尚未接入。
|
* 本接口供管理后台使用;智能体按 timeoutCode 读小时数做超时判定。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -81,6 +81,9 @@ public class InquiryResponseTimeoutController
|
|||||||
if (body.getTimeoutHours() == null) {
|
if (body.getTimeoutHours() == null) {
|
||||||
return Result.error("超时小时不能为空");
|
return Result.error("超时小时不能为空");
|
||||||
}
|
}
|
||||||
|
if (body.getTimeoutHours().compareTo(java.math.BigDecimal.ZERO) < 0) {
|
||||||
|
return Result.error("超时小时不能为负数");
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
responseTimeoutService.updateTimeoutHours(body.getId(), body.getTimeoutHours(), currentUsername());
|
responseTimeoutService.updateTimeoutHours(body.getId(), body.getTimeoutHours(), currentUsername());
|
||||||
return Result.OK("已保存");
|
return Result.OK("已保存");
|
||||||
|
|||||||
+3
-3
@@ -19,7 +19,7 @@ import java.util.Date;
|
|||||||
* <p>
|
* <p>
|
||||||
* 维度行由种子固定(运输方式/角色/线路类别/运输类型),后台只允许改 timeoutHours。
|
* 维度行由种子固定(运输方式/角色/线路类别/运输类型),后台只允许改 timeoutHours。
|
||||||
* timeoutCode 每条唯一,供智能体单码查询超时小时;roleCode 仅为角色维度,可重复。
|
* timeoutCode 每条唯一,供智能体单码查询超时小时;roleCode 仅为角色维度,可重复。
|
||||||
* 本表是配置真相;工单超时判定后续再读本表,本期仅 CRUD 小时数。
|
* 本表是配置真相;工单超时判定读 timeoutHours(允许小数,0=不监测)。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@@ -49,8 +49,8 @@ public class InquiryResponseTimeout implements Serializable {
|
|||||||
@ApiModelProperty("运输类型(海运/陆运产品有值,其余空串)")
|
@ApiModelProperty("运输类型(海运/陆运产品有值,其余空串)")
|
||||||
private String transportType;
|
private String transportType;
|
||||||
|
|
||||||
@ApiModelProperty("超时小时,整数≥0")
|
@ApiModelProperty("超时小时,允许小数,0=不监测")
|
||||||
private Integer timeoutHours;
|
private java.math.BigDecimal timeoutHours;
|
||||||
|
|
||||||
@ApiModelProperty("展示排序")
|
@ApiModelProperty("展示排序")
|
||||||
private Integer sortNo;
|
private Integer sortNo;
|
||||||
|
|||||||
+11
@@ -116,6 +116,17 @@ public class InquiryTicket implements Serializable {
|
|||||||
@ApiModelProperty("事件异常摘要")
|
@ApiModelProperty("事件异常摘要")
|
||||||
private String eventException;
|
private String eventException;
|
||||||
|
|
||||||
|
@ApiModelProperty("事件异常当前等待种类")
|
||||||
|
private String eventWaitKind;
|
||||||
|
|
||||||
|
@ApiModelProperty("事件异常当前等待起点")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date eventWaitStartedAt;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前等待是否已告警 0/1")
|
||||||
|
private Integer eventWaitAlerted;
|
||||||
|
|
||||||
@ApiModelProperty("系统异常摘要")
|
@ApiModelProperty("系统异常摘要")
|
||||||
private String systemException;
|
private String systemException;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -15,10 +15,10 @@ public interface IInquiryResponseTimeoutService extends IService<InquiryResponse
|
|||||||
* 仅更新超时小时数;维度字段不可改。
|
* 仅更新超时小时数;维度字段不可改。
|
||||||
*
|
*
|
||||||
* @param id 配置行 id
|
* @param id 配置行 id
|
||||||
* @param timeoutHours 新小时数(≥0)
|
* @param timeoutHours 新小时数(≥0,允许小数,0=不监测)
|
||||||
* @param updateBy 操作人登录名
|
* @param updateBy 操作人登录名
|
||||||
*/
|
*/
|
||||||
void updateTimeoutHours(String id, int timeoutHours, String updateBy);
|
void updateTimeoutHours(String id, java.math.BigDecimal timeoutHours, String updateBy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把陆运产品「普件,…」运输类型对齐产品确认的括号文案。
|
* 把陆运产品「普件,…」运输类型对齐产品确认的括号文案。
|
||||||
|
|||||||
+20
@@ -136,4 +136,24 @@ public interface IInquiryWorkOrderService extends IService<InquiryTicket> {
|
|||||||
* 只改到期行,不加全局锁。
|
* 只改到期行,不加全局锁。
|
||||||
*/
|
*/
|
||||||
java.util.List<java.util.Map<String, Object>> claimDueNegotiate();
|
java.util.List<java.util.Map<String, Object>> claimDueNegotiate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始盯事件异常等待。种类相同不重置起点;种类不同重置并清已告警。不改六态。
|
||||||
|
*/
|
||||||
|
Map<String, Object> startEventWait(String workOrderNo, String waitKind);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空当前事件异常等待三列,不改 eventException 摘要、不改六态。
|
||||||
|
*/
|
||||||
|
Map<String, Object> clearEventWait(String workOrderNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列出未告警且可盯的等待中工单,供 Worker 巡检。
|
||||||
|
*/
|
||||||
|
java.util.List<java.util.Map<String, Object>> listEventWaits();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追加事件异常摘要并标记当前等待已告警。不改六态。
|
||||||
|
*/
|
||||||
|
Map<String, Object> recordEventException(String workOrderNo, String eventException);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -71,8 +71,8 @@ public class InquiryResponseTimeoutServiceImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateTimeoutHours(String id, int timeoutHours, String updateBy) {
|
public void updateTimeoutHours(String id, java.math.BigDecimal timeoutHours, String updateBy) {
|
||||||
if (timeoutHours < 0) {
|
if (timeoutHours == null || timeoutHours.compareTo(java.math.BigDecimal.ZERO) < 0) {
|
||||||
throw new IllegalArgumentException("超时小时不能为负数");
|
throw new IllegalArgumentException("超时小时不能为负数");
|
||||||
}
|
}
|
||||||
InquiryResponseTimeout row = getById(id);
|
InquiryResponseTimeout row = getById(id);
|
||||||
|
|||||||
+200
-1
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jeecg.modules.inquiry.domain.AirGroupActivateRule;
|
import org.jeecg.modules.inquiry.domain.AirGroupActivateRule;
|
||||||
|
import org.jeecg.modules.inquiry.domain.EventExceptionRule;
|
||||||
import org.jeecg.modules.inquiry.domain.TicketStatuses;
|
import org.jeecg.modules.inquiry.domain.TicketStatuses;
|
||||||
import org.jeecg.modules.inquiry.dto.AgentTicketCreateRequest;
|
import org.jeecg.modules.inquiry.dto.AgentTicketCreateRequest;
|
||||||
import org.jeecg.modules.inquiry.dto.TicketAbnormalRequest;
|
import org.jeecg.modules.inquiry.dto.TicketAbnormalRequest;
|
||||||
@@ -101,7 +102,7 @@ public class InquiryWorkOrderServiceImpl extends ServiceImpl<InquiryTicketMapper
|
|||||||
if ("-".equals(filters.get("eventException"))) {
|
if ("-".equals(filters.get("eventException"))) {
|
||||||
qw.and(w -> w.isNull(InquiryTicket::getEventException).or().eq(InquiryTicket::getEventException, "").or().eq(InquiryTicket::getEventException, "-"));
|
qw.and(w -> w.isNull(InquiryTicket::getEventException).or().eq(InquiryTicket::getEventException, "").or().eq(InquiryTicket::getEventException, "-"));
|
||||||
} else {
|
} else {
|
||||||
qw.eq(InquiryTicket::getEventException, filters.get("eventException"));
|
qw.like(InquiryTicket::getEventException, filters.get("eventException"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(filters.get("systemException"))) {
|
if (StringUtils.isNotBlank(filters.get("systemException"))) {
|
||||||
@@ -1405,6 +1406,204 @@ public class InquiryWorkOrderServiceImpl extends ServiceImpl<InquiryTicketMapper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始盯当前等待。可盯状态才写;同种类不重置起点。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> startEventWait(String workOrderNo, String waitKind) {
|
||||||
|
Map<String, Object> out = new LinkedHashMap<>();
|
||||||
|
String no = StringUtils.trimToEmpty(workOrderNo);
|
||||||
|
String kind = StringUtils.trimToEmpty(waitKind);
|
||||||
|
InquiryTicket ticket = findByWorkOrderNo(no);
|
||||||
|
if (ticket == null) {
|
||||||
|
out.put("ok", false);
|
||||||
|
out.put("error", "not_found");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
if (!EventExceptionRule.isWatchable(ticket.getStatus()) || kind.isEmpty()) {
|
||||||
|
out.put("ok", false);
|
||||||
|
out.put("error", "not_watchable");
|
||||||
|
out.put("status", ticket.getStatus());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
Date now = new Date();
|
||||||
|
EventExceptionRule.EventWaitState next = EventExceptionRule.applyStart(
|
||||||
|
ticket.getEventWaitKind(), ticket.getEventWaitStartedAt(),
|
||||||
|
ticket.getEventWaitAlerted(), kind, now);
|
||||||
|
ticket.setEventWaitKind(next.kind);
|
||||||
|
ticket.setEventWaitStartedAt(next.startedAt);
|
||||||
|
ticket.setEventWaitAlerted(next.alerted);
|
||||||
|
ticket.setUpdateTime(now);
|
||||||
|
updateById(ticket);
|
||||||
|
out.put("ok", true);
|
||||||
|
out.put("work_order_no", no);
|
||||||
|
out.put("eventWaitKind", next.kind);
|
||||||
|
out.put("eventWaitAlerted", next.alerted);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> clearEventWait(String workOrderNo) {
|
||||||
|
Map<String, Object> out = new LinkedHashMap<>();
|
||||||
|
InquiryTicket ticket = findByWorkOrderNo(StringUtils.trimToEmpty(workOrderNo));
|
||||||
|
if (ticket == null) {
|
||||||
|
out.put("ok", false);
|
||||||
|
out.put("error", "not_found");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
ticket.setEventWaitKind(null);
|
||||||
|
ticket.setEventWaitStartedAt(null);
|
||||||
|
ticket.setEventWaitAlerted(0);
|
||||||
|
ticket.setUpdateTime(new Date());
|
||||||
|
updateById(ticket);
|
||||||
|
out.put("ok", true);
|
||||||
|
out.put("work_order_no", ticket.getWorkOrderNo());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> listEventWaits() {
|
||||||
|
List<InquiryTicket> rows = list(new LambdaQueryWrapper<InquiryTicket>()
|
||||||
|
.isNotNull(InquiryTicket::getEventWaitKind)
|
||||||
|
.ne(InquiryTicket::getEventWaitKind, "")
|
||||||
|
.and(w -> w.isNull(InquiryTicket::getEventWaitAlerted)
|
||||||
|
.or().eq(InquiryTicket::getEventWaitAlerted, 0))
|
||||||
|
.notIn(InquiryTicket::getStatus,
|
||||||
|
TicketStatuses.DEAL, TicketStatuses.CLOSED, TicketStatuses.HANDOFF));
|
||||||
|
List<Map<String, Object>> out = new ArrayList<>();
|
||||||
|
if (rows == null) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
for (InquiryTicket ticket : rows) {
|
||||||
|
if (ticket == null || !EventExceptionRule.isWatchable(ticket.getStatus())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<String, Object> one = new LinkedHashMap<>();
|
||||||
|
one.put("workOrderNo", ticket.getWorkOrderNo());
|
||||||
|
one.put("work_order_no", ticket.getWorkOrderNo());
|
||||||
|
one.put("status", ticket.getStatus());
|
||||||
|
one.put("businessLine", StringUtils.defaultString(ticket.getBusinessLine()));
|
||||||
|
one.put("business_line", StringUtils.defaultString(ticket.getBusinessLine()));
|
||||||
|
one.put("eventWaitKind", ticket.getEventWaitKind());
|
||||||
|
one.put("event_wait_kind", ticket.getEventWaitKind());
|
||||||
|
if (ticket.getEventWaitStartedAt() != null) {
|
||||||
|
String started = fmt.format(ticket.getEventWaitStartedAt());
|
||||||
|
one.put("eventWaitStartedAt", started);
|
||||||
|
one.put("event_wait_started_at", started);
|
||||||
|
}
|
||||||
|
one.put("salesWecomId", StringUtils.defaultString(ticket.getSalesWecomId()));
|
||||||
|
one.put("sales_wecom_id", StringUtils.defaultString(ticket.getSalesWecomId()));
|
||||||
|
one.put("salesName", StringUtils.defaultString(ticket.getSalesName()));
|
||||||
|
one.put("sales_name", StringUtils.defaultString(ticket.getSalesName()));
|
||||||
|
one.put("collabChatId", StringUtils.defaultString(ticket.getCollabChatId()));
|
||||||
|
one.put("collab_chat_id", StringUtils.defaultString(ticket.getCollabChatId()));
|
||||||
|
List<String> members = parseMemberIds(ticket.getCollabMemberIds());
|
||||||
|
one.put("collabMemberIds", members);
|
||||||
|
one.put("collab_member_ids", members);
|
||||||
|
one.put("eventException", StringUtils.defaultString(ticket.getEventException()));
|
||||||
|
Map<String, String> facts = new LinkedHashMap<>();
|
||||||
|
if (StringUtils.isNotBlank(ticket.getFactsJson())) {
|
||||||
|
JSONObject parsed = JSON.parseObject(ticket.getFactsJson());
|
||||||
|
if (parsed != null) {
|
||||||
|
for (String key : parsed.keySet()) {
|
||||||
|
if (parsed.get(key) != null) {
|
||||||
|
facts.put(key, String.valueOf(parsed.get(key)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
one.put("facts", facts);
|
||||||
|
if (ticket.getNextFollowupAt() != null) {
|
||||||
|
one.put("nextFollowupAt", fmt.format(ticket.getNextFollowupAt()));
|
||||||
|
one.put("next_followup_at", fmt.format(ticket.getNextFollowupAt()));
|
||||||
|
}
|
||||||
|
one.put("watchers", buildEventWatchers(ticket, members));
|
||||||
|
out.add(one);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> recordEventException(String workOrderNo, String eventException) {
|
||||||
|
Map<String, Object> out = new LinkedHashMap<>();
|
||||||
|
InquiryTicket ticket = findByWorkOrderNo(StringUtils.trimToEmpty(workOrderNo));
|
||||||
|
if (ticket == null) {
|
||||||
|
out.put("ok", false);
|
||||||
|
out.put("error", "not_found");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
String type = StringUtils.trimToEmpty(eventException);
|
||||||
|
ticket.setEventException(EventExceptionRule.appendSummary(ticket.getEventException(), type));
|
||||||
|
ticket.setEventWaitAlerted(1);
|
||||||
|
ticket.setUpdateTime(new Date());
|
||||||
|
updateById(ticket);
|
||||||
|
appendLog(ticket, ticket.getStatus(), ticket.getStatus(), "event_exception", "agent", type);
|
||||||
|
out.put("ok", true);
|
||||||
|
out.put("work_order_no", ticket.getWorkOrderNo());
|
||||||
|
out.put("eventException", ticket.getEventException());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Map<String, Object>> buildEventWatchers(InquiryTicket ticket, List<String> memberIds) {
|
||||||
|
List<Map<String, Object>> out = new ArrayList<>();
|
||||||
|
Set<String> seen = new HashSet<>();
|
||||||
|
List<String> ids = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(ticket.getSalesWecomId())) {
|
||||||
|
ids.add(ticket.getSalesWecomId().trim());
|
||||||
|
}
|
||||||
|
if (memberIds != null) {
|
||||||
|
ids.addAll(memberIds);
|
||||||
|
}
|
||||||
|
if (ids.isEmpty()) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
List<InquiryStaffRole> rows = staffRoleMapper.selectList(new LambdaQueryWrapper<InquiryStaffRole>()
|
||||||
|
.in(InquiryStaffRole::getWecomId, ids)
|
||||||
|
.eq(InquiryStaffRole::getStatus, "active"));
|
||||||
|
Map<String, InquiryStaffRole> byId = new HashMap<>();
|
||||||
|
if (rows != null) {
|
||||||
|
for (InquiryStaffRole row : rows) {
|
||||||
|
if (row != null && StringUtils.isNotBlank(row.getWecomId())) {
|
||||||
|
byId.put(row.getWecomId().trim(), row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(ticket.getSalesWecomId())) {
|
||||||
|
String sid = ticket.getSalesWecomId().trim();
|
||||||
|
InquiryStaffRole sales = byId.get(sid);
|
||||||
|
Map<String, Object> one = new LinkedHashMap<>();
|
||||||
|
one.put("wecomId", sid);
|
||||||
|
one.put("name", sales != null ? StringUtils.defaultString(sales.getName())
|
||||||
|
: StringUtils.defaultString(ticket.getSalesName()));
|
||||||
|
one.put("roleCode", sales != null ? StringUtils.defaultString(sales.getRoleCode()) : "sales");
|
||||||
|
one.put("notifyEventException", sales != null && sales.getNotifyEventException() != null
|
||||||
|
? sales.getNotifyEventException() : 0);
|
||||||
|
out.add(one);
|
||||||
|
seen.add(sid);
|
||||||
|
}
|
||||||
|
for (String uid : memberIds == null ? Collections.<String>emptyList() : memberIds) {
|
||||||
|
if (StringUtils.isBlank(uid) || seen.contains(uid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
InquiryStaffRole row = byId.get(uid);
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<String, Object> one = new LinkedHashMap<>();
|
||||||
|
one.put("wecomId", uid);
|
||||||
|
one.put("name", StringUtils.defaultString(row.getName()));
|
||||||
|
one.put("roleCode", StringUtils.defaultString(row.getRoleCode()));
|
||||||
|
one.put("notifyEventException", row.getNotifyEventException() == null ? 0 : row.getNotifyEventException());
|
||||||
|
out.add(one);
|
||||||
|
seen.add(uid);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
private void appendLog(InquiryTicket ticket, String from, String to, String action, String operator, String remark) {
|
private void appendLog(InquiryTicket ticket, String from, String to, String action, String operator, String remark) {
|
||||||
InquiryTicketStatusLog log = new InquiryTicketStatusLog();
|
InquiryTicketStatusLog log = new InquiryTicketStatusLog();
|
||||||
log.setTicketId(ticket.getId());
|
log.setTicketId(ticket.getId());
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
-- 超时小时改为小数,0 表示该规则不监测。
|
||||||
|
-- 仅改 inquiry_robot;幂等说明:重复执行若已是 decimal 会报 1060/1064,可忽略。
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
ALTER TABLE `inq_response_timeout`
|
||||||
|
MODIFY COLUMN `timeout_hours` decimal(10,4) NOT NULL DEFAULT 0 COMMENT '超时小时,允许小数,0=不监测';
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
-- 工单事件异常当前等待:种类、起点、是否已告警。
|
||||||
|
-- 仅改 inquiry_robot。列已存在则跳过(手工执行前请 DESCRIBE inq_ticket)。
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
ALTER TABLE `inq_ticket`
|
||||||
|
ADD COLUMN `event_wait_kind` varchar(32) NULL COMMENT '事件异常当前等待' AFTER `event_exception`,
|
||||||
|
ADD COLUMN `event_wait_started_at` datetime NULL COMMENT '当前等待起点' AFTER `event_wait_kind`,
|
||||||
|
ADD COLUMN `event_wait_alerted` tinyint NULL DEFAULT 0 COMMENT '当前等待是否已告警' AFTER `event_wait_started_at`;
|
||||||
@@ -82,14 +82,14 @@ async function loadList() {
|
|||||||
onMounted(() => loadList());
|
onMounted(() => loadList());
|
||||||
|
|
||||||
function onHoursInput(id, raw) {
|
function onHoursInput(id, raw) {
|
||||||
const n = Math.floor(Number(raw));
|
const n = Number(raw);
|
||||||
draftHours.value[id] = Number.isFinite(n) && n >= 0 ? n : 0;
|
draftHours.value[id] = Number.isFinite(n) && n >= 0 ? n : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function commitHours(row) {
|
async function commitHours(row) {
|
||||||
const hours = draftHours.value[row.id];
|
const hours = draftHours.value[row.id];
|
||||||
if (hours == null || !Number.isFinite(hours) || hours < 0) {
|
if (hours == null || !Number.isFinite(hours) || hours < 0) {
|
||||||
message.warning('超时小时须为 ≥0 的整数');
|
message.warning('超时小时须为 ≥0 的数字,支持小数');
|
||||||
draftHours.value[row.id] = row.timeoutHours;
|
draftHours.value[row.id] = row.timeoutHours;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ async function commitHours(row) {
|
|||||||
<template>
|
<template>
|
||||||
<div class="sys-setting-page">
|
<div class="sys-setting-page">
|
||||||
<div class="toolbar-bar">
|
<div class="toolbar-bar">
|
||||||
<span class="hint">固定规则,仅可改超时小时;编码唯一只读,供智能体调用;失焦或回车保存</span>
|
<span class="hint">固定规则,仅可改超时小时(支持小数,0=不监测);编码唯一只读,供智能体调用;失焦或回车保存</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="loading" style="padding: 24px; color: #94a3b8">加载中…</div>
|
<div v-if="loading" style="padding: 24px; color: #94a3b8">加载中…</div>
|
||||||
@@ -151,7 +151,7 @@ async function commitHours(row) {
|
|||||||
class="field hours-input"
|
class="field hours-input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="1"
|
step="0.01"
|
||||||
:value="draftHours[row.id]"
|
:value="draftHours[row.id]"
|
||||||
:disabled="savingId === row.id"
|
:disabled="savingId === row.id"
|
||||||
@input="onHoursInput(row.id, $event.target.value)"
|
@input="onHoursInput(row.id, $event.target.value)"
|
||||||
|
|||||||
Reference in New Issue
Block a user