|
|
@@ -31,11 +31,45 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
<!-- 主图片区域 -->
|
|
|
- <view class="main-photo">
|
|
|
- <image
|
|
|
- :src="currentImg.addr"
|
|
|
- class="main-photo-image"
|
|
|
- />
|
|
|
+ <view class="main-photo" v-if="currentImg.addr">
|
|
|
+ <movable-area class="movable-area" :style="{ height: containerHeight }">
|
|
|
+ <movable-view
|
|
|
+ class="movable-view"
|
|
|
+ direction="all"
|
|
|
+ scale="true"
|
|
|
+ scale-min="1"
|
|
|
+ scale-max="5"
|
|
|
+ >
|
|
|
+ <view class="image-container">
|
|
|
+ <!-- 原图 -->
|
|
|
+ <image
|
|
|
+ :src="currentImg.addr"
|
|
|
+ class="main-photo-image"
|
|
|
+ mode="widthFix"
|
|
|
+ @load="onImageLoad"
|
|
|
+ />
|
|
|
+ <!-- 虫子标记层 -->
|
|
|
+ <view class="bug-markers" v-if="bugMarkers.length > 0">
|
|
|
+ <view
|
|
|
+ v-for="(marker, index) in bugMarkers"
|
|
|
+ :key="index"
|
|
|
+ class="bug-marker"
|
|
|
+ :style="{
|
|
|
+ left: marker.x + '%',
|
|
|
+ top: marker.y + '%',
|
|
|
+ width: marker.width + '%',
|
|
|
+ height: marker.height + '%',
|
|
|
+ borderColor: marker.color
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <view class="bug-label" :style="{ color: marker.color }">
|
|
|
+ {{ getPestName(marker.id) }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </movable-view>
|
|
|
+ </movable-area>
|
|
|
<view class="photo-timestamp">{{ formatDate(currentImg.addtime) }}</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -69,14 +103,14 @@
|
|
|
</view>
|
|
|
<view class="pest-item" v-for="(p, i) in pest[1]" :key="i">
|
|
|
<view class="pest-info">
|
|
|
- <view class="pest-color" :style="{ backgroundColor: getRandomColor() }"></view>
|
|
|
+ <view class="pest-color" :style="{ backgroundColor: getPestColor(p.pest_name) }"></view>
|
|
|
<text class="pest-name">{{ p.pest_name }}</text>
|
|
|
</view>
|
|
|
<text class="pest-count">{{ p.pest_num }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <u-calendar v-model="show" :mode="mode" @change="handleChange" :max-date="maxDate" :min-date="minDate"></u-calendar>
|
|
|
+ <u-calendar v-model="show" :mode="mode" @change="handleChange" :max-date="maxDate" :min-date="minDate" :defaultDate="defaultDate"></u-calendar>
|
|
|
<u-picker v-model="showPicker" mode="selector" :range="selectorRange" range-key="id" :default-selector="[0]" @confirm="confirmHandler"></u-picker>
|
|
|
</view>
|
|
|
</template>
|
|
|
@@ -89,6 +123,7 @@ export default {
|
|
|
mode: 'range',
|
|
|
maxDate: this.formatTime(new Date()),
|
|
|
minDate: this.formatTime(new Date(new Date().getFullYear(), 0, 1)),
|
|
|
+ defaultDate: this.formatTime(new Date(new Date().getFullYear(), 0, 1)),
|
|
|
showPicker: false,
|
|
|
selectorRange: [],
|
|
|
title: '查看图片',
|
|
|
@@ -116,17 +151,24 @@ export default {
|
|
|
pest_list_arr:[],
|
|
|
thumbnails: [],
|
|
|
currentImg:{},
|
|
|
+ bugMarkers: [],
|
|
|
+ imageWidth: 0,
|
|
|
+ imageHeight: 0,
|
|
|
+ imgOld_id:'',
|
|
|
+ containerHeight: '300px',
|
|
|
+ pestDict: {}, // 虫子字典 {id: name}
|
|
|
+ pestColorMap: {}, // 害虫颜色映射 {pestName: color}
|
|
|
};
|
|
|
},
|
|
|
- onLoad(options) {
|
|
|
+ async onLoad(options) {
|
|
|
const {id,img_id,currentYear} = options
|
|
|
this.device_id = id
|
|
|
- this.img_id = img_id
|
|
|
+ this.imgOld_id = img_id
|
|
|
this.currentYear = currentYear
|
|
|
this.time_begin = this.currentYear + '-01-01'
|
|
|
this.time_end = this.currentYear + '-12-31'
|
|
|
- this.maxDate = this.formatTime(new Date())
|
|
|
- this.minDate = this.formatTime(new Date(new Date().getFullYear(), 0, 1))
|
|
|
+ this.maxDate = this.formatTime(this.time_end)
|
|
|
+ this.minDate = this.formatTime(this.time_begin)
|
|
|
this.selectorRange = [];
|
|
|
const nowYear = new Date().getFullYear();
|
|
|
for(let i = 0;i<50;i++){
|
|
|
@@ -136,12 +178,17 @@ export default {
|
|
|
}
|
|
|
this.selectorRange.push(item);
|
|
|
}
|
|
|
+ this.pestList = [];
|
|
|
+ await this.getPestDict();
|
|
|
this.getPestLevelMap();
|
|
|
this.getPestList();
|
|
|
- this.getDevicePhotoDetails();
|
|
|
+ // this.getDevicePhotoDetails();
|
|
|
},
|
|
|
methods: {
|
|
|
- confirmHandler(e){
|
|
|
+ getPestName(id){
|
|
|
+ return this.pestDict[id] || id;
|
|
|
+ },
|
|
|
+ async confirmHandler(e){
|
|
|
this.currentYear = this.selectorRange[e].id;
|
|
|
if(this.currentYear == new Date().getFullYear()){
|
|
|
this.time_begin = this.formatTime(new Date(new Date().getFullYear(), 0, 1));
|
|
|
@@ -152,18 +199,44 @@ export default {
|
|
|
this.time_begin = this.formatTime(new Date(this.currentYear, 0, 1));
|
|
|
this.time_end = this.formatTime(new Date(this.currentYear, 11, 31));
|
|
|
this.maxDate = this.formatTime(new Date(this.currentYear, 11, 31));
|
|
|
- this.minDate = this.formatTime(new Date(this.currentYear, 0, 1));
|
|
|
+ this.minDate = this.formatTime(new Date(this.currentYear, 0, 1));
|
|
|
+ this.defaultDate = this.minDate;
|
|
|
}
|
|
|
this.showPicker = false;
|
|
|
+ this.pestList = [];
|
|
|
+ this.thumbnails = [];
|
|
|
+ await this.getPestList();
|
|
|
},
|
|
|
- handleChange(e){
|
|
|
+ async handleChange(e){
|
|
|
console.log(e,'e')
|
|
|
this.time_begin = e.startDate;
|
|
|
this.time_begin = e.endDate;
|
|
|
- this.getPestList()
|
|
|
+ this.pestList = [];
|
|
|
+ await this.getPestList()
|
|
|
+ this.currentImg = {};
|
|
|
},
|
|
|
- getRandomColor(){
|
|
|
- return this.colors[Math.floor(Math.random() * this.colors.length)]
|
|
|
+ getPestColor(pestName) {
|
|
|
+ // 如果该害虫已有颜色,直接返回
|
|
|
+ if (this.pestColorMap[pestName]) {
|
|
|
+ return this.pestColorMap[pestName];
|
|
|
+ }
|
|
|
+ // 为新害虫分配颜色
|
|
|
+ const usedColors = Object.values(this.pestColorMap);
|
|
|
+ // 找一个未使用的颜色
|
|
|
+ let color;
|
|
|
+ for (const c of this.colors) {
|
|
|
+ if (!usedColors.includes(c)) {
|
|
|
+ color = c;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果所有颜色都用完了,使用哈希值确定颜色
|
|
|
+ if (!color) {
|
|
|
+ const hash = pestName.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
|
+ color = this.colors[hash % this.colors.length];
|
|
|
+ }
|
|
|
+ this.pestColorMap[pestName] = color;
|
|
|
+ return color;
|
|
|
},
|
|
|
getLevelDisplayName(level) {
|
|
|
const levelMap = {
|
|
|
@@ -190,7 +263,18 @@ export default {
|
|
|
},
|
|
|
});
|
|
|
this.thumbnails = res?.data || [];
|
|
|
- console.log(this.thumbnails,'resres2222res')
|
|
|
+ //如果和旧的id相同,就用旧的id不然就用第一个
|
|
|
+ if(this.thumbnails.find(item => item.ids == this.imgOld_id)){
|
|
|
+ this.img_id = this.imgOld_id
|
|
|
+ }else{
|
|
|
+ this.img_id = this.thumbnails[0].ids
|
|
|
+ }
|
|
|
+ this.getDevicePhotoDetails();
|
|
|
+ // if(this.img_id){
|
|
|
+ // this.currentImg = this.thumbnails.find(item => item.ids == this.img_id) || this.thumbnails[0] || {}
|
|
|
+ // }else{
|
|
|
+ // this.currentImg = this.thumbnails[0] || {}
|
|
|
+ // }
|
|
|
},
|
|
|
formatTime(dateString) {
|
|
|
const date = new Date(dateString);
|
|
|
@@ -210,6 +294,22 @@ export default {
|
|
|
}
|
|
|
this.pestYype = pestYype
|
|
|
},
|
|
|
+ // 获取虫子字典
|
|
|
+ async getPestDict() {
|
|
|
+ try {
|
|
|
+ const res = await this.$myRequest({
|
|
|
+ url: '/api/api_gateway?method=forecast.pest_info.pest_dict',
|
|
|
+ method: 'POST',
|
|
|
+ data:{
|
|
|
+ type_name: '1'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.pestDict = res || {};
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取虫子字典失败:', error);
|
|
|
+ this.pestDict = {};
|
|
|
+ }
|
|
|
+ },
|
|
|
formatDate(dateString) {
|
|
|
const date = new Date(dateString*1000);
|
|
|
const year = date.getFullYear();
|
|
|
@@ -230,7 +330,10 @@ export default {
|
|
|
img_id: this.img_id,
|
|
|
},
|
|
|
});
|
|
|
+ console.log('获取图片详情成功:', res);
|
|
|
this.currentImg = res;
|
|
|
+ // 处理label参数生成bugMarkers
|
|
|
+ this.processBugMarkers();
|
|
|
const pest_list = res.pest_list
|
|
|
const pestArr = new Map()
|
|
|
for(let key in this.pestYype){
|
|
|
@@ -253,6 +356,86 @@ export default {
|
|
|
}
|
|
|
this.pestList = pestList
|
|
|
},
|
|
|
+ onImageLoad(e) {
|
|
|
+ this.imageWidth = e.detail.width;
|
|
|
+ this.imageHeight = e.detail.height;
|
|
|
+
|
|
|
+ // 计算容器显示高度(根据屏幕宽度和图片宽高比)
|
|
|
+ const systemInfo = uni.getSystemInfoSync();
|
|
|
+ const screenWidth = systemInfo.windowWidth;
|
|
|
+ const containerWidth = screenWidth - 24; // 减去左右margin (24rpx ≈ 12px)
|
|
|
+ const displayHeight = (containerWidth / this.imageWidth) * this.imageHeight;
|
|
|
+
|
|
|
+ this.containerHeight = displayHeight + 'px';
|
|
|
+ console.log('图片尺寸:', this.imageWidth, this.imageHeight, '容器高度:', this.containerHeight);
|
|
|
+
|
|
|
+ // 图片加载完成后处理bugMarkers
|
|
|
+ this.processBugMarkers();
|
|
|
+ },
|
|
|
+
|
|
|
+ processBugMarkers() {
|
|
|
+ console.log('开始处理label参数:', this.currentImg.label);
|
|
|
+ if (!this.currentImg.label) {
|
|
|
+ console.log('没有label参数');
|
|
|
+ this.bugMarkers = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果没有图片尺寸,先设置默认值
|
|
|
+ if (!this.imageWidth || !this.imageHeight) {
|
|
|
+ console.log('没有图片尺寸,使用默认值');
|
|
|
+ this.imageWidth = 1000;
|
|
|
+ this.imageHeight = 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 处理label参数,将单引号替换为双引号
|
|
|
+ let labelStr = this.currentImg.label;
|
|
|
+ labelStr = labelStr.replace(/'/g, '"');
|
|
|
+ const label = JSON.parse(labelStr);
|
|
|
+ const markers = [];
|
|
|
+
|
|
|
+ // 根据原图宽度计算缩放比例
|
|
|
+ let scaleRatio;
|
|
|
+ if (this.imageWidth >= 5000) {
|
|
|
+ scaleRatio = 1;
|
|
|
+ } else if (this.imageWidth >= 4000) {
|
|
|
+ scaleRatio = 1;
|
|
|
+ } else {
|
|
|
+ scaleRatio = 1;
|
|
|
+ }
|
|
|
+ console.log('原图宽度:', this.imageWidth, '缩放比例:', scaleRatio);
|
|
|
+
|
|
|
+ label.forEach(item => {
|
|
|
+ for (let key in item) {
|
|
|
+ const [x1, y1, x2, y2] = item[key];
|
|
|
+ // 使用缩放比例计算标记位置和尺寸
|
|
|
+ const x = (x1 * scaleRatio / this.imageWidth) * 100;
|
|
|
+ const y = (y1 * scaleRatio / this.imageHeight) * 100;
|
|
|
+ const width = ((x2 - x1) * scaleRatio / this.imageWidth) * 100;
|
|
|
+ const height = ((y2 - y1) * scaleRatio / this.imageHeight) * 100;
|
|
|
+
|
|
|
+ // 从字典中获取虫子名字(尝试字符串和数字两种类型)
|
|
|
+ const pestName = this.pestDict[key] || this.pestDict[String(key)] || key;
|
|
|
+ const color = this.getPestColor(pestName);
|
|
|
+
|
|
|
+ markers.push({
|
|
|
+ id: pestName, // 显示虫子名字
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ color
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.bugMarkers = markers;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('处理label参数失败:', error);
|
|
|
+ this.bugMarkers = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
handleBack() {
|
|
|
uni.navigateBack({
|
|
|
delta: 1
|
|
|
@@ -270,6 +453,15 @@ export default {
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+::v-deep .u-calendar__action{
|
|
|
+ display:flex;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+::v-deep .u-hover-class{
|
|
|
+ .u-calendar__content__item__inner{
|
|
|
+ color:#aaa !important;
|
|
|
+ }
|
|
|
+}
|
|
|
.device-photo-page {
|
|
|
background-color: #F5F5F5;
|
|
|
min-height: 100vh;
|
|
|
@@ -405,12 +597,81 @@ export default {
|
|
|
border-radius: 16rpx;
|
|
|
padding: 0;
|
|
|
overflow: hidden;
|
|
|
+ .movable-area {
|
|
|
+ width: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .movable-view {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .image-container {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
|
|
|
.main-photo-image {
|
|
|
width: 100%;
|
|
|
- height: 400rpx;
|
|
|
- object-fit: cover;
|
|
|
- border-radius: 8rpx;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记层 */
|
|
|
+ .bug-markers {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记 */
|
|
|
+ .bug-marker {
|
|
|
+ position: absolute;
|
|
|
+ border: 2rpx solid;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记标签 */
|
|
|
+ .bug-label {
|
|
|
+ position: absolute;
|
|
|
+ top: -24rpx;
|
|
|
+ left: 0;
|
|
|
+ padding: 2rpx 6rpx;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: white;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记层 */
|
|
|
+ .bug-markers {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记 */
|
|
|
+ .bug-marker {
|
|
|
+ position: absolute;
|
|
|
+ border: 2rpx solid;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ pointer-events: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 虫子标记标签 */
|
|
|
+ .bug-label {
|
|
|
+ position: absolute;
|
|
|
+ top: -30rpx;
|
|
|
+ left: 0;
|
|
|
+ padding: 4rpx 8rpx;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.photo-timestamp {
|