|
|
@@ -13,18 +13,18 @@
|
|
|
<view class="operation-container" v-if="isShowOperation" @click="closeOperationHandler">
|
|
|
<view class="operation-background"></view>
|
|
|
<view class="operation-content">
|
|
|
- <view class="operation-item" v-if="isShowPhoto" @click="handlePhotoClick">
|
|
|
+ <!-- <view class="operation-item" v-if="isShowPhoto" @click="handlePhotoClick">
|
|
|
<image :src="photoIcon" class="operation-icon"></image>
|
|
|
拍照
|
|
|
- </view>
|
|
|
+ </view> -->
|
|
|
<view class="operation-item" @click="handleServiceClick">
|
|
|
<image :src="serviceIcon" class="operation-icon"></image>
|
|
|
维修
|
|
|
</view>
|
|
|
- <view class="operation-item" @click="handleSettingClick">
|
|
|
+ <!-- <view class="operation-item" @click="handleSettingClick">
|
|
|
<image :src="settingIcon" class="operation-icon"></image>
|
|
|
设置
|
|
|
- </view>
|
|
|
+ </view> -->
|
|
|
<!-- <view class="operation-item" @click="handleSimClick">
|
|
|
<image :src="simIcon" class="operation-icon"></image>
|
|
|
SIM卡
|
|
|
@@ -65,13 +65,20 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="tabs-timer-container" @click="showCalendar">
|
|
|
- <view class="tabs-timer-item">
|
|
|
- {{startDate}}
|
|
|
- </view>
|
|
|
- 至
|
|
|
- <view class="tabs-timer-item">
|
|
|
- {{endDate}}
|
|
|
- </view>
|
|
|
+ <block v-if="isRangeDate">
|
|
|
+ <view class="tabs-timer-item">
|
|
|
+ {{startDate}}
|
|
|
+ </view>
|
|
|
+ 至
|
|
|
+ <view class="tabs-timer-item">
|
|
|
+ {{endDate}}
|
|
|
+ </view>
|
|
|
+ </block>
|
|
|
+ <block v-else>
|
|
|
+ <view class="tabs-timer-item">
|
|
|
+ {{imageDate}}
|
|
|
+ </view>
|
|
|
+ </block>
|
|
|
<u-icon name="calendar" size="36" class="calendar-icon"></u-icon>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -81,14 +88,6 @@
|
|
|
:total="total"
|
|
|
:pest_order="pest_order"
|
|
|
/>
|
|
|
- <PestEchart
|
|
|
- :pest_order="pest_order"
|
|
|
- @getInfo="getInfo"
|
|
|
- :endDate="endDate"
|
|
|
- :d_id="deviceInfo.d_id"
|
|
|
- :day="day"
|
|
|
- :pest="pest"
|
|
|
- />
|
|
|
<RodentAnalysis :active="activeTab === 'pestAnalysis'" :device-id="deviceInfo.id" :start="analysisStart" :end="analysisEnd" />
|
|
|
<!-- <PestArchive
|
|
|
:pest_info="pestInfo"
|
|
|
@@ -97,21 +96,36 @@
|
|
|
<u-empty text="暂无数据"></u-empty>
|
|
|
</view> -->
|
|
|
</view>
|
|
|
- <view v-if="activeTab === 'viewImage'">
|
|
|
- <!-- 实现下拉加载 -->
|
|
|
- <scroll-view class="scroll-view" scroll-y style="height: 60vh;" @scrolltolower="handleReachBottom">
|
|
|
- <photoImage
|
|
|
- :images="imageList"
|
|
|
- :pestList="pestList"
|
|
|
- :disableShow="disableShow"
|
|
|
- :ding_one_device_id="ding_one_device_id"
|
|
|
- :ding_three_device_id="ding_three_device_id"
|
|
|
- :ding_two_device_id="ding_two_device_id"
|
|
|
- @changeTab="changeTab"
|
|
|
- :currentYear="currentYear"
|
|
|
- :deviceInfo="deviceInfo"
|
|
|
- />
|
|
|
- </scroll-view>
|
|
|
+ <view class="tabs" v-if="activeTab === 'viewImage'">
|
|
|
+ <view class="tab-container">
|
|
|
+ <view class="tab-item" :class="imageTab === 'viewImage'?'active':''" @click="handleImageTabClick('viewImage')">
|
|
|
+ 监测图像(前后左右)
|
|
|
+ </view>
|
|
|
+ <view class="tab-item" :class="imageTab === 'downImage'?'active':''" @click="handleImageTabClick('downImage')">
|
|
|
+ 监测图像(下)
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-show="imageTab === 'viewImage'">
|
|
|
+ <!-- 实现下拉加载 -->
|
|
|
+ <scroll-view class="scroll-view" scroll-y style="height: 60vh;" @scrolltolower="handleReachBottom">
|
|
|
+ <photoImage
|
|
|
+ :images="imageList"
|
|
|
+ :pestList="pestList"
|
|
|
+ :disableShow="disableShow"
|
|
|
+ :ding_one_device_id="ding_one_device_id"
|
|
|
+ :ding_three_device_id="ding_three_device_id"
|
|
|
+ :ding_two_device_id="ding_two_device_id"
|
|
|
+ @changeTab="changeTab"
|
|
|
+ :currentYear="currentYear"
|
|
|
+ :deviceInfo="deviceInfo"
|
|
|
+ />
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ <view v-show="imageTab === 'downImage'">
|
|
|
+ <scroll-view class="scroll-view" scroll-y style="height: 60vh;">
|
|
|
+ <downImage :images="downImageList" :deviceInfo="deviceInfo" />
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
<view v-if="activeTab === 'aiAnalysis'">
|
|
|
<AiChat
|
|
|
@@ -131,16 +145,16 @@
|
|
|
/>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <u-calendar v-model="show" :mode="mode" range-color="#999" btn-type="success" active-bg-color="#0BBC58" range-bg-color="rgba(11,188,88,0.13)" @change="handleChange" :max-date="maxDate" :min-date="minDate"></u-calendar>
|
|
|
+ <u-calendar v-model="show" :mode="calendarMode" range-color="#999" btn-type="success" active-bg-color="#0BBC58" range-bg-color="rgba(11,188,88,0.13)" @change="handleChange" :max-date="maxDate" :min-date="minDate"></u-calendar>
|
|
|
<u-picker v-model="showPicker" mode="selector" :range="selectorRange" range-key="id" :default-selector="[0]" @confirm="confirmHandler"></u-picker>
|
|
|
</view>
|
|
|
</template>
|
|
|
<script>
|
|
|
import DeviceCard from './components/DeviceCard.vue';
|
|
|
import PestDiscern from './components/pestDiscern.vue';
|
|
|
-import PestEchart from './components/pestEchart.vue';
|
|
|
import PestArchive from './components/pestArchive.vue';
|
|
|
import photoImage from './components/photoImage.vue';
|
|
|
+import downImage from './components/downImage.vue';
|
|
|
import DeviceData from './components/deviceData.vue';
|
|
|
import AiChat from './components/aiChat.vue';
|
|
|
import RodentAnalysis from './components/rodentAnalysis.vue';
|
|
|
@@ -150,9 +164,9 @@ export default {
|
|
|
DeviceCard,
|
|
|
PestDiscern,
|
|
|
AiChat,
|
|
|
- PestEchart,
|
|
|
PestArchive,
|
|
|
photoImage,
|
|
|
+ downImage,
|
|
|
DeviceData,
|
|
|
RodentAnalysis,
|
|
|
},
|
|
|
@@ -174,24 +188,25 @@ export default {
|
|
|
minDate: this.formatDate(new Date(new Date().getFullYear(), 0, 1)),
|
|
|
show: false,
|
|
|
showSim: false,
|
|
|
- // 当前日期向前推30天 格式2026-01-01 月份和日期小于10的时候前面加个0
|
|
|
- startDate: this.formatDate(new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000)),
|
|
|
+ // 鼠情分析/设备数据用的时间区间:结束为今天,开始为7天前 格式2026-01-01
|
|
|
+ startDate: this.formatDate(new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000)),
|
|
|
endDate: this.formatDate(new Date()),
|
|
|
- mode: 'range',
|
|
|
+ // 图像数据用单日,默认今天(onLoad会按time_folder接口更新为最近有数据的日期)
|
|
|
+ imageDate: this.formatDate(new Date()),
|
|
|
imageList: [],
|
|
|
+ downImageList: [],
|
|
|
pest_order:{},
|
|
|
pestMessage:'',
|
|
|
deviceInfo: {},
|
|
|
- pestInfo: {},
|
|
|
time: '',
|
|
|
activeTab: 'pestAnalysis',
|
|
|
+ // 图像数据内的子切换:viewImage-前后左右 downImage-下
|
|
|
+ imageTab: 'viewImage',
|
|
|
deviceType: '',
|
|
|
camera_id: '',
|
|
|
location: '',
|
|
|
total: 0,
|
|
|
imgTotal: 0,
|
|
|
- day: [],
|
|
|
- pest: [],
|
|
|
page:1,
|
|
|
is_pest:'',
|
|
|
page_size:24,
|
|
|
@@ -206,6 +221,13 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ // 鼠情分析/设备数据用区间选择,图像数据用单日选择
|
|
|
+ isRangeDate() {
|
|
|
+ return this.activeTab === 'pestAnalysis' || this.activeTab === 'deviceData';
|
|
|
+ },
|
|
|
+ calendarMode() {
|
|
|
+ return this.isRangeDate ? 'range' : 'date';
|
|
|
+ },
|
|
|
// 鼠情分析查询范围(秒级时间戳)
|
|
|
analysisStart() {
|
|
|
return this.startDate ? new Date(this.startDate + ' 00:00:00').getTime() / 1000 : 0;
|
|
|
@@ -214,12 +236,14 @@ export default {
|
|
|
return this.endDate ? new Date(this.endDate + ' 23:59:59').getTime() / 1000 : 0;
|
|
|
}
|
|
|
},
|
|
|
- onLoad(options){
|
|
|
+ async onLoad(options){
|
|
|
this.deviceInfo = JSON.parse(options.info);
|
|
|
const { ding_one_device_id, ding_three_device_id, ding_two_device_id } = this.deviceInfo;
|
|
|
this.ding_one_device_id = ding_one_device_id;
|
|
|
this.ding_three_device_id = ding_three_device_id;
|
|
|
this.ding_two_device_id = ding_two_device_id;
|
|
|
+ // 先取有数据的日期,默认选中最近的一天,再加载各模块数据
|
|
|
+ await this.initDateFolder();
|
|
|
this.getPestAnalysis();
|
|
|
this.isShow();
|
|
|
const currentYear = new Date().getFullYear();
|
|
|
@@ -346,29 +370,26 @@ export default {
|
|
|
},
|
|
|
confirmHandler(e){
|
|
|
this.currentYear = this.selectorRange[e].id;
|
|
|
- if(this.currentYear == new Date().getFullYear()){
|
|
|
- // 结束日期为this.endDate的月份和日期加上选择的年份
|
|
|
+ if(this.calendarMode === 'range'){
|
|
|
+ // 区间选择:结束日期保持月日仅切换年份,开始日期为结束日期前7天
|
|
|
const timeDate = this.currentYear + '-' + this.endDate.split('-')[1] + '-' + this.endDate.split('-')[2];
|
|
|
this.endDate = this.formatDate(new Date(timeDate));
|
|
|
- // 开始日期为结束日期前30天
|
|
|
- this.startDate = this.formatDate(new Date(new Date(this.endDate).getTime() - 30 * 24 * 60 * 60 * 1000));
|
|
|
+ this.startDate = this.formatDate(new Date(new Date(this.endDate).getTime() - 7 * 24 * 60 * 60 * 1000));
|
|
|
+ }else{
|
|
|
+ // 单日选择:保持月日不变,仅切换年份
|
|
|
+ const timeDate = this.currentYear + '-' + this.imageDate.split('-')[1] + '-' + this.imageDate.split('-')[2];
|
|
|
+ this.imageDate = this.formatDate(new Date(timeDate));
|
|
|
+ }
|
|
|
+ if(this.currentYear == new Date().getFullYear()){
|
|
|
this.maxDate = this.formatDate(new Date());
|
|
|
this.minDate = this.formatDate(new Date(new Date().getFullYear(), 0, 1));
|
|
|
}else{
|
|
|
- // 结束日期为this.endDate的月份和日期加上选择的年份
|
|
|
- const timeDate = this.currentYear + '-' + this.endDate.split('-')[1] + '-' + this.endDate.split('-')[2];
|
|
|
- this.endDate = this.formatDate(new Date(timeDate));
|
|
|
- // 开始日期为结束日期前30天
|
|
|
- this.startDate = this.formatDate(new Date(new Date(this.endDate).getTime() - 30 * 24 * 60 * 60 * 1000));
|
|
|
this.maxDate = this.formatDate(new Date(this.currentYear, 11, 31));
|
|
|
this.minDate = this.formatDate(new Date(this.currentYear, 0, 1));
|
|
|
}
|
|
|
this.initAction();
|
|
|
this.showPicker = false;
|
|
|
},
|
|
|
- getInfo(info){
|
|
|
- this.pestInfo = info;
|
|
|
- },
|
|
|
// 格式化日期为YYYY-MM-DD格式,月份和日期小于10时前面加0
|
|
|
formatDate(date) {
|
|
|
const year = date.getFullYear();
|
|
|
@@ -377,8 +398,12 @@ export default {
|
|
|
return `${year}-${month}-${day}`;
|
|
|
},
|
|
|
handleChange(e){
|
|
|
- this.startDate = e.startDate;
|
|
|
- this.endDate = e.endDate;
|
|
|
+ if(this.calendarMode === 'range'){
|
|
|
+ this.startDate = e.startDate;
|
|
|
+ this.endDate = e.endDate;
|
|
|
+ }else{
|
|
|
+ this.imageDate = e.result;
|
|
|
+ }
|
|
|
this.page = 1;
|
|
|
this.initAction();
|
|
|
},
|
|
|
@@ -397,8 +422,12 @@ export default {
|
|
|
}else if(this.activeTab === 'aiAnalysis'){
|
|
|
this.getAiAnalysis();
|
|
|
}else if(this.activeTab === 'viewImage'){
|
|
|
- this.initPest();
|
|
|
- this.initImageList();
|
|
|
+ if(this.imageTab === 'viewImage'){
|
|
|
+ this.initPest();
|
|
|
+ this.initImageList();
|
|
|
+ }else{
|
|
|
+ this.initDownImageList();
|
|
|
+ }
|
|
|
}else if(this.activeTab === 'deviceData'){
|
|
|
this.getPolylineData();
|
|
|
this.getDeviceHistoryData();
|
|
|
@@ -411,6 +440,14 @@ export default {
|
|
|
this.activeTab = tab;
|
|
|
this.initAction();
|
|
|
},
|
|
|
+ // 图像数据内的子切换,不影响上方 图像数据/鼠情分析 的选中状态
|
|
|
+ handleImageTabClick(tab) {
|
|
|
+ if(this.imageTab === tab){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.imageTab = tab;
|
|
|
+ this.initAction();
|
|
|
+ },
|
|
|
async initImageList(isLoadMore){
|
|
|
if(isLoadMore){
|
|
|
this.page++;
|
|
|
@@ -423,8 +460,8 @@ export default {
|
|
|
method: 'POST',
|
|
|
data: {
|
|
|
device_id: this.deviceInfo.id,
|
|
|
- start: new Date(this.startDate + ' 00:00:00').getTime()/1000,// 秒级时间戳
|
|
|
- end: new Date(this.endDate + ' 23:59:59').getTime()/1000,// 秒级时间戳
|
|
|
+ start: new Date(this.imageDate + ' 00:00:00').getTime()/1000,// 秒级时间戳
|
|
|
+ end: new Date(this.imageDate + ' 23:59:59').getTime()/1000,// 秒级时间戳
|
|
|
page: this.page,
|
|
|
page_number: this.page_size,
|
|
|
},
|
|
|
@@ -438,6 +475,53 @@ export default {
|
|
|
this.imageList = data;
|
|
|
}
|
|
|
},
|
|
|
+ async initDownImageList(){
|
|
|
+ uni.showLoading({
|
|
|
+ title: '加载中',
|
|
|
+ })
|
|
|
+ const res = await this.$myRequest({
|
|
|
+ url: '/api/api_gateway?method=forecast.shuhai.shuhai_down_imgs',
|
|
|
+ method: 'POST',
|
|
|
+ data: {
|
|
|
+ device_id: this.deviceInfo.id,
|
|
|
+ start: new Date(this.imageDate + ' 00:00:00').getTime()/1000,// 秒级时间戳
|
|
|
+ end: new Date(this.imageDate + ' 23:59:59').getTime()/1000,// 秒级时间戳
|
|
|
+ },
|
|
|
+ });
|
|
|
+ uni.hideLoading();
|
|
|
+ this.downImageList = res?.data || [];
|
|
|
+ },
|
|
|
+ // 获取有数据的日期,默认选中最近的一天
|
|
|
+ async initDateFolder(){
|
|
|
+ const res = await this.$myRequest({
|
|
|
+ url: '/api/api_gateway?method=forecast.shuhai.shuhai_time_folder',
|
|
|
+ method: 'POST',
|
|
|
+ data: {
|
|
|
+ device_id: this.deviceInfo.id,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // 返回结构:[{ "2026": { "01": [3] } }, { "2025": { "12": [13], ... } }]
|
|
|
+ const folders = res?.data || [];
|
|
|
+ const dates = [];
|
|
|
+ folders.forEach(yearItem => {
|
|
|
+ for(const year in yearItem){
|
|
|
+ const months = yearItem[year] || {};
|
|
|
+ for(const month in months){
|
|
|
+ (months[month] || []).forEach(day => {
|
|
|
+ dates.push(`${year}-${month}-${String(day).padStart(2, '0')}`);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if(!dates.length){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // YYYY-MM-DD 格式可直接按字符串比较
|
|
|
+ dates.sort((a, b) => b.localeCompare(a));
|
|
|
+ const today = this.formatDate(new Date());
|
|
|
+ // 日历最大可选今天,数据日期超过今天时取今天
|
|
|
+ this.imageDate = dates[0] > today ? today : dates[0];
|
|
|
+ },
|
|
|
async initPest(){
|
|
|
const res = await this.$myRequest({
|
|
|
url: '/api/api_gateway?method=forecast.new_cbd.pest_type_list',
|
|
|
@@ -447,8 +531,8 @@ export default {
|
|
|
page_size:999999,
|
|
|
device_id: this.deviceInfo.id,
|
|
|
identify_model: 'B',
|
|
|
- time_begin: this.formatDate(new Date(this.startDate)) + ' 00:00:00',// 格式化开始时间YYYY-MM-DD HH:MM:SS
|
|
|
- time_end: this.formatDate(new Date(this.endDate)) + ' 23:59:59',// 格式化结束时间YYYY-MM-DD HH:MM:SS
|
|
|
+ time_begin: this.formatDate(new Date(this.imageDate)) + ' 00:00:00',// 格式化开始时间YYYY-MM-DD HH:MM:SS
|
|
|
+ time_end: this.formatDate(new Date(this.imageDate)) + ' 23:59:59',// 格式化结束时间YYYY-MM-DD HH:MM:SS
|
|
|
},
|
|
|
});
|
|
|
const data = res?.data || [];
|
|
|
@@ -490,42 +574,30 @@ export default {
|
|
|
},
|
|
|
async getPestAnalysis(){
|
|
|
const res = await this.$myRequest({
|
|
|
- url: '/api/api_gateway?method=forecast.cbd_analysis.analysis_pest_result',
|
|
|
+ url: '/api/api_gateway?method=forecast.shuhai.shuhai_analysis',
|
|
|
method: 'POST',
|
|
|
data: {
|
|
|
- d_id: this.deviceInfo.d_id,
|
|
|
- start: this.startDate,
|
|
|
- end: this.endDate,
|
|
|
- model: 'B'
|
|
|
+ device_id: this.deviceInfo.id,
|
|
|
+ start: this.analysisStart,// 秒级时间戳
|
|
|
+ end: this.analysisEnd,// 秒级时间戳
|
|
|
},
|
|
|
});
|
|
|
- console.log(res,'resresres')
|
|
|
- const pest_order = res?.pest_order;
|
|
|
- this.getInfo({});
|
|
|
- let total = 0;
|
|
|
+ // total:[{name,value}] → pest_order:{name:value},供识别统计/物种图表tabs使用
|
|
|
+ const totalList = res?.total || [];
|
|
|
+ const pest_order = {};
|
|
|
+ totalList.forEach(item => {
|
|
|
+ pest_order[item.name] = item.value || 0;
|
|
|
+ });
|
|
|
+ const total = totalList.reduce((sum, item) => sum + (item.value || 0), 0);
|
|
|
this.pests = [];
|
|
|
- const data = [];
|
|
|
for(let key in pest_order){
|
|
|
- total += pest_order[key] || 0;
|
|
|
this.pests.push({
|
|
|
name: key,
|
|
|
- percent: (pest_order[key] / total) * 100
|
|
|
- })
|
|
|
- data.push({
|
|
|
- name: key,
|
|
|
- value: pest_order[key] || 0
|
|
|
+ percent: total ? (pest_order[key] / total) * 100 : 0
|
|
|
})
|
|
|
}
|
|
|
this.pest_order = pest_order;
|
|
|
- this.formatePestMessage([...data.reverse()]);
|
|
|
- this.day = res?.day || [];
|
|
|
- const pest = res?.pest || [];
|
|
|
- this.pest = pest;
|
|
|
- // pest.forEach(p =>{
|
|
|
- // for(let i = 0;i< p.length;i++){
|
|
|
- // this.pest.push(p[i]);
|
|
|
- // }
|
|
|
- // })
|
|
|
+ this.formatePestMessage([...totalList].reverse());
|
|
|
this.total = total;
|
|
|
}
|
|
|
}
|
|
|
@@ -687,7 +759,8 @@ export default {
|
|
|
.tabs-timer-container{
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- width: calc(100% - 256rpx);
|
|
|
+ justify-content: center;
|
|
|
+ width: calc(100% - 206rpx);
|
|
|
height: 64rpx;
|
|
|
line-height: 64rpx;
|
|
|
text-align: center;
|
|
|
@@ -700,8 +773,10 @@ export default {
|
|
|
color: #656565;
|
|
|
margin: 16rpx;
|
|
|
position: relative;
|
|
|
+ white-space: nowrap;
|
|
|
.tabs-timer-item{
|
|
|
- width: 42%;
|
|
|
+ width: auto;
|
|
|
+ flex-shrink: 0;
|
|
|
color: #656565;
|
|
|
text-align: center;
|
|
|
font-family: "Source Han Sans CN VF";
|
|
|
@@ -710,6 +785,7 @@ export default {
|
|
|
}
|
|
|
.calendar-icon{
|
|
|
margin-left: 24rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
}
|
|
|
.tab-item {
|