From e46bfa3ff94a8a1b4daf37c7fcb79c2fab22a72c Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期五, 29 五月 2026 17:10:00 +0800
Subject: [PATCH] 新增智能电表、空调管理
---
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalDataServiceImpl.java | 32 +++
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/dto/YwElectricalDataSyncDTO.java | 13 +
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalDataService.java | 5
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwElectricalDataCloudController.java | 10 +
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalBizService.java | 3
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwWorkDeskEnergyService.java | 5
admin/src/views/business/ywelectricaldata.vue | 137 +++++++++++++++--
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkDeskEnergyServiceImpl.java | 104 +++++++++---
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java | 160 ++++++++++++++++++-
9 files changed, 406 insertions(+), 63 deletions(-)
diff --git a/admin/src/views/business/ywelectricaldata.vue b/admin/src/views/business/ywelectricaldata.vue
index 7dc1ab5..3235191 100644
--- a/admin/src/views/business/ywelectricaldata.vue
+++ b/admin/src/views/business/ywelectricaldata.vue
@@ -80,6 +80,33 @@
:pagination="tableData.pagination"
/>
</template>
+ <el-dialog
+ title="绔嬪嵆鎶勮〃"
+ :visible.sync="syncDialogVisible"
+ width="520px"
+ append-to-body
+ @closed="resetSyncForm"
+ >
+ <el-form ref="syncFormRef" :model="syncForm" :rules="syncRules" label-width="110px">
+ <el-form-item label="鎶勮〃鏃堕棿娈�" prop="readTimeRange">
+ <el-date-picker
+ v-model="syncForm.readTimeRange"
+ type="datetimerange"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ range-separator="-"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ :picker-options="syncPickerOptions"
+ style="width: 100%"
+ />
+ </el-form-item>
+ <p class="sync-tip">鏃堕棿娈垫渶闀夸笉瓒呰繃7澶�</p>
+ </el-form>
+ <template v-slot:footer>
+ <el-button @click="syncDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="isReading" @click="submitSync">纭鎶勮〃</el-button>
+ </template>
+ </el-dialog>
</TableLayout>
</template>
@@ -108,7 +135,32 @@
readTimeRange: []
},
roomOptions: [],
- isReading: false
+ isReading: false,
+ syncDialogVisible: false,
+ syncMinDate: null,
+ syncForm: {
+ readTimeRange: []
+ },
+ syncRules: {
+ readTimeRange: [{ required: true, message: '璇烽�夋嫨鎶勮〃鏃堕棿娈�', trigger: 'change' }]
+ }
+ }
+ },
+ computed: {
+ syncPickerOptions () {
+ return {
+ onPick: ({ minDate, maxDate }) => {
+ this.syncMinDate = minDate && !maxDate ? minDate : null
+ },
+ disabledDate: (time) => {
+ if (!this.syncMinDate) return false
+ const anchor = dayjs(this.syncMinDate)
+ const min = anchor.subtract(7, 'day').startOf('day')
+ const max = anchor.add(7, 'day').endOf('day')
+ const current = dayjs(time)
+ return current.isBefore(min) || current.isAfter(max)
+ }
+ }
}
},
created () {
@@ -181,22 +233,69 @@
this.search()
},
handleReadNow () {
- this.$dialog.actionConfirm('纭绔嬪嵆浠庣涓夋柟骞冲彴鍚屾鎶勮〃鏁版嵁鍚楋紵', '鎿嶄綔纭鎻愰啋')
- .then(() => {
- this.isReading = true
- dataApi.syncAll({})
- .then(res => {
- this.$tip.apiSuccess(res || '鎶勮〃鍚屾鎴愬姛')
- this.search()
- })
- .catch(e => {
- this.$tip.apiFailed(e)
- })
- .finally(() => {
- this.isReading = false
- })
+ this.syncForm.readTimeRange = this.defaultSyncRange()
+ this.syncDialogVisible = true
+ this.$nextTick(() => {
+ if (this.$refs.syncFormRef) {
+ this.$refs.syncFormRef.clearValidate()
+ }
+ })
+ },
+ defaultSyncRange () {
+ const end = dayjs()
+ const start = end.subtract(24, 'hour')
+ return [start.format('YYYY-MM-DD HH:mm:ss'), end.format('YYYY-MM-DD HH:mm:ss')]
+ },
+ resetSyncForm () {
+ this.syncMinDate = null
+ this.syncForm.readTimeRange = []
+ if (this.$refs.syncFormRef) {
+ this.$refs.syncFormRef.resetFields()
+ }
+ },
+ validateSyncRange (range) {
+ if (!range || range.length !== 2) {
+ this.$tip.warning('璇烽�夋嫨鎶勮〃鏃堕棿娈�')
+ return false
+ }
+ const start = dayjs(range[0])
+ const end = dayjs(range[1])
+ if (!start.isValid() || !end.isValid()) {
+ this.$tip.warning('鎶勮〃鏃堕棿鏍煎紡涓嶆纭�')
+ return false
+ }
+ if (!end.isAfter(start)) {
+ this.$tip.warning('鎶勮〃寮�濮嬫椂闂村繀椤绘棭浜庣粨鏉熸椂闂�')
+ return false
+ }
+ if (end.diff(start, 'day', true) > 7) {
+ this.$tip.warning('鎶勮〃鏃堕棿娈典笉鑳借秴杩�7澶�')
+ return false
+ }
+ return true
+ },
+ submitSync () {
+ this.$refs.syncFormRef.validate(valid => {
+ if (!valid) return
+ const range = this.syncForm.readTimeRange
+ if (!this.validateSyncRange(range)) return
+ this.isReading = true
+ dataApi.syncAll({
+ readTimeBegin: range[0],
+ readTimeEnd: range[1]
})
- .catch(() => {})
+ .then(res => {
+ this.$tip.apiSuccess(res || '鎶勮〃鍚屾鎴愬姛')
+ this.syncDialogVisible = false
+ this.search()
+ })
+ .catch(e => {
+ this.$tip.apiFailed(e)
+ })
+ .finally(() => {
+ this.isReading = false
+ })
+ })
},
formatJsfs (val) {
if (val == null || val === '') return '-'
@@ -235,4 +334,10 @@
<style scoped>
.red { color: #f56c6c; }
+.sync-tip {
+ margin: 0 0 0 110px;
+ color: #909399;
+ font-size: 12px;
+ line-height: 1.5;
+}
</style>
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwElectricalDataCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwElectricalDataCloudController.java
index babb5eb..13df3ec 100644
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwElectricalDataCloudController.java
+++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwElectricalDataCloudController.java
@@ -7,6 +7,7 @@
import com.doumee.core.model.ApiResponse;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.dto.YwElectricalDataSyncDTO;
import com.doumee.dao.business.model.Device;
import com.doumee.dao.business.model.YwElectricalData;
import com.doumee.service.business.YwElectricalDataService;
@@ -14,6 +15,7 @@
import com.doumee.config.annotation.CloudRequiredPermission;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
@@ -94,7 +96,11 @@
@ApiOperation("绔嬪嵆鎶勮〃锛堝悓姝ョ涓夋柟鎶勮〃鏁版嵁锛�")
@PostMapping("/syncAll")
@CloudRequiredPermission("business:ywelectricaldata:sync")
- public ApiResponse<String> syncAll(@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
- return ApiResponse.success(ywElectricalDataService.syncFromPlatform());
+ public ApiResponse<String> syncAll(@RequestBody(required = false) YwElectricalDataSyncDTO dto,
+ @RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+ if (dto == null || (StringUtils.isBlank(dto.getReadTimeBegin()) && StringUtils.isBlank(dto.getReadTimeEnd()))) {
+ return ApiResponse.success(ywElectricalDataService.syncFromPlatform());
+ }
+ return ApiResponse.success(ywElectricalDataService.syncFromPlatform(dto.getReadTimeBegin(), dto.getReadTimeEnd()));
}
}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/dto/YwElectricalDataSyncDTO.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/dto/YwElectricalDataSyncDTO.java
new file mode 100644
index 0000000..34eabee
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/dto/YwElectricalDataSyncDTO.java
@@ -0,0 +1,13 @@
+package com.doumee.dao.business.dto;
+
+import lombok.Data;
+
+@Data
+public class YwElectricalDataSyncDTO {
+
+ /** 鎶勮〃寮�濮嬫椂闂� yyyy-MM-dd HH:mm:ss */
+ private String readTimeBegin;
+
+ /** 鎶勮〃缁撴潫鏃堕棿 yyyy-MM-dd HH:mm:ss */
+ private String readTimeEnd;
+}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalBizService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalBizService.java
index 540e88c..c924826 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalBizService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalBizService.java
@@ -35,6 +35,9 @@
/** 鎵嬪姩浠庣涓夋柟骞冲彴鎷夊彇鎶勮〃鏁版嵁鍏ュ簱 */
String syncMeterDataFromPlatform();
+ /** 鎵嬪姩浠庣涓夋柟骞冲彴鎷夊彇鎸囧畾鏃堕棿娈垫妱琛ㄦ暟鎹叆搴� */
+ String syncMeterDataFromPlatform(String readTimeBegin, String readTimeEnd);
+
void cleanLogBeforeThreeMonths();
void enrichList(List<YwElectrical> list);
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalDataService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalDataService.java
index 73a7488..b616aad 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalDataService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwElectricalDataService.java
@@ -113,4 +113,9 @@
* 浠庣涓夋柟骞冲彴鍚屾鎶勮〃鏁版嵁
*/
String syncFromPlatform();
+
+ /**
+ * 浠庣涓夋柟骞冲彴鍚屾鎸囧畾鏃堕棿娈垫妱琛ㄦ暟鎹�
+ */
+ String syncFromPlatform(String readTimeBegin, String readTimeEnd);
}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwWorkDeskEnergyService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwWorkDeskEnergyService.java
index dd64e4c..1d5f75d 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwWorkDeskEnergyService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/YwWorkDeskEnergyService.java
@@ -12,4 +12,9 @@
List<DailyEnergyStatVO> electricalDailyStats();
List<DailyEnergyStatVO> conditionerDailyStats();
+
+ /**
+ * 鎶勮〃鍚屾鍚庯紝鎸夋妱琛ㄦ椂闂存鍓嶅悗鍚勬墿灞曚竴澶╋紝鍒锋柊姣忔棩鐢甸噺/鐢佃垂缁熻
+ */
+ String refreshElectricalDailyStatsForRange(String readTimeBegin, String readTimeEnd);
}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
index 8ab9565..2a76435 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
@@ -64,6 +64,12 @@
private static final int ELE_READ_TYPE_METER = 3;
/** queryData 鐢佃〃鐘舵�佽鎯呭姛鑳� ID */
private static final String QUERY_DATA_FUNCTION_METER_STATUS = "253";
+ /** DataRequest 鍗曟鏈�澶ф潯鏁帮紙鎺ュ彛 limit 涓婇檺 1000锛� */
+ private static final int QUERY_DATA_PAGE_SIZE = 500;
+ /** 鎶勮〃/DataRequest 鏌ヨ鏃堕棿璺ㄥ害涓婇檺锛堝ぉ锛� */
+ private static final int MAX_METER_QUERY_DAYS = 7;
+ /** 鍒嗛〉 total 鍚堢悊涓婇檺锛岄伩鍏嶈鎶婃椂闂存埑褰撲綔鎬绘潯鏁� */
+ private static final int QUERY_DATA_TOTAL_SANITY_MAX = 100_000;
@Autowired
private YwElectricalMapper ywElectricalMapper;
@@ -829,7 +835,7 @@
@Override
public void syncMeterDataScheduled() {
try {
- syncMeterDataInternal();
+ syncMeterDataInternal(null, null);
} catch (Exception e) {
log.warn("syncMeterDataScheduled failed", e);
}
@@ -837,8 +843,36 @@
@Override
public String syncMeterDataFromPlatform() {
- MeterDataSyncStats stats = syncMeterDataInternal();
+ MeterDataSyncStats stats = syncMeterDataInternal(null, null);
return "鎶勮〃鍚屾瀹屾垚锛氭柊澧炪��" + stats.addCount + "銆戞潯锛岃烦杩囬噸澶嶃��" + stats.skipCount + "銆戞潯";
+ }
+
+ @Override
+ public String syncMeterDataFromPlatform(String readTimeBegin, String readTimeEnd) {
+ if (StringUtils.isBlank(readTimeBegin) || StringUtils.isBlank(readTimeEnd)) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "璇烽�夋嫨鎶勮〃鏃堕棿娈�");
+ }
+ String startTime = readTimeBegin.trim();
+ String endTime = readTimeEnd.trim();
+ validateManualSyncTimeRange(startTime, endTime);
+ String expandedStart = expandStartByOneDay(startTime);
+ MeterDataSyncStats stats = syncMeterDataInternal(expandedStart, endTime);
+ return "鎶勮〃鍚屾瀹屾垚锛氭柊澧炪��" + stats.addCount + "銆戞潯锛岃烦杩囬噸澶嶃��" + stats.skipCount + "銆戞潯";
+ }
+
+ private String expandStartByOneDay(String startTime) {
+ try {
+ Date start = DateUtil.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss");
+ if (start == null) {
+ return startTime;
+ }
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(start);
+ cal.add(Calendar.DAY_OF_MONTH, -1);
+ return DateUtil.formatDate(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
+ } catch (Exception e) {
+ return startTime;
+ }
}
private static class MeterDataSyncStats {
@@ -846,12 +880,14 @@
private int skipCount;
}
- private MeterDataSyncStats syncMeterDataInternal() {
+ private MeterDataSyncStats syncMeterDataInternal(String startTime, String endTime) {
MeterDataSyncStats stats = new MeterDataSyncStats();
- String startTime = resolveSyncStartTime();
- QueryDataRequest param = buildQueryDataRequest(startTime, DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
- log.info("sync meter data, start_time={}, end_time={}", startTime, param.getEnd_time());
- List<QueryDataInfoResponse> list = fetchQueryDataList(param);
+ String resolvedStart = StringUtils.isNotBlank(startTime) ? startTime : resolveSyncStartTime();
+ String resolvedEnd = StringUtils.isNotBlank(endTime) ? endTime : DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
+ resolvedStart = capQueryStartTime(resolvedStart, resolvedEnd, MAX_METER_QUERY_DAYS);
+ QueryDataRequest param = buildQueryDataRequest(resolvedStart, resolvedEnd);
+ log.info("sync meter data, start_time={}, end_time={}", resolvedStart, param.getEnd_time());
+ List<QueryDataInfoResponse> list = fetchAllQueryDataList(param);
if (CollectionUtils.isEmpty(list)) {
return stats;
}
@@ -875,6 +911,51 @@
return stats;
}
+ private void validateManualSyncTimeRange(String startTime, String endTime) {
+ if (!startTime.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")
+ || !endTime.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿鏍煎紡涓嶆纭�");
+ }
+ Date start;
+ Date end;
+ try {
+ start = DateUtil.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss");
+ end = DateUtil.StringToDate(endTime, "yyyy-MM-dd HH:mm:ss");
+ } catch (Exception e) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿鏍煎紡涓嶆纭�");
+ }
+ if (start == null || end == null || !start.before(end)) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃寮�濮嬫椂闂村繀椤绘棭浜庣粨鏉熸椂闂�");
+ }
+ long diffMs = end.getTime() - start.getTime();
+ if (diffMs > (long) MAX_METER_QUERY_DAYS * 24 * 60 * 60 * 1000) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿娈典笉鑳借秴杩�" + MAX_METER_QUERY_DAYS + "澶�");
+ }
+ }
+
+ private String capQueryStartTime(String startTime, String endTime, int maxDays) {
+ if (StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)) {
+ return startTime;
+ }
+ try {
+ Date start = DateUtil.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss");
+ Date end = DateUtil.StringToDate(endTime, "yyyy-MM-dd HH:mm:ss");
+ if (start == null || end == null || !start.before(end)) {
+ return startTime;
+ }
+ long maxMs = (long) maxDays * 24 * 60 * 60 * 1000;
+ if (end.getTime() - start.getTime() <= maxMs) {
+ return startTime;
+ }
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(end);
+ cal.add(Calendar.DAY_OF_MONTH, -maxDays);
+ return DateUtil.formatDate(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
+ } catch (Exception e) {
+ return startTime;
+ }
+ }
+
/** 鍗曡〃鎶勮〃鍚庝粠绗笁鏂规媺鍙栨渶鏂版暟鎹叆搴擄紝杩斿洖鏄惁鏈夋柊璁板綍 */
private boolean syncMeterDataForElectrical(YwElectrical e) {
if (e == null || StringUtils.isBlank(e.getAddress())) {
@@ -887,7 +968,7 @@
DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
List<QueryDataInfoResponse> list;
try {
- list = fetchQueryDataList(param);
+ list = fetchAllQueryDataList(param);
} catch (BusinessException ex) {
log.warn("sync meter data for electricalId={} failed: {}", e.getId(), ex.getMessage());
return false;
@@ -918,17 +999,66 @@
param.setStart_time(startTime);
param.setEnd_time(endTime);
param.setOffset(0);
- param.setLimit(500);
+ param.setLimit(QUERY_DATA_PAGE_SIZE);
return param;
}
- private List<QueryDataInfoResponse> fetchQueryDataList(QueryDataRequest param) {
- ElectronicDataResponse response = ElectronicToolUtil.queryDataRequest(param);
- if (!ElectronicToolUtil.isDataApiSuccess(response)) {
- throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),
- ElectronicToolUtil.dataApiErrorMessage(response, "鎶勮〃鏁版嵁鍚屾澶辫触"));
+ /** 鎸� DataRequest 鍒嗛〉 total 寰幆鎷夊彇鍏ㄩ儴鎶勮〃鏁版嵁 */
+ private List<QueryDataInfoResponse> fetchAllQueryDataList(QueryDataRequest param) {
+ if (param == null) {
+ return Collections.emptyList();
}
- return parseQueryDataList(response);
+ int limit = param.getLimit() > 0 ? param.getLimit() : QUERY_DATA_PAGE_SIZE;
+ List<QueryDataInfoResponse> all = new ArrayList<>();
+ int offset = 0;
+ Integer total = null;
+ int pageNo = 0;
+ while (true) {
+ pageNo++;
+ param.setOffset(offset);
+ param.setLimit(limit);
+ ElectronicDataResponse response = ElectronicToolUtil.queryDataRequest(param);
+ if (!ElectronicToolUtil.isDataApiSuccess(response)) {
+ throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),
+ ElectronicToolUtil.dataApiErrorMessage(response, "鎶勮〃鏁版嵁鍚屾澶辫触"));
+ }
+ List<QueryDataInfoResponse> page = parseQueryDataList(response);
+ if (!CollectionUtils.isEmpty(page)) {
+ all.addAll(page);
+ }
+ if (total == null) {
+ total = resolveQueryTotal(response);
+ }
+ log.info("sync meter data page={}, offset={}, pageSize={}, accumulated={}, total={}",
+ pageNo, offset, page.size(), all.size(), total);
+ if (total != null && total > 0) {
+ offset += limit;
+ if (offset >= total) {
+ break;
+ }
+ continue;
+ }
+ if (CollectionUtils.isEmpty(page) || page.size() < limit) {
+ break;
+ }
+ offset += limit;
+ if (pageNo >= 200) {
+ log.warn("sync meter data pagination exceeded safety page limit, accumulated={}", all.size());
+ break;
+ }
+ }
+ return all;
+ }
+
+ private Integer resolveQueryTotal(ElectronicDataResponse response) {
+ if (response == null || response.getTotal() == null) {
+ return null;
+ }
+ int total = response.getTotal();
+ if (total <= 0 || total > QUERY_DATA_TOTAL_SANITY_MAX) {
+ return null;
+ }
+ return total;
}
private List<QueryDataInfoResponse> parseQueryDataList(ElectronicDataResponse response) {
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalDataServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalDataServiceImpl.java
index b05ad19..0f265b1 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalDataServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalDataServiceImpl.java
@@ -15,12 +15,14 @@
import com.doumee.dao.business.model.YwElectricalRoom;
import com.doumee.service.business.YwElectricalBizService;
import com.doumee.service.business.YwElectricalDataService;
+import com.doumee.service.business.YwWorkDeskEnergyService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
+import java.text.SimpleDateFormat;
import java.util.List;
/**
@@ -33,6 +35,8 @@
private YwElectricalDataMapper ywElectricalDataMapper;
@Autowired
private YwElectricalBizService ywElectricalBizService;
+ @Autowired
+ private YwWorkDeskEnergyService ywWorkDeskEnergyService;
@Override
public Integer create(YwElectricalData ywElectricalData) {
@@ -137,13 +141,28 @@
.eq(YwElectricalRoom::getRoomId, model.getRoomId());
}
if (model.getReadTimeBegin() != null) {
- queryWrapper.ge(YwElectricalData::getCreateDate, Utils.Date.getStart(model.getReadTimeBegin()));
+ String begin = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
+ .format(Utils.Date.getStart(model.getReadTimeBegin()));
+ queryWrapper.and(w -> w.and(w1 -> w1.isNotNull(YwElectricalData::getAddTime)
+ .ne(YwElectricalData::getAddTime, "")
+ .ge(YwElectricalData::getAddTime, begin))
+ .or(w2 -> w2.and(w3 -> w3.isNull(YwElectricalData::getAddTime)
+ .or().eq(YwElectricalData::getAddTime, ""))
+ .ge(YwElectricalData::getCreateDate, Utils.Date.getStart(model.getReadTimeBegin()))));
}
if (model.getReadTimeEnd() != null) {
- queryWrapper.le(YwElectricalData::getCreateDate, Utils.Date.getEnd(model.getReadTimeEnd()));
+ String end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
+ .format(Utils.Date.getEnd(model.getReadTimeEnd()));
+ queryWrapper.and(w -> w.and(w1 -> w1.isNotNull(YwElectricalData::getAddTime)
+ .ne(YwElectricalData::getAddTime, "")
+ .le(YwElectricalData::getAddTime, end))
+ .or(w2 -> w2.and(w3 -> w3.isNull(YwElectricalData::getAddTime)
+ .or().eq(YwElectricalData::getAddTime, ""))
+ .le(YwElectricalData::getCreateDate, Utils.Date.getEnd(model.getReadTimeEnd()))));
}
- queryWrapper.orderByDesc(YwElectricalData::getCreateDate)
+ queryWrapper.orderByDesc(YwElectricalData::getAddTime)
+ .orderByDesc(YwElectricalData::getCreateDate)
.orderByDesc(YwElectricalData::getId);
IPage<YwElectricalData> result = ywElectricalDataMapper.selectJoinPage(page, YwElectricalData.class, queryWrapper);
PageData<YwElectricalData> pageData = PageData.from(result);
@@ -161,4 +180,11 @@
public String syncFromPlatform() {
return ywElectricalBizService.syncMeterDataFromPlatform();
}
+
+ @Override
+ public String syncFromPlatform(String readTimeBegin, String readTimeEnd) {
+ String syncMsg = ywElectricalBizService.syncMeterDataFromPlatform(readTimeBegin, readTimeEnd);
+ String statsMsg = ywWorkDeskEnergyService.refreshElectricalDailyStatsForRange(readTimeBegin, readTimeEnd);
+ return syncMsg + "锛�" + statsMsg;
+ }
}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkDeskEnergyServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkDeskEnergyServiceImpl.java
index aa2d11c..5d7812b 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkDeskEnergyServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkDeskEnergyServiceImpl.java
@@ -1,7 +1,10 @@
package com.doumee.service.business.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
import com.doumee.core.utils.Constants;
+import com.doumee.core.utils.DateUtil;
import com.doumee.dao.business.YwConditionerUsageMapper;
import com.doumee.dao.business.YwElectricalDataMapper;
import com.doumee.dao.business.model.YwConditionerUsage;
@@ -18,6 +21,7 @@
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -42,13 +46,54 @@
public List<DailyEnergyStatVO> electricalDailyStats() {
LocalDate end = LocalDate.now();
LocalDate start = end.minusDays(DAYS - 1L);
- LocalDate queryStart = start.minusDays(1L);
+ return buildElectricalDailyStats(start, end);
+ }
+
+ @Override
+ public String refreshElectricalDailyStatsForRange(String readTimeBegin, String readTimeEnd) {
+ if (StringUtils.isBlank(readTimeBegin) || StringUtils.isBlank(readTimeEnd)) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿娈典笉鑳戒负绌�");
+ }
+ LocalDate start = parseDateTime(readTimeBegin.trim()).minusDays(1);
+ LocalDate end = parseDateTime(readTimeEnd.trim()).plusDays(1);
+ if (start.isAfter(end)) {
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿娈垫棤鏁�");
+ }
+ buildElectricalDailyStats(start, end);
+ return "宸插埛鏂版瘡鏃ョ數閲�/鐢佃垂缁熻锛�" + start.format(DATE_FMT) + " ~ " + end.format(DATE_FMT) + "锛�";
+ }
+
+ @Override
+ public List<DailyEnergyStatVO> conditionerDailyStats() {
+ LocalDate end = LocalDate.now();
+ LocalDate start = end.minusDays(DAYS - 1L);
Map<String, DailyEnergyStatVO> bucket = initDailyBucket(start, end);
- List<YwElectricalData> rows = ywElectricalDataMapper.selectList(new QueryWrapper<YwElectricalData>().lambda()
- .eq(YwElectricalData::getIsdeleted, Constants.ZERO)
- .ge(YwElectricalData::getCreateDate, java.sql.Date.valueOf(queryStart))
- .le(YwElectricalData::getCreateDate, java.sql.Date.valueOf(end.plusDays(1))));
+ List<YwConditionerUsage> rows = ywConditionerUsageMapper.selectList(new QueryWrapper<YwConditionerUsage>().lambda()
+ .eq(YwConditionerUsage::getIsdeleted, Constants.ZERO)
+ .ge(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(start))
+ .le(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(end)));
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ for (YwConditionerUsage row : rows) {
+ if (row.getUsageDate() == null) {
+ continue;
+ }
+ String dayKey = sdf.format(row.getUsageDate());
+ if (!bucket.containsKey(dayKey)) {
+ continue;
+ }
+ DailyEnergyStatVO stat = bucket.get(dayKey);
+ stat.setTotalKwh(stat.getTotalKwh().add(nullToZero(row.getSumDl())));
+ stat.setTotalFee(stat.getTotalFee().add(nullToZero(row.getSumDf())));
+ }
+ return normalizeBucket(bucket);
+ }
+
+ private List<DailyEnergyStatVO> buildElectricalDailyStats(LocalDate start, LocalDate end) {
+ LocalDate queryStart = start.minusDays(1L);
+ Map<String, DailyEnergyStatVO> bucket = initDailyBucket(start, end);
+ List<YwElectricalData> rows = loadElectricalRowsForStats(queryStart, end);
SimpleDateFormat dayFmt = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat readTimeFmt = new SimpleDateFormat(READ_TIME_PATTERN);
@@ -93,31 +138,36 @@
return normalizeBucket(bucket);
}
- @Override
- public List<DailyEnergyStatVO> conditionerDailyStats() {
- LocalDate end = LocalDate.now();
- LocalDate start = end.minusDays(DAYS - 1L);
- Map<String, DailyEnergyStatVO> bucket = initDailyBucket(start, end);
+ private List<YwElectricalData> loadElectricalRowsForStats(LocalDate queryStart, LocalDate end) {
+ String queryStartStr = queryStart.format(DATE_FMT) + " 00:00:00";
+ String queryEndStr = end.format(DATE_FMT) + " 23:59:59";
+ return ywElectricalDataMapper.selectList(new QueryWrapper<YwElectricalData>().lambda()
+ .eq(YwElectricalData::getIsdeleted, Constants.ZERO)
+ .and(w -> w.and(w1 -> w1.isNotNull(YwElectricalData::getAddTime)
+ .ne(YwElectricalData::getAddTime, "")
+ .ge(YwElectricalData::getAddTime, queryStartStr)
+ .le(YwElectricalData::getAddTime, queryEndStr))
+ .or(w2 -> w2.and(w3 -> w3.isNull(YwElectricalData::getAddTime)
+ .or().eq(YwElectricalData::getAddTime, ""))
+ .ge(YwElectricalData::getCreateDate, java.sql.Date.valueOf(queryStart))
+ .le(YwElectricalData::getCreateDate, java.sql.Date.valueOf(end.plusDays(1))))));
+ }
- List<YwConditionerUsage> rows = ywConditionerUsageMapper.selectList(new QueryWrapper<YwConditionerUsage>().lambda()
- .eq(YwConditionerUsage::getIsdeleted, Constants.ZERO)
- .ge(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(start))
- .le(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(end)));
-
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- for (YwConditionerUsage row : rows) {
- if (row.getUsageDate() == null) {
- continue;
+ private static LocalDate parseDateTime(String text) {
+ if (text.length() >= 10) {
+ try {
+ return LocalDate.parse(text.substring(0, 10), DATE_FMT);
+ } catch (DateTimeParseException ignored) {
}
- String dayKey = sdf.format(row.getUsageDate());
- if (!bucket.containsKey(dayKey)) {
- continue;
- }
- DailyEnergyStatVO stat = bucket.get(dayKey);
- stat.setTotalKwh(stat.getTotalKwh().add(nullToZero(row.getSumDl())));
- stat.setTotalFee(stat.getTotalFee().add(nullToZero(row.getSumDf())));
}
- return normalizeBucket(bucket);
+ try {
+ Date date = DateUtil.StringToDate(text, READ_TIME_PATTERN);
+ if (date != null) {
+ return date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
+ }
+ } catch (Exception ignored) {
+ }
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鎶勮〃鏃堕棿鏍煎紡涓嶆纭�");
}
private static void upsertLatestReading(Map<String, Map<String, MeterDayReading>> meterDayLatest,
--
Gitblit v1.9.3