| | |
| | | VITE_APP_BASE=/manage |
| | | |
| | | # 服务地址 |
| | | VITE_APP_URL = https://wrj.shuixiongit.com/api |
| | | # VITE_APP_URL = https://wrj.shuixiongit.com/api |
| | | VITE_APP_URL= http://192.168.1.7 |
| | | # 域名 |
| | | VITE_APP_AREA_NAME = wss://wrj.shuixiongit.com |
| | | |
| | |
| | | import request from '@/axios' |
| | | import request from '@/axios'; |
| | | // 事件概况总数 |
| | | export const getJobEventTotal = () => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/total', |
| | | method: 'get', |
| | | }) |
| | | } |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/total', |
| | | method: 'get', |
| | | }); |
| | | }; |
| | | // 事件概况分类数 |
| | | export const getJobEventByStatus = data => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/eventByStatus', |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/eventByStatus', |
| | | method: 'post', |
| | | data, |
| | | }); |
| | | }; |
| | | // 行业任务统计 |
| | | export const industryJobNumPieChart = data => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/deviceEventList', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/deviceEventList', |
| | | method: 'post', |
| | | data: data, |
| | | }); |
| | | }; |
| | | // 事件任务统计 |
| | | export const jobEventBar = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar', |
| | | method: 'post', |
| | | data: data, |
| | | }); |
| | | }; |
| | | // 设备统计 |
| | | export const getStatics = (areaCode) => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/deviceStatistics', |
| | | method: 'post', |
| | | params: { |
| | | areaCode |
| | | }, |
| | | }); |
| | | }; |
| | | // 日历 |
| | | export const getStatics = areaCode => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/deviceStatistics', |
| | | method: 'post', |
| | | params: { |
| | | areaCode, |
| | | }, |
| | | }); |
| | | }; |
| | | // 日历 |
| | | export const getCalen = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar', |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobEventBarByMouth', |
| | | method: 'post', |
| | | data, |
| | | }); |
| | | }; |
| | | // 飞行统计 |
| | | export const getFly = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/deviceFlyTimeAndDistance', |
| | | method: 'post', |
| | | data, |
| | | }); |
| | | }; |
| | | // 飞行时长 里程 任务数 |
| | | export const getFlyTime = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/deviceFlyTimeAndDistanceBar', |
| | | method: 'post', |
| | | data, |
| | | }); |
| | | }; |
| | |
| | | :key="index" |
| | | class="todo-item" |
| | | :class="`status-${item.status}`" |
| | | @click="jumporder()" |
| | | > |
| | | <div class="status-indicator"></div> |
| | | |
| | |
| | | date: '2025.03.26', |
| | | }, |
| | | ]); |
| | | const jumporder=()=>{ |
| | | console.log('tiao'); |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <template> |
| | | <div class="calenBox"> |
| | | <el-calendar ref="calendar" v-model="leftValue" @change="handleMonthChange(date)"> |
| | | <el-calendar ref="calendar" v-model="leftValue"> |
| | | <template #date-cell="{ data }"> |
| | | <div> |
| | | <div class="date-number">{{ data.day.slice(8, 10) }}</div> |
| | |
| | | :class="event.type" |
| | | > |
| | | <span></span> |
| | | {{ event.content }} |
| | | {{ event.name }}{{ event.value }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | () => leftValue.value, |
| | | (newV, oldV) => { |
| | | if (newV && dayjs(newV).isSame(dayjs(), 'day')) { |
| | | console.log('点击了今天'); |
| | | } |
| | | |
| | | if (newV && oldV) { |
| | | const newDate = dayjs(newV); |
| | | const oldDate = dayjs(oldV); |
| | | |
| | | if (newDate.isBefore(oldDate, 'month')) { |
| | | console.log('点击了上个月'); |
| | | } else if (newDate.isAfter(oldDate, 'month')) { |
| | | console.log('点击了下个月'); |
| | | } |
| | | const newDateStr = newDate.format('YYYY-MM-DD HH:mm:ss'); |
| | | const oldDateStr = oldDate.format('YYYY-MM-DD HH:mm:ss'); |
| | | // console.log('新日期:', newDateStr, '旧日期:', oldDateStr); |
| | | params.value = { |
| | | start_date: newDate.startOf('month').format('YYYY-MM-DD HH:mm:ss'), |
| | | end_date: newDate.endOf('month').format('YYYY-MM-DD HH:mm:ss'), |
| | | }; |
| | | |
| | | // if (newDate.isBefore(oldDate, 'month')) { |
| | | // console.log('点击了上个月', params.value); |
| | | // } else if (newDate.isAfter(oldDate, 'month')) { |
| | | // console.log('点击了下个月', params.value); |
| | | // } |
| | | getJobEventBar(); |
| | | } |
| | | }, |
| | | { deep: true } |
| | | { deep: true, immediate: true } |
| | | ); |
| | | const handleMonthChange = date => { |
| | | console.log('date', date); |
| | | |
| | | // 获取当前视图月份的第一天 |
| | | const firstDay = new Date(date.getFullYear(), date.getMonth(), 1); |
| | | |
| | | // 获取当前视图月份的最后一天 |
| | | const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0); |
| | | |
| | | // 格式化为YYYY-MM-DD格式(可选) |
| | | const formatDate = d => d.toISOString().slice(0, 10); |
| | | |
| | | console.log('首日:', formatDate(firstDay)); |
| | | console.log('末日:', formatDate(lastDay)); |
| | | }; |
| | | // 获取日期数字 |
| | | const getDate = date => { |
| | | return date.getDate(); |
| | | }; |
| | | // 获取对应日期的事件 |
| | | const getEvents = dateString => { |
| | | // console.log('000',dateString); |
| | | |
| | | return events.value[dateString] || []; |
| | | }; |
| | | const monthRange = getCurrentMonthRange(); |
| | | params.value = monthRange; |
| | | const getJobEventBar = () => { |
| | | const monthRange = getCurrentMonthRange(); |
| | | params.value = monthRange; |
| | | console.log(monthRange); |
| | | getCalen(params.value).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | // events.value = res.data.data |
| | | console.log('日历', res.data.data); |
| | | events.value = res.data.data |
| | | // console.log('日历', res.data.data); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | |
| | | margin: 2px 0; |
| | | border-radius: 3px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | // overflow: hidden; |
| | | // text-overflow: ellipsis; |
| | | |
| | | &.work-order { |
| | | // background: #ecf5ff; |
| | |
| | | <div class="card-title"> |
| | | <img :src="jc1" alt="" /> |
| | | <div class="cardtotal"> |
| | | <p>机巢事件数量排名</p> |
| | | <p>机巢工单数量排名</p> |
| | | <!-- <div class="total-number">111</div> |
| | | <span>个</span> --> |
| | | </div> |
| | |
| | | const echartsRef = ref(null); |
| | | let { chart: jcchart } = useEchartsResize(echartsRef); |
| | | const jcOrder = ref([]); |
| | | const props = defineProps({ |
| | | dateSelect: { |
| | | type: String, |
| | | }, |
| | | }); |
| | | const params = reactive({ |
| | | date_enum: props.dateSelect, |
| | | }); |
| | | // 获取机巢事件数据 |
| | | const getIndustryJobNumPieChart = value => { |
| | | industryJobNumPieChart(value).then(res => { |
| | | console.log('ppp', res); |
| | | |
| | | const getIndustryJobNumPieChart = () => { |
| | | industryJobNumPieChart(params).then(res => { |
| | | const resList = res?.data?.data || []; |
| | | jcOrder.value = resList; |
| | | pieInit(resList); |
| | | }); |
| | | }; |
| | | watch( |
| | | () => props.dateSelect, |
| | | newVal => { |
| | | params.date_enum = newVal; |
| | | getIndustryJobNumPieChart(); |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | const pieInit = resList => { |
| | | // 处理数据,过滤掉没有name的项 |
| | | const validData = resList.filter(item => item.name); |
| | | |
| | | // 准备图表数据 |
| | | const colors = [ |
| | | '#F87E04', |
| | | '#FFC400', |
| | | '#08BC44', |
| | | '#07B5FF', |
| | | '#A98DFF', |
| | | '#9ABFFF' |
| | | ]; |
| | | const optionData = { |
| | | yAxisData: validData.map(item => item.name), |
| | | seriesData: validData.map(item => item.value), |
| | |
| | | type: 'bar', |
| | | data: optionData.seriesData, // 使用处理后的数值数据 |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | // 修改为根据索引返回不同颜色 |
| | | color: (params) => { |
| | | if (params.dataIndex < 5) { |
| | | // 前5条使用固定颜色 |
| | | return colors[params.dataIndex % colors.length]; |
| | | } |
| | | // 第6条及之后保持原渐变 |
| | | return new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#93BAFF' }, |
| | | { offset: 1, color: '#C5DEFF' }, |
| | | ]), |
| | | { offset: 1, color: '#C5DEFF' } |
| | | ]); |
| | | } |
| | | }, |
| | | barWidth: '30%', |
| | | label: { |
| | |
| | | jcchart.value.setOption(option); |
| | | }; |
| | | onMounted(() => { |
| | | getIndustryJobNumPieChart({ date_enum: 'CURRENT_WEEK' }); |
| | | getIndustryJobNumPieChart(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .machineNest { |
| | | width: 100%; |
| | | .nestTop { |
| | | .card-title { |
| | | display: flex; |
| | |
| | | <div class="title"> |
| | | <div class="name"> |
| | | <span> 设备统计</span> |
| | | <img src="/src/assets/images/workbench/st1.png" alt="" /> |
| | | <img @click="refresh" src="/src/assets/images/workbench/st1.png" alt="" /> |
| | | </div> |
| | | <div class="arrow"> |
| | | <div class="arrow" @click="jumppage"> |
| | | <img src="/src/assets/images/workbench/st2.png" alt="" /> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="grid-container"> |
| | | <div class="grid-container1" > |
| | | <div v-for="(item, index) in Object.keys(newtitleData)" :key="index" class="device-card"> |
| | | <div class="device-title"> |
| | | <img :src="test[item].img" :alt="newtitleData[item].name" /> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="status-list"> |
| | | |
| | | <div |
| | | v-for="(status, statusIndex) in newtitleData[item].status_map" |
| | | :key="statusIndex" |
| | | class="status-item" |
| | | :class="getStatusStyle(test[item]?.name, statusIndex)" |
| | | :style="{ color: getStatusColor(test[item]?.name, statusIndex) }" |
| | | > |
| | | <span class="indicator"></span> |
| | | <span class="label">{{ getStatusLabel(test[item]?.name, statusIndex) }}</span> |
| | | <span class="count" |
| | | >{{ status }} {{ test[item]?.name === '无人机' ? '架' : '个' }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> --> |
| | | <div class="grid-container1"> |
| | | <div v-for="(item, index) in Object.keys(newtitleData)" :key="index" class="device-card"> |
| | | <div class="device-title"> |
| | | <img :src="test[item].img" :alt="newtitleData[item].name" /> |
| | | <div class="itemcenter"> |
| | | <div>{{ test[item]?.name || '--' }}</div> |
| | | <span class="shu">{{ newtitleData[item].total_num }}</span> |
| | | <span>个</span> |
| | | </div> |
| | | </div> |
| | | <div class="status-list"> |
| | | <!-- :class="`status-${statusIndex}`" --> |
| | | <div |
| | | v-for="(status, statusIndex) in newtitleData[item].status_map" |
| | | :key="statusIndex" |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="grid-container" > |
| | | <div v-for="(item, index) in Object.keys(newtitleData)" :key="index" class="device-card"> |
| | | <div class="device-title"> |
| | | <img :src="test[item].img" :alt="newtitleData[item].name" /> |
| | | <div class="itemcenter"> |
| | | <div>{{ test[item]?.name || '--' }}</div> |
| | | <span class="shu">{{ newtitleData[item].total_num }}</span> |
| | | <span>个</span> |
| | | </div> |
| | | <div class="status-list"> |
| | | <div |
| | | v-for="(status, statusIndex) in newtitleData[item].status_map" |
| | | :key="statusIndex" |
| | | class="status-item" |
| | | :class="getStatusStyle(test[item]?.name, statusIndex)" |
| | | :style="{ color: getStatusColor(test[item]?.name, statusIndex) }" |
| | | > |
| | | <span |
| | | class="indicator" |
| | | :style="{ |
| | | backgroundColor: getStatusBackground(test[item]?.name, statusIndex), |
| | | color: getStatusColor(test[item]?.name, statusIndex), |
| | | }" |
| | | ></span> |
| | | <span class="label">{{ getStatusLabel(test[item]?.name, statusIndex) }}</span> |
| | | <span class="count" |
| | | >{{ status }} {{ test[item]?.name === '无人机' ? '架' : '个' }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> --> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import titleImg6 from '@/assets/images/workbench/st9.png'; |
| | | import { getStatics } from '@/api/home/index'; |
| | | const store = useStore(); |
| | | Object.key; |
| | | // Object.key; |
| | | // 运维人员:1912328766238597121 |
| | | // 政企专员:1912467025014923265 |
| | | const refresh=()=>{ |
| | | getStaticsList() |
| | | } |
| | | const jumppage=()=>{ |
| | | console.log('跳转'); |
| | | |
| | | } |
| | | const userInfo = computed(() => store.getters.userInfo); |
| | | console.log('userInfo', userInfo.value.role_id); |
| | | const newtitleData = ref({}); |
| | | const titleData = ref([ |
| | | { |
| | | img: titleImg1, |
| | | name: '机巢', |
| | | total_num: 52, |
| | | working: 0, |
| | | leisure: 0, |
| | | offline: 0, |
| | | }, |
| | | { |
| | | img: titleImg2, |
| | | name: '无人机', |
| | | total_num: 52, |
| | | working: 0, |
| | | leisure: 0, |
| | | offline: 0, |
| | | }, |
| | | { |
| | | img: titleImg3, |
| | | name: '监控设备', |
| | | total_num: 52, |
| | | working: 0, |
| | | leisure: 0, |
| | | offline: 0, |
| | | }, |
| | | { |
| | | img: titleImg4, |
| | | name: '移动机巢', |
| | | total_num: 52, |
| | | working: 0, |
| | | leisure: 0, |
| | | offline: 0, |
| | | }, |
| | | ]); |
| | | const test = { |
| | | no_move_list: { |
| | | name: '机巢', |
| | |
| | | 4: '作业中', |
| | | '-1': '离线中', |
| | | }; |
| | | // 流量 状态 0充足,1=流量到期,2=不足 |
| | | const flowStatus = { |
| | | 0: '流量无忧', |
| | | 1: '流量到期', |
| | | 2: '流量不足', |
| | | }; |
| | | // "监控状态 1=在线,0=离线" |
| | | const monitorStatus = { |
| | | 0: '离线中', |
| | | 1: '在线中', |
| | | }; |
| | | // 机巢保险 1=保险,0=未保险 |
| | | const insureStatus = { |
| | | 0: '临近到期', |
| | | 1: '正常期限', |
| | |
| | | const getStaticsList = () => { |
| | | getStatics(userInfo.value.detail.areaCode).then(res => { |
| | | newtitleData.value = res.data.data; |
| | | console.log('设备', newtitleData.value); |
| | | // console.log('设备', newtitleData.value); |
| | | }); |
| | | }; |
| | | |
| | |
| | | monitor: '个', |
| | | mobile: '个', |
| | | }; |
| | | const titleData = ref([ |
| | | { |
| | | img: titleImg1, |
| | | name: '机巢', |
| | | type: 'nest', |
| | | data: 52, |
| | | statuses: [ |
| | | { type: 'working', label: '作业中', count: 20 }, |
| | | { type: 'idle', label: '空间中', count: 20 }, |
| | | { type: 'offline', label: '离线中', count: 20 }, |
| | | ], |
| | | }, |
| | | { |
| | | img: titleImg2, |
| | | name: '无人机', |
| | | data: 52, |
| | | type: 'drone', |
| | | statuses: [ |
| | | { type: 'working', label: '作业中', count: 20 }, |
| | | { type: 'idle', label: '空间中', count: 20 }, |
| | | { type: 'offline', label: '离线中', count: 20 }, |
| | | ], |
| | | }, |
| | | { |
| | | img: titleImg3, |
| | | name: '监控设备', |
| | | type: 'monitor', |
| | | data: 52, |
| | | statuses: [ |
| | | { type: 'working', label: '作业中', count: 20 }, |
| | | { type: 'idle', label: '空间中', count: 20 }, |
| | | { type: 'offline', label: '离线中', count: 20 }, |
| | | ], |
| | | }, |
| | | { |
| | | img: titleImg4, |
| | | name: '移动机巢', |
| | | type: 'mobile', |
| | | data: 52, |
| | | statuses: [ |
| | | { type: 'working', label: '作业中', count: 20 }, |
| | | { type: 'idle', label: '空间中', count: 20 }, |
| | | { type: 'offline', label: '离线中', count: 20 }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | onMounted(() => { |
| | | getStaticsList(); |
| | | }); |
| | |
| | | |
| | | <style scoped lang="scss"> |
| | | .statistics { |
| | | // height: 174px; |
| | | min-height: 174px; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 8px 8px; |
| | | margin-bottom: 10px; |
| | |
| | | span { |
| | | margin-right: 4px; |
| | | } |
| | | img{ |
| | | cursor: pointer;} |
| | | } |
| | | .arrow { |
| | | cursor: pointer; |
| | |
| | | .grid-container { |
| | | padding: 0 14px 0 21px; |
| | | display: grid; |
| | | grid-template-columns: repeat(6, 1fr); |
| | | grid-template-columns: repeat(4, 1fr); |
| | | .device-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | |
| | | } |
| | | .status-list { |
| | | display: grid; |
| | | |
| | | margin-left: 5px; |
| | | .status-item { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | <div class="ratio"> |
| | | 占比 |
| | | <span :style="{ color: item.color }" |
| | | >{{ (item.rate / 100) * 100 }}%</span |
| | | >{{ ((item.rate * 100) / 100).toFixed(2) }}%</span |
| | | > |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | <div class="flycenter"> |
| | | <div class="centerBox"> |
| | | <div class="centerItem" v-for="(item, index) in 3" :key="index"> |
| | | <div><img src="@/assets/images/workbench/fy2.png" alt="" />飞行时长</div> |
| | | <div class="flydata"><span>5421.56</span>时</div> |
| | | <div class="centerItem" v-for="(itemfly, index) in flyTypeList" :key="index"> |
| | | <div class="flyimg"><img :src="itemfly.img" alt="" />{{itemfly.name}}</div> |
| | | <div class="flydata"><span>{{itemfly.value}}</span>{{unitMap[itemfly.name]}}</div> |
| | | </div> |
| | | </div> |
| | | <div class="lineChart"> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="centerRight"> |
| | | <flyratio></flyratio> |
| | | <flyratio :dateSelect="dateSelect"></flyratio> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | import * as echarts from 'echarts'; |
| | | import useEchartsResize from '@/hooks/useEchartsResize'; |
| | | import { mapGetters } from 'vuex'; |
| | | import { ref } from 'vue'; |
| | | import { getJobEventByStatus, getJobEventTotal,getFly,getFlyTime } from '@/api/home/index'; |
| | | import overviewImg1 from '@/assets/images/workbench/tc1.png'; |
| | | import overviewImg2 from '@/assets/images/workbench/tc2.png'; |
| | | import overviewImg3 from '@/assets/images/workbench/tc3.png'; |
| | |
| | | import overviewImg5 from '@/assets/images/workbench/tc5.png'; |
| | | import overviewImg6 from '@/assets/images/workbench/tc6.png'; |
| | | import flyImg1 from '@/assets/images/workbench/fy2.png'; |
| | | import flyImg2 from '@/assets/images/workbench/fy3.png'; |
| | | import flyImg3 from '@/assets/images/workbench/fy4.png'; |
| | | import statistics from './components/statistics.vue'; |
| | | import { getJobEventByStatus, getJobEventTotal } from '@/api/home/index'; |
| | | // const value = ref(new Date()); |
| | | let checked = ref('CURRENT_WEEK'); |
| | | let timeListStr = ['本周', '本月', '本年']; |
| | | let timeListEnum = ['CURRENT_WEEK', 'CURRENT_MONTH', 'CURRENT_YEAR']; |
| | | const params = ref({ |
| | | date_enum: 'CURRENT_WEEK', |
| | | device_sn: '', |
| | | end_date: undefined, |
| | | start_date: undefined, |
| | | }); |
| | | const dateSelect = ref('CURRENT_WEEK'); |
| | | let timeClick = (item, index) => { |
| | | checked.value = item; |
| | | params.value.date_enum = item; |
| | | dateSelect.value = item; |
| | | console.log('日期选择', params.value.date_enum); |
| | | getTypeData(); |
| | | }; |
| | |
| | | { name: '处理中', value: 0, img: overviewImg4, color: '#FF8B26', status: '3', rate: 0 }, |
| | | { name: '已完成', value: 0, img: overviewImg5, color: '#0291A1', status: '4', rate: 0 }, |
| | | ]); |
| | | const keyMapping = { |
| | | '飞行时长': 'total_flight_time', |
| | | '飞行里程': 'total_flight_distance', |
| | | '任务成果': 'event_num' |
| | | }; |
| | | const unitMap = { |
| | | '飞行时长': '时', |
| | | '飞行里程': '千米', |
| | | '任务成果': '个' |
| | | }; |
| | | const flyTypeList = ref([ |
| | | { name: '飞行时长', value: 0, img: overviewImg2 }, |
| | | { name: '飞行里程', value: 0, img: overviewImg3 }, |
| | | { name: '任务成功', value: 0, img: overviewImg4 }, |
| | | { name: '飞行时长', value: 0, img: flyImg1 }, |
| | | { name: '飞行里程', value: 0, img: flyImg2 }, |
| | | { name: '任务成果', value: 0, img: flyImg3 }, |
| | | ]); |
| | | const params = ref({ |
| | | date_enum: 'CURRENT_WEEK', |
| | | device_sn: '', |
| | | end_date: undefined, |
| | | start_date: undefined, |
| | | }); |
| | | |
| | | const eventTotal = ref(0); |
| | | const data = ref([]); |
| | | // 工单统计 |
| | | const getTypeData = () => { |
| | | getJobEventByStatus(params.value).then(res => { |
| | | const resList = res?.data?.data || []; |
| | | console.log('工单统计', res.data.data); |
| | | |
| | | resList.forEach(item => { |
| | | eventTypeList.value.forEach(item1 => { |
| | | if (item1.name === item.name) { |
| | |
| | | initChart(resList); |
| | | }); |
| | | }; |
| | | // 飞行统计 |
| | | |
| | | const getFlyList=()=>{ |
| | | getFly(params.value).then(res=>{ |
| | | flyTypeList.value = flyTypeList.value.map(item => ({ |
| | | ...item, |
| | | value: res.data.data[keyMapping[item.name]] || 0 |
| | | })); |
| | | }) |
| | | } |
| | | const getFlyTimeList=()=>{ |
| | | getFlyTime(params.value).then(res=>{ |
| | | const resList = res?.data?.data || []; |
| | | console.log('飞行统计11',res.data.data); |
| | | lineCharts(resList) |
| | | }) |
| | | } |
| | | // 图表 |
| | | const echartsRef = ref(null); |
| | | let { chart } = useEchartsResize(echartsRef); |
| | |
| | | fontWeight: '600', |
| | | }, |
| | | top: '40%', |
| | | left: 'center', |
| | | left: '50%', |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '', |
| | | type: 'pie', |
| | | radius: ['30%', '45%'], |
| | | radius: ['40%', '55%'], |
| | | avoidLabelOverlap: true, |
| | | // avoidLabelOverlap: false, |
| | | left: '10%', |
| | | label: { |
| | | formatter: `{a|{b}}: {b|{d}%}`, |
| | | formatter: (params) => { |
| | | return `{a|${params.name}}: ${params.data.rate}%`; |
| | | }, |
| | | alignTo: 'labelLine', |
| | | rich: { |
| | | a: { |
| | |
| | | }; |
| | | |
| | | // 柱状图 |
| | | const lineCharts = () => { |
| | | const lineCharts = (bardata) => { |
| | | const categories = bardata?.map(item => item.name); // x轴类别 |
| | | const flight_distance=[] |
| | | const flight_time=[] |
| | | const event_num=[] |
| | | var option = { |
| | | tooltip: { |
| | | trigger: 'item', |
| | |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], |
| | | data: categories, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#cdd5e2', |
| | |
| | | }, |
| | | }, |
| | | }, |
| | | // 移除第二个y轴配置 |
| | | |
| | | { |
| | | type: 'log', |
| | | name: '', |
| | | nameTextStyle: { |
| | | color: '#666666', |
| | | }, |
| | | min: 1, |
| | | logBase: 3, |
| | | axisLine: { |
| | | show: false, |
| | | lineStyle: { |
| | | color: '#cdd5e2', |
| | | }, |
| | | }, |
| | | |
| | | splitLine: { |
| | | show: true, // 显示分割线 |
| | | lineStyle: { |
| | | type: 'dashed', // 设置为虚线 |
| | | color: '#cdd5e2', // 颜色与轴线一致 |
| | | width: 1, // 线宽 |
| | | opacity: 0.5, // 透明度 |
| | | }, |
| | | }, |
| | | axisLabel: { |
| | | textStyle: { |
| | | color: '#666666', |
| | | }, |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#cdd5e2', |
| | | }, |
| | | }, |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | |
| | | { |
| | | name: '任务成果', |
| | | type: 'line', |
| | | yAxisIndex: 0, // 改为使用第一个y轴 |
| | | yAxisIndex: 1, // 改为使用第一个y轴 |
| | | smooth: true, |
| | | // symbol: 'circle', |
| | | // symbolSize: 8, |
| | |
| | | |
| | | getTypeData(); |
| | | lineCharts(); |
| | | getFlyList() |
| | | getFlyTimeList() |
| | | }); |
| | | </script> |
| | | |
| | |
| | | .status-item { |
| | | display: flex; |
| | | text-align: center; |
| | | justify-content: space-between; |
| | | height: 97px; |
| | | max-width: 148px; |
| | | background: #f6f8fe; |
| | | border-radius: 8px 8px 8px 8px; |
| | | img { |
| | |
| | | } |
| | | .flycenter { |
| | | margin-top: 13px; |
| | | |
| | | .centerBox { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | .centerItem { |
| | | padding: 7px 7px 0 15px; |
| | | // width: 196px; |
| | |
| | | border-radius: 8px 8px 8px 8px; |
| | | border: 1px solid #ffffff; |
| | | margin-right: 16px; |
| | | img{ |
| | | width: 15px; |
| | | height: 15px; |
| | | margin-right: 5px; |
| | | } |
| | | .flyimg { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .flydata { |
| | | margin-top: 15px; |
| | | text-align: right; |
| | |
| | | } |
| | | } |
| | | } |
| | | .centerRight { |
| | | width: 40%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .workright { |
| | | width: 32%; |
| | | } |