|
@@ -430,9 +430,9 @@
|
|
|
</svg>
|
|
</svg>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 日期标签:独立于绘图区 -->
|
|
|
|
|
|
|
+ <!-- 日期标签:根据数据量和日期跨度智能显示 -->
|
|
|
<view class="chartLabels">
|
|
<view class="chartLabels">
|
|
|
- <text v-for="(label, idx) in traceDetail.environment.chart.labels" :key="`label-${idx}`">{{ label }}</text>
|
|
|
|
|
|
|
+ <text v-for="(item, idx) in chartXAxisLabels" :key="`label-${idx}`" :class="{'label-hidden': item.hidden}">{{ item.label }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
@@ -629,13 +629,14 @@
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { computed, ref, reactive } from 'vue'
|
|
import { computed, ref, reactive } from 'vue'
|
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
|
-import {getTraceDetail } from '@/api/base/index.js'
|
|
|
|
|
|
|
+import {getTraceDetail, listWeather } from '@/api/base/index.js'
|
|
|
import {
|
|
import {
|
|
|
getDeviceCollectorDetail,
|
|
getDeviceCollectorDetail,
|
|
|
getChannels,
|
|
getChannels,
|
|
|
playStart,
|
|
playStart,
|
|
|
pause ,
|
|
pause ,
|
|
|
- querySnap
|
|
|
|
|
|
|
+ querySnap,
|
|
|
|
|
+ fetchDevicesByType
|
|
|
} from '@/api/device.js'
|
|
} from '@/api/device.js'
|
|
|
import Jessibuca from '@/components/common/jessibuca.vue'
|
|
import Jessibuca from '@/components/common/jessibuca.vue'
|
|
|
// 页面状态选择(H5 演示用):通过路由参数传入 state 即可切换 mock 场景
|
|
// 页面状态选择(H5 演示用):通过路由参数传入 state 即可切换 mock 场景
|
|
@@ -701,7 +702,7 @@ const isH5IOS = computed(() => {
|
|
|
})
|
|
})
|
|
|
// 响应式数据
|
|
// 响应式数据
|
|
|
const deviceInfo = reactive({
|
|
const deviceInfo = reactive({
|
|
|
- deviceId: '34020000001110000001',
|
|
|
|
|
|
|
+ deviceId: '',
|
|
|
name: '设备加载中...',
|
|
name: '设备加载中...',
|
|
|
status: 'off',
|
|
status: 'off',
|
|
|
location: '正在获取位置...',
|
|
location: '正在获取位置...',
|
|
@@ -717,6 +718,17 @@ const deviceInfo = reactive({
|
|
|
fmp4StreamUrl: '', // fmp4 流地址(App Android 用)
|
|
fmp4StreamUrl: '', // fmp4 流地址(App Android 用)
|
|
|
imageUrl: '' // 设备图片(如果有)
|
|
imageUrl: '' // 设备图片(如果有)
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+// 气象数据(独立响应式变量,用于土壤养分趋势图)
|
|
|
|
|
+const weatherData = ref({
|
|
|
|
|
+ labels: [],
|
|
|
|
|
+ values: {
|
|
|
|
|
+ n: [],
|
|
|
|
|
+ p: [],
|
|
|
|
|
+ k: []
|
|
|
|
|
+ },
|
|
|
|
|
+ items:[]
|
|
|
|
|
+})
|
|
|
const MOCK_TRACE_DETAILS = {
|
|
const MOCK_TRACE_DETAILS = {
|
|
|
normal: {
|
|
normal: {
|
|
|
product: {
|
|
product: {
|
|
@@ -1070,11 +1082,10 @@ onLoad((opts) => {
|
|
|
// 优先使用路由参数中的 id,其次使用 URL 路径中的 id
|
|
// 优先使用路由参数中的 id,其次使用 URL 路径中的 id
|
|
|
const finalId = batchId || 1
|
|
const finalId = batchId || 1
|
|
|
loadData(finalId)
|
|
loadData(finalId)
|
|
|
- queryChannels()
|
|
|
|
|
|
|
+ // queryChannels()
|
|
|
routeOptions.value = opts || {}
|
|
routeOptions.value = opts || {}
|
|
|
mockStateKey.value = resolveStateKey(opts || {})
|
|
mockStateKey.value = resolveStateKey(opts || {})
|
|
|
startTimeUpdate()
|
|
startTimeUpdate()
|
|
|
-
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
// #ifdef MP-WEIXIN
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
livePlayerContext.value = uni.createVideoContext('myVideo')
|
|
livePlayerContext.value = uni.createVideoContext('myVideo')
|
|
@@ -1097,8 +1108,38 @@ onLoad((opts) => {
|
|
|
}, 500)
|
|
}, 500)
|
|
|
// #endif
|
|
// #endif
|
|
|
})
|
|
})
|
|
|
|
|
+// 加载设备列表
|
|
|
|
|
+const loadDeviceList = (currentFieldId) => {
|
|
|
|
|
+ // 构建查询参数
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ deviceType: 'monitor',
|
|
|
|
|
+ fieldId: currentFieldId || undefined
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 调用API获取设备列表
|
|
|
|
|
+ fetchDevicesByType(params)
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ console.log("res", res);
|
|
|
|
|
+ if (res.data.code === 200 && res.data.rows) {
|
|
|
|
|
+ const { rows, total: totalCount } = res.data;
|
|
|
|
|
+ queryChannels(rows[0].deviceId)// 根据设备ID查询摄像头
|
|
|
|
|
+ } else {
|
|
|
|
|
+ handleApiError(res);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(error => {
|
|
|
|
|
+ console.error('获取设备列表失败', error);
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '获取设备列表失败',
|
|
|
|
|
+ icon: 'none'
|
|
|
|
|
+ });
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
// 根据设备id获取通道列表
|
|
// 根据设备id获取通道列表
|
|
|
- const queryChannels = () => {
|
|
|
|
|
|
|
+ const queryChannels = (deviceId) => {
|
|
|
|
|
+ deviceInfo.deviceId = deviceId
|
|
|
console.log('========== [诊断] queryChannels 被调用 ==========')
|
|
console.log('========== [诊断] queryChannels 被调用 ==========')
|
|
|
getChannels(deviceInfo.deviceId)
|
|
getChannels(deviceInfo.deviceId)
|
|
|
.then(response => {
|
|
.then(response => {
|
|
@@ -1208,10 +1249,51 @@ const loadData = async (batchId) => {
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 调用接口
|
|
|
|
|
const res = await getTraceDetail(batchId)
|
|
const res = await getTraceDetail(batchId)
|
|
|
- traceInfo.value = res.data.data
|
|
|
|
|
- console.log('接口返回数据:', res)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (res && res.data && res.data.data) {
|
|
|
|
|
+ traceInfo.value = res.data.data
|
|
|
|
|
+ } else {
|
|
|
|
|
+ traceInfo.value = {}
|
|
|
|
|
+ }
|
|
|
|
|
+ loadDeviceList(res.data.data.fieldId) // 根据地块ID查询设备信息
|
|
|
|
|
+
|
|
|
|
|
+ const beginCollectTime = formatDateTime(traceInfo.value.startPlantingTime);
|
|
|
|
|
+ const endCollectTime = formatDateTime(traceInfo.value.packageDate);
|
|
|
|
|
+ const paramsMap = {
|
|
|
|
|
+ beginCollectTime:beginCollectTime,
|
|
|
|
|
+ endCollectTime:endCollectTime,
|
|
|
|
|
+ params: {
|
|
|
|
|
+ plotId: traceInfo.value.fieldId
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询气象数据并更新到 weatherData
|
|
|
|
|
+ listWeather(paramsMap).then(res => {
|
|
|
|
|
+ if (res && res.data && res.data.data) {
|
|
|
|
|
+ const data = res.data.data
|
|
|
|
|
+ // 更新气象数据到独立的响应式变量
|
|
|
|
|
+ weatherData.value = {
|
|
|
|
|
+ labels: data.weatherDate || [],
|
|
|
|
|
+ values: {
|
|
|
|
|
+ n: data.weatherAvgSoilN || [],
|
|
|
|
|
+ p: data.weatherAvgSoilP || [],
|
|
|
|
|
+ k: data.weatherAvgSoilK || []
|
|
|
|
|
+ },
|
|
|
|
|
+ items:[
|
|
|
|
|
+ { label: '气温', value: data.weatherRealtimeData.temperature+'℃', status: '种植期平均' },
|
|
|
|
|
+ { label: '湿度', value: data.weatherRealtimeData.humidity+'%', status: '种植期平均' },
|
|
|
|
|
+ { label: '降雨量', value: data.weatherRealtimeData.rainfallA+'mm', status: '种植期累计' },
|
|
|
|
|
+ { label: '光照', value: '充足', status: '表现稳定' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log('气象数据已更新:', weatherData.value)
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ console.error('获取气象数据失败:', err)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ console.log('接口返回数据:', traceInfo.value)
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('加载失败', error)
|
|
console.error('加载失败', error)
|
|
|
// 错误提示已在拦截器中自动处理
|
|
// 错误提示已在拦截器中自动处理
|
|
@@ -1222,6 +1304,12 @@ const loadData = async (batchId) => {
|
|
|
traceLoaded.value = true
|
|
traceLoaded.value = true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+// 工具函数:把日期字符串转为 年月日时分秒格式
|
|
|
|
|
+const formatDateTime = (dateStr) => {
|
|
|
|
|
+ if (!dateStr) return '';
|
|
|
|
|
+ // 截取日期部分 + 拼接 00:00:00
|
|
|
|
|
+ return dateStr.substring(0, 10) + ' 00:00:00';
|
|
|
|
|
+};
|
|
|
// 视频播放错误处理
|
|
// 视频播放错误处理
|
|
|
const onVideoError = (e) => {
|
|
const onVideoError = (e) => {
|
|
|
console.error('========== [诊断] 视频播放错误 ==========')
|
|
console.error('========== [诊断] 视频播放错误 ==========')
|
|
@@ -1900,27 +1988,42 @@ const traceDetail = computed(() => {
|
|
|
// 时间轴逻辑:演示态使用 mock + 真实态使用真实数据
|
|
// 时间轴逻辑:演示态使用 mock + 真实态使用真实数据
|
|
|
farmTimeline: (() => {
|
|
farmTimeline: (() => {
|
|
|
// 判断是否有真实时间轴数据
|
|
// 判断是否有真实时间轴数据
|
|
|
- const hasRealTimeline = Array.isArray(data.farmTimeline) && data.farmTimeline.length > 0
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const hasRealTimeline = data.startPlantingTime == '' || data.startPlantingTime == null
|
|
|
|
|
+
|
|
|
let timeline = []
|
|
let timeline = []
|
|
|
-
|
|
|
|
|
- if (!hasRealTimeline) {
|
|
|
|
|
- // 演示态:使用完整 mock 时间轴(用于页面展示验证)
|
|
|
|
|
- timeline = [
|
|
|
|
|
- { time: '2026-03-01', stage: 'planting', title: '开始种植', desc: '本批次产品进入种植管理阶段' },
|
|
|
|
|
- { time: '2026-03-12', stage: 'care', title: '生长期养护', desc: '种植期间已持续开展灌溉、施肥等日常养护' },
|
|
|
|
|
- { time: '2026-03-20', stage: 'inspection', title: '田间巡检', desc: '种植期间已持续开展长势检查与环境巡检' },
|
|
|
|
|
- { time: data.produceDate || '', stage: 'harvest', title: '成熟采收', desc: '本批次产品进入成熟采收阶段' },
|
|
|
|
|
- { time: (data.reports?.[0]?.reportDate) || '', stage: 'test', title: '安全检测', desc: '已完成安全检测,相关结果可查' },
|
|
|
|
|
- { time: data.packageDate || '', stage: 'pack', title: '包装日期:出库', desc: '已完成包装日期:整理,进入销售流通环节' }
|
|
|
|
|
- ]
|
|
|
|
|
- } else {
|
|
|
|
|
- // 真实态:使用真实数据 + 补充系统节点
|
|
|
|
|
- timeline = [...data.farmTimeline]
|
|
|
|
|
- const stageSet = new Set(timeline.map(n => n.stage))
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if(!hasRealTimeline){
|
|
|
|
|
+ // 开始种植
|
|
|
|
|
+ if (data.startPlantingTime) {
|
|
|
|
|
+ timeline.push({
|
|
|
|
|
+ time: data.startPlantingTime,
|
|
|
|
|
+ stage: 'planting',
|
|
|
|
|
+ title: '开始种植',
|
|
|
|
|
+ desc: '本批次产品进入种植管理阶段'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 生长养护
|
|
|
|
|
+ if (data.growingPeriodTime) {
|
|
|
|
|
+ timeline.push({
|
|
|
|
|
+ time: data.growingPeriodTime,
|
|
|
|
|
+ stage: 'care',
|
|
|
|
|
+ title: '生长期养护',
|
|
|
|
|
+ desc: '种植期间已持续开展灌溉、施肥等日常养护'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 田间巡检
|
|
|
|
|
+ if (data.inspectionTime) {
|
|
|
|
|
+ timeline.push({
|
|
|
|
|
+ time: data.inspectionTime,
|
|
|
|
|
+ stage: 'inspection',
|
|
|
|
|
+ title: '田间巡检',
|
|
|
|
|
+ desc: '种植期间已持续开展长势检查与环境巡检'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 成熟采收
|
|
// 成熟采收
|
|
|
- if (data.produceDate && !stageSet.has('harvest')) {
|
|
|
|
|
|
|
+ if (data.produceDate) {
|
|
|
timeline.push({
|
|
timeline.push({
|
|
|
time: data.produceDate,
|
|
time: data.produceDate,
|
|
|
stage: 'harvest',
|
|
stage: 'harvest',
|
|
@@ -1928,9 +2031,9 @@ const traceDetail = computed(() => {
|
|
|
desc: '本批次产品进入成熟采收阶段'
|
|
desc: '本批次产品进入成熟采收阶段'
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 安全检测
|
|
// 安全检测
|
|
|
- if (data.reports && data.reports.length > 0 && !stageSet.has('test')) {
|
|
|
|
|
|
|
+ if (data.reports && data.reports.length > 0) {
|
|
|
const validDates = data.reports
|
|
const validDates = data.reports
|
|
|
.map(r => r.reportDate)
|
|
.map(r => r.reportDate)
|
|
|
.filter(d => d && /^\d{4}-\d{2}-\d{2}/.test(d))
|
|
.filter(d => d && /^\d{4}-\d{2}-\d{2}/.test(d))
|
|
@@ -1943,10 +2046,20 @@ const traceDetail = computed(() => {
|
|
|
desc: '已完成安全检测,相关结果可查'
|
|
desc: '已完成安全检测,相关结果可查'
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
+ }else{
|
|
|
|
|
+ const validDates = data.certificate
|
|
|
|
|
+ if (validDates) {
|
|
|
|
|
+ timeline.push({
|
|
|
|
|
+ time: validDates.certIssueDate,
|
|
|
|
|
+ stage: 'test',
|
|
|
|
|
+ title: '安全检测',
|
|
|
|
|
+ desc: '已完成安全检测,相关结果可查'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 包装日期:出库
|
|
|
|
|
- if (data.packageDate && !stageSet.has('pack')) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 包装出库
|
|
|
|
|
+ if (data.packageDate) {
|
|
|
timeline.push({
|
|
timeline.push({
|
|
|
time: data.packageDate,
|
|
time: data.packageDate,
|
|
|
stage: 'pack',
|
|
stage: 'pack',
|
|
@@ -1955,7 +2068,7 @@ const traceDetail = computed(() => {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// stage 顺序权重
|
|
// stage 顺序权重
|
|
|
const stageOrder = {
|
|
const stageOrder = {
|
|
|
planting: 1,
|
|
planting: 1,
|
|
@@ -1965,26 +2078,27 @@ const traceDetail = computed(() => {
|
|
|
test: 5,
|
|
test: 5,
|
|
|
pack: 6
|
|
pack: 6
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 按业务阶段排序,同 stage 内再按时间
|
|
// 按业务阶段排序,同 stage 内再按时间
|
|
|
timeline.sort((a, b) => {
|
|
timeline.sort((a, b) => {
|
|
|
const orderA = stageOrder[a.stage] || 99
|
|
const orderA = stageOrder[a.stage] || 99
|
|
|
const orderB = stageOrder[b.stage] || 99
|
|
const orderB = stageOrder[b.stage] || 99
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 先按 stage 排序
|
|
// 先按 stage 排序
|
|
|
if (orderA !== orderB) {
|
|
if (orderA !== orderB) {
|
|
|
return orderA - orderB
|
|
return orderA - orderB
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 同 stage 再按时间
|
|
// 同 stage 再按时间
|
|
|
if (!a.time) return -1
|
|
if (!a.time) return -1
|
|
|
if (!b.time) return 1
|
|
if (!b.time) return 1
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return a.time > b.time ? 1 : -1
|
|
return a.time > b.time ? 1 : -1
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return timeline.slice(0, 6)
|
|
return timeline.slice(0, 6)
|
|
|
- })(),
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ )(),
|
|
|
camera: {
|
|
camera: {
|
|
|
liveUrl: data.camera?.liveUrl || '',
|
|
liveUrl: data.camera?.liveUrl || '',
|
|
|
coverImage: data.camera?.coverImage || '',
|
|
coverImage: data.camera?.coverImage || '',
|
|
@@ -1997,19 +2111,14 @@ const traceDetail = computed(() => {
|
|
|
summary: '本批次种植期环境稳定,整体处于适宜生长区间',
|
|
summary: '本批次种植期环境稳定,整体处于适宜生长区间',
|
|
|
chart: {
|
|
chart: {
|
|
|
type: 'npk_trend',
|
|
type: 'npk_trend',
|
|
|
- labels: ['03-01', '03-06', '03-10', '03-15', '03-21', '03-27', '04-01'],
|
|
|
|
|
|
|
+ labels: weatherData.value.labels,
|
|
|
values: {
|
|
values: {
|
|
|
- n: [26.2, 25.8, 26.4, 25.9, 26.6, 26.1, 26.4],
|
|
|
|
|
- p: [20.5, 20.1, 20.4, 20.0, 20.3, 20.2, 20.4],
|
|
|
|
|
- k: [14.2, 14.6, 14.3, 14.7, 14.4, 14.8, 14.5]
|
|
|
|
|
|
|
+ n: weatherData.value.values.n,
|
|
|
|
|
+ p: weatherData.value.values.p,
|
|
|
|
|
+ k: weatherData.value.values.k
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- items: [
|
|
|
|
|
- { label: '气温', value: '22.3℃', status: '种植期平均' },
|
|
|
|
|
- { label: '湿度', value: '45%', status: '种植期平均' },
|
|
|
|
|
- { label: '降雨量', value: '118mm', status: '种植期累计' },
|
|
|
|
|
- { label: '光照', value: '充足', status: '表现稳定' }
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ items: weatherData.value.items,
|
|
|
current: {
|
|
current: {
|
|
|
temperature: '24.5℃',
|
|
temperature: '24.5℃',
|
|
|
humidity: '42.2%'
|
|
humidity: '42.2%'
|
|
@@ -2274,6 +2383,47 @@ const chartPaths = computed(() => chartData.value.paths)
|
|
|
|
|
|
|
|
const chartAreas = computed(() => chartData.value.areas)
|
|
const chartAreas = computed(() => chartData.value.areas)
|
|
|
|
|
|
|
|
|
|
+// 智能计算 X 轴标签:根据数据量和日期跨度决定哪些显示
|
|
|
|
|
+const chartXAxisLabels = computed(() => {
|
|
|
|
|
+ const labels = traceDetail.value?.environment?.chart?.labels || []
|
|
|
|
|
+ if (!labels.length) return []
|
|
|
|
|
+
|
|
|
|
|
+ // 如果标签数量 <= 7,全部显示
|
|
|
|
|
+ if (labels.length <= 7) {
|
|
|
|
|
+ return labels.map(label => ({ label, hidden: false }))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 数量 > 7,需要智能抽取
|
|
|
|
|
+ const result = []
|
|
|
|
|
+ const total = labels.length
|
|
|
|
|
+
|
|
|
|
|
+ // 计算最大显示数量(根据容器宽度,每个标签最小约 60px)
|
|
|
|
|
+ const avgSpacing = 700 / total
|
|
|
|
|
+
|
|
|
|
|
+ if (avgSpacing < 60) {
|
|
|
|
|
+ // 标签太密集,只显示首尾 + 每隔一段显示一个
|
|
|
|
|
+ const step = Math.max(1, Math.floor(total / 6))
|
|
|
|
|
+ for (let i = 0; i < total; i++) {
|
|
|
|
|
+ if (i === 0 || i === total - 1 || i % step === 0) {
|
|
|
|
|
+ result.push({ label: labels[i], hidden: false })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result.push({ label: '', hidden: true })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 标签间距足够,每隔一个显示
|
|
|
|
|
+ for (let i = 0; i < total; i++) {
|
|
|
|
|
+ if (i % 2 === 0) {
|
|
|
|
|
+ result.push({ label: labels[i], hidden: false })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result.push({ label: '', hidden: true })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
const reportImages = computed(() => {
|
|
const reportImages = computed(() => {
|
|
|
const items = traceDetail.value?.report?.items
|
|
const items = traceDetail.value?.report?.items
|
|
|
if (Array.isArray(items)) {
|
|
if (Array.isArray(items)) {
|
|
@@ -3276,6 +3426,10 @@ function previewDoc(kind, index) {
|
|
|
color: rgba(84, 106, 93, 0.4);
|
|
color: rgba(84, 106, 93, 0.4);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.chartLabels .label-hidden {
|
|
|
|
|
+ visibility: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.environmentChartLegend {
|
|
.environmentChartLegend {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
justify-content: center;
|
|
justify-content: center;
|