reportEngine:重新生成报告
This commit is contained in:
parent
32613c73db
commit
e81c128e1c
@ -71,6 +71,17 @@ public class ReportController extends BaseController {
|
|||||||
return AjaxResult.success("报表生成任务已提交,请稍后查询状态", reportNo);
|
return AjaxResult.success("报表生成任务已提交,请稍后查询状态", reportNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新生成失败的报表(沿用首次生成的设备口径与时间窗口,生成新的报告编号)
|
||||||
|
*/
|
||||||
|
@ApiOperation("重新生成失败报表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('iot:report:generate')")
|
||||||
|
@PostMapping("/regenerate/{reportNo}")
|
||||||
|
public AjaxResult regenerate(@PathVariable("reportNo") String reportNo) {
|
||||||
|
String newReportNo = reportAsyncExecutor.resubmitFailed(reportNo);
|
||||||
|
return AjaxResult.success("报表生成任务已重新提交,请稍后查询状态", newReportNo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询报表生成状态
|
* 查询报表生成状态
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.fastbee.report.executor;
|
package com.fastbee.report.executor;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.fastbee.common.core.redis.RedisCache;
|
import com.fastbee.common.core.redis.RedisCache;
|
||||||
import com.fastbee.common.enums.MonitorCategory;
|
import com.fastbee.common.enums.MonitorCategory;
|
||||||
import com.fastbee.common.utils.StringUtils;
|
import com.fastbee.common.utils.StringUtils;
|
||||||
@ -33,6 +34,7 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@ -136,6 +138,63 @@ public class ReportAsyncExecutor {
|
|||||||
return reportNo;
|
return reportNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新生成失败的报告
|
||||||
|
*
|
||||||
|
* <p>按落库的原始请求参数重新提交异步任务,返回新报告编号(原失败记录保留,便于追溯)。
|
||||||
|
* 时间窗口固定回放首次生成时已解析出来的 start/end,避免"日报/周报"这类周期报告
|
||||||
|
* 隔天重生成时被重新解析成另一个统计区间。</p>
|
||||||
|
*
|
||||||
|
* @param reportNo 失败记录的报告编号
|
||||||
|
* @return 新报告编号
|
||||||
|
*/
|
||||||
|
public String resubmitFailed(String reportNo) {
|
||||||
|
ReportRecord record = reportRecordService.findByReportNo(reportNo);
|
||||||
|
if (record == null) {
|
||||||
|
throw new ReportException("报告不存在:" + reportNo);
|
||||||
|
}
|
||||||
|
if (!ReportRecord.STATUS_FAILED.equals(record.getStatus())) {
|
||||||
|
throw new ReportException("仅生成失败的报告可以重新生成");
|
||||||
|
}
|
||||||
|
return submitAsyncTask(restoreRequest(record));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还原首次生成时的请求参数
|
||||||
|
*
|
||||||
|
* <p>优先使用落库的 request_json(保留 groupId / deviceIds 多测点口径),
|
||||||
|
* 历史记录缺该列时退化为记录中的设备ID 单设备重建。</p>
|
||||||
|
*/
|
||||||
|
private ReportRequest restoreRequest(ReportRecord record) {
|
||||||
|
ReportRequest request = null;
|
||||||
|
if (StringUtils.isNotEmpty(record.getRequestJson())) {
|
||||||
|
try {
|
||||||
|
request = JSON.parseObject(record.getRequestJson(), ReportRequest.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("报告原始请求解析失败,退化为单设备重生成 reportNo={} json={}",
|
||||||
|
record.getReportNo(), record.getRequestJson(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request == null) {
|
||||||
|
request = new ReportRequest();
|
||||||
|
request.setDeviceId(record.getDeviceId());
|
||||||
|
}
|
||||||
|
request.setStartTime(formatGmt8(record.getStartTime()));
|
||||||
|
request.setEndTime(formatGmt8(record.getEndTime()));
|
||||||
|
// 清空周期参数:start/end 已确定,若保留 period 会在 start/end 缺失时被按"今天"重新解析
|
||||||
|
request.setPeriod(null);
|
||||||
|
request.setAnchorDate(null);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatGmt8(Date time) {
|
||||||
|
if (time == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return LocalDateTime.ofInstant(time.toInstant(), ZoneOffset.ofHours(8))
|
||||||
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步执行生成逻辑(支持多测点:网关子设备 / 直连多选 / 设备分组)
|
* 异步执行生成逻辑(支持多测点:网关子设备 / 直连多选 / 设备分组)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -51,5 +51,11 @@ public class ReportRecord extends BaseEntity {
|
|||||||
|
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首次生成时的原始请求 JSON(ReportRequest),供失败重生成回放,
|
||||||
|
* 保证 groupId / deviceIds 多测点口径与首次一致
|
||||||
|
*/
|
||||||
|
private String requestJson;
|
||||||
|
|
||||||
private Long tenantId;
|
private Long tenantId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.fastbee.report.record;
|
package com.fastbee.report.record;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.fastbee.common.utils.DateUtils;
|
import com.fastbee.common.utils.DateUtils;
|
||||||
import com.fastbee.report.core.ReportContext;
|
import com.fastbee.report.core.ReportContext;
|
||||||
import com.fastbee.report.mapper.ReportRecordMapper;
|
import com.fastbee.report.mapper.ReportRecordMapper;
|
||||||
@ -34,6 +35,10 @@ public class ReportRecordServiceImpl implements ReportRecordService {
|
|||||||
record.setStartTime(toGmt8Date(context.getTimeWindow().getStartTime()));
|
record.setStartTime(toGmt8Date(context.getTimeWindow().getStartTime()));
|
||||||
record.setEndTime(toGmt8Date(context.getTimeWindow().getEndTime()));
|
record.setEndTime(toGmt8Date(context.getTimeWindow().getEndTime()));
|
||||||
record.setStatus(ReportRecord.STATUS_CREATING);
|
record.setStatus(ReportRecord.STATUS_CREATING);
|
||||||
|
// 落库原始请求,失败后可用同一口径(含 groupId / deviceIds)重新生成
|
||||||
|
if (context.getRequest() != null) {
|
||||||
|
record.setRequestJson(JSON.toJSONString(context.getRequest()));
|
||||||
|
}
|
||||||
record.setTenantId(context.getTenantId());
|
record.setTenantId(context.getTenantId());
|
||||||
record.setCreateBy(context.getCreateBy());
|
record.setCreateBy(context.getCreateBy());
|
||||||
record.setCreateTime(now);
|
record.setCreateTime(now);
|
||||||
|
|||||||
@ -14,6 +14,18 @@
|
|||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
ALTER TABLE `iot_product` ADD COLUMN `monitor_category_code` VARCHAR(64) DEFAULT NULL COMMENT '监测分类编码(CRACK_METER/DEEP_DISPLACEMENT/AXIAL_FORCE/STATIC_LEVEL/VIBRATING_WIRE/STRAIN_GAUGE/WATER_LEVEL/RANGING_METER/INCLINOMETER/THERMOMETER/RAIN_GAUGE)' AFTER `category_name`;
|
ALTER TABLE `iot_product` ADD COLUMN `monitor_category_code` VARCHAR(64) DEFAULT NULL COMMENT '监测分类编码(CRACK_METER/DEEP_DISPLACEMENT/AXIAL_FORCE/STATIC_LEVEL/VIBRATING_WIRE/STRAIN_GAUGE/WATER_LEVEL/RANGING_METER/INCLINOMETER/THERMOMETER/RAIN_GAUGE)' AFTER `category_name`;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- 1. 设备级基准点(相对测量用)
|
||||||
|
-- 静力水准等设备的读数是相对基准点的,累计变化量需按
|
||||||
|
-- 「(当前读数 − 基准点当前读数) − (初始读数 − 基准点初始读数)」计算。
|
||||||
|
-- deviceId 全局唯一,因此天然支持跨网关引用
|
||||||
|
-- (如 GW2 的监测点引用 GW1 下的参考点)。
|
||||||
|
-- 留空表示该设备为绝对量测量,不参与基准点换算。
|
||||||
|
-- ============================================================
|
||||||
|
ALTER TABLE iot_device
|
||||||
|
ADD COLUMN baseline_device_id BIGINT NULL COMMENT '基准点设备ID(相对测量用,留空=绝对量)' AFTER serial_number;
|
||||||
|
|
||||||
|
|
||||||
-- 存量产品按产品名回填监测分类
|
-- 存量产品按产品名回填监测分类
|
||||||
UPDATE `iot_product` SET `monitor_category_code` = 'CRACK_METER'
|
UPDATE `iot_product` SET `monitor_category_code` = 'CRACK_METER'
|
||||||
WHERE (`monitor_category_code` IS NULL OR `monitor_category_code` = '')
|
WHERE (`monitor_category_code` IS NULL OR `monitor_category_code` = '')
|
||||||
@ -107,6 +119,7 @@ CREATE TABLE `report_record` (
|
|||||||
`file_name` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '文件名称',
|
`file_name` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '文件名称',
|
||||||
`file_url` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '文件地址',
|
`file_url` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '文件地址',
|
||||||
`error_message` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '失败原因',
|
`error_message` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '失败原因',
|
||||||
|
`request_json` varchar(2048) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '原始生成请求JSON(失败重生成用,保留 groupId/deviceIds 口径)',
|
||||||
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
|
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
|
||||||
`create_by` varchar(64) COLLATE utf8_unicode_ci DEFAULT '' COMMENT '创建者',
|
`create_by` varchar(64) COLLATE utf8_unicode_ci DEFAULT '' COMMENT '创建者',
|
||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
@ -117,6 +130,22 @@ CREATE TABLE `report_record` (
|
|||||||
UNIQUE KEY `uk_report_no` (`report_no`) USING BTREE
|
UNIQUE KEY `uk_report_no` (`report_no`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='报告生成记录';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='报告生成记录';
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
-- 2.4 report_record 原始请求列(失败重生成)
|
||||||
|
-- 全新库:上面 CREATE TABLE 已含 request_json 列;
|
||||||
|
-- 存量库:由下面的语句补列。用 information_schema 做存在性判断,可重复执行
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
SET @exist_col := (SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'report_record'
|
||||||
|
AND COLUMN_NAME = 'request_json');
|
||||||
|
SET @ddl_sql := IF(@exist_col = 0,
|
||||||
|
'ALTER TABLE `report_record` ADD COLUMN `request_json` varchar(2048) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ''原始生成请求JSON(失败重生成用,保留 groupId/deviceIds 口径)'' AFTER `error_message`',
|
||||||
|
'SELECT ''skip: report_record.request_json already exists'' AS info');
|
||||||
|
PREPARE ddl_stmt FROM @ddl_sql;
|
||||||
|
EXECUTE ddl_stmt;
|
||||||
|
DEALLOCATE PREPARE ddl_stmt;
|
||||||
|
|
||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
-- 3. oss_config:MinIO 默认配置(未购买云 OSS → 自建 MinIO)
|
-- 3. oss_config:MinIO 默认配置(未购买云 OSS → 自建 MinIO)
|
||||||
-- endpoint:后端连接 MinIO 的 S3 API 地址(若后端与 MinIO 同机可改为 http://127.0.0.1:9000)
|
-- endpoint:后端连接 MinIO 的 S3 API 地址(若后端与 MinIO 同机可改为 http://127.0.0.1:9000)
|
||||||
@ -125,7 +154,7 @@ CREATE TABLE `report_record` (
|
|||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
UPDATE `oss_config` SET `status` = '1' WHERE `config_key` IN ('aliyun', 'qiniu');
|
UPDATE `oss_config` SET `status` = '1' WHERE `config_key` IN ('aliyun', 'qiniu');
|
||||||
|
|
||||||
INSERT IGNORE INTO `oss_config`
|
INSERT INTO `oss_config`
|
||||||
(tenant_id, tenant_name, config_key, access_key, secret_key, bucket_name, prefix,
|
(tenant_id, tenant_name, config_key, access_key, secret_key, bucket_name, prefix,
|
||||||
endpoint, domain, is_https, region, access_policy, status, del_flag, create_by, create_time, update_by, update_time, remark)
|
endpoint, domain, is_https, region, access_policy, status, del_flag, create_by, create_time, update_by, update_time, remark)
|
||||||
VALUES
|
VALUES
|
||||||
@ -135,12 +164,26 @@ VALUES
|
|||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
-- 4. 历史报表菜单与权限(数据中心 3343 下新增)
|
-- 4. 历史报表菜单与权限(数据中心 3343 下新增)
|
||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
INSERT IGNORE INTO `sys_menu`
|
INSERT INTO `sys_menu`
|
||||||
(menu_id, menu_name, parent_id, order_num, `path`, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
(menu_id, menu_name, parent_id, order_num, `path`, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||||
VALUES
|
VALUES
|
||||||
(3610, '历史报表', 3343, 4, 'reportHistory', 'dataCenter/reportHistory', NULL, 1, 0, 'C', '0', '0', 'iot:report:list', 'documentation', 'admin', NOW(), 'admin', NOW(), '设备监测报告历史报表'),
|
(3610, '历史报表', 3343, 4, 'reportHistory', 'dataCenter/reportHistory', NULL, 1, 0, 'C', '0', '0', 'iot:report:list', 'documentation', 'admin', NOW(), 'admin', NOW(), '设备监测报告历史报表'),
|
||||||
(3611, '报表生成', 3610, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'iot:report:generate', '#', 'admin', NOW(), 'admin', NOW(), '生成并导出分析报告');
|
(3611, '报表生成', 3610, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'iot:report:generate', '#', 'admin', NOW(), 'admin', NOW(), '生成并导出分析报告');
|
||||||
|
|
||||||
INSERT IGNORE INTO `sys_menu_translate` (id, zh_cn, en_us) VALUES
|
INSERT INTO `sys_menu_translate` (id, zh_cn, en_us) VALUES
|
||||||
(3610, '历史报表', 'Report history'),
|
(3610, '历史报表', 'Report history'),
|
||||||
(3611, '报表生成', 'Generate report');
|
(3611, '报表生成', 'Generate report');
|
||||||
|
|
||||||
|
-- 初始数据
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'DEEP_DISPLACEMENT', 'displacement', 20.000000, 30.000000, 50.000000, 2.000000, 3.000000, 5.000000, 'mm', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'STATIC_LEVEL', 'settlement', 15.000000, 25.000000, 40.000000, 1.500000, 2.000000, 3.000000, 'mm', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'CRACK_METER', 'crack_width', 0.300000, 0.500000, 1.000000, 0.050000, 0.100000, 0.200000, 'mm', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'AXIAL_FORCE', 'axial_force', NULL, NULL, NULL, NULL, NULL, NULL, 'kN', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'RANGING_METER', 'distance', 15.000000, 25.000000, 40.000000, 1.000000, 2.000000, 3.000000, 'mm', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'INCLINOMETER', 'inclination', 1.000000, 2.000000, 3.000000, 0.100000, 0.200000, 0.500000, '°', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'WATER_LEVEL', 'water_level', 0.500000, 1.000000, 2.000000, 0.500000, 1.000000, 1.500000, 'm', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'STRAIN_GAUGE', 'strain', 500.000000, 800.000000, 1000.000000, 50.000000, 100.000000, 200.000000, 'με', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'VIBRATING_WIRE', 'frequency', 30.000000, 40.000000, 50.000000, NULL, NULL, NULL, 'Hz', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'THERMOMETER', 'temperature', 10.000000, 15.000000, 20.000000, 2.000000, 3.000000, 5.000000, '℃', 'admin', NOW());
|
||||||
|
INSERT INTO fastbee.iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, warning_rate, alarm_rate, control_rate, unit, create_by, create_time) VALUES(0, 0, 'RAIN_GAUGE', 'rainfall', 25.000000, 50.000000, 100.000000, 25.000000, 50.000000, 100.000000, 'mm', 'admin', NOW());
|
||||||
|
|
||||||
|
|||||||
@ -1,110 +0,0 @@
|
|||||||
-- 报告阈值初始化脚本(基于 JGJ 8-2016、GB 50497-2019 等行业标准)
|
|
||||||
-- 使用方式:在 fastbee 数据库中执行此脚本
|
|
||||||
-- 说明:product_id=0 表示全局默认,可被产品级/设备级配置覆盖
|
|
||||||
|
|
||||||
-- 1. 深部位移(累计位移控制值通常 30-100mm,速率预警值 2mm/d)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'DEEP_DISPLACEMENT', 'displacement', 20.00, 30.00, 50.00, 'mm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 2. 静力水准(累计沉降控制值通常 20-60mm,速率预警值 2mm/d)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'STATIC_LEVEL', 'settlement', 15.00, 25.00, 40.00, 'mm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 3. 裂缝计(裂缝宽度控制值通常 0.3-1.0mm,变化量预警值 0.2mm)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'CRACK_METER', 'crack_width', 0.30, 0.50, 1.00, 'mm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 4. 轴力计(轴力控制值按设计值的 60%-80%,这里设为相对值)
|
|
||||||
-- 注:轴力阈值通常需根据设计值动态计算,此处仅作示例
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'AXIAL_FORCE', 'axial_force', NULL, NULL, NULL, 'kN', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 5. 测距仪(收敛变形控制值通常 20-50mm)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'RANGING_METER', 'distance', 15.00, 25.00, 40.00, 'mm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 6. 倾角计(倾斜角度控制值通常 1°-3°)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'INCLINOMETER', 'inclination', 1.00, 2.00, 3.00, '°', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 7. 水位计(水位变化控制值通常 0.5-2.0m)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'WATER_LEVEL', 'water_level', 0.50, 1.00, 2.00, 'm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 8. 应变计(应变控制值通常 ±1000με)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'STRAIN_GAUGE', 'strain', 500.00, 800.00, 1000.00, 'με', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 9. 振弦式传感器(频率变化控制值通常 ±50Hz)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'VIBRATING_WIRE', 'frequency', 30.00, 40.00, 50.00, 'Hz', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 10. 温度计(温度变化控制值通常 ±15℃)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'THERMOMETER', 'temperature', 10.00, 15.00, 20.00, '℃', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 11. 雨量计(累计降雨量预警值通常 50mm/d)
|
|
||||||
INSERT INTO iot_things_threshold (product_id, device_id, monitor_category_code, metric_identifier, warning_value, alarm_value, control_value, unit, create_by, create_time)
|
|
||||||
VALUES (0, 0, 'RAIN_GAUGE', 'rainfall', 25.00, 50.00, 100.00, 'mm', 'admin', NOW());
|
|
||||||
|
|
||||||
-- 说明:
|
|
||||||
-- 1. 以上阈值基于 JGJ 8-2016《建筑变形测量规范》、GB 50497-2019《建筑基坑工程监测标准》
|
|
||||||
-- 等行业标准,适用于一般建筑工程。实际项目应根据设计要求调整。
|
|
||||||
-- 2. product_id=0 表示全局默认,如需针对特定产品,请复制以上记录并修改 product_id。
|
|
||||||
-- 3. metric_identifier 需与物模型标识符匹配,如不匹配则阈值不生效。
|
|
||||||
-- 4. 预警值 < 报警值 < 控制值,系统会按当前值与阈值的比较自动判断安全等级。
|
|
||||||
|
|
||||||
|
|
||||||
-- 结构安全监测改造:设备级基准点 + 阈值速率维度(双控)
|
|
||||||
-- 执行前请确认已备份,且字段尚未存在(MySQL 不支持 ADD COLUMN IF NOT EXISTS,重复执行会报错)
|
|
||||||
|
|
||||||
-- ============================================================
|
|
||||||
-- 1. 设备级基准点(相对测量用)
|
|
||||||
-- 静力水准等设备的读数是相对基准点的,累计变化量需按
|
|
||||||
-- 「(当前读数 − 基准点当前读数) − (初始读数 − 基准点初始读数)」计算。
|
|
||||||
-- deviceId 全局唯一,因此天然支持跨网关引用
|
|
||||||
-- (如 GW2 的监测点引用 GW1 下的参考点)。
|
|
||||||
-- 留空表示该设备为绝对量测量,不参与基准点换算。
|
|
||||||
-- ============================================================
|
|
||||||
ALTER TABLE iot_device
|
|
||||||
ADD COLUMN baseline_device_id BIGINT NULL COMMENT '基准点设备ID(相对测量用,留空=绝对量)' AFTER serial_number;
|
|
||||||
|
|
||||||
-- ============================================================
|
|
||||||
-- 2. 阈值表:变化速率维度
|
|
||||||
-- 依据 GB 50497-2019 第 8.0.4 条(强制性条文):
|
|
||||||
-- 监测报警按「累计变化量」与「变化速率」双控,任一超限即取较严重等级。
|
|
||||||
-- 单位统一为「单位/天」,例如 mm/d、kN/d。
|
|
||||||
-- ============================================================
|
|
||||||
ALTER TABLE iot_things_threshold
|
|
||||||
ADD COLUMN warning_rate DECIMAL(18, 6) NULL COMMENT '变化速率预警值(单位/天)' AFTER control_value,
|
|
||||||
ADD COLUMN alarm_rate DECIMAL(18, 6) NULL COMMENT '变化速率报警值(单位/天)' AFTER warning_rate,
|
|
||||||
ADD COLUMN control_rate DECIMAL(18, 6) NULL COMMENT '变化速率控制值(单位/天)' AFTER alarm_rate;
|
|
||||||
|
|
||||||
-- ============================================================
|
|
||||||
-- 附:各行业规范推荐取值(供配置产品阈值时参考,不写入全局默认值)
|
|
||||||
-- 未配置阈值的产品将输出「待评估」,不会伪造为「安全」。
|
|
||||||
--
|
|
||||||
-- 监测项目 累计控制值 速率预警值 依据
|
|
||||||
-- 深部位移(测斜) 40~50mm (0.4%~0.5%H) 3~5 mm/d GB 50497-2019
|
|
||||||
-- 支护结构顶部位移 25~30mm (0.2%~0.3%H) 3~5 mm/d GB 50497-2019
|
|
||||||
-- 周边地表沉降 25~35mm 3~5 mm/d GB 50497-2019
|
|
||||||
-- 管片结构沉降 硬土 10~20 / 软土 20~30mm 2~3 mm/d GB 50911-2013
|
|
||||||
-- 管片结构隆起 10mm 1 mm/d GB 50911-2013
|
|
||||||
-- 净空收敛(测距仪) 0.2%D 或 10mm 3 mm/d GB 50911-2013
|
|
||||||
-- 差异沉降 0.04%La 3 mm/d GB 50911-2013
|
|
||||||
-- 地下水位变化 1000~2000mm(常年变幅外) 500 mm/d GB 50497-2019 表8.0.5
|
|
||||||
-- 裂缝(结构性/既有) 1.5~3mm 持续发展 GB 50497-2019 表8.0.5
|
|
||||||
-- 裂缝(地表/新增) 1~3mm 持续发展 GB 50497-2019 表8.0.5
|
|
||||||
-- 锚索/支撑轴力 构件承载力设计值的 80% ≥80% 且持续增长 GB 50497-2019 8.0.6
|
|
||||||
-- 管线沉降(刚性/压力) 10~20mm 2 mm/d GB 50497-2019 表8.0.5
|
|
||||||
-- 构筑物及无压管线 20~25mm 2 mm/d GB 50157-2013
|
|
||||||
-- 建筑物倾斜 — 2°/d GB 50157-2013
|
|
||||||
--
|
|
||||||
-- 三级取值比例(设计允许值为基准):
|
|
||||||
-- 预警值 ≈ 60%~70% 报警值 ≈ 80% 控制值 = 100%
|
|
||||||
-- 速率细则:
|
|
||||||
-- 达到规定值、或连续 3 次超过该值的 70%,即应预警;
|
|
||||||
-- 底板浇筑完成后,速率不宜超过速率预警值的 70%。
|
|
||||||
-- 注:雨量计不是安全指标,规范中是工况触发因素(雨季/暴雨后须加测),
|
|
||||||
-- 不应参与预警判定。
|
|
||||||
-- ============================================================
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
# 数据中心 · 历史记录 · 曲线趋势图改造方案
|
|
||||||
|
|
||||||
## 1. 背景与问题
|
|
||||||
|
|
||||||
### 1.1 业务场景
|
|
||||||
|
|
||||||
路径:**数据中心 → 历史记录**([`history.vue`](../src/views/dataCenter/history.vue))。
|
|
||||||
|
|
||||||
页面含三个 Tab:**设备**、**网关设备**、**场景**,各自有「曲线趋势图」或网关下的计算量 / 多设备对比 / 单子设备折线图。
|
|
||||||
|
|
||||||
### 1.2 原始痛点
|
|
||||||
|
|
||||||
| 问题 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 多曲线「压成直线」 | 多物模型量级差异大(如位移 168、角度 3、电压 12),共用单 Y 轴时范围被拉大,小幅波动在图上不可见。 |
|
|
||||||
| 多 Y 轴布局异常 | 为每条曲线建隐藏 Y 轴时,ECharts 会为多轴计算偏移,曲线一多时绘图区被挤到一侧。 |
|
|
||||||
| 图例占用空间 | 网关多设备对比图例项极多,默认换行占满高度,挤压 grid。 |
|
|
||||||
| X 轴可读性 | 时间点密集时标签重叠。 |
|
|
||||||
| 垂直空间不足 | 固定 480px 高度时,几十条归一化曲线仍显拥挤。 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 总体思路
|
|
||||||
|
|
||||||
1. **独立 Y 轴模式**:不再使用「每 series 一个 Y 轴」,改为 **按每条曲线自身 min-max 归一化到 [-100, 100]**,**共用一条数值 Y 轴**,避免多轴布局副作用;**Tooltip 始终展示原始值**。
|
|
||||||
2. **共享 Y 轴模式**:保留原逻辑,单 Y 轴 + `scale: true`,便于对比绝对量级。
|
|
||||||
3. **归一化坐标展示**:独立模式下 Y 轴可见,刻度约 -100%~100%,并附说明性网格线。
|
|
||||||
4. **网关图**:图例与 grid 与设备 Tab 对齐策略;X 轴旋转 + 对齐刻度;必要时配合底部留白与 dataZoom。
|
|
||||||
5. **动态高度**:按 **series 数量** 增加图表容器高度(有上下限),并在 DOM 更新后 `resize`。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 功能开关
|
|
||||||
|
|
||||||
- **数据字段**:`independentYAxis`(默认 `true`)。
|
|
||||||
- **UI**:设备 / 网关 / 场景三个图表卡片头部 **「独立Y轴 | 共享Y轴」** 开关。
|
|
||||||
- **切换行为**:`handleYAxisModeChange` 在 `$nextTick` 内按当前 Tab 与已有数据调用对应 `draw*Line`,无需重新请求接口。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. 核心实现
|
|
||||||
|
|
||||||
### 4.1 归一化(独立模式)
|
|
||||||
|
|
||||||
**方法**:`applyIndependentScale(series)`
|
|
||||||
|
|
||||||
- 对每条 `series.data` 中可解析为数字的点,取该 series 全体有效点的 `min`、`max`。
|
|
||||||
- 映射公式:`value = ((num - min) / (max - min)) * 200 - 100`,落在 **[-100, 100]**。
|
|
||||||
- **常量序列**(`max === min`):映射为 **0**(中间水平线)。
|
|
||||||
- 每个数据点存为 `{ value, _original }`,`_original` 为归一化前的原始值(兼容负数与非数字展示)。
|
|
||||||
|
|
||||||
**返回的 Y 轴配置**(单轴):
|
|
||||||
|
|
||||||
- `min: -100`, `max: 100`
|
|
||||||
- `axisLine` / `axisTick` 显示
|
|
||||||
- `axisLabel.formatter`: 显示为 `xx%`(表示相对本曲线量程的位置,非物理单位)
|
|
||||||
- `splitLine`:虚线网格,便于读趋势
|
|
||||||
|
|
||||||
### 4.2 Tooltip
|
|
||||||
|
|
||||||
**方法**:`independentScaleTooltip()`
|
|
||||||
|
|
||||||
- `trigger: 'axis'`
|
|
||||||
- `formatter`:时间轴标签 + 各 series **原始值**(从 `p.data._original` 读取)
|
|
||||||
|
|
||||||
### 4.3 共享模式
|
|
||||||
|
|
||||||
- `yAxis`: `{ type: 'value', scale: true }`
|
|
||||||
- `tooltip`: `{ trigger: 'axis' }`(默认)
|
|
||||||
|
|
||||||
### 4.4 涉及的绘图方法
|
|
||||||
|
|
||||||
| 方法 | Tab / 场景 |
|
|
||||||
|------|------------|
|
|
||||||
| `drawDevLine` | 设备 |
|
|
||||||
| `drawGwCalcLine` | 网关 · 计算量 |
|
|
||||||
| `drawGwSingleLine` | 网关 · 单子设备 |
|
|
||||||
| `drawSubCompareLine` | 网关 · 多设备同一变量对比 |
|
|
||||||
| `drawSceneLine` | 场景 |
|
|
||||||
|
|
||||||
以上方法在 `independentYAxis === true` 时均走 `applyIndependentScale` + `independentScaleTooltip`。
|
|
||||||
|
|
||||||
### 4.5 网关图布局要点
|
|
||||||
|
|
||||||
- `legend`: `align: 'right'`, `left: '3%'`, `top: '3%'`(与多行图例协调)
|
|
||||||
- `grid.top: '30%'`,为图例留出区域,避免与曲线重叠
|
|
||||||
- `xAxis`: `boundaryGap: true`, `axisTick.alignWithLabel: true`, `axisLabel.rotate: 30`
|
|
||||||
- `dataZoom`: `inside` + 滑块,便于时间范围缩放
|
|
||||||
- `toolbox`: 数据视图、还原、保存图片(与设备 Tab 能力对齐)
|
|
||||||
|
|
||||||
### 4.6 动态图表高度
|
|
||||||
|
|
||||||
**数据字段**(像素):
|
|
||||||
|
|
||||||
- `devChartHeight`, `gwCalcChartHeight`, `gwSingleChartHeight`, `subCompareChartHeight`, `sceneChartHeight`(默认 480)
|
|
||||||
|
|
||||||
**方法**:`calcChartHeight(seriesCount)`
|
|
||||||
|
|
||||||
```text
|
|
||||||
height = clamp(480, seriesCount * 14 + 360, 1200)
|
|
||||||
```
|
|
||||||
|
|
||||||
即:最少 480px,随曲线数量增加,**最多 1200px**。
|
|
||||||
|
|
||||||
**模板**:各图表容器使用 `:style="{ height: xxxChartHeight + 'px', ... }"`。
|
|
||||||
|
|
||||||
**绘制流程**:
|
|
||||||
|
|
||||||
1. 先算好 `series` 与 `series.length`,赋值对应 `xxxChartHeight`
|
|
||||||
2. `this.$nextTick(() => { init/clear → setOption → chart.resize() })`
|
|
||||||
保证先根据新高度更新 DOM,再初始化/重绘 ECharts。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 数据流(简图)
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph input [数据]
|
|
||||||
API[历史接口]
|
|
||||||
end
|
|
||||||
subgraph mode [模式]
|
|
||||||
IND[独立Y轴]
|
|
||||||
SHR[共享Y轴]
|
|
||||||
end
|
|
||||||
subgraph render [渲染]
|
|
||||||
NORM[逐条 min-max 到 -100~100]
|
|
||||||
ONEAXIS[单 Y 轴]
|
|
||||||
TT[Tooltip 原始值]
|
|
||||||
end
|
|
||||||
API --> IND
|
|
||||||
API --> SHR
|
|
||||||
IND --> NORM --> ONEAXIS
|
|
||||||
ONEAXIS --> TT
|
|
||||||
SHR --> ONEAXIS
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 使用说明(给产品/测试)
|
|
||||||
|
|
||||||
1. **独立 Y 轴(推荐多曲线看趋势)**:纵轴为各曲线**自身量程内的相对位置**(-100%~100%),对比不同物理量时看形状;**真实数值以 Tooltip 与下方表格为准**。
|
|
||||||
2. **共享 Y 轴**:纵轴为**真实数值**,适合量级接近、需比大小的变量;量级差很大时仍可能出现「看起来像直线」。
|
|
||||||
3. **曲线很多时**:图会自动变高(上限约 1200px),页面可纵向滚动查看全图。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 相关文件
|
|
||||||
|
|
||||||
| 文件 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| [`yack-web/src/views/dataCenter/history.vue`](../src/views/dataCenter/history.vue) | 全部图表逻辑、开关、高度、归一化 |
|
|
||||||
| [`yack-web/src/api/data/center.js`](../src/api/data/center.js) | 历史数据接口(未因本方案变更协议) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 版本与维护建议
|
|
||||||
|
|
||||||
- 若需调整「多高算够」,改 `calcChartHeight` 中的系数 `14`、基础 `360`、上下限 `480`/`1200` 即可。
|
|
||||||
- 若产品要求 Y 轴显示「归一化」文案而非 `%`,可在 `applyIndependentScale` 返回的 `axisLabel` 中改为固定文案或 `name`/`nameLocation`。
|
|
||||||
- 新增同类折线图时,复用:`applyIndependentScale` / `independentScaleTooltip` / `calcChartHeight` + `$nextTick` + `resize` 模式。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*文档对应实现:历史记录页曲线趋势图(多 Tab、独立/共享 Y 轴、归一化 -100~100、动态高度)。*
|
|
||||||
@ -9,6 +9,14 @@ export function generateDeviceReport(data) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新生成失败的报告(沿用首次口径,返回新的报告编号)
|
||||||
|
export function regenerateReport(reportNo) {
|
||||||
|
return request({
|
||||||
|
url: '/iot/report/regenerate/' + reportNo,
|
||||||
|
method: 'post',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 历史报表分页列表(仅未过期)
|
// 历史报表分页列表(仅未过期)
|
||||||
export function listReportRecords(query) {
|
export function listReportRecords(query) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -47,7 +47,7 @@
|
|||||||
<el-tag :type="statusType(scope.row.status)" size="mini">{{ statusText(scope.row.status) }}</el-tag>
|
<el-tag :type="statusType(scope.row.status)" size="mini">{{ statusText(scope.row.status) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
<el-table-column label="操作" width="190" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 'SUCCESS'"
|
v-if="scope.row.status === 'SUCCESS'"
|
||||||
@ -56,14 +56,22 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
@click="handleDownload(scope.row)"
|
@click="handleDownload(scope.row)"
|
||||||
>下载</el-button>
|
>下载</el-button>
|
||||||
|
<template v-if="scope.row.status === 'FAILED'">
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 'FAILED'"
|
|
||||||
type="danger"
|
type="danger"
|
||||||
plain
|
plain
|
||||||
icon="el-icon-warning-outline"
|
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleShowError(scope.row)"
|
@click="handleShowError(scope.row)"
|
||||||
>失败原因</el-button>
|
>失败原因</el-button>
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['iot:report:generate']"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
size="mini"
|
||||||
|
:loading="regeneratingNo === scope.row.reportNo"
|
||||||
|
@click="handleRegenerate(scope.row)"
|
||||||
|
>重新生成</el-button>
|
||||||
|
</template>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 'CREATING'"
|
v-if="scope.row.status === 'CREATING'"
|
||||||
plain
|
plain
|
||||||
@ -111,7 +119,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { listReportRecords, downloadReportRecord } from '@/api/iot/report';
|
import { listReportRecords, downloadReportRecord, regenerateReport } from '@/api/iot/report';
|
||||||
import { blobValidate } from '@/utils/ruoyi';
|
import { blobValidate } from '@/utils/ruoyi';
|
||||||
|
|
||||||
/** 报告保留天数,与后端 LogCleanTask#cleanLogs 默认保留天数一致 */
|
/** 报告保留天数,与后端 LogCleanTask#cleanLogs 默认保留天数一致 */
|
||||||
@ -128,6 +136,8 @@ export default {
|
|||||||
pollTimer: null,
|
pollTimer: null,
|
||||||
errorVisible: false,
|
errorVisible: false,
|
||||||
errorRow: {},
|
errorRow: {},
|
||||||
|
/** 正在重新生成的报告编号(按钮 loading) */
|
||||||
|
regeneratingNo: null,
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -234,6 +244,31 @@ export default {
|
|||||||
this.errorRow = row || {};
|
this.errorRow = row || {};
|
||||||
this.errorVisible = true;
|
this.errorVisible = true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 重新生成失败报告:沿用首次生成的设备口径与时间窗口,
|
||||||
|
* 后端生成新报告编号,原失败记录保留用于追溯
|
||||||
|
*/
|
||||||
|
handleRegenerate(row) {
|
||||||
|
if (!row || !row.reportNo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.regeneratingNo = row.reportNo;
|
||||||
|
regenerateReport(row.reportNo)
|
||||||
|
.then((res) => {
|
||||||
|
if (res && res.code === 200) {
|
||||||
|
this.$message.success('已重新提交生成任务,完成后可下载');
|
||||||
|
this.getList(true);
|
||||||
|
} else {
|
||||||
|
this.$message.error((res && res.msg) || '重新生成失败');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.error('重新生成失败,请稍后重试');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.regeneratingNo = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
categoryText(code) {
|
categoryText(code) {
|
||||||
const map = {
|
const map = {
|
||||||
CRACK_METER: '裂缝计',
|
CRACK_METER: '裂缝计',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user