8 files modified
2 files added
| | |
| | | params, |
| | | }) |
| | | } |
| | | // 获取天气建议 |
| | | export const getDroneSuggest = params => { |
| | | return request({ |
| | | url: `/drone-device-core/dp/home/getDroneSuggest`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | |
| | | <div class="left"> |
| | | {{ title }} |
| | | </div> |
| | | <div class="right" v-if="show" @click="attrs.onDetails()">详情 ></div> |
| | | <div class="right" v-if="show" @click="attrs.onDetails()">{{ text }} ></div> |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | |
| | | type: String, |
| | | default: '机巢概况', |
| | | }, |
| | | text: { |
| | | type: String, |
| | | default: '详情', |
| | | }, |
| | | }); |
| | | const attrs = useAttrs(); |
| | | const show = ref(attrs.onDetails); |
| | |
| | | <div class="line"></div> |
| | | <div class="weather"> |
| | | <img src="@/assets/images/home/homeLeft/tq.png" alt="" /> |
| | | <span class="tq">阴天</span> |
| | | <span class="qk">适合飞行</span> |
| | | <span class="tq">{{ weather }}</span> |
| | | <span class="qk">{{ isFly }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import dayjs from 'dayjs'; |
| | | import { getDroneSuggest } from '@/api/home/common'; |
| | | |
| | | |
| | | const time = ref(''); |
| | | const updateTime = () => { |
| | | time.value = dayjs().format('YYYY.MM.DD HH:mm:ss'); |
| | | }; |
| | | |
| | | // 天气 |
| | | const weather = ref(''); |
| | | // 是否适合飞行 |
| | | const isFly = ref(''); |
| | | // 获取天气建议 |
| | | const getWeatherSuggest = () => { |
| | | getDroneSuggest().then(res => { |
| | | if (res.data.code !== 0) return; |
| | | weather.value = res.data.data.weather; |
| | | isFly.value = res.data.data.flightAdvice; |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getWeatherSuggest(); |
| | | updateTime(); // 立即执行一次 |
| | | time.value = setInterval(updateTime, 1000); |
| | | }); |
| | |
| | | |
| | | const home = { |
| | | state: { |
| | | machineNestDetail: false, // 机巢详情 |
| | | singleUavHome: {}, |
| | | singleTotal: {}, // 统计单个机巢数据 |
| | | // 项目id |
| | |
| | | }, |
| | | actions: {}, |
| | | mutations: { |
| | | setMachineNestDetail: (state, data) => { |
| | | state.machineNestDetail = data; |
| | | }, |
| | | setSingleUavHome: (state, data) => { |
| | | state.singleUavHome = data; |
| | | }, |
| | |
| | | <div class="home-left"> |
| | | <!--时间 天气--> |
| | | <common-weather></common-weather> |
| | | <!--机巢概况--> |
| | | <overview-next></overview-next> |
| | | <!--巡检任务情况--> |
| | | <inspection-rask-details></inspection-rask-details> |
| | | <template v-if="machineNestListRef"> |
| | | <!--机巢列表--> |
| | | <MachineNestList></MachineNestList> |
| | | </template> |
| | | <template v-else> |
| | | <!--机巢概况--> |
| | | <overview-next></overview-next> |
| | | <!--巡检任务情况--> |
| | | <inspection-rask-details></inspection-rask-details> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import OverviewNext from './OverviewNext.vue'; |
| | | import InspectionRaskDetails from './InspectionRaskDetails.vue'; |
| | | import CommonWeather from '@/components/CommonWeather.vue'; |
| | | import MachineNestList from './MachineNestList.vue'; |
| | | import { useStore } from 'vuex'; |
| | | |
| | | const store = useStore(); |
| | | const machineNestListRef = ref(false); |
| | | |
| | | // 监听机巢详情变化 |
| | | watch( |
| | | () => store.state.home.machineNestDetail, |
| | | (newVal) => { |
| | | machineNestListRef.value = newVal; |
| | | }, |
| | | { immediate: true } // 添加立即执行选项 |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| New file |
| | |
| | | <!-- 机巢详情列表 --> |
| | | <template> |
| | | <common-title text="返回" :style="{ marginLeft: pxToRem(14) }" @details="detailsFun"></common-title> |
| | | <div class="machine-nest-list"> |
| | | <MachineNestTotal @searchNickName="handleSearch" /> |
| | | <div class="content-wrapper"> |
| | | <div class="table-list"> |
| | | <div class="table-item" v-for="item in tableList"> |
| | | <img src="" alt=""> |
| | | <div class="middle"> |
| | | <div class="title">{{ item.nickname }}</div> |
| | | <div class="number">飞行次数:{{ item.fly_count }}次 飞行里程:{{ item.flight_mileage }}km</div> |
| | | <div class="result">任务成果:{{ item.accumulate_data }}个 飞行时长:{{ item.hour }}h</div> |
| | | </div> |
| | | <div class="right" :class="item.status==='WORKING'?'atcive':''" @click="signMachineNestClick(item)"> |
| | | {{ item.status==='OFFLINE'?'离线中':(item.status==='WORKING'?'作业中':'空闲中') }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="pagination-container"> |
| | | <el-pagination |
| | | v-model:current-page="pageParams.current" |
| | | v-model:page-size="pageParams.size" |
| | | :total="pageParams.total" |
| | | :page-sizes="[5, 10, 20]" |
| | | layout="total, prev, pager, next" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | background |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import MachineNestTotal from './components/MachineNestTotal.vue'; |
| | | import { selectDevicePage } from '@/api/home/machineNest.js' |
| | | import { useStore } from 'vuex'; |
| | | |
| | | const store = useStore(); |
| | | |
| | | const searchText = ref(''); |
| | | // 分页参数 |
| | | const pageParams = ref({ |
| | | current: 1, |
| | | size: 8, |
| | | total: 0 |
| | | }); |
| | | |
| | | // 机巢列表 |
| | | const tableList = ref([]); |
| | | // 机巢列表数据 |
| | | const getTableList = () => { |
| | | const params = { |
| | | nickname: searchText.value, |
| | | current: pageParams.value.current, |
| | | size: pageParams.value.size |
| | | }; |
| | | selectDevicePage(params).then((res) => { |
| | | if (res.data.code !== 0) return; |
| | | tableList.value = res.data.data.records; |
| | | pageParams.value.total = res.data.data.total; |
| | | }); |
| | | }; |
| | | |
| | | // 搜索数据 |
| | | const handleSearch = (name) => { |
| | | console.log(name, '哒哒哒'); |
| | | searchText.value = name; |
| | | pageParams.value.current = 1; |
| | | tableList.value = []; |
| | | getTableList(); |
| | | } |
| | | |
| | | // 分页方法 |
| | | const handleSizeChange = (val) => { |
| | | pageParams.value.size = val; |
| | | pageParams.value.current = 1; |
| | | getTableList(); |
| | | }; |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | pageParams.value.current = val; |
| | | getTableList(); |
| | | }; |
| | | |
| | | // 单个机巢详情 |
| | | const signMachineNestClick = (item) => { |
| | | store.commit('setSingleUavHome', item); |
| | | } |
| | | |
| | | // 返回 |
| | | const detailsFun = () => { |
| | | store.commit('setMachineNestDetail', false); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .machine-nest-list { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | margin-left: 29px; |
| | | padding: 16px 16px; |
| | | width: 390px; |
| | | height: 838px; |
| | | background: linear-gradient( |
| | | 270deg, |
| | | rgba(31, 62, 122, 0) 0%, |
| | | rgba(31, 62, 122, 0.35) 21%, |
| | | #1f3e7a 100% |
| | | ); |
| | | border-radius: 0px 0px 0px 0px; |
| | | opacity: 0.85; |
| | | .content-wrapper { |
| | | position: relative; |
| | | height: calc(100% - 130px); |
| | | .table-list { |
| | | height: calc(100% - 50px); |
| | | overflow-y: auto; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #fff; |
| | | .table-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | justify-items: center; |
| | | align-items: center; |
| | | margin-top: 10px; |
| | | img { |
| | | width: 48px; |
| | | height: 48px; |
| | | } |
| | | .middle { |
| | | .number, |
| | | .result { |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | .right { |
| | | color: #6fc3ff; |
| | | cursor: pointer; |
| | | } |
| | | .atcive { |
| | | color: #04f020; |
| | | background: linear-gradient( 90deg, rgba(12,45,92,1) 0%, #154671 50%, rgba(12,45,92,1) 100%), linear-gradient( 90deg, rgba(12,45,92,1) 0%, rgba(12,45,92,1) 50%, rgba(12,45,92,1) 100%); |
| | | } |
| | | } |
| | | } |
| | | .pagination-container { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | :deep(.el-pagination) { |
| | | --el-pagination-bg-color: transparent; |
| | | --el-pagination-text-color: #fff; |
| | | --el-pagination-button-color: #fff; |
| | | --el-pagination-hover-color: #409eff; |
| | | |
| | | .el-pagination__total { |
| | | color: #fff; |
| | | } |
| | | |
| | | .btn-prev, |
| | | .btn-next, |
| | | .number { |
| | | background-color: transparent; |
| | | color: #fff; |
| | | |
| | | &:hover { |
| | | color: #409eff; |
| | | } |
| | | } |
| | | |
| | | .is-active { |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <common-title :style="{ marginLeft: pxToRem(14) }" @details="detailsFun"></common-title> |
| | | <div class="overview-next"> |
| | | <div class="next-num"> |
| | | <div class="total"> |
| | | <div class="value">{{ total }}</div> |
| | | <div class="name">机巢总数</div> |
| | | </div> |
| | | <div class="status"> |
| | | <div v-for="item in listNum"> |
| | | <div :style="{ color: item.color }" class="value">{{ item.value }}</div> |
| | | <div class="name">{{ item.name }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="search-box"> |
| | | <el-input v-model="searchText" placeholder="请输入机巢名称" class="input-with-select"> |
| | | <template #append> |
| | | <el-button :icon="Search" @click="searchNickName"/> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | <MachineNestTotal @searchNickName="handleSearch" /> |
| | | <div class="table-list"> |
| | | <div class="table-header"> |
| | | <div class="name">机巢名称</div> |
| | |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | | import { Search } from '@element-plus/icons-vue'; |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import { getDeviceInfoNum, selectDevicePage } from '@/api/home/machineNest.js' |
| | | import MachineNestTotal from './components/MachineNestTotal.vue'; |
| | | import { selectDevicePage } from '@/api/home/machineNest.js' |
| | | import { useStore } from 'vuex'; |
| | | |
| | | const store = useStore(); |
| | | |
| | | // 统计机巢总数 |
| | | let total = ref(0); |
| | | // 机巢统计 |
| | | let listNum = ref([ |
| | | { name: '空闲中', value: 89, color: '#FFA768' }, |
| | | { name: '作业中', value: 100, color: '#8EFFAC' }, |
| | | { name: '离线中', value: 66, color: '#FFFFFF' }, |
| | | // { name: '异常', value: 10, color: '#FF8E8E' }, |
| | | ]); |
| | | // 获取机巢列表 |
| | | const getList = () => { |
| | | getDeviceInfoNum().then((res) => { |
| | | if (res.data.code !== 0) return; |
| | | let result = res.data.data; |
| | | listNum.value[0].value = result.ex_num; |
| | | listNum.value[1].value = result.leisure_num; |
| | | listNum.value[2].value = result.offline_num; |
| | | total.value = result.device_num; |
| | | }); |
| | | } |
| | | |
| | | const isMore = ref(true); |
| | | // 控制加载状态 |
| | | const busy = ref(false); |
| | | // 机巢搜索名称 |
| | | let searchText = ref('') |
| | | const searchText = ref(''); |
| | | // 分页参数 |
| | | const pageParams = ref({ |
| | | current: 1, |
| | |
| | | const getTableList = () => { |
| | | const params = { |
| | | nickname: searchText.value, |
| | | is_execute: false, |
| | | type: 1, |
| | | is_execute: true, |
| | | current: pageParams.value.current, |
| | | size: pageParams.value.size |
| | | }; |
| | | selectDevicePage(params).then((res) => { |
| | | // if (res.data.code !== 0) return; |
| | | if (res.data.code !== 0) return; |
| | | if (res.data.data.records.length === 0) return (isMore.value = false); |
| | | pageParams.value.current += 1; |
| | | tableList.value = [...tableList.value, ...res.data.data.records]; |
| | |
| | | }; |
| | | |
| | | // 搜索数据 |
| | | const searchNickName = () => { |
| | | const handleSearch = (name) => { |
| | | searchText.value = name; |
| | | pageParams.value.current = 1; |
| | | tableList.value = []; |
| | | isMore.value = true |
| | |
| | | } |
| | | |
| | | const detailsFun = () => { |
| | | console.log('details'); |
| | | store.commit('setMachineNestDetail', true); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getTableList(); |
| | | }); |
| | | </script> |
| | |
| | | border-radius: 0px 0px 0px 0px; |
| | | opacity: 0.85; |
| | | margin-bottom: 10px; |
| | | .next-num { |
| | | width: 358px; |
| | | height: 92px; |
| | | background: url(@/assets/images/home/homeLeft/next-num.png) no-repeat center / 100% 100%; |
| | | position: relative; |
| | | .total { |
| | | position: absolute; |
| | | left: 22px; |
| | | top: 28px; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | line-height: 19px; |
| | | .value { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-size: 26px; |
| | | text-align: center; |
| | | } |
| | | } |
| | | .status { |
| | | position: absolute; |
| | | top: 16px; |
| | | right: 30px; |
| | | width: 200px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | line-height: 30px; |
| | | .name { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | } |
| | | .value { |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | } |
| | | } |
| | | } |
| | | .search-box { |
| | | margin-top: 19px; |
| | | margin-right: 16px; |
| | | :deep(.el-input__wrapper) { |
| | | background-color: rgba(0, 112, 255, 0.1); |
| | | background: rgba(0, 15, 34, 0.5); |
| | | box-shadow: 0 0 0 1px #0070ff inset; |
| | | } |
| | | |
| | | :deep(.el-input-group__append) { |
| | | background: rgba(0, 112, 255, 0.38); |
| | | .el-button { |
| | | background-color: transparent; |
| | | border: 1px solid #0070ff; |
| | | border-left: none; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | color: #fff; |
| | | &::placeholder { |
| | | color: rgba(255, 255, 255, 0.6); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .table-list { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | margin: 16px; |
| New file |
| | |
| | | <!-- 机巢头部统计 --> |
| | | <template> |
| | | <div class="machine-nest-total"> |
| | | <div class="next-num"> |
| | | <div class="total"> |
| | | <div class="value">{{ total }}</div> |
| | | <div class="name">机巢总数</div> |
| | | </div> |
| | | <div class="status"> |
| | | <div v-for="item in listNum"> |
| | | <div :style="{ color: item.color }" class="value">{{ item.value }}</div> |
| | | <div class="name">{{ item.name }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="search-box"> |
| | | <el-input v-model="searchNameText" placeholder="请输入机巢名称" class="input-with-select"> |
| | | <template #append> |
| | | <el-button :icon="Search" @click="searchNickName"/> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from '@element-plus/icons-vue'; |
| | | import { getDeviceInfoNum } from '@/api/home/machineNest.js' |
| | | |
| | | // 统计机巢总数 |
| | | let total = ref(0); |
| | | // 机巢统计 |
| | | let listNum = ref([ |
| | | { name: '空闲中', value: 89, color: '#FFA768' }, |
| | | { name: '作业中', value: 100, color: '#8EFFAC' }, |
| | | { name: '离线中', value: 66, color: '#FFFFFF' }, |
| | | // { name: '异常', value: 10, color: '#FF8E8E' }, |
| | | ]); |
| | | // 获取机巢列表 |
| | | const getList = () => { |
| | | getDeviceInfoNum().then((res) => { |
| | | if (res.data.code !== 0) return; |
| | | let result = res.data.data; |
| | | listNum.value[0].value = result.ex_num; |
| | | listNum.value[1].value = result.leisure_num; |
| | | listNum.value[2].value = result.offline_num; |
| | | total.value = result.device_num; |
| | | }); |
| | | } |
| | | |
| | | // 机巢搜索名称 |
| | | let searchNameText = ref(''); |
| | | |
| | | const emit = defineEmits(['searchNickName']); |
| | | // 搜索事件 |
| | | const searchNickName = () => { |
| | | emit('searchNickName', searchNameText.value); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .machine-nest-total { |
| | | .next-num { |
| | | width: 358px; |
| | | height: 92px; |
| | | background: url(@/assets/images/home/homeLeft/next-num.png) no-repeat center / 100% 100%; |
| | | position: relative; |
| | | .total { |
| | | position: absolute; |
| | | left: 22px; |
| | | top: 28px; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | line-height: 19px; |
| | | .value { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-size: 26px; |
| | | text-align: center; |
| | | } |
| | | } |
| | | .status { |
| | | position: absolute; |
| | | top: 16px; |
| | | right: 30px; |
| | | width: 200px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | line-height: 30px; |
| | | .name { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | } |
| | | .value { |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | } |
| | | } |
| | | } |
| | | .search-box { |
| | | margin-top: 19px; |
| | | margin-right: 16px; |
| | | :deep(.el-input__wrapper) { |
| | | background-color: rgba(0, 112, 255, 0.1); |
| | | background: rgba(0, 15, 34, 0.5); |
| | | box-shadow: 0 0 0 1px #0070ff inset; |
| | | } |
| | | |
| | | :deep(.el-input-group__append) { |
| | | background: rgba(0, 112, 255, 0.38); |
| | | .el-button { |
| | | background-color: transparent; |
| | | border: 1px solid #0070ff; |
| | | border-left: none; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | color: #fff; |
| | | &::placeholder { |
| | | color: rgba(255, 255, 255, 0.6); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button @click="addTask">新增任务</el-button> |
| | | <el-button type="text" @click="toggleExpand"> |
| | | {{ isExpand ? '收起' : '展开' }} |
| | | <el-icon class="el-icon--right"> |
| | |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 新增任务 |
| | | const addTask = () => { |
| | | // 跳转新增任务页面 |
| | | window.open('/#/task/add'); |
| | | }; |
| | | |
| | | let taskAlgorithm = ref([]); |
| | | let taskBusiness = ref([]); |
| | | |
| | |
| | | // 机巢 |
| | | let machineData = ref([]); |
| | | |
| | | // 处理部门数据为树形结构 |
| | | const handleDeptData = (data) => { |
| | | deptTreeData.value = []; // 初始化数组 |
| | | data.forEach(item => { |
| | | let treeNode = { |
| | | id: item.area_code, |
| | | name: item.area_name, |
| | | children: [] |
| | | }; |
| | | // 处理设备子节点 |
| | | if (item.devices && item.devices.length > 0) { |
| | | item.devices.forEach(device => { |
| | | treeNode.children.push({ |
| | | id: device.device_sn, |
| | | name: device.nickname |
| | | }); |
| | | }); |
| | | } |
| | | deptTreeData.value.push(treeNode); |
| | | }); |
| | | }; |
| | | // 部门下得机巢 |
| | | const requestDockInfo = () => { |
| | | getDockInfo().then((res) => { |
| | |
| | | width: calc(100% - 400px - 400px - 100px); |
| | | height: 60px; |
| | | background: rgba(31, 62, 122, 0.95); |
| | | padding: 10px 20px; |
| | | // padding: 10px 20px; |
| | | transition: all 0.3s; |
| | | &.is-expand { |
| | | height: auto; |
| | |
| | | <el-table-column prop="ai_type_str" label="关联算法" /> |
| | | <el-table-column prop="status" label="任务状态" > |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | {{ scope.row.status ? getStatusText(scope.row.status) : '' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="industry_type_str" label="任务类型" /> |
| | |
| | | }; |
| | | // 状态文字 |
| | | const getStatusText = (status) => { |
| | | console.log('哒哒哒',status) |
| | | const statusMap = { |
| | | 1: '待执行', |
| | | 2: '执行中', |