From aa710969e00e9d7e56a276066a239f74d5c49310 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 31 三月 2026 21:47:07 +0800
Subject: [PATCH] #
---
src/main/webapp/views/basStationErrLog/basStationErrLog.html | 670 ++++++++++++++
src/main/java/com/zy/asrs/mapper/BasStationErrLogMapper.java | 9
src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java | 21
src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java | 2
src/main/java/com/zy/core/thread/support/StationErrLogSupport.java | 138 +++
src/main/java/com/zy/asrs/entity/WrkAnalysis.java | 8
src/main/webapp/static/js/basStationErrLog/basStationErrLog.js | 1165 +++++++++++++++++++++++++
src/main/resources/i18n/en-US/legacy.properties | 3
src/main/java/com/zy/asrs/controller/WrkMastLogController.java | 16
src/main/java/com/zy/asrs/service/impl/BasStationErrLogServiceImpl.java | 11
src/main/resources/mapper/BasStationErrLogMapper.xml | 29
src/main/java/com/zy/asrs/controller/BasStationErrLogController.java | 129 ++
src/main/java/com/zy/asrs/service/BasStationErrLogService.java | 7
src/main/webapp/static/js/wrkMastLog/wrkMastLog.js | 112 ++
src/main/java/com/zy/core/thread/impl/ZyStationThread.java | 2
src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java | 2
src/main/resources/i18n/zh-CN/legacy.properties | 3
src/main/java/com/zy/core/enums/RedisKeyType.java | 1
src/main/java/com/zy/asrs/entity/BasStationErrLog.java | 211 ++++
src/main/java/com/zy/core/thread/impl/v5/StationV5StatusReader.java | 2
src/main/resources/sql/20260331_add_station_err_log.sql | 172 +++
21 files changed, 2,702 insertions(+), 11 deletions(-)
diff --git a/src/main/java/com/zy/asrs/controller/BasStationErrLogController.java b/src/main/java/com/zy/asrs/controller/BasStationErrLogController.java
new file mode 100644
index 0000000..4307712
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/BasStationErrLogController.java
@@ -0,0 +1,129 @@
+package com.zy.asrs.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.core.annotations.ManagerAuth;
+import com.core.common.BaseRes;
+import com.core.common.Cools;
+import com.core.common.DateUtils;
+import com.core.common.R;
+import com.zy.asrs.entity.BasStationErrLog;
+import com.zy.asrs.service.BasStationErrLogService;
+import com.zy.common.web.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+public class BasStationErrLogController extends BaseController {
+
+ @Autowired
+ private BasStationErrLogService basStationErrLogService;
+
+ @RequestMapping(value = "/basStationErrLog/{id}/auth")
+ @ManagerAuth
+ public R get(@PathVariable("id") String id) {
+ return R.ok(basStationErrLogService.getById(String.valueOf(id)));
+ }
+
+ @RequestMapping(value = "/basStationErrLog/list/auth")
+ @ManagerAuth
+ public R list(@RequestParam(defaultValue = "1") Integer curr,
+ @RequestParam(defaultValue = "10") Integer limit,
+ @RequestParam(required = false) String orderByField,
+ @RequestParam(required = false) String orderByType,
+ @RequestParam(required = false) String condition,
+ @RequestParam Map<String, Object> param) {
+ QueryWrapper<BasStationErrLog> wrapper = new QueryWrapper<>();
+ excludeTrash(param);
+ convert(param, wrapper);
+ allLike(BasStationErrLog.class, param.keySet(), wrapper, condition);
+ if (!Cools.isEmpty(orderByField)) {
+ wrapper.orderBy(true, "asc".equals(orderByType), humpToLine(orderByField));
+ }
+ return R.ok(basStationErrLogService.page(new Page<>(curr, limit), wrapper));
+ }
+
+ private <T> void convert(Map<String, Object> map, QueryWrapper<T> wrapper) {
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
+ String val = String.valueOf(entry.getValue());
+ String column = humpToLine(entry.getKey());
+ if (val.contains(RANGE_TIME_LINK)) {
+ String[] dates = val.split(RANGE_TIME_LINK);
+ wrapper.ge(column, DateUtils.convert(dates[0]));
+ wrapper.le(column, DateUtils.convert(dates[1]));
+ } else {
+ wrapper.like(column, val);
+ }
+ }
+ }
+
+ @RequestMapping(value = "/basStationErrLog/add/auth")
+ @ManagerAuth
+ public R add(BasStationErrLog basStationErrLog) {
+ basStationErrLogService.save(basStationErrLog);
+ return R.ok();
+ }
+
+ @RequestMapping(value = "/basStationErrLog/update/auth")
+ @ManagerAuth
+ public R update(BasStationErrLog basStationErrLog) {
+ if (Cools.isEmpty(basStationErrLog) || basStationErrLog.getId() == null) {
+ return R.error();
+ }
+ basStationErrLogService.updateById(basStationErrLog);
+ return R.ok();
+ }
+
+ @RequestMapping(value = "/basStationErrLog/delete/auth")
+ @ManagerAuth
+ public R delete(@RequestParam(value = "ids[]") Integer[] ids) {
+ for (Integer id : ids) {
+ basStationErrLogService.removeById(id);
+ }
+ return R.ok();
+ }
+
+ @RequestMapping(value = "/basStationErrLog/export/auth")
+ @ManagerAuth
+ public R export(@RequestBody JSONObject param) {
+ QueryWrapper<BasStationErrLog> wrapper = new QueryWrapper<>();
+ List<String> fields = JSONObject.parseArray(param.getJSONArray("fields").toJSONString(), String.class);
+ Map<String, Object> map = excludeTrash(param.getJSONObject("basStationErrLog"));
+ convert(map, wrapper);
+ List<BasStationErrLog> list = basStationErrLogService.list(wrapper);
+ return R.ok(exportSupport(list, fields));
+ }
+
+ @RequestMapping(value = "/basStationErrLogQuery/auth")
+ @ManagerAuth
+ public R query(String condition) {
+ QueryWrapper<BasStationErrLog> wrapper = new QueryWrapper<>();
+ wrapper.like("id", condition);
+ Page<BasStationErrLog> page = basStationErrLogService.page(new Page<>(0, 10), wrapper);
+ List<Map<String, Object>> result = new ArrayList<>();
+ for (BasStationErrLog basStationErrLog : page.getRecords()) {
+ Map<String, Object> map = new HashMap<>();
+ map.put("id", basStationErrLog.getId());
+ map.put("value", basStationErrLog.getId());
+ result.add(map);
+ }
+ return R.ok(result);
+ }
+
+ @RequestMapping(value = "/basStationErrLog/check/column/auth")
+ @ManagerAuth
+ public R query(@RequestBody JSONObject param) {
+ QueryWrapper<BasStationErrLog> wrapper = new QueryWrapper<BasStationErrLog>()
+ .eq(humpToLine(String.valueOf(param.get("key"))), param.get("val"));
+ if (null != basStationErrLogService.getOne(wrapper)) {
+ return R.parse(BaseRes.REPEAT).add(getComment(BasStationErrLog.class, String.valueOf(param.get("key"))));
+ }
+ return R.ok();
+ }
+}
diff --git a/src/main/java/com/zy/asrs/controller/WrkMastLogController.java b/src/main/java/com/zy/asrs/controller/WrkMastLogController.java
index 5d89021..b01b3d7 100644
--- a/src/main/java/com/zy/asrs/controller/WrkMastLogController.java
+++ b/src/main/java/com/zy/asrs/controller/WrkMastLogController.java
@@ -17,12 +17,22 @@
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
@RestController
public class WrkMastLogController extends BaseController {
+
+ private static final Set<String> EXACT_SEARCH_COLUMNS = new HashSet<>(Arrays.asList(
+ "wrk_sts",
+ "io_type",
+ "sta_no",
+ "source_sta_no"
+ ));
@Autowired
private WrkMastLogService wrkMastLogService;
@@ -65,10 +75,10 @@
wrapper.ge(column, DateUtils.convert(dates[0]));
wrapper.le(column, DateUtils.convert(dates[1]));
} else {
- if ("manu_type".equals(column)) {
- wrapper.like(column, val);
- } else {
+ if (EXACT_SEARCH_COLUMNS.contains(column)) {
wrapper.eq(column, val);
+ } else {
+ wrapper.like(column, val);
}
}
}
diff --git a/src/main/java/com/zy/asrs/entity/BasStationErrLog.java b/src/main/java/com/zy/asrs/entity/BasStationErrLog.java
new file mode 100644
index 0000000..d315e3f
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/BasStationErrLog.java
@@ -0,0 +1,211 @@
+package com.zy.asrs.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.core.common.Cools;
+import com.core.common.SpringUtils;
+import com.zy.asrs.service.BasStationService;
+import com.zy.asrs.service.BasWrkIotypeService;
+import com.zy.asrs.service.BasWrkStatusService;
+import com.zy.system.entity.User;
+import com.zy.system.service.UserService;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Data
+@TableName("asr_bas_station_err_log")
+public class BasStationErrLog implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value = "缂栧彿")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "宸ヤ綔鍙�")
+ @TableField("wrk_no")
+ private Integer wrkNo;
+
+ @ApiModelProperty(value = "鍙戠敓鏃堕棿")
+ @TableField("start_time")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date startTime;
+
+ @ApiModelProperty(value = "缁撴潫鏃堕棿")
+ @TableField("end_time")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date endTime;
+
+ @ApiModelProperty(value = "宸ヤ綔鐘舵��")
+ @TableField("wrk_sts")
+ private Long wrkSts;
+
+ @ApiModelProperty(value = "鍏ュ嚭搴撶被鍨�")
+ @TableField("io_type")
+ private Integer ioType;
+
+ @ApiModelProperty(value = "绔欑偣鍙�")
+ @TableField("station_id")
+ private Integer stationId;
+
+ @ApiModelProperty(value = "鐩爣搴撲綅")
+ @TableField("loc_no")
+ private String locNo;
+
+ @ApiModelProperty(value = "鐩爣绔�")
+ @TableField("sta_no")
+ private Integer staNo;
+
+ @ApiModelProperty(value = "婧愮珯")
+ @TableField("source_sta_no")
+ private Integer sourceStaNo;
+
+ @ApiModelProperty(value = "婧愬簱浣�")
+ @TableField("source_loc_no")
+ private String sourceLocNo;
+
+ @ApiModelProperty(value = "鏉$爜")
+ private String barcode;
+
+ @ApiModelProperty(value = "寮傚父鐮�")
+ @TableField("err_code")
+ private Integer errCode;
+
+ @ApiModelProperty(value = "寮傚父")
+ private String error;
+
+ @ApiModelProperty(value = "寮傚父鎯呭喌 1: 鏈鐞� 2: 宸蹭慨澶�")
+ private Integer status;
+
+ @ApiModelProperty(value = "娣诲姞鏃堕棿")
+ @TableField("create_time")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ @ApiModelProperty(value = "娣诲姞浜哄憳")
+ @TableField("create_by")
+ private Long createBy;
+
+ @ApiModelProperty(value = "淇敼鏃堕棿")
+ @TableField("update_time")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date updateTime;
+
+ @ApiModelProperty(value = "淇敼浜哄憳")
+ @TableField("update_by")
+ private Long updateBy;
+
+ @ApiModelProperty(value = "澶囨敞")
+ private String memo;
+
+ @ApiModelProperty(value = "绯荤粺鐘舵�佹暟鎹�")
+ @TableField("system_status")
+ private String systemStatus;
+
+ public String getStartTime$() {
+ return formatDate(startTime);
+ }
+
+ public String getEndTime$() {
+ return formatDate(endTime);
+ }
+
+ public String getWrkSts$() {
+ if (wrkSts == null) {
+ return null;
+ }
+ BasWrkStatusService service = SpringUtils.getBean(BasWrkStatusService.class);
+ if (service == null) {
+ return String.valueOf(wrkSts);
+ }
+ BasWrkStatus basWrkStatus = service.getById(wrkSts);
+ return basWrkStatus == null ? String.valueOf(wrkSts) : basWrkStatus.getWrkDesc();
+ }
+
+ public String getIoType$() {
+ if (ioType == null) {
+ return null;
+ }
+ BasWrkIotypeService service = SpringUtils.getBean(BasWrkIotypeService.class);
+ if (service == null) {
+ return String.valueOf(ioType);
+ }
+ BasWrkIotype basWrkIotype = service.getById(ioType);
+ return basWrkIotype == null ? String.valueOf(ioType) : basWrkIotype.getIoDesc();
+ }
+
+ public String getStationLabel$() {
+ if (stationId == null) {
+ return null;
+ }
+ BasStationService service = SpringUtils.getBean(BasStationService.class);
+ if (service == null) {
+ return String.valueOf(stationId);
+ }
+ BasStation basStation = service.getById(stationId);
+ if (basStation == null || Cools.isEmpty(basStation.getStationAlias())) {
+ return String.valueOf(stationId);
+ }
+ return stationId + " - " + basStation.getStationAlias();
+ }
+
+ public String getStatus$() {
+ if (status == null) {
+ return null;
+ }
+ switch (status) {
+ case 1:
+ return "鏈鐞�";
+ case 2:
+ return "宸蹭慨澶�";
+ default:
+ return String.valueOf(status);
+ }
+ }
+
+ public String getCreateTime$() {
+ return formatDate(createTime);
+ }
+
+ public String getCreateBy$() {
+ if (createBy == null) {
+ return null;
+ }
+ UserService service = SpringUtils.getBean(UserService.class);
+ if (service == null) {
+ return String.valueOf(createBy);
+ }
+ User user = service.getById(createBy);
+ return user == null ? String.valueOf(createBy) : String.valueOf(user.getId());
+ }
+
+ public String getUpdateTime$() {
+ return formatDate(updateTime);
+ }
+
+ public String getUpdateBy$() {
+ if (updateBy == null) {
+ return null;
+ }
+ UserService service = SpringUtils.getBean(UserService.class);
+ if (service == null) {
+ return String.valueOf(updateBy);
+ }
+ User user = service.getById(updateBy);
+ return user == null ? String.valueOf(updateBy) : String.valueOf(user.getId());
+ }
+
+ private String formatDate(Date value) {
+ if (Cools.isEmpty(value)) {
+ return "";
+ }
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value);
+ }
+}
diff --git a/src/main/java/com/zy/asrs/entity/WrkAnalysis.java b/src/main/java/com/zy/asrs/entity/WrkAnalysis.java
index e17b96b..df43106 100644
--- a/src/main/java/com/zy/asrs/entity/WrkAnalysis.java
+++ b/src/main/java/com/zy/asrs/entity/WrkAnalysis.java
@@ -139,6 +139,14 @@
@TableField("rgv_fault_duration_ms")
private Long rgvFaultDurationMs;
+ @ApiModelProperty(value = "杈撻�佺珯鐐规晠闅滄鏁�")
+ @TableField("station_fault_count")
+ private Integer stationFaultCount;
+
+ @ApiModelProperty(value = "杈撻�佺珯鐐规晠闅滆�楁椂姣")
+ @TableField("station_fault_duration_ms")
+ private Long stationFaultDurationMs;
+
@ApiModelProperty(value = "鏁版嵁瀹屾暣鎬�")
@TableField("metric_completeness")
private String metricCompleteness;
diff --git a/src/main/java/com/zy/asrs/mapper/BasStationErrLogMapper.java b/src/main/java/com/zy/asrs/mapper/BasStationErrLogMapper.java
new file mode 100644
index 0000000..7a09f39
--- /dev/null
+++ b/src/main/java/com/zy/asrs/mapper/BasStationErrLogMapper.java
@@ -0,0 +1,9 @@
+package com.zy.asrs.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zy.asrs.entity.BasStationErrLog;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface BasStationErrLogMapper extends BaseMapper<BasStationErrLog> {
+}
diff --git a/src/main/java/com/zy/asrs/service/BasStationErrLogService.java b/src/main/java/com/zy/asrs/service/BasStationErrLogService.java
new file mode 100644
index 0000000..7c68e39
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/BasStationErrLogService.java
@@ -0,0 +1,7 @@
+package com.zy.asrs.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zy.asrs.entity.BasStationErrLog;
+
+public interface BasStationErrLogService extends IService<BasStationErrLog> {
+}
diff --git a/src/main/java/com/zy/asrs/service/impl/BasStationErrLogServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/BasStationErrLogServiceImpl.java
new file mode 100644
index 0000000..9610b18
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/impl/BasStationErrLogServiceImpl.java
@@ -0,0 +1,11 @@
+package com.zy.asrs.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zy.asrs.entity.BasStationErrLog;
+import com.zy.asrs.mapper.BasStationErrLogMapper;
+import com.zy.asrs.service.BasStationErrLogService;
+import org.springframework.stereotype.Service;
+
+@Service("basStationErrLogService")
+public class BasStationErrLogServiceImpl extends ServiceImpl<BasStationErrLogMapper, BasStationErrLog> implements BasStationErrLogService {
+}
diff --git a/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
index 6bbaac2..da83645 100644
--- a/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
@@ -46,6 +46,7 @@
private final BasCrnpErrLogService basCrnpErrLogService;
private final BasDualCrnpErrLogService basDualCrnpErrLogService;
private final BasRgvErrLogService basRgvErrLogService;
+ private final BasStationErrLogService basStationErrLogService;
private final BasStationService basStationService;
private final BasWrkStatusService basWrkStatusService;
private final WrkMastService wrkMastService;
@@ -54,6 +55,7 @@
BasCrnpErrLogService basCrnpErrLogService,
BasDualCrnpErrLogService basDualCrnpErrLogService,
BasRgvErrLogService basRgvErrLogService,
+ BasStationErrLogService basStationErrLogService,
BasStationService basStationService,
BasWrkStatusService basWrkStatusService,
WrkMastService wrkMastService) {
@@ -61,6 +63,7 @@
this.basCrnpErrLogService = basCrnpErrLogService;
this.basDualCrnpErrLogService = basDualCrnpErrLogService;
this.basRgvErrLogService = basRgvErrLogService;
+ this.basStationErrLogService = basStationErrLogService;
this.basStationService = basStationService;
this.basWrkStatusService = basWrkStatusService;
this.wrkMastService = wrkMastService;
@@ -89,6 +92,8 @@
entity.setDualCrnFaultDurationMs(defaultLong(entity.getDualCrnFaultDurationMs()));
entity.setRgvFaultCount(defaultInt(entity.getRgvFaultCount()));
entity.setRgvFaultDurationMs(defaultLong(entity.getRgvFaultDurationMs()));
+ entity.setStationFaultCount(defaultInt(entity.getStationFaultCount()));
+ entity.setStationFaultDurationMs(defaultLong(entity.getStationFaultDurationMs()));
entity.setMetricCompleteness(METRIC_PARTIAL);
entity.setUpdateTime(now);
this.saveOrUpdate(entity);
@@ -243,6 +248,8 @@
entity.setDualCrnFaultDurationMs(faultSummary.dualDurationMs);
entity.setRgvFaultCount(faultSummary.rgvCount);
entity.setRgvFaultDurationMs(faultSummary.rgvDurationMs);
+ entity.setStationFaultCount(faultSummary.stationCount);
+ entity.setStationFaultDurationMs(faultSummary.stationDurationMs);
entity.setMetricCompleteness(resolveMetricCompleteness(wrkMast, entity));
entity.setUpdateTime(time);
this.saveOrUpdate(entity);
@@ -610,6 +617,7 @@
addDeviceFaultDuration(durationMap, "鍗曞爢鍨涙満", item.getCrnNo(), item.getCrnFaultDurationMs());
addDeviceFaultDuration(durationMap, "鍙屽伐浣嶅爢鍨涙満", item.getDualCrnNo(), item.getDualCrnFaultDurationMs());
addDeviceFaultDuration(durationMap, "RGV", item.getRgvNo(), item.getRgvFaultDurationMs());
+ addDeviceFaultDuration(durationMap, "杈撻�佺珯鐐�", null, item.getStationFaultDurationMs());
}
List<Map<String, Object>> result = new ArrayList<>();
durationMap.forEach((name, durationMs) -> result.add(slice(name, durationMs)));
@@ -680,6 +688,7 @@
target.put("crnFaultDurationMs", analysis == null ? 0L : defaultLong(analysis.getCrnFaultDurationMs()));
target.put("dualCrnFaultDurationMs", analysis == null ? 0L : defaultLong(analysis.getDualCrnFaultDurationMs()));
target.put("rgvFaultDurationMs", analysis == null ? 0L : defaultLong(analysis.getRgvFaultDurationMs()));
+ target.put("stationFaultDurationMs", analysis == null ? 0L : defaultLong(analysis.getStationFaultDurationMs()));
target.put("metricCompleteness", analysis == null ? METRIC_PARTIAL : analysis.getMetricCompleteness());
}
@@ -691,14 +700,17 @@
List<BasCrnpErrLog> crnList = basCrnpErrLogService.list(new QueryWrapper<BasCrnpErrLog>().eq("wrk_no", wrkNo));
List<BasDualCrnpErrLog> dualList = basDualCrnpErrLogService.list(new QueryWrapper<BasDualCrnpErrLog>().eq("wrk_no", wrkNo));
List<BasRgvErrLog> rgvList = basRgvErrLogService.list(new QueryWrapper<BasRgvErrLog>().eq("task_no", wrkNo));
+ List<BasStationErrLog> stationList = basStationErrLogService.list(new QueryWrapper<BasStationErrLog>().eq("wrk_no", wrkNo));
summary.crnCount = crnList.size();
summary.crnDurationMs = durationMs(crnList, finishTime);
summary.dualCount = dualList.size();
summary.dualDurationMs = durationMs(dualList, finishTime);
summary.rgvCount = rgvList.size();
summary.rgvDurationMs = durationMs(rgvList, finishTime);
- summary.totalCount = summary.crnCount + summary.dualCount + summary.rgvCount;
- summary.totalDurationMs = summary.crnDurationMs + summary.dualDurationMs + summary.rgvDurationMs;
+ summary.stationCount = stationList.size();
+ summary.stationDurationMs = durationMs(stationList, finishTime);
+ summary.totalCount = summary.crnCount + summary.dualCount + summary.rgvCount + summary.stationCount;
+ summary.totalDurationMs = summary.crnDurationMs + summary.dualDurationMs + summary.rgvDurationMs + summary.stationDurationMs;
summary.hasFault = summary.totalCount > 0 ? 1 : 0;
return summary;
}
@@ -717,6 +729,9 @@
} else if (item instanceof BasRgvErrLog) {
startTime = ((BasRgvErrLog) item).getStartTime();
endTime = ((BasRgvErrLog) item).getEndTime();
+ } else if (item instanceof BasStationErrLog) {
+ startTime = ((BasStationErrLog) item).getStartTime();
+ endTime = ((BasStationErrLog) item).getEndTime();
}
if (startTime == null) {
continue;
@@ -977,6 +992,8 @@
private long dualDurationMs;
private int rgvCount;
private long rgvDurationMs;
+ private int stationCount;
+ private long stationDurationMs;
}
private static class BucketAccumulator {
diff --git a/src/main/java/com/zy/core/enums/RedisKeyType.java b/src/main/java/com/zy/core/enums/RedisKeyType.java
index fef34ca..cd1b8e3 100644
--- a/src/main/java/com/zy/core/enums/RedisKeyType.java
+++ b/src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -24,6 +24,7 @@
DEVICE_ERR_ACTIVE_RGV("device_err_active_rgv_"),
DEVICE_ERR_ACTIVE_CRN("device_err_active_crn_"),
DEVICE_ERR_ACTIVE_DUAL_CRN("device_err_active_dual_crn_"),
+ DEVICE_ERR_ACTIVE_STATION("device_err_active_station_"),
DEVICE_STATION_MOVE_RESET("device_station_move_reset_"),
CRN_SEND_COMMAND_LOCK("crn_send_command_lock_"),
diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationThread.java b/src/main/java/com/zy/core/thread/impl/ZyStationThread.java
index a4a1e98..769a168 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationThread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationThread.java
@@ -9,6 +9,7 @@
import com.zy.core.network.DeviceConnectPool;
import com.zy.core.thread.StationThread;
import com.zy.core.thread.support.RecentStationArrivalTracker;
+import com.zy.core.thread.support.StationErrLogSupport;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
@@ -160,6 +161,7 @@
}
OutputQueue.DEVP.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛",DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
+ StationErrLogSupport.sync(deviceConfig, redisUtil, statusList);
if (System.currentTimeMillis() - deviceDataLogTime > deviceLogCollectTime) {
//淇濆瓨鏁版嵁璁板綍
diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java
index 6accb28..5abc04a 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java
@@ -31,6 +31,7 @@
import com.zy.core.network.ZyStationConnectDriver;
import com.zy.core.network.entity.ZyStationStatusEntity;
import com.zy.core.thread.support.RecentStationArrivalTracker;
+import com.zy.core.thread.support.StationErrLogSupport;
import com.zy.core.utils.DeviceLogRedisKeyBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -165,6 +166,7 @@
}
OutputQueue.DEVP.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛", DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
+ StationErrLogSupport.sync(deviceConfig, redisUtil, statusList);
if (System.currentTimeMillis() - deviceDataLogTime > deviceLogCollectTime) {
DeviceDataLog deviceDataLog = new DeviceDataLog();
diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
index 46cb90d..a08a715 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
@@ -32,6 +32,7 @@
import com.zy.core.network.entity.ZyStationStatusEntity;
import com.zy.core.thread.impl.v5.StationMoveSegmentExecutor;
import com.zy.core.thread.support.RecentStationArrivalTracker;
+import com.zy.core.thread.support.StationErrLogSupport;
import com.zy.core.utils.DeviceLogRedisKeyBuilder;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
@@ -174,6 +175,7 @@
}
OutputQueue.DEVP.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛", DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
+ StationErrLogSupport.sync(deviceConfig, redisUtil, statusList);
if (System.currentTimeMillis() - deviceDataLogTime > deviceLogCollectTime) {
DeviceDataLog deviceDataLog = new DeviceDataLog();
diff --git a/src/main/java/com/zy/core/thread/impl/v5/StationV5StatusReader.java b/src/main/java/com/zy/core/thread/impl/v5/StationV5StatusReader.java
index 72f2b96..3d532e2 100644
--- a/src/main/java/com/zy/core/thread/impl/v5/StationV5StatusReader.java
+++ b/src/main/java/com/zy/core/thread/impl/v5/StationV5StatusReader.java
@@ -18,6 +18,7 @@
import com.zy.core.network.ZyStationConnectDriver;
import com.zy.core.network.entity.ZyStationStatusEntity;
import com.zy.core.thread.support.RecentStationArrivalTracker;
+import com.zy.core.thread.support.StationErrLogSupport;
import com.zy.core.utils.DeviceLogRedisKeyBuilder;
import java.text.MessageFormat;
@@ -108,6 +109,7 @@
OutputQueue.DEVP.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛",
DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
+ StationErrLogSupport.sync(deviceConfig, redisUtil, statusList);
if (System.currentTimeMillis() - deviceDataLogTime > deviceLogCollectTime) {
DeviceDataLog deviceDataLog = new DeviceDataLog();
diff --git a/src/main/java/com/zy/core/thread/support/StationErrLogSupport.java b/src/main/java/com/zy/core/thread/support/StationErrLogSupport.java
new file mode 100644
index 0000000..8d34431
--- /dev/null
+++ b/src/main/java/com/zy/core/thread/support/StationErrLogSupport.java
@@ -0,0 +1,138 @@
+package com.zy.core.thread.support;
+
+import com.alibaba.fastjson.JSONObject;
+import com.core.common.Cools;
+import com.core.common.SpringUtils;
+import com.zy.asrs.entity.BasStationErrLog;
+import com.zy.asrs.entity.DeviceConfig;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.service.BasStationErrLogService;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.common.utils.RedisUtil;
+import com.zy.core.enums.RedisKeyType;
+import com.zy.core.model.protocol.StationProtocol;
+
+import java.util.Date;
+import java.util.List;
+
+public final class StationErrLogSupport {
+
+ private StationErrLogSupport() {
+ }
+
+ public static void sync(DeviceConfig deviceConfig, RedisUtil redisUtil, List<StationProtocol> statusList) {
+ if (redisUtil == null || statusList == null || statusList.isEmpty()) {
+ return;
+ }
+ try {
+ BasStationErrLogService errLogService = SpringUtils.getBean(BasStationErrLogService.class);
+ if (errLogService == null) {
+ return;
+ }
+ WrkMastService wrkMastService = null;
+ try {
+ wrkMastService = SpringUtils.getBean(WrkMastService.class);
+ } catch (Exception ignore) {
+ }
+ for (StationProtocol stationProtocol : statusList) {
+ syncOne(deviceConfig, redisUtil, errLogService, wrkMastService, stationProtocol);
+ }
+ } catch (Exception ignore) {
+ }
+ }
+
+ private static void syncOne(DeviceConfig deviceConfig,
+ RedisUtil redisUtil,
+ BasStationErrLogService errLogService,
+ WrkMastService wrkMastService,
+ StationProtocol stationProtocol) {
+ if (stationProtocol == null || stationProtocol.getStationId() == null) {
+ return;
+ }
+ String errFlagKey = RedisKeyType.DEVICE_ERR_ACTIVE_STATION.key + stationProtocol.getStationId();
+ Object active = redisUtil.get(errFlagKey);
+ Date now = new Date();
+ if (hasError(stationProtocol)) {
+ if (active != null) {
+ return;
+ }
+ BasStationErrLog log = new BasStationErrLog();
+ Integer wrkNo = stationProtocol.getTaskNo();
+ if (wrkNo != null && wrkNo > 0) {
+ log.setWrkNo(wrkNo);
+ }
+ log.setStartTime(now);
+ log.setStationId(stationProtocol.getStationId());
+ log.setStaNo(stationProtocol.getTargetStaNo());
+ log.setBarcode(stationProtocol.getBarcode());
+ log.setErrCode(normalizeErrCode(stationProtocol.getError()));
+ log.setError(resolveError(stationProtocol));
+ log.setStatus(1);
+ log.setCreateTime(now);
+ log.setSystemStatus(buildSystemStatus(deviceConfig, stationProtocol));
+ fillWorkContext(log, wrkMastService, wrkNo);
+ errLogService.save(log);
+ if (log.getId() != null) {
+ redisUtil.set(errFlagKey, log.getId(), 60 * 60 * 24);
+ }
+ return;
+ }
+
+ if (active == null) {
+ return;
+ }
+ BasStationErrLog update = new BasStationErrLog();
+ update.setId(Long.valueOf(String.valueOf(active)));
+ update.setEndTime(now);
+ update.setStatus(2);
+ update.setUpdateTime(now);
+ errLogService.updateById(update);
+ redisUtil.del(errFlagKey);
+ }
+
+ private static void fillWorkContext(BasStationErrLog log, WrkMastService wrkMastService, Integer wrkNo) {
+ if (wrkMastService == null || wrkNo == null || wrkNo <= 0) {
+ return;
+ }
+ WrkMast wrkMast = wrkMastService.selectByWorkNo(wrkNo);
+ if (wrkMast == null) {
+ return;
+ }
+ log.setWrkSts(wrkMast.getWrkSts());
+ log.setIoType(wrkMast.getIoType());
+ log.setLocNo(wrkMast.getLocNo());
+ log.setSourceStaNo(wrkMast.getSourceStaNo());
+ log.setSourceLocNo(wrkMast.getSourceLocNo());
+ if (log.getStaNo() == null) {
+ log.setStaNo(wrkMast.getStaNo());
+ }
+ if (Cools.isEmpty(log.getBarcode())) {
+ log.setBarcode(wrkMast.getBarcode());
+ }
+ }
+
+ private static boolean hasError(StationProtocol stationProtocol) {
+ return normalizeErrCode(stationProtocol.getError()) != null || !Cools.isEmpty(stationProtocol.getErrorMsg());
+ }
+
+ private static Integer normalizeErrCode(Integer errCode) {
+ return errCode != null && errCode > 0 ? errCode : null;
+ }
+
+ private static String resolveError(StationProtocol stationProtocol) {
+ if (!Cools.isEmpty(stationProtocol.getErrorMsg())) {
+ return stationProtocol.getErrorMsg();
+ }
+ Integer errCode = normalizeErrCode(stationProtocol.getError());
+ return errCode == null ? null : "绔欑偣鎶ヨ";
+ }
+
+ private static String buildSystemStatus(DeviceConfig deviceConfig, StationProtocol stationProtocol) {
+ JSONObject snapshot = new JSONObject();
+ if (deviceConfig != null) {
+ snapshot.put("deviceNo", deviceConfig.getDeviceNo());
+ }
+ snapshot.put("stationProtocol", stationProtocol);
+ return snapshot.toJSONString();
+ }
+}
diff --git a/src/main/resources/i18n/en-US/legacy.properties b/src/main/resources/i18n/en-US/legacy.properties
index 5c33986..68e990a 100644
--- a/src/main/resources/i18n/en-US/legacy.properties
+++ b/src/main/resources/i18n/en-US/legacy.properties
@@ -1028,6 +1028,7 @@
鍙屽伐浣嶅爢鍨涙満寮傚父鏃ュ織=Dual-station Crane Error Log
RGV鍛戒护鏃ュ織=RGV Command Log
RGV寮傚父鏃ュ織=RGV Error Log
+杈撻�佺珯鐐瑰紓甯告棩蹇�=Conveyor Station Error Log
杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=Conveyor Station Command Log
绯荤粺閰嶇疆=System Configuration
鏂板涓夋柟鎺ュ彛缁熻=Add Third-party API Statistics
@@ -1076,6 +1077,8 @@
淇敼RGV鍛戒护鏃ュ織=Edit RGV Command Log
鏂板RGV寮傚父鏃ュ織=Add RGV Error Log
淇敼RGV寮傚父鏃ュ織=Edit RGV Error Log
+鏂板杈撻�佺珯鐐瑰紓甯告棩蹇�=Add Conveyor Station Error Log
+淇敼杈撻�佺珯鐐瑰紓甯告棩蹇�=Edit Conveyor Station Error Log
鏂板杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=Add Conveyor Station Command Log
淇敼杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=Edit Conveyor Station Command Log
鏂板绯荤粺閰嶇疆=Add System Configuration
diff --git a/src/main/resources/i18n/zh-CN/legacy.properties b/src/main/resources/i18n/zh-CN/legacy.properties
index ff78c24..fd1c429 100644
--- a/src/main/resources/i18n/zh-CN/legacy.properties
+++ b/src/main/resources/i18n/zh-CN/legacy.properties
@@ -108,6 +108,7 @@
鍙屽伐浣嶅爢鍨涙満寮傚父鏃ュ織=鍙屽伐浣嶅爢鍨涙満寮傚父鏃ュ織
RGV鍛戒护鏃ュ織=RGV鍛戒护鏃ュ織
RGV寮傚父鏃ュ織=RGV寮傚父鏃ュ織
+杈撻�佺珯鐐瑰紓甯告棩蹇�=杈撻�佺珯鐐瑰紓甯告棩蹇�
杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=杈撻�佺珯鐐瑰懡浠ゆ棩蹇�
绯荤粺閰嶇疆=绯荤粺閰嶇疆
鏂板涓夋柟鎺ュ彛缁熻=鏂板涓夋柟鎺ュ彛缁熻
@@ -156,6 +157,8 @@
淇敼RGV鍛戒护鏃ュ織=淇敼RGV鍛戒护鏃ュ織
鏂板RGV寮傚父鏃ュ織=鏂板RGV寮傚父鏃ュ織
淇敼RGV寮傚父鏃ュ織=淇敼RGV寮傚父鏃ュ織
+鏂板杈撻�佺珯鐐瑰紓甯告棩蹇�=鏂板杈撻�佺珯鐐瑰紓甯告棩蹇�
+淇敼杈撻�佺珯鐐瑰紓甯告棩蹇�=淇敼杈撻�佺珯鐐瑰紓甯告棩蹇�
鏂板杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=鏂板杈撻�佺珯鐐瑰懡浠ゆ棩蹇�
淇敼杈撻�佺珯鐐瑰懡浠ゆ棩蹇�=淇敼杈撻�佺珯鐐瑰懡浠ゆ棩蹇�
鏂板绯荤粺閰嶇疆=鏂板绯荤粺閰嶇疆
diff --git a/src/main/resources/mapper/BasStationErrLogMapper.xml b/src/main/resources/mapper/BasStationErrLogMapper.xml
new file mode 100644
index 0000000..697312b
--- /dev/null
+++ b/src/main/resources/mapper/BasStationErrLogMapper.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zy.asrs.mapper.BasStationErrLogMapper">
+
+ <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BasStationErrLog">
+ <id column="id" property="id" />
+ <result column="wrk_no" property="wrkNo" />
+ <result column="start_time" property="startTime" />
+ <result column="end_time" property="endTime" />
+ <result column="wrk_sts" property="wrkSts" />
+ <result column="io_type" property="ioType" />
+ <result column="station_id" property="stationId" />
+ <result column="loc_no" property="locNo" />
+ <result column="sta_no" property="staNo" />
+ <result column="source_sta_no" property="sourceStaNo" />
+ <result column="source_loc_no" property="sourceLocNo" />
+ <result column="barcode" property="barcode" />
+ <result column="err_code" property="errCode" />
+ <result column="error" property="error" />
+ <result column="status" property="status" />
+ <result column="create_time" property="createTime" />
+ <result column="create_by" property="createBy" />
+ <result column="update_time" property="updateTime" />
+ <result column="update_by" property="updateBy" />
+ <result column="memo" property="memo" />
+ <result column="system_status" property="systemStatus" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/sql/20260331_add_station_err_log.sql b/src/main/resources/sql/20260331_add_station_err_log.sql
new file mode 100644
index 0000000..be5f1fd
--- /dev/null
+++ b/src/main/resources/sql/20260331_add_station_err_log.sql
@@ -0,0 +1,172 @@
+CREATE TABLE IF NOT EXISTS `asr_bas_station_err_log` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+ `wrk_no` int DEFAULT NULL COMMENT '宸ヤ綔鍙�',
+ `start_time` datetime DEFAULT NULL COMMENT '鍙戠敓鏃堕棿',
+ `end_time` datetime DEFAULT NULL COMMENT '缁撴潫鏃堕棿',
+ `wrk_sts` bigint DEFAULT NULL COMMENT '宸ヤ綔鐘舵��',
+ `io_type` int DEFAULT NULL COMMENT '鍏ュ嚭搴撶被鍨�',
+ `station_id` int DEFAULT NULL COMMENT '绔欑偣鍙�',
+ `loc_no` varchar(64) DEFAULT NULL COMMENT '鐩爣搴撲綅',
+ `sta_no` int DEFAULT NULL COMMENT '鐩爣绔�',
+ `source_sta_no` int DEFAULT NULL COMMENT '婧愮珯',
+ `source_loc_no` varchar(64) DEFAULT NULL COMMENT '婧愬簱浣�',
+ `barcode` varchar(128) DEFAULT NULL COMMENT '鏉$爜',
+ `err_code` int DEFAULT NULL COMMENT '寮傚父鐮�',
+ `error` text COMMENT '寮傚父鎻忚堪',
+ `status` int DEFAULT NULL COMMENT '寮傚父鎯呭喌 1鏈鐞� 2宸蹭慨澶�',
+ `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+ `create_by` bigint DEFAULT NULL COMMENT '鍒涘缓浜�',
+ `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+ `update_by` bigint DEFAULT NULL COMMENT '鏇存柊浜�',
+ `memo` varchar(255) DEFAULT NULL COMMENT '澶囨敞',
+ `system_status` longtext COMMENT '绯荤粺鐘舵�佸揩鐓�',
+ PRIMARY KEY (`id`),
+ KEY `idx_station_err_log_wrk_no` (`wrk_no`),
+ KEY `idx_station_err_log_station_id` (`station_id`),
+ KEY `idx_station_err_log_status` (`status`),
+ KEY `idx_station_err_log_start_time` (`start_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='杈撻�佺珯鐐瑰紓甯告棩蹇�';
+
+SET @wrk_analysis_table_exists := (
+ SELECT COUNT(*)
+ FROM `information_schema`.`TABLES`
+ WHERE `TABLE_SCHEMA` = DATABASE()
+ AND `TABLE_NAME` = 'asr_wrk_analysis'
+);
+
+SET @station_fault_count_exists := (
+ SELECT COUNT(*)
+ FROM `information_schema`.`COLUMNS`
+ WHERE `TABLE_SCHEMA` = DATABASE()
+ AND `TABLE_NAME` = 'asr_wrk_analysis'
+ AND `COLUMN_NAME` = 'station_fault_count'
+);
+
+SET @station_fault_duration_exists := (
+ SELECT COUNT(*)
+ FROM `information_schema`.`COLUMNS`
+ WHERE `TABLE_SCHEMA` = DATABASE()
+ AND `TABLE_NAME` = 'asr_wrk_analysis'
+ AND `COLUMN_NAME` = 'station_fault_duration_ms'
+);
+
+SET @sql_station_fault_count := IF(
+ @wrk_analysis_table_exists = 1 AND @station_fault_count_exists = 0,
+ 'ALTER TABLE `asr_wrk_analysis` ADD COLUMN `station_fault_count` int DEFAULT 0 COMMENT ''杈撻�佺珯鐐规晠闅滄鏁�'' AFTER `rgv_fault_duration_ms`',
+ 'SELECT 1'
+);
+PREPARE stmt_station_fault_count FROM @sql_station_fault_count;
+EXECUTE stmt_station_fault_count;
+DEALLOCATE PREPARE stmt_station_fault_count;
+
+SET @sql_station_fault_duration := IF(
+ @wrk_analysis_table_exists = 1 AND @station_fault_duration_exists = 0,
+ 'ALTER TABLE `asr_wrk_analysis` ADD COLUMN `station_fault_duration_ms` bigint DEFAULT 0 COMMENT ''杈撻�佺珯鐐规晠闅滆�楁椂姣'' AFTER `station_fault_count`',
+ 'SELECT 1'
+);
+PREPARE stmt_station_fault_duration FROM @sql_station_fault_duration;
+EXECUTE stmt_station_fault_duration;
+DEALLOCATE PREPARE stmt_station_fault_duration;
+
+UPDATE `asr_wrk_analysis` a
+LEFT JOIN (
+ SELECT
+ e.`wrk_no`,
+ COUNT(*) AS `fault_count`,
+ SUM(
+ CASE
+ WHEN e.`start_time` IS NULL THEN 0
+ ELSE GREATEST(
+ TIMESTAMPDIFF(
+ MICROSECOND,
+ e.`start_time`,
+ COALESCE(e.`end_time`, wl.`modi_time`, wl.`io_time`, wl.`appe_time`, e.`start_time`)
+ ),
+ 0
+ ) DIV 1000
+ END
+ ) AS `fault_duration_ms`
+ FROM `asr_bas_station_err_log` e
+ LEFT JOIN `asr_wrk_mast_log` wl ON wl.`wrk_no` = e.`wrk_no`
+ GROUP BY e.`wrk_no`
+) s ON s.`wrk_no` = a.`wrk_no`
+SET a.`station_fault_count` = COALESCE(s.`fault_count`, 0),
+ a.`station_fault_duration_ms` = COALESCE(s.`fault_duration_ms`, 0),
+ a.`fault_count` = COALESCE(a.`crn_fault_count`, 0)
+ + COALESCE(a.`dual_crn_fault_count`, 0)
+ + COALESCE(a.`rgv_fault_count`, 0)
+ + COALESCE(s.`fault_count`, 0),
+ a.`fault_duration_ms` = COALESCE(a.`crn_fault_duration_ms`, 0)
+ + COALESCE(a.`dual_crn_fault_duration_ms`, 0)
+ + COALESCE(a.`rgv_fault_duration_ms`, 0)
+ + COALESCE(s.`fault_duration_ms`, 0),
+ a.`has_fault` = CASE
+ WHEN COALESCE(a.`crn_fault_count`, 0)
+ + COALESCE(a.`dual_crn_fault_count`, 0)
+ + COALESCE(a.`rgv_fault_count`, 0)
+ + COALESCE(s.`fault_count`, 0) > 0 THEN 1
+ ELSE 0
+ END,
+ a.`update_time` = NOW()
+WHERE @wrk_analysis_table_exists = 1;
+
+SET @station_err_log_parent_id := COALESCE(
+ (
+ SELECT `id`
+ FROM `sys_resource`
+ WHERE `code` = 'logReport' AND `level` = 1
+ ORDER BY `id`
+ LIMIT 1
+ ),
+ (
+ SELECT `id`
+ FROM `sys_resource`
+ WHERE `code` = 'develop' AND `level` = 1
+ ORDER BY `id`
+ LIMIT 1
+ )
+);
+
+INSERT INTO `sys_resource`(`code`, `name`, `resource_id`, `level`, `sort`, `status`)
+SELECT 'basStationErrLog/basStationErrLog.html', '杈撻�佺珯鐐瑰紓甯告棩蹇�', @station_err_log_parent_id, 2, 995, 1
+FROM dual
+WHERE @station_err_log_parent_id IS NOT NULL
+ AND NOT EXISTS (
+ SELECT 1
+ FROM `sys_resource`
+ WHERE `code` = 'basStationErrLog/basStationErrLog.html' AND `level` = 2
+ );
+
+UPDATE `sys_resource`
+SET `name` = '杈撻�佺珯鐐瑰紓甯告棩蹇�',
+ `resource_id` = @station_err_log_parent_id,
+ `level` = 2,
+ `sort` = 995,
+ `status` = 1
+WHERE `code` = 'basStationErrLog/basStationErrLog.html' AND `level` = 2;
+
+SET @station_err_log_id := (
+ SELECT `id`
+ FROM `sys_resource`
+ WHERE `code` = 'basStationErrLog/basStationErrLog.html' AND `level` = 2
+ ORDER BY `id`
+ LIMIT 1
+);
+
+INSERT INTO `sys_resource`(`code`, `name`, `resource_id`, `level`, `sort`, `status`)
+SELECT 'basStationErrLog/basStationErrLog.html#view', '鏌ョ湅', @station_err_log_id, 3, 1, 1
+FROM dual
+WHERE @station_err_log_id IS NOT NULL
+ AND NOT EXISTS (
+ SELECT 1
+ FROM `sys_resource`
+ WHERE `code` = 'basStationErrLog/basStationErrLog.html#view' AND `level` = 3
+ );
+
+UPDATE `sys_resource`
+SET `name` = '鏌ョ湅',
+ `resource_id` = @station_err_log_id,
+ `level` = 3,
+ `sort` = 1,
+ `status` = 1
+WHERE `code` = 'basStationErrLog/basStationErrLog.html#view' AND `level` = 3;
diff --git a/src/main/webapp/static/js/basStationErrLog/basStationErrLog.js b/src/main/webapp/static/js/basStationErrLog/basStationErrLog.js
new file mode 100644
index 0000000..86a95eb
--- /dev/null
+++ b/src/main/webapp/static/js/basStationErrLog/basStationErrLog.js
@@ -0,0 +1,1165 @@
+(function () {
+ var simpleEntityName = 'basStationErrLog';
+ var entityName = 'BasStationErrLog';
+ var primaryKeyField = 'id';
+ var fieldMeta = dedupeFieldMeta([
+ {
+ field: 'id',
+ columnName: 'id',
+ label: '缂栥��銆�鍙�',
+ tableProp: 'id',
+ exportField: 'id',
+ kind: 'text',
+ valueType: 'number',
+ required: true,
+ primaryKey: true,
+ sortable: true,
+ textarea: false,
+ minWidth: 90,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'wrkNo',
+ columnName: 'wrk_no',
+ label: '宸� 浣� 鍙�',
+ tableProp: 'wrkNo',
+ exportField: 'wrkNo',
+ kind: 'text',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 116,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'startTime',
+ columnName: 'start_time',
+ label: '鍙戠敓鏃堕棿',
+ tableProp: 'startTime$',
+ exportField: 'startTime$',
+ kind: 'date',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 168,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'endTime',
+ columnName: 'end_time',
+ label: '缁撴潫鏃堕棿',
+ tableProp: 'endTime$',
+ exportField: 'endTime$',
+ kind: 'date',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 168,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'wrkSts',
+ columnName: 'wrk_sts',
+ label: '宸ヤ綔鐘舵��',
+ tableProp: 'wrkSts$',
+ exportField: 'wrkSts$',
+ kind: 'foreign',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: 'basWrkStatus',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'ioType',
+ columnName: 'io_type',
+ label: '鍏ュ嚭搴撶被鍨�',
+ tableProp: 'ioType$',
+ exportField: 'ioType$',
+ kind: 'foreign',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 116,
+ enumOptions: [],
+ foreignQuery: 'basWrkIotype',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'stationId',
+ columnName: 'station_id',
+ label: '杈撻�佺珯鐐�',
+ tableProp: 'stationLabel$',
+ exportField: 'stationLabel$',
+ kind: 'foreign',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 130,
+ enumOptions: [],
+ foreignQuery: 'basStation',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'locNo',
+ columnName: 'loc_no',
+ label: '鐩爣搴撲綅',
+ tableProp: 'locNo',
+ exportField: 'locNo',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'staNo',
+ columnName: 'sta_no',
+ label: '鐩� 鏍� 绔�',
+ tableProp: 'staNo',
+ exportField: 'staNo',
+ kind: 'text',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 116,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'sourceStaNo',
+ columnName: 'source_sta_no',
+ label: '婧愩��銆�绔�',
+ tableProp: 'sourceStaNo',
+ exportField: 'sourceStaNo',
+ kind: 'text',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'sourceLocNo',
+ columnName: 'source_loc_no',
+ label: '婧� 搴� 浣�',
+ tableProp: 'sourceLocNo',
+ exportField: 'sourceLocNo',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 116,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'barcode',
+ columnName: 'barcode',
+ label: '鏉°��銆�鐮�',
+ tableProp: 'barcode',
+ exportField: 'barcode',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'errCode',
+ columnName: 'err_code',
+ label: '寮� 甯� 鐮�',
+ tableProp: 'errCode',
+ exportField: 'errCode',
+ kind: 'text',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 116,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'error',
+ columnName: 'error',
+ label: '寮傘��銆�甯�',
+ tableProp: 'error',
+ exportField: 'error',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'status',
+ columnName: 'status',
+ label: '寮傚父鎯呭喌',
+ tableProp: 'status$',
+ exportField: 'status$',
+ kind: 'enum',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 120,
+ enumOptions: [{ rawValue: '1', label: '鏈鐞�' }, { rawValue: '2', label: '宸蹭慨澶�' }],
+ foreignQuery: '',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'createTime',
+ columnName: 'create_time',
+ label: '娣诲姞鏃堕棿',
+ tableProp: 'createTime$',
+ exportField: 'createTime$',
+ kind: 'date',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 168,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'createBy',
+ columnName: 'create_by',
+ label: '娣诲姞浜哄憳',
+ tableProp: 'createBy$',
+ exportField: 'createBy$',
+ kind: 'foreign',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: 'user',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'updateTime',
+ columnName: 'update_time',
+ label: '淇敼鏃堕棿',
+ tableProp: 'updateTime$',
+ exportField: 'updateTime$',
+ kind: 'date',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 168,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'updateBy',
+ columnName: 'update_by',
+ label: '淇敼浜哄憳',
+ tableProp: 'updateBy$',
+ exportField: 'updateBy$',
+ kind: 'foreign',
+ valueType: 'number',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 110,
+ enumOptions: [],
+ foreignQuery: 'user',
+ checkboxActiveRaw: '1',
+ checkboxInactiveRaw: '0'
+ },
+ {
+ field: 'memo',
+ columnName: 'memo',
+ label: '澶囥��銆�娉�',
+ tableProp: 'memo',
+ exportField: 'memo',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: true,
+ minWidth: 180,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ },
+ {
+ field: 'systemStatus',
+ columnName: 'system_status',
+ label: '绯荤粺鐘舵�佹暟鎹�',
+ tableProp: 'systemStatus',
+ exportField: 'systemStatus',
+ kind: 'text',
+ valueType: 'string',
+ required: false,
+ primaryKey: false,
+ sortable: false,
+ textarea: false,
+ minWidth: 134,
+ enumOptions: [],
+ foreignQuery: '',
+ checkboxActiveRaw: 'Y',
+ checkboxInactiveRaw: 'N'
+ }
+
+ ]);
+
+ function formatFieldLabel(field) {
+ var raw = field && field.label ? String(field.label).trim() : '';
+ if (raw) {
+ return raw;
+ }
+ raw = field && field.columnName ? field.columnName : (field && field.field ? field.field : '');
+ if (!raw) {
+ return '';
+ }
+ raw = String(raw)
+ .replace(/\$/g, '')
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
+ .replace(/_/g, ' ')
+ .replace(/\s+/g, ' ')
+ .trim();
+ return raw.replace(/\b[a-z]/g, function (letter) {
+ return letter.toUpperCase();
+ });
+ }
+
+ function dedupeFieldMeta(list) {
+ var result = [];
+ var seen = {};
+ (list || []).forEach(function (field) {
+ if (!field || !field.field || seen[field.field]) {
+ return;
+ }
+ field.label = formatFieldLabel(field);
+ seen[field.field] = true;
+ result.push(field);
+ });
+ return result;
+ }
+
+ function isEmptyValue(value) {
+ return value === null || value === undefined || value === '';
+ }
+
+ function stringValue(value) {
+ return isEmptyValue(value) ? '' : String(value);
+ }
+
+ function valueOrDash(value) {
+ return isEmptyValue(value) ? '--' : value;
+ }
+
+ function normalizeOptionValue(field, rawValue) {
+ if (rawValue === null || rawValue === undefined) {
+ return null;
+ }
+ if (rawValue === '') {
+ return '';
+ }
+ if (field && field.valueType === 'number') {
+ var numberVal = Number(rawValue);
+ return isNaN(numberVal) ? rawValue : numberVal;
+ }
+ return String(rawValue);
+ }
+
+ function isSearchableField(field) {
+ return !!field && field.kind !== 'image' && !field.textarea;
+ }
+
+ function isSortableField(field) {
+ if (!field) {
+ return false;
+ }
+ if (field.primaryKey) {
+ return true;
+ }
+ return field.kind !== 'image' && !field.textarea && field.kind !== 'foreign';
+ }
+
+ function defaultFieldValue(field) {
+ if (field.primaryKey) {
+ return null;
+ }
+ if (field.kind === 'checkbox') {
+ return normalizeOptionValue(field, field.checkboxInactiveRaw);
+ }
+ return '';
+ }
+
+ function defaultSearchFieldValue(field) {
+ if (field.kind === 'date') {
+ return [];
+ }
+ if (field.kind === 'enum' || field.kind === 'checkbox') {
+ return null;
+ }
+ return '';
+ }
+
+ function createSearchDefaults() {
+ var result = {
+ condition: ''
+ };
+ fieldMeta.forEach(function (field) {
+ if (!isSearchableField(field)) {
+ return;
+ }
+ result[field.field] = defaultSearchFieldValue(field);
+ });
+ return result;
+ }
+
+ function createSearchDisplayDefaults() {
+ var result = {};
+ fieldMeta.forEach(function (field) {
+ if (field.kind === 'foreign' && isSearchableField(field)) {
+ result[field.field] = '';
+ }
+ });
+ return result;
+ }
+
+ function createDefaultVisibleColumnKeys() {
+ return fieldMeta.map(function (field) {
+ return field.field;
+ });
+ }
+
+ function createFormDefaults() {
+ var result = {};
+ fieldMeta.forEach(function (field) {
+ result[field.field] = defaultFieldValue(field);
+ });
+ return result;
+ }
+
+ function createDisplayDefaults() {
+ var result = {};
+ fieldMeta.forEach(function (field) {
+ if (field.kind === 'foreign') {
+ result[field.field] = '';
+ }
+ });
+ return result;
+ }
+
+ function createFormRules() {
+ var rules = {};
+ fieldMeta.forEach(function (field) {
+ if (field.primaryKey || !field.required) {
+ return;
+ }
+ rules[field.field] = [{
+ required: true,
+ message: (field.kind === 'date' || field.kind === 'enum' ? '璇烽�夋嫨' : '璇疯緭鍏�') + field.label,
+ trigger: (field.kind === 'date' || field.kind === 'enum') ? 'change' : 'blur'
+ }];
+ });
+ return rules;
+ }
+
+ function getTableValue(row, field) {
+ var prop = field.tableProp || field.field;
+ if (row && !isEmptyValue(row[prop])) {
+ return row[prop];
+ }
+ return row ? row[field.field] : '';
+ }
+
+ function isCheckboxChecked(row, field) {
+ var value = row ? row[field.field] : null;
+ var activeValue = normalizeOptionValue(field, field.checkboxActiveRaw);
+ return String(value) === String(activeValue);
+ }
+
+ function exportCell(value) {
+ return stringValue(value).replace(/\t/g, ' ').replace(/\r?\n/g, ' ');
+ }
+
+ function escapeHtml(value) {
+ return exportCell(value)
+ .replace(/&/g, '&')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+ }
+
+ function buildPayload(form) {
+ var payload = {};
+ fieldMeta.forEach(function (field) {
+ var value = form[field.field];
+ if (field.primaryKey) {
+ if (!isEmptyValue(value)) {
+ payload[field.field] = value;
+ }
+ return;
+ }
+ if (field.kind === 'foreign' && isEmptyValue(value)) {
+ value = null;
+ }
+ if (field.kind === 'enum' && value === '') {
+ value = null;
+ }
+ if (field.kind === 'checkbox' && isEmptyValue(value)) {
+ value = normalizeOptionValue(field, field.checkboxInactiveRaw);
+ }
+ if (field.valueType === 'number' && !isEmptyValue(value)) {
+ value = Number(value);
+ }
+ if (field.valueType === 'number' && value === '') {
+ value = null;
+ }
+ payload[field.field] = value;
+ });
+ return payload;
+ }
+
+ function fillFormFromRow(row, form, display) {
+ fieldMeta.forEach(function (field) {
+ if (field.primaryKey) {
+ form[field.field] = row[field.field];
+ return;
+ }
+ if (field.kind === 'date') {
+ form[field.field] = row[field.tableProp] || row[field.field] || '';
+ return;
+ }
+ if (field.kind === 'foreign') {
+ form[field.field] = isEmptyValue(row[field.field]) ? '' : normalizeOptionValue(field, row[field.field]);
+ if (display) {
+ display[field.field] = row[field.tableProp] || (isEmptyValue(row[field.field]) ? '' : String(row[field.field]));
+ }
+ return;
+ }
+ if (field.kind === 'enum') {
+ form[field.field] = isEmptyValue(row[field.field]) ? '' : normalizeOptionValue(field, row[field.field]);
+ return;
+ }
+ if (field.kind === 'checkbox') {
+ form[field.field] = isEmptyValue(row[field.field])
+ ? normalizeOptionValue(field, field.checkboxInactiveRaw)
+ : normalizeOptionValue(field, row[field.field]);
+ return;
+ }
+ form[field.field] = isEmptyValue(row[field.field])
+ ? ''
+ : (field.valueType === 'number' ? String(row[field.field]) : row[field.field]);
+ });
+ }
+
+ function resolveSearchParam(field) {
+ if (field.kind === 'date' && field.columnName) {
+ return field.columnName;
+ }
+ return field.field;
+ }
+
+ function createDownloadFile(filename, titles, rows) {
+ var html = [
+ '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">',
+ '<head><meta charset="UTF-8"></head><body><table border="1"><thead><tr>',
+ titles.map(function (title) {
+ return '<th>' + escapeHtml(title) + '</th>';
+ }).join(''),
+ '</tr></thead><tbody>',
+ (rows || []).map(function (row) {
+ return '<tr>' + (row || []).map(function (value) {
+ return '<td style="mso-number-format:\\@;">' + escapeHtml(value) + '</td>';
+ }).join('') + '</tr>';
+ }).join(''),
+ '</tbody></table></body></html>'
+ ].join('');
+ var blob = new Blob(['\ufeff' + html], {
+ type: 'application/vnd.ms-excel;charset=utf-8;'
+ });
+ var anchor = document.createElement('a');
+ anchor.href = URL.createObjectURL(blob);
+ anchor.download = filename;
+ document.body.appendChild(anchor);
+ anchor.click();
+ setTimeout(function () {
+ URL.revokeObjectURL(anchor.href);
+ document.body.removeChild(anchor);
+ }, 0);
+ }
+
+ function buildTimestamp() {
+ var now = new Date();
+ var pad = function (num) {
+ return num < 10 ? '0' + num : String(num);
+ };
+ return now.getFullYear()
+ + pad(now.getMonth() + 1)
+ + pad(now.getDate())
+ + '_'
+ + pad(now.getHours())
+ + pad(now.getMinutes())
+ + pad(now.getSeconds());
+ }
+
+ function authHeaders() {
+ return {
+ token: localStorage.getItem('token')
+ };
+ }
+
+ function handleForbidden(res) {
+ if (res && res.code === 403) {
+ top.location.href = baseUrl + '/';
+ return true;
+ }
+ return false;
+ }
+
+ var sharedMethods = {
+ authHeaders: authHeaders,
+ handleForbidden: handleForbidden,
+ valueOrDash: valueOrDash,
+ stringValue: stringValue,
+ getTableValue: getTableValue,
+ isCheckboxChecked: isCheckboxChecked,
+ normalizeOptionValue: normalizeOptionValue,
+ isSortableField: isSortableField,
+ getSuggestionFetcher: function (field) {
+ var self = this;
+ return function (queryString, callback) {
+ self.fetchForeignSuggestions(field, queryString, callback);
+ };
+ },
+ fetchForeignSuggestions: function (field, queryString, callback) {
+ if (!field.foreignQuery || !queryString) {
+ callback([]);
+ return;
+ }
+ var self = this;
+ $.ajax({
+ url: baseUrl + '/' + field.foreignQuery + 'Query/auth',
+ method: 'GET',
+ headers: self.authHeaders(),
+ data: { condition: queryString },
+ success: function (res) {
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200 || !Array.isArray(res.data)) {
+ callback([]);
+ return;
+ }
+ callback(res.data.map(function (item) {
+ return {
+ id: item.id,
+ value: item.value
+ };
+ }));
+ },
+ error: function () {
+ callback([]);
+ }
+ });
+ },
+ handleForeignSelect: function (field, item) {
+ this.$set(this.displayTarget, field.field, item && item.value ? item.value : '');
+ this.$set(this.formTarget, field.field, item && item.id !== undefined ? normalizeOptionValue(field, item.id) : '');
+ },
+ handleForeignInput: function (field) {
+ if (!this.displayTarget || !this.formTarget) {
+ return;
+ }
+ if (this.displayTarget[field.field]) {
+ return;
+ }
+ this.$set(this.formTarget, field.field, '');
+ }
+ };
+
+ if (document.getElementById('app')) {
+ new Vue({
+ el: '#app',
+ data: function () {
+ return {
+ fieldMeta: fieldMeta,
+ primaryKeyField: primaryKeyField,
+ loading: false,
+ exporting: false,
+ tableData: [],
+ selection: [],
+ advancedFiltersVisible: false,
+ allColumns: fieldMeta.slice(),
+ visibleColumnKeys: createDefaultVisibleColumnKeys(),
+ searchForm: createSearchDefaults(),
+ searchDisplay: createSearchDisplayDefaults(),
+ page: {
+ curr: 1,
+ limit: 15,
+ total: 0
+ },
+ sortState: {
+ prop: '',
+ order: ''
+ },
+ dialog: {
+ visible: false,
+ mode: 'create',
+ submitting: false
+ },
+ layoutTimer: null,
+ tableResizeHandler: null,
+ dialogForm: createFormDefaults(),
+ dialogDisplay: createDisplayDefaults(),
+ dialogRules: createFormRules()
+ };
+ },
+ computed: {
+ searchableFields: function () {
+ return this.fieldMeta.filter(function (field) {
+ return isSearchableField(field);
+ });
+ },
+ quickSearchableFields: function () {
+ var result = [];
+ this.searchableFields.forEach(function (field) {
+ if (result.length >= 3 || field.kind === 'date') {
+ return;
+ }
+ result.push(field);
+ });
+ return result;
+ },
+ advancedSearchableFields: function () {
+ var quickKeys = this.quickSearchableFields.map(function (field) {
+ return field.field;
+ });
+ return this.searchableFields.filter(function (field) {
+ return quickKeys.indexOf(field.field) === -1;
+ });
+ },
+ hasAdvancedFilters: function () {
+ return this.advancedSearchableFields.length > 0;
+ },
+ visibleColumns: function () {
+ var keys = this.visibleColumnKeys;
+ return this.allColumns.filter(function (field) {
+ return keys.indexOf(field.field) !== -1;
+ });
+ },
+ editableFields: function () {
+ return this.fieldMeta.filter(function (field) {
+ return !field.primaryKey;
+ });
+ },
+ exportColumns: function () {
+ return this.visibleColumns.map(function (field) {
+ return {
+ field: field.exportField || field.tableProp || field.field,
+ label: field.label
+ };
+ });
+ },
+ tableHeight: function () {
+ return this.advancedFiltersVisible && this.hasAdvancedFilters
+ ? 'calc(100vh - 390px)'
+ : 'calc(100vh - 300px)';
+ },
+ formTarget: function () {
+ return this.dialogForm;
+ },
+ displayTarget: function () {
+ return this.dialogDisplay;
+ }
+ },
+ created: function () {
+ this.loadTable();
+ },
+ mounted: function () {
+ var self = this;
+ self.requestTableLayout(80);
+ self.tableResizeHandler = function () {
+ self.requestTableLayout(80);
+ };
+ window.addEventListener('resize', self.tableResizeHandler);
+ },
+ beforeDestroy: function () {
+ if (this.layoutTimer) {
+ clearTimeout(this.layoutTimer);
+ this.layoutTimer = null;
+ }
+ if (this.tableResizeHandler) {
+ window.removeEventListener('resize', this.tableResizeHandler);
+ this.tableResizeHandler = null;
+ }
+ },
+ methods: $.extend({}, sharedMethods, {
+ requestTableLayout: function (delay) {
+ var self = this;
+ if (self.layoutTimer) {
+ clearTimeout(self.layoutTimer);
+ }
+ self.$nextTick(function () {
+ self.layoutTimer = setTimeout(function () {
+ var table = self.$refs.dataTable;
+ if (table && typeof table.doLayout === 'function') {
+ table.doLayout();
+ }
+ }, delay || 40);
+ });
+ },
+ isColumnVisible: function (fieldName) {
+ return this.visibleColumnKeys.indexOf(fieldName) !== -1;
+ },
+ toggleColumn: function (fieldName, visible) {
+ if (visible) {
+ if (this.visibleColumnKeys.indexOf(fieldName) === -1) {
+ this.visibleColumnKeys.push(fieldName);
+ }
+ this.requestTableLayout(80);
+ return;
+ }
+ if (this.visibleColumnKeys.length === 1) {
+ this.$message.warning('鑷冲皯淇濈暀涓�鍒�');
+ return;
+ }
+ this.visibleColumnKeys = this.visibleColumnKeys.filter(function (item) {
+ return item !== fieldName;
+ });
+ this.requestTableLayout(80);
+ },
+ selectAllColumns: function () {
+ this.visibleColumnKeys = createDefaultVisibleColumnKeys();
+ this.requestTableLayout(80);
+ },
+ resetColumns: function () {
+ this.visibleColumnKeys = createDefaultVisibleColumnKeys();
+ this.requestTableLayout(80);
+ },
+ toggleAdvancedFilters: function () {
+ this.advancedFiltersVisible = !this.advancedFiltersVisible;
+ this.requestTableLayout(260);
+ },
+ handleSearchForeignSelect: function (field, item) {
+ this.$set(this.searchDisplay, field.field, item && item.value ? item.value : '');
+ this.$set(this.searchForm, field.field, item && item.id !== undefined ? normalizeOptionValue(field, item.id) : '');
+ },
+ handleSearchForeignInput: function (field) {
+ if (this.searchDisplay[field.field]) {
+ return;
+ }
+ this.$set(this.searchForm, field.field, '');
+ },
+ buildQueryParams: function () {
+ var self = this;
+ var params = {
+ curr: self.page.curr,
+ limit: self.page.limit
+ };
+ if (self.searchForm.condition) {
+ params.condition = self.searchForm.condition;
+ }
+ self.searchableFields.forEach(function (field) {
+ var value = self.searchForm[field.field];
+ if (field.kind === 'date') {
+ if (value && value.length === 2) {
+ params[resolveSearchParam(field)] = value[0] + ' - ' + value[1];
+ }
+ return;
+ }
+ if (!isEmptyValue(value)) {
+ params[resolveSearchParam(field)] = value;
+ }
+ });
+ if (self.sortState.prop && self.sortState.order) {
+ params.orderByField = self.sortState.prop;
+ params.orderByType = self.sortState.order === 'ascending' ? 'asc' : 'desc';
+ }
+ return params;
+ },
+ loadTable: function () {
+ var self = this;
+ self.loading = true;
+ $.ajax({
+ url: baseUrl + '/' + simpleEntityName + '/list/auth',
+ method: 'GET',
+ headers: self.authHeaders(),
+ data: self.buildQueryParams(),
+ success: function (res) {
+ self.loading = false;
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200) {
+ self.$message.error((res && res.msg) ? res.msg : '鍔犺浇澶辫触');
+ return;
+ }
+ var payload = res.data || {};
+ self.tableData = Array.isArray(payload.records) ? payload.records : [];
+ self.page.total = payload.total || 0;
+ self.requestTableLayout(80);
+ },
+ error: function () {
+ self.loading = false;
+ self.requestTableLayout(80);
+ self.$message.error('鍔犺浇澶辫触');
+ }
+ });
+ },
+ handleSearch: function () {
+ this.page.curr = 1;
+ this.loadTable();
+ },
+ handleReset: function () {
+ this.searchForm = createSearchDefaults();
+ this.searchDisplay = createSearchDisplayDefaults();
+ this.advancedFiltersVisible = false;
+ this.page.curr = 1;
+ this.sortState = {
+ prop: '',
+ order: ''
+ };
+ this.loadTable();
+ },
+ handleSelectionChange: function (rows) {
+ this.selection = rows || [];
+ },
+ handleSortChange: function (payload) {
+ this.sortState = {
+ prop: payload && payload.prop ? payload.prop : '',
+ order: payload && payload.order ? payload.order : ''
+ };
+ this.page.curr = 1;
+ this.loadTable();
+ },
+ handleCurrentChange: function (curr) {
+ this.page.curr = curr;
+ this.loadTable();
+ },
+ handleSizeChange: function (limit) {
+ this.page.limit = limit;
+ this.page.curr = 1;
+ this.loadTable();
+ },
+ resetDialogState: function () {
+ this.dialogForm = createFormDefaults();
+ this.dialogDisplay = createDisplayDefaults();
+ if (this.$refs.dialogForm) {
+ this.$refs.dialogForm.clearValidate();
+ }
+ },
+ openCreateDialog: function () {
+ this.dialog.mode = 'create';
+ this.dialog.visible = true;
+ this.$nextTick(this.resetDialogState);
+ },
+ openEditDialog: function (row) {
+ var self = this;
+ self.dialog.mode = 'edit';
+ self.dialog.visible = true;
+ self.$nextTick(function () {
+ self.resetDialogState();
+ fillFormFromRow(row, self.dialogForm, self.dialogDisplay);
+ if (self.$refs.dialogForm) {
+ self.$refs.dialogForm.clearValidate();
+ }
+ });
+ },
+ submitDialog: function () {
+ var self = this;
+ if (!self.$refs.dialogForm) {
+ return;
+ }
+ self.$refs.dialogForm.validate(function (valid) {
+ if (!valid) {
+ return false;
+ }
+ self.dialog.submitting = true;
+ $.ajax({
+ url: baseUrl + '/' + simpleEntityName + '/' + (self.dialog.mode === 'create' ? 'add' : 'update') + '/auth',
+ method: 'POST',
+ headers: self.authHeaders(),
+ data: buildPayload(self.dialogForm),
+ success: function (res) {
+ self.dialog.submitting = false;
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200) {
+ self.$message.error((res && res.msg) ? res.msg : '淇濆瓨澶辫触');
+ return;
+ }
+ self.$message.success(res.msg || '淇濆瓨鎴愬姛');
+ self.dialog.visible = false;
+ self.loadTable();
+ },
+ error: function () {
+ self.dialog.submitting = false;
+ self.$message.error('淇濆瓨澶辫触');
+ }
+ });
+ return true;
+ });
+ },
+ removeSelection: function () {
+ var self = this;
+ var ids = self.selection.map(function (row) {
+ return row[self.primaryKeyField];
+ });
+ self.removeRows(ids);
+ },
+ removeRows: function (ids) {
+ var self = this;
+ if (!ids || ids.length === 0) {
+ self.$message.warning('璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁');
+ return;
+ }
+ self.$confirm('纭畾鍒犻櫎閫変腑鐨勮褰曞悧锛�', '鎻愮ず', { type: 'warning' }).then(function () {
+ $.ajax({
+ url: baseUrl + '/' + simpleEntityName + '/delete/auth',
+ method: 'POST',
+ headers: self.authHeaders(),
+ traditional: true,
+ data: { 'ids[]': ids },
+ success: function (res) {
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200) {
+ self.$message.error((res && res.msg) ? res.msg : '鍒犻櫎澶辫触');
+ return;
+ }
+ self.$message.success(res.msg || '鍒犻櫎鎴愬姛');
+ self.selection = [];
+ if (self.tableData.length === ids.length && self.page.curr > 1) {
+ self.page.curr = self.page.curr - 1;
+ }
+ self.loadTable();
+ },
+ error: function () {
+ self.$message.error('鍒犻櫎澶辫触');
+ }
+ });
+ }).catch(function () {});
+ },
+ exportRows: function () {
+ var self = this;
+ self.exporting = true;
+ var requestBody = {
+ fields: self.exportColumns.map(function (item) {
+ return item.field;
+ })
+ };
+ requestBody[simpleEntityName] = self.buildQueryParams();
+ $.ajax({
+ url: baseUrl + '/' + simpleEntityName + '/export/auth',
+ method: 'POST',
+ headers: $.extend({ 'Content-Type': 'application/json;charset=UTF-8' }, self.authHeaders()),
+ data: JSON.stringify(requestBody),
+ success: function (res) {
+ self.exporting = false;
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200) {
+ self.$message.error((res && res.msg) ? res.msg : '瀵煎嚭澶辫触');
+ return;
+ }
+ createDownloadFile(
+ simpleEntityName + '_' + buildTimestamp() + '.xls',
+ self.exportColumns.map(function (item) {
+ return item.label;
+ }),
+ Array.isArray(res.data) ? res.data : []
+ );
+ self.$message.success('瀵煎嚭鎴愬姛');
+ },
+ error: function () {
+ self.exporting = false;
+ self.$message.error('瀵煎嚭澶辫触');
+ }
+ });
+ }
+ })
+ });
+ }
+
+})();
diff --git a/src/main/webapp/static/js/wrkMastLog/wrkMastLog.js b/src/main/webapp/static/js/wrkMastLog/wrkMastLog.js
index 1dd1f6c..dbab215 100644
--- a/src/main/webapp/static/js/wrkMastLog/wrkMastLog.js
+++ b/src/main/webapp/static/js/wrkMastLog/wrkMastLog.js
@@ -1345,20 +1345,20 @@
},
wrkSts: {
label: '宸ヤ綔鐘舵��',
- kind: 'foreign',
+ kind: 'enum',
tableProp: 'wrkSts$',
exportField: 'wrkSts$',
- foreignQuery: 'basWrkStatus',
+ enumOptions: [],
searchable: true,
quickSearch: true,
minWidth: 160
},
ioType: {
label: '鍏ュ嚭搴撶被鍨�',
- kind: 'foreign',
+ kind: 'enum',
tableProp: 'ioType$',
exportField: 'ioType$',
- foreignQuery: 'basWrkIotype',
+ enumOptions: [],
searchable: true,
quickSearch: true,
minWidth: 160
@@ -1385,10 +1385,18 @@
minWidth: 90
},
sourceStaNo: {
- label: '婧愮珯'
+ label: '婧愮珯',
+ kind: 'enum',
+ enumOptions: [],
+ searchable: true,
+ minWidth: 120
},
staNo: {
- label: '鐩爣绔�'
+ label: '鐩爣绔�',
+ kind: 'enum',
+ enumOptions: [],
+ searchable: true,
+ minWidth: 120
},
sourceLocNo: {
label: '婧愬簱浣�',
@@ -1416,6 +1424,7 @@
},
barcode: {
label: '鏉$爜',
+ searchable: true,
minWidth: 140
},
modiUser: {
@@ -1804,6 +1813,39 @@
};
}
+ function getFieldByName(fieldName) {
+ for (var i = 0; i < fieldMeta.length; i += 1) {
+ if (fieldMeta[i] && fieldMeta[i].field === fieldName) {
+ return fieldMeta[i];
+ }
+ }
+ return null;
+ }
+
+ function buildEnumOptions(records, valueField, labelField) {
+ var options = [];
+ var seen = {};
+ (records || []).forEach(function (item) {
+ if (!item) {
+ return;
+ }
+ var rawValue = item[valueField];
+ if (isEmptyValue(rawValue)) {
+ return;
+ }
+ var key = String(rawValue);
+ if (seen[key]) {
+ return;
+ }
+ seen[key] = true;
+ options.push({
+ rawValue: key,
+ label: isEmptyValue(item[labelField]) ? key : String(item[labelField])
+ });
+ });
+ return options;
+ }
+
function handleForbidden(res) {
if (res && res.code === 403) {
top.location.href = baseUrl + '/';
@@ -1961,6 +2003,7 @@
}
},
created: function () {
+ this.loadSearchEnumOptions();
this.loadTable();
},
mounted: function () {
@@ -2038,6 +2081,63 @@
}
this.$set(this.searchForm, field.field, '');
},
+ loadSearchEnumOptions: function () {
+ var self = this;
+ [
+ {
+ field: 'wrkSts',
+ url: baseUrl + '/basWrkStatus/list/auth',
+ valueField: 'wrkSts',
+ labelField: 'wrkDesc',
+ limit: 200
+ },
+ {
+ field: 'ioType',
+ url: baseUrl + '/basWrkIotype/list/auth',
+ valueField: 'ioType',
+ labelField: 'ioDesc',
+ limit: 200
+ },
+ {
+ field: 'staNo',
+ url: baseUrl + '/basStation/list/auth',
+ valueField: 'stationId',
+ labelField: 'stationId',
+ limit: 500
+ },
+ {
+ field: 'sourceStaNo',
+ url: baseUrl + '/basStation/list/auth',
+ valueField: 'stationId',
+ labelField: 'stationId',
+ limit: 500
+ }
+ ].forEach(function (config) {
+ $.ajax({
+ url: config.url,
+ method: 'GET',
+ headers: self.authHeaders(),
+ data: {
+ curr: 1,
+ limit: config.limit
+ },
+ success: function (res) {
+ if (self.handleForbidden(res)) {
+ return;
+ }
+ if (!res || res.code !== 200) {
+ return;
+ }
+ var payload = res.data || {};
+ var field = getFieldByName(config.field);
+ if (!field) {
+ return;
+ }
+ self.$set(field, 'enumOptions', buildEnumOptions(payload.records, config.valueField, config.labelField));
+ }
+ });
+ });
+ },
buildQueryParams: function () {
var self = this;
var params = {
diff --git a/src/main/webapp/views/basStationErrLog/basStationErrLog.html b/src/main/webapp/views/basStationErrLog/basStationErrLog.html
new file mode 100644
index 0000000..6467147
--- /dev/null
+++ b/src/main/webapp/views/basStationErrLog/basStationErrLog.html
@@ -0,0 +1,670 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="utf-8">
+ <title>BasStationErrLog 绠$悊</title>
+ <meta name="renderer" content="webkit">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+ <link rel="stylesheet" href="../../static/vue/element/element.css">
+ <link rel="stylesheet" href="../../static/css/cool.css">
+ <style>
+ :root {
+ --card-bg: rgba(255, 255, 255, 0.94);
+ --card-border: rgba(216, 226, 238, 0.95);
+ --text-main: #243447;
+ }
+
+ [v-cloak] {
+ display: none;
+ }
+
+ html,
+ body {
+ margin: 0;
+ min-height: 100%;
+ color: var(--text-main);
+ font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei", sans-serif;
+ background:
+ radial-gradient(1000px 420px at 0% -10%, rgba(44, 107, 193, 0.12), transparent 56%),
+ radial-gradient(900px 400px at 100% 0%, rgba(28, 150, 126, 0.10), transparent 58%),
+ linear-gradient(180deg, #f2f6fb 0%, #f8fafc 100%);
+ }
+
+ .page-shell {
+ max-width: 1700px;
+ margin: 0 auto;
+ padding: 14px;
+ box-sizing: border-box;
+ }
+
+ .card-shell {
+ position: relative;
+ border-radius: 24px;
+ border: 1px solid var(--card-border);
+ background:
+ radial-gradient(760px 220px at -8% 0%, rgba(43, 117, 196, 0.05), transparent 55%),
+ radial-gradient(680px 200px at 108% 10%, rgba(24, 150, 129, 0.05), transparent 58%),
+ var(--card-bg);
+ box-shadow: 0 16px 32px rgba(44, 67, 96, 0.08);
+ overflow: hidden;
+ }
+
+ .card-body {
+ position: relative;
+ z-index: 1;
+ }
+
+ .list-toolbar {
+ padding: 12px 16px 10px;
+ border-bottom: 1px solid rgba(222, 230, 239, 0.92);
+ }
+
+ .toolbar-main {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 8px;
+ flex-wrap: wrap;
+ }
+
+ .toolbar-left {
+ flex: 1 1 960px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+ }
+
+ .toolbar-search {
+ flex: 1 1 auto;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+ }
+
+ .toolbar-search-item {
+ flex: 0 0 152px;
+ min-width: 152px;
+ }
+
+ .toolbar-search-item.keyword {
+ flex: 0 0 220px;
+ min-width: 220px;
+ }
+
+ .toolbar-query-actions,
+ .toolbar-ops {
+ display: flex;
+ gap: 8px;
+ flex-wrap: wrap;
+ }
+
+ .toolbar-ops {
+ justify-content: flex-end;
+ }
+
+ .list-toolbar .el-input__inner,
+ .list-toolbar .el-range-editor.el-input__inner,
+ .advanced-panel .el-input__inner,
+ .advanced-panel .el-range-editor.el-input__inner {
+ height: 32px;
+ line-height: 32px;
+ }
+
+ .list-toolbar .el-range-editor.el-input__inner,
+ .advanced-panel .el-range-editor.el-input__inner {
+ align-items: center;
+ }
+
+ .list-toolbar .el-input__icon,
+ .advanced-panel .el-input__icon {
+ line-height: 32px;
+ }
+
+ .list-toolbar .el-range-editor .el-range__icon,
+ .list-toolbar .el-range-editor .el-range-separator,
+ .list-toolbar .el-range-editor .el-range__close-icon,
+ .advanced-panel .el-range-editor .el-range__icon,
+ .advanced-panel .el-range-editor .el-range-separator,
+ .advanced-panel .el-range-editor .el-range__close-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ line-height: 1;
+ }
+
+ .list-toolbar .el-button,
+ .advanced-panel .el-button {
+ padding: 8px 12px;
+ border-radius: 8px;
+ }
+
+ .advanced-panel {
+ padding: 10px 16px 12px;
+ border-bottom: 1px solid rgba(222, 230, 239, 0.92);
+ background: rgba(248, 251, 254, 0.78);
+ }
+
+ .advanced-grid {
+ display: grid;
+ grid-template-columns: repeat(6, minmax(0, 1fr));
+ gap: 8px;
+ }
+
+ .advanced-item {
+ min-width: 0;
+ }
+
+ .advanced-item.span-2 {
+ grid-column: span 2;
+ }
+
+ .table-wrap {
+ padding: 10px 16px;
+ }
+
+ .table-shell {
+ border-radius: 20px;
+ overflow: hidden;
+ border: 1px solid rgba(217, 227, 238, 0.98);
+ background: rgba(255, 255, 255, 0.95);
+ }
+
+ .table-shell .el-table {
+ border-radius: 20px;
+ overflow: hidden;
+ }
+
+ .table-shell .el-table th {
+ background: #f7fafc;
+ color: #53677d;
+ font-weight: 700;
+ }
+
+ .payload-cell {
+ display: inline-block;
+ max-width: 280px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .mono {
+ font-family: Menlo, Monaco, Consolas, "Liberation Mono", monospace;
+ }
+
+ .pager-bar {
+ padding: 0 16px 16px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ }
+
+ .column-popover {
+ max-width: 320px;
+ }
+
+ .column-popover-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 10px;
+ font-size: 13px;
+ font-weight: 700;
+ color: var(--text-main);
+ }
+
+ .column-list {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px 10px;
+ max-height: 280px;
+ overflow: auto;
+ padding-right: 4px;
+ }
+
+ .dialog-panel .el-dialog {
+ border-radius: 24px;
+ overflow: hidden;
+ }
+
+ .dialog-panel .el-dialog__header {
+ padding: 22px 24px 12px;
+ background: linear-gradient(180deg, #f8fbff 0%, #f3f7fb 100%);
+ border-bottom: 1px solid rgba(224, 232, 241, 0.92);
+ }
+
+ .dialog-panel .el-dialog__title {
+ font-weight: 700;
+ color: var(--text-main);
+ }
+
+ .dialog-panel .el-dialog__body {
+ padding: 18px 24px 8px;
+ }
+
+ .dialog-footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ }
+
+ @media (max-width: 1520px) {
+ .advanced-grid {
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+ }
+ }
+
+ @media (max-width: 1280px) {
+ .advanced-grid {
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ }
+ }
+
+ @media (max-width: 960px) {
+ .toolbar-left {
+ flex-basis: 100%;
+ }
+
+ .advanced-grid {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ }
+
+ .advanced-item.span-2 {
+ grid-column: span 2;
+ }
+ }
+
+ @media (max-width: 720px) {
+ .page-shell {
+ padding: 12px;
+ }
+
+ .toolbar-search-item,
+ .toolbar-search-item.keyword {
+ min-width: 100%;
+ flex-basis: 100%;
+ }
+
+ .toolbar-query-actions,
+ .toolbar-ops {
+ width: 100%;
+ }
+
+ .advanced-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+
+ .advanced-item.span-2 {
+ grid-column: span 2;
+ }
+ }
+
+ @media (max-width: 560px) {
+ .advanced-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .advanced-item.span-2 {
+ grid-column: auto;
+ }
+
+ .list-toolbar,
+ .advanced-panel,
+ .table-wrap,
+ .pager-bar {
+ padding-left: 14px;
+ padding-right: 14px;
+ }
+
+ .column-list {
+ grid-template-columns: 1fr;
+ }
+ }
+ </style>
+</head>
+<body>
+<div id="app" class="page-shell" v-cloak>
+ <section class="card-shell list-card">
+ <div class="card-body">
+ <div class="list-toolbar">
+ <div class="toolbar-main">
+ <div class="toolbar-left">
+ <div class="toolbar-search">
+ <div class="toolbar-search-item keyword">
+ <el-input
+ v-model.trim="searchForm.condition"
+ size="small"
+ clearable
+ placeholder="璇疯緭鍏�"
+ @keyup.enter.native="handleSearch">
+ </el-input>
+ </div>
+ <div
+ v-for="field in quickSearchableFields"
+ :key="'quick-' + field.field"
+ class="toolbar-search-item">
+ <el-select
+ v-if="field.kind === 'enum'"
+ v-model="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ style="width: 100%;">
+ <el-option
+ v-for="option in field.enumOptions"
+ :key="'quick-' + field.field + '-' + option.rawValue"
+ :label="option.label"
+ :value="normalizeOptionValue(field, option.rawValue)">
+ </el-option>
+ </el-select>
+ <el-autocomplete
+ v-else-if="field.kind === 'foreign'"
+ v-model="searchDisplay[field.field]"
+ size="small"
+ :fetch-suggestions="getSuggestionFetcher(field)"
+ :placeholder="field.label"
+ style="width: 100%;"
+ @select="handleSearchForeignSelect(field, $event)"
+ @input="handleSearchForeignInput(field)">
+ <template slot-scope="{ item }">
+ <div class="mono">{{ item.value }}</div>
+ <div style="font-size:12px;color:#8a98ac;">ID: {{ item.id }}</div>
+ </template>
+ </el-autocomplete>
+ <el-select
+ v-else-if="field.kind === 'checkbox'"
+ v-model="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ style="width: 100%;">
+ <el-option label="鏄�" :value="normalizeOptionValue(field, field.checkboxActiveRaw)"></el-option>
+ <el-option label="鍚�" :value="normalizeOptionValue(field, field.checkboxInactiveRaw)"></el-option>
+ </el-select>
+ <el-input
+ v-else
+ v-model.trim="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ @keyup.enter.native="handleSearch">
+ </el-input>
+ </div>
+ </div>
+ <div class="toolbar-query-actions">
+ <el-button size="small" type="primary" icon="el-icon-search" @click="handleSearch">鎼滅储</el-button>
+ <el-button size="small" icon="el-icon-refresh-left" @click="handleReset">閲嶇疆</el-button>
+ <el-button
+ v-if="hasAdvancedFilters"
+ size="small"
+ plain
+ :icon="advancedFiltersVisible ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
+ @click="toggleAdvancedFilters">
+ {{ advancedFiltersVisible ? '鏀惰捣' : '绛涢��' }}
+ </el-button>
+ </div>
+ </div>
+ <div class="toolbar-ops">
+ <el-button size="small" type="primary" plain icon="el-icon-plus" @click="openCreateDialog">鏂板</el-button>
+ <el-button size="small" type="danger" plain icon="el-icon-delete" :disabled="selection.length === 0" @click="removeSelection">鍒犻櫎</el-button>
+ <el-popover
+ placement="bottom"
+ width="320"
+ trigger="click"
+ popper-class="column-popover">
+ <div class="column-popover-head">
+ <span>鍒楄缃�</span>
+ <div>
+ <el-button type="text" @click="selectAllColumns">鍏ㄩ��</el-button>
+ <el-button type="text" @click="resetColumns">閲嶇疆</el-button>
+ </div>
+ </div>
+ <div class="column-list">
+ <el-checkbox
+ v-for="field in allColumns"
+ :key="'column-' + field.field"
+ :value="isColumnVisible(field.field)"
+ @change="toggleColumn(field.field, $event)">
+ {{ field.label }}
+ </el-checkbox>
+ </div>
+ <el-button slot="reference" size="small" plain icon="el-icon-setting">鍒楄缃�</el-button>
+ </el-popover>
+ <el-button size="small" plain icon="el-icon-download" :loading="exporting" @click="exportRows">瀵煎嚭</el-button>
+ </div>
+ </div>
+ </div>
+
+ <el-collapse-transition>
+ <div v-show="advancedFiltersVisible && hasAdvancedFilters" class="advanced-panel">
+ <div class="advanced-grid">
+ <div
+ v-for="field in advancedSearchableFields"
+ :key="'advanced-' + field.field"
+ :class="['advanced-item', field.kind === 'date' ? 'span-2' : '']">
+ <el-date-picker
+ v-if="field.kind === 'date'"
+ v-model="searchForm[field.field]"
+ size="small"
+ type="datetimerange"
+ unlink-panels
+ range-separator="鑷�"
+ :start-placeholder="field.label + '寮�濮�'"
+ :end-placeholder="field.label + '缁撴潫'"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ style="width: 100%;">
+ </el-date-picker>
+ <el-select
+ v-else-if="field.kind === 'enum'"
+ v-model="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ style="width: 100%;">
+ <el-option
+ v-for="option in field.enumOptions"
+ :key="'advanced-' + field.field + '-' + option.rawValue"
+ :label="option.label"
+ :value="normalizeOptionValue(field, option.rawValue)">
+ </el-option>
+ </el-select>
+ <el-autocomplete
+ v-else-if="field.kind === 'foreign'"
+ v-model="searchDisplay[field.field]"
+ size="small"
+ :fetch-suggestions="getSuggestionFetcher(field)"
+ :placeholder="field.label"
+ style="width: 100%;"
+ @select="handleSearchForeignSelect(field, $event)"
+ @input="handleSearchForeignInput(field)">
+ <template slot-scope="{ item }">
+ <div class="mono">{{ item.value }}</div>
+ <div style="font-size:12px;color:#8a98ac;">ID: {{ item.id }}</div>
+ </template>
+ </el-autocomplete>
+ <el-select
+ v-else-if="field.kind === 'checkbox'"
+ v-model="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ style="width: 100%;">
+ <el-option label="鏄�" :value="normalizeOptionValue(field, field.checkboxActiveRaw)"></el-option>
+ <el-option label="鍚�" :value="normalizeOptionValue(field, field.checkboxInactiveRaw)"></el-option>
+ </el-select>
+ <el-input
+ v-else
+ v-model.trim="searchForm[field.field]"
+ size="small"
+ clearable
+ :placeholder="field.label"
+ @keyup.enter.native="handleSearch">
+ </el-input>
+ </div>
+ </div>
+ </div>
+ </el-collapse-transition>
+
+ <div class="table-wrap">
+ <div class="table-shell">
+ <el-table
+ ref="dataTable"
+ :key="'table-' + visibleColumnKeys.join('|')"
+ v-loading="loading"
+ :data="tableData"
+ border
+ stripe
+ :height="tableHeight"
+ @selection-change="handleSelectionChange"
+ @sort-change="handleSortChange">
+ <el-table-column type="selection" width="52" align="center"></el-table-column>
+ <el-table-column
+ v-for="field in visibleColumns"
+ :key="field.field"
+ :prop="field.field"
+ :label="field.label"
+ :width="field.primaryKey ? 90 : null"
+ :min-width="field.primaryKey ? null : field.minWidth"
+ :sortable="isSortableField(field) ? 'custom' : false"
+ :show-overflow-tooltip="field.kind !== 'image'"
+ align="center">
+ <template slot-scope="scope">
+ <el-image
+ v-if="field.kind === 'image' && getTableValue(scope.row, field)"
+ :src="getTableValue(scope.row, field)"
+ fit="cover"
+ style="width: 48px; height: 48px; border-radius: 10px;">
+ </el-image>
+ <el-tag v-else-if="field.kind === 'enum'" size="mini" type="success">
+ {{ valueOrDash(getTableValue(scope.row, field)) }}
+ </el-tag>
+ <el-tag v-else-if="field.kind === 'checkbox'" size="mini" :type="isCheckboxChecked(scope.row, field) ? 'success' : 'info'">
+ {{ isCheckboxChecked(scope.row, field) ? '鏄�' : '鍚�' }}
+ </el-tag>
+ <span v-else-if="field.textarea" class="payload-cell mono" :title="stringValue(getTableValue(scope.row, field))">
+ {{ valueOrDash(getTableValue(scope.row, field)) }}
+ </span>
+ <span v-else>{{ valueOrDash(getTableValue(scope.row, field)) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="160" fixed="right" align="center">
+ <template slot-scope="scope">
+ <el-button type="text" @click="openEditDialog(scope.row)">淇敼</el-button>
+ <el-button type="text" style="color:#f56c6c;" @click="removeRows([scope.row[primaryKeyField]])">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+
+ <div class="pager-bar">
+ <el-pagination
+ small
+ background
+ layout="total, sizes, prev, pager, next, jumper"
+ :current-page="page.curr"
+ :page-size="page.limit"
+ :page-sizes="[15, 30, 50, 100, 200, 500]"
+ :total="page.total"
+ @current-change="handleCurrentChange"
+ @size-change="handleSizeChange">
+ </el-pagination>
+ </div>
+ </div>
+ </section>
+
+ <el-dialog
+ class="dialog-panel"
+ :title="dialog.mode === 'create' ? '鏂板杈撻�佺珯鐐瑰紓甯告棩蹇�' : '淇敼杈撻�佺珯鐐瑰紓甯告棩蹇�'"
+ :visible.sync="dialog.visible"
+ width="760px"
+ :close-on-click-modal="false">
+ <el-form
+ ref="dialogForm"
+ :model="dialogForm"
+ :rules="dialogRules"
+ label-width="110px"
+ size="small">
+ <el-row :gutter="16">
+ <el-col
+ v-for="field in editableFields"
+ :key="'dialog-' + field.field"
+ :span="field.textarea || field.kind === 'image' ? 24 : 12">
+ <el-form-item :label="field.label" :prop="field.field">
+ <el-date-picker
+ v-if="field.kind === 'date'"
+ v-model="dialogForm[field.field]"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ :placeholder="'璇烽�夋嫨' + field.label"
+ style="width: 100%;">
+ </el-date-picker>
+ <el-select
+ v-else-if="field.kind === 'enum'"
+ v-model="dialogForm[field.field]"
+ clearable
+ :placeholder="'璇烽�夋嫨' + field.label"
+ style="width: 100%;">
+ <el-option
+ v-for="option in field.enumOptions"
+ :key="'dialog-' + field.field + '-' + option.rawValue"
+ :label="option.label"
+ :value="normalizeOptionValue(field, option.rawValue)">
+ </el-option>
+ </el-select>
+ <el-autocomplete
+ v-else-if="field.kind === 'foreign'"
+ v-model="dialogDisplay[field.field]"
+ :fetch-suggestions="getSuggestionFetcher(field)"
+ :placeholder="'璇疯緭鍏�' + field.label"
+ style="width: 100%;"
+ @select="handleForeignSelect(field, $event)"
+ @input="handleForeignInput(field)">
+ <template slot-scope="{ item }">
+ <div class="mono">{{ item.value }}</div>
+ <div style="font-size:12px;color:#8a98ac;">ID: {{ item.id }}</div>
+ </template>
+ </el-autocomplete>
+ <el-switch
+ v-else-if="field.kind === 'checkbox'"
+ v-model="dialogForm[field.field]"
+ :active-value="normalizeOptionValue(field, field.checkboxActiveRaw)"
+ :inactive-value="normalizeOptionValue(field, field.checkboxInactiveRaw)"
+ active-color="#13ce66"
+ inactive-color="#c0c4cc">
+ </el-switch>
+ <el-input
+ v-else-if="field.textarea"
+ v-model.trim="dialogForm[field.field]"
+ type="textarea"
+ :rows="3"
+ :placeholder="'璇疯緭鍏�' + field.label">
+ </el-input>
+ <el-input
+ v-else
+ v-model.trim="dialogForm[field.field]"
+ :placeholder="'璇疯緭鍏�' + field.label">
+ </el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="dialog.visible = false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="dialog.submitting" @click="submitDialog">淇濆瓨</el-button>
+ </div>
+ </el-dialog>
+</div>
+
+<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
+<script type="text/javascript" src="../../static/vue/element/element.js"></script>
+<script type="text/javascript" src="../../static/js/basStationErrLog/basStationErrLog.js?v=20260331" charset="utf-8"></script>
+</body>
+</html>
--
Gitblit v1.9.1