Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard
8 files modified
6 files renamed
17 files added
2 files deleted
| | |
| | | #开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖) |
| | | # VITE_APP_API_URL = https://wrj.shuixiongit.com/api |
| | | # VITE_APP_API_URL = http://192.168.1.7 |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| | | |
| | |
| | | |
| | | # 是否在打包时开启压缩,支持 gzip 和 brotli |
| | | VITE_BUILD_COMPRESS = gzip |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| | |
| | | |
| | | #测试环境配置 |
| | | VITE_APP_ENV = 'test' |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 字典查询 行业 算法 工单类型 |
| | | export const getDictionary = params => { |
| | | return request({ |
| | | url: `/blade-system/dict-biz/listByCodes?code=${params}`, |
| | | method: 'get', |
| | | }) |
| | | } |
| | | |
| | | // 区域 |
| | | export const deptsByAreaCode = params => { |
| | | return request({ |
| | | url: `/blade-system/dept/deptsByAreaCode`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 获取机场信息 |
| | | export const getDockInfo = params => { |
| | | return request({ |
| | | url: `/drone-device-core/dp/home/getDockInfo`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | |
| | | params: {}, |
| | | }) |
| | | } |
| | | |
| | | // 设备-任务列表 |
| | | export const getDeviceJobList = (data,params) => { |
| | | return request({ |
| | | url: `/drone-device-core/wayline/waylineJobInfo/jobList`, |
| | | method: 'post', |
| | | data, |
| | | params |
| | | }) |
| | | } |
| | | |
| | | // 设备-事件列表 |
| | | export const getDeviceEventList = (data,params) => { |
| | | return request({ |
| | | url: `/drone-device-core/jobEvent/eventPage`, |
| | | method: 'post', |
| | | data, |
| | | params |
| | | }) |
| | | } |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 任务总数统计 |
| | | export const totalJobNum = params => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/totalJobNum', |
| | | method: 'get', |
| | | params: params, |
| | | }) |
| | | } |
| | | // 其他任务统计 |
| | | export const jobStatistics = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobStatistics', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | // 行业任务统计 |
| | | export const industryJobNumPieChart = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/industryJobNumPieChart', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | // 时间任务统计 |
| | | export const jobNumBar = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobNumBar', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | // 事件任务统计 |
| | | export const jobEventBar = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | // 任务列表 |
| | | export const jobList = data => { |
| | | return request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobList?current=' + data.current + '&size=' + data.size, |
| | | method: 'post', |
| | | data: {}, |
| | | }) |
| | | } |
| | | |
| | | |
| | |
| | | ]); |
| | | |
| | | const handleClick = ({ path, name }) => { |
| | | if (!['首页', '任务管理'].includes(name)) return ElMessage.warning('正在开发中'); |
| | | if (!['首页', '任务管理'].includes(name)) return ElMessage.warning('正在加急开发中...'); |
| | | // 更新 leftList 的 active 状态 |
| | | leftList.value.forEach(item => { |
| | | item.active = item.path === path; |
| | |
| | | setToken(token) |
| | | state.token = token |
| | | setStore({ name: 'token', content: state.token }) |
| | | console.log('顶顶顶111', token) |
| | | window.localStorage.setItem(ELocalStorageKey.Token, token) |
| | | }, |
| | | SET_REFRESH_TOKEN: (state, refreshToken) => { |
| File was renamed from src/views/SignMachineNest/components/MachineLeft/InspectionRaskDetails.vue |
| | |
| | | import { pxToRem } from '@/utils/rem'; |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import CommonDateTime from '@/components/CommonDateTime.vue'; |
| | | import { jobNumBar, eventNumPie } from '@/api/home/index.js' |
| | | import { jobNumBar, eventNumPie } from '@/api/home' |
| | | |
| | | // 日期 |
| | | const currenDate = dayjs().format('YYYY-MM-DD'); |
| | |
| | | margin-top: 10px; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="machine-left"> |
| | | <!--时间 天气--> |
| | | <common-weather></common-weather> |
| | | <!-- 机巢数据 --> |
| | | <MachineData></MachineData> |
| | | <div class="do-return" @click="goBack"> |
| | | <img src="../../../assets/images/signMachineNest/return.png" alt="" /> |
| | | </div> |
| | | <!--巡检任务详情--> |
| | | <InspectionRaskDetails></InspectionRaskDetails> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import CommonWeather from '@/components/CommonWeather.vue'; |
| | | import MachineData from './MachineData.vue'; |
| | | import InspectionRaskDetails from './InspectionRaskDetails.vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import { useStore } from 'vuex'; |
| | | |
| | | const router = useRouter(); |
| | | const store = useStore() |
| | | |
| | | const goBack = () => { |
| | | store.commit('setSingleUavHome', {}); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .machine-left { |
| | | position: absolute; |
| | | top: 88px; |
| | | color: #e7f5ff; |
| | | .do-return { |
| | | position: absolute; |
| | | top: 50px; |
| | | right: -50px; |
| | | cursor: pointer; |
| | | img { |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| File was renamed from src/views/SignMachineNest/components/MachineRight/InspectionRaskList.vue |
| | |
| | | </span> |
| | | </div> |
| | | <div class="left-b"> |
| | | <img src="@/assets/images/signMachineNest/machineRight/date.png" alt="" />{{ item.begin_time }} |
| | | <img src="@/assets/images/signMachineNest/machineRight/name.png" alt="" />{{ item.creator_name || '' }} |
| | | <img src="../../../assets/images/signMachineNest/machineRight/date.png" alt="" />{{ item.begin_time }} |
| | | <img src="../../../assets/images/signMachineNest/machineRight/name.png" alt="" />{{ item.creator_name || '' }} |
| | | </div> |
| | | </div> |
| | | <div class="right"> |
| | | <img src="@/assets/images/signMachineNest/machineRight/return.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/return.png" alt=""> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <script setup> |
| | | import { Search } from '@element-plus/icons-vue'; |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import { getBeforeJob, getTodayJob } from '@/api/home/index.js' |
| | | import { getBeforeJob, getTodayJob } from '@/api/home' |
| | | |
| | | const isMore = ref(true); |
| | | // 控制加载状态 |
| | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| File was renamed from src/views/SignMachineNest/components/MachineRight/MachineStatus.vue |
| | |
| | | <div :style="{ marginLeft: pxToRem(14) }"> |
| | | <div class="machine-status"> |
| | | <div class="info"> |
| | | <img src="@/assets/images/signMachineNest/machineRight/wrj.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/wrj.png" alt=""> |
| | | <div class="info-right"> |
| | | <div class="name">{{ osdVisible?.callsign || '--' }}</div> |
| | | <div class="wz"> |
| | |
| | | <div class="status"> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/height.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/height.png" alt=""> |
| | | <span class="text">实时真高</span> |
| | | </div> |
| | | <div class="text-data">{{ detailInfo.height || '--' }}<span class="text">米</span></div> |
| | | </div> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/speed.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/speed.png" alt=""> |
| | | <span class="text">飞行速度</span> |
| | | </div> |
| | | <div class="text-data">{{ detailInfo.horizontal_speed }}<span class="text">米/秒</span></div> |
| | | </div> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/signal.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/signal.png" alt=""> |
| | | <span class="text">信号强度</span> |
| | | </div> |
| | | <div class="text-data">{{ detailInfo.quality }}</div> |
| | | </div> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/electricity.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/electricity.png" alt=""> |
| | | <span class="text">电池电量</span> |
| | | </div> |
| | | <div v-if="drone_charge_state.capacity_percent != 0" class="text-data"> |
| | |
| | | </div> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/distance.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/distance.png" alt=""> |
| | | <span class="text">飞行距离</span> |
| | | </div> |
| | | <div class="text-data">{{ singleTotal.flight_mileage }}<span class="text">km</span></div> |
| | | </div> |
| | | <div class="card"> |
| | | <div> |
| | | <img src="@/assets/images/signMachineNest/machineRight/duration.png" alt=""> |
| | | <img src="../../../assets/images/signMachineNest/machineRight/duration.png" alt=""> |
| | | <span class="text">飞行时长</span> |
| | | </div> |
| | | <div class="text-data">{{ singleTotal.hour_count }}<span class="text">h</span></div> |
| | |
| | | import { EModeCode, EDockModeText, EModeText } from '@/utils/staticData/device'; |
| | | import { getLnglatAltitude } from '@/utils/cesium/mapUtil.js'; |
| | | import { useStore } from 'vuex'; |
| | | import MachineTableDetails from '@/views/SignMachineNest/components/MachineRight/components/MachineTableDetails.vue'; |
| | | import MachineTableDetails from '@/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue'; |
| | | |
| | | const store = useStore(); |
| | | // 获取机巢信息 |
| New file |
| | |
| | | <template> |
| | | <el-divider content-position="left">相关事件 {{total}}次</el-divider> |
| | | <el-table :data="list" style="width: 100%"> |
| | | <el-table-column prop="id" label="id" /> |
| | | <el-table-column prop="event_name" label="名称" /> |
| | | <el-table-column prop="media_type" label="类型" /> |
| | | <el-table-column prop="ai_types" label="关联算法" /> |
| | | <el-table-column prop="photo_url" label="图片url" /> |
| | | <el-table-column prop="video_url" label="视频url" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.status === 0" type="info">待处理</el-tag> |
| | | <el-tag v-if="scope.row.status === 1" type="success">待分拨</el-tag> |
| | | <el-tag v-if="scope.row.status === 2" type="warning">待处理</el-tag> |
| | | <el-tag v-if="scope.row.status === 3" type="success">处理中</el-tag> |
| | | <el-tag v-if="scope.row.status === 4" type="success">已完成</el-tag> |
| | | <el-tag v-if="scope.row.status === 5" type="success">已完结</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="event_dict_key" label="event_dict_key" /> |
| | | <el-table-column prop="create_time" label="创建时间" /> |
| | | |
| | | <el-table-column label="操作" > |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="examine(scope.row)">审核</el-button> |
| | | <el-button type="primary" link @click="distribution(scope.row)">分拨</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | background |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | v-model:current-page="sizeParams.current" |
| | | v-model:page-size="sizeParams.size" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | @change="pageChange" |
| | | /> |
| | | </template> |
| | | <script setup> |
| | | import { useStore } from 'vuex' |
| | | import { getDeviceEventList } from '@/api/home/machineNest' |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | |
| | | const list = ref([]) |
| | | const params = ref({ |
| | | device_sn: null, |
| | | }) |
| | | const sizeParams = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | }) |
| | | const store = useStore() |
| | | const device_sn = computed(() => store.state.home.singleUavHome.device_sn) |
| | | const total = ref(0) |
| | | |
| | | const distribution = row => { |
| | | ElMessage.warning('正在加急开发中...') |
| | | } |
| | | const examine = row => { |
| | | ElMessage.warning('正在加急开发中...') |
| | | } |
| | | |
| | | const getList = () => { |
| | | params.value.device_sn = device_sn.value |
| | | getDeviceEventList(params.value, sizeParams.value).then(res => { |
| | | const resData = res?.data?.data || {} |
| | | list.value = resData.records |
| | | total.value = resData.total |
| | | }) |
| | | } |
| | | const pageChange = val => { |
| | | sizeParams.value.current = val |
| | | getList() |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <template> |
| | | <el-divider content-position="left">相关任务 {{ total }}次</el-divider> |
| | | <el-table :data="list" style="width: 100%"> |
| | | <el-table-column prop="id" label="id" /> |
| | | <el-table-column prop="name" label="名称" /> |
| | | <el-table-column prop="industry_type_str" label="任务类型" /> |
| | | <el-table-column prop="ai_type_str" label="关联算法" /> |
| | | <el-table-column prop="event_number" label="事件工单" /> |
| | | <el-table-column prop="remark" label="备注" /> |
| | | <el-table-column prop="area_code" label="地区代码" /> |
| | | <el-table-column prop="begin_time" label="开始时间" /> |
| | | <el-table-column prop="end_time" label="结束时间" /> |
| | | <el-table-column prop="creator_name" label="创建者" /> |
| | | <el-table-column label="操作"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="viewJob(scope.row)">查看</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | background |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | v-model:current-page="sizeParams.current" |
| | | v-model:page-size="sizeParams.size" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | @change="pageChange" |
| | | /> |
| | | |
| | | <DeviceJobDetails v-model:show="deviceJobDetailsShow"/> |
| | | |
| | | </template> |
| | | <script setup> |
| | | import { useStore } from 'vuex' |
| | | import { getDeviceJobList } from '@/api/home/machineNest' |
| | | import DeviceJobDetails from './DeviceJobDetails/DeviceJobDetails.vue'; |
| | | |
| | | const list = ref([]) |
| | | const params = ref({ |
| | | device_sn: null, |
| | | }) |
| | | const sizeParams = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | }) |
| | | const store = useStore() |
| | | const device_sn = computed(() => store.state.home.singleUavHome.device_sn) |
| | | const total = ref(0) |
| | | const deviceJobDetailsShow = ref(false) |
| | | const jobId = ref(null) |
| | | provide('jobId', jobId) |
| | | const viewJob = (row) => { |
| | | jobId.value = row.id |
| | | deviceJobDetailsShow.value = true |
| | | } |
| | | |
| | | const getList = () => { |
| | | params.value.device_sn = device_sn.value |
| | | getDeviceJobList(params.value, sizeParams.value).then(res => { |
| | | const resData = res?.data?.data || {} |
| | | list.value = resData.records |
| | | total.value = resData.total |
| | | }) |
| | | } |
| | | |
| | | const pageChange = val => { |
| | | sizeParams.value.current = val |
| | | getList() |
| | | } |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <!-- 任务详情 --> |
| | | <template> |
| | | <el-dialog |
| | | append-to-body |
| | | modal-class="detailsOfHistoricalTasks" |
| | | v-model="isShow" |
| | | title="历史任务详情" |
| | | :width="pxToRem(1500)" |
| | | :close-on-click-modal="false" |
| | | :destroy-on-close="true" |
| | | > |
| | | <div class="content"> |
| | | <div class="contentLeft"> |
| | | <el-divider content-position="left">详情</el-divider> |
| | | <div class="infoBox"> |
| | | <div class="itemBox" v-for="item in infoList"> |
| | | <div class="itemTitle">{{ item.name }}:</div> |
| | | <div class="itemValue">{{ item.value }}</div> |
| | | </div> |
| | | </div> |
| | | <JobRelatedEvents v-if="isShow" /> |
| | | <el-divider content-position="left">任务成果 xxx个</el-divider> |
| | | <div class="imgListBox"> |
| | | <div v-for="item in imgList" class="imgItem">xxx图片</div> |
| | | </div> |
| | | </div> |
| | | <div class="contentRight">map</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { pxToRem } from '@/utils/rem' |
| | | import JobRelatedEvents from './JobRelatedEvents.vue' |
| | | |
| | | const isShow = defineModel('show') |
| | | |
| | | |
| | | const imgList = ref([ |
| | | { name: '图片1', url: 'xxx' }, |
| | | { name: '图片1', url: 'xxx' }, |
| | | { name: '图片1', url: 'xxx' }, |
| | | { name: '图片1', url: 'xxx' }, |
| | | ]) |
| | | |
| | | const infoList = ref([ |
| | | { name: '任务编号', value: 'xxx' }, |
| | | { name: '任务所属机巢', value: 'xxx' }, |
| | | { name: '关联算法', value: 'xxx' }, |
| | | { name: '任务名称', value: 'xxx' }, |
| | | { name: '所属单位', value: 'xxx' }, |
| | | { name: '任务类型', value: 'xxx' }, |
| | | { name: '任务周期', value: 'xxx' }, |
| | | { name: '飞行事件', value: 'xxx' }, |
| | | { name: '任务频次', value: 'xxx' }, |
| | | { name: '任务描述', value: 'xxx' }, |
| | | ]) |
| | | |
| | | onMounted(() => {}) |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .detailsOfHistoricalTasks { |
| | | .el-dialog { |
| | | --el-dialog-margin-top: 5vh; |
| | | } |
| | | |
| | | .el-pagination { |
| | | justify-content: center; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .el-dialog__body { |
| | | height: 80vh; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss" scoped> |
| | | .content { |
| | | display: flex; |
| | | height: 100%; |
| | | |
| | | .contentLeft { |
| | | width: 900px; |
| | | overflow: auto; |
| | | |
| | | .infoBox { |
| | | display: grid; |
| | | grid-template-columns: repeat(3, 1fr); |
| | | gap: 10px; // 列之间的间距 |
| | | padding: 10px; |
| | | |
| | | .itemBox { |
| | | background-color: #fff; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | padding: 15px; |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .itemTitle { |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .itemValue { |
| | | color: #666; |
| | | } |
| | | } |
| | | |
| | | .imgListBox { |
| | | display: flex; |
| | | |
| | | .imgItem { |
| | | width: 200px; |
| | | height: 200px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .contentRight { |
| | | width: 0; |
| | | flex-grow: 1; |
| | | background: #19ad8d; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <el-divider content-position="left">关联事件 {{total}}个</el-divider> |
| | | <el-table :data="list" style="width: 100%" > |
| | | <el-table-column prop="event_num" label="编号" /> |
| | | <el-table-column prop="event_name" label="名称" /> |
| | | <el-table-column prop="media_type" label="类型" /> |
| | | <el-table-column prop="photo_url" label="图片url" /> |
| | | <el-table-column prop="video_url" label="视频url" /> |
| | | <el-table-column prop="remark" label="备注" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.status === 0" type="info">待处理</el-tag> |
| | | <el-tag v-if="scope.row.status === 1" type="success">待分拨</el-tag> |
| | | <el-tag v-if="scope.row.status === 2" type="warning">待处理</el-tag> |
| | | <el-tag v-if="scope.row.status === 3" type="success">处理中</el-tag> |
| | | <el-tag v-if="scope.row.status === 4" type="success">已完成</el-tag> |
| | | <el-tag v-if="scope.row.status === 5" type="success">已完结</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="wayline_job_id" label=" 任务id" /> |
| | | <el-table-column label="操作" > |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="examine(scope.row)">审核</el-button> |
| | | <el-button type="primary" link @click="distribution(scope.row)">分拨</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | background |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | v-model:current-page="sizeParams.current" |
| | | v-model:page-size="sizeParams.size" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | @change="pageChange" |
| | | /> |
| | | </template> |
| | | <script setup> |
| | | import { useStore } from 'vuex' |
| | | import { getDeviceEventList } from '@/api/home/machineNest' |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const jobId = inject("jobId"); |
| | | |
| | | const list = ref([ |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | {event_num:''}, |
| | | ]) |
| | | const params = ref({ |
| | | device_sn: null, |
| | | }) |
| | | const sizeParams = ref({ |
| | | current: 1, |
| | | size: 1, |
| | | }) |
| | | const store = useStore() |
| | | const child_sn = computed(() => store.state.home.singleUavHome.child_sn) |
| | | const total = ref(10) |
| | | |
| | | const distribution = row => { |
| | | ElMessage.warning('正在加急开发中...') |
| | | } |
| | | const examine = row => { |
| | | ElMessage.warning('正在加急开发中...') |
| | | } |
| | | |
| | | const getList = () => { |
| | | params.value.device_sn = child_sn.value |
| | | getDeviceEventList(params.value, sizeParams.value).then(res => { |
| | | const resData = res?.data?.data || {} |
| | | list.value = resData.records |
| | | total.value = resData.total |
| | | }) |
| | | } |
| | | const pageChange = val => { |
| | | sizeParams.value.current = val |
| | | getList() |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // getList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <!-- 机巢列表详情 --> |
| | | <template> |
| | | <el-dialog |
| | | modal-class="machineTableDetails" |
| | | v-model="isShowDetails" |
| | | title="机巢详情" |
| | | :width="pxToRem(1500)" |
| | | :close-on-click-modal="false" |
| | | :destroy-on-close="true" |
| | | > |
| | | <el-divider content-position="left">详情</el-divider> |
| | | <div class="infoBox"> |
| | | <div class="itemBox" v-for="item in infoList"> |
| | | <div class="itemTitle">{{ item.name }}:</div> |
| | | <div class="itemValue">{{ item.value }}</div> |
| | | </div> |
| | | </div> |
| | | <DeviceJob v-if="isShowDetails" /> |
| | | <DeviceEvent v-if="isShowDetails" /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import DeviceEvent from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceEvent.vue' |
| | | import DeviceJob from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJob.vue' |
| | | import { pxToRem } from '@/utils/rem'; |
| | | |
| | | const isShowDetails = defineModel('show') |
| | | |
| | | const infoList = ref([ |
| | | { name: '机巢名称', value: 'xxx' }, |
| | | { name: '机巢所属地区', value: 'xxx' }, |
| | | { name: '机巢状态', value: 'xxx' }, |
| | | { name: '任务成功', value: 'xxx' }, |
| | | { name: '机巢位置', value: 'xxx' }, |
| | | ]) |
| | | |
| | | onMounted(() => {}) |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .machineTableDetails { |
| | | .el-pagination { |
| | | text-align: left; |
| | | padding: 20px; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss" scoped> |
| | | .infoBox { |
| | | display: grid; |
| | | grid-template-columns: repeat(3, 1fr); |
| | | gap: 10px; // 列之间的间距 |
| | | padding: 10px; |
| | | |
| | | .itemBox { |
| | | background-color: #fff; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | padding: 15px; |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .itemTitle { |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .itemValue { |
| | | margin-top: 5px; |
| | | color: #666; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import MachineLeft from './components/MachineLeft/MachineLeft.vue' |
| | | import MachineRight from './components/MachineRight/MachineRight.vue'; |
| | | import MachineLeft from '@/views/SignMachineNest/MachineLeft/MachineLeft.vue' |
| | | import MachineRight from '@/views/SignMachineNest/MachineRight/MachineRight.vue'; |
| | | import { useConnectWebSocket } from '../../utils/websocket/connect-websocket'; |
| | | import { getWebsocketUrl } from '@/websocket/util/config'; |
| | | import { EBizCode } from '@/utils/staticData/enums.js'; |
| | |
| | | |
| | | const messageHandler = (result) => { |
| | | let payload = JSON.parse(result) // 为了兼容聊天消息 |
| | | // console.log('payload', payload) |
| | | if (!payload) return |
| | | switch (payload.biz_code) { |
| | | case EBizCode.GatewayOsd: { |
| | |
| | | getFlightStatistics(singleUavHome.value.device_sn).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | const result = res.data.data; |
| | | console.log(result); |
| | | console.log(result); |
| | | store.commit('setSingleTotal', result); |
| | | }) |
| | | }; |
| | |
| | | onUnmounted(() => { |
| | | connectWs?.value?.close(); |
| | | }); |
| | | </script> |
| | | </script> |
| | |
| | | <script setup> |
| | | |
| | | import TaskLeft from "./components/TaskLeft/TaskLeft.vue"; |
| | | import TaskRight from "./components/TaskRight/TaskRight.vue"; |
| | | import TaskIntermediateContent from "./components/TaskIntermediateContent/TaskIntermediateContent.vue"; |
| | | </script> |
| | | |
| | | <template> |
| | | TaskManage |
| | | <TaskLeft/> |
| | | <TaskIntermediateContent /> |
| | | <TaskRight/> |
| | | </template> |
| | | |
| | | |
| | | <style scoped lang="scss"> |
| | | |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="search-box"> |
| | | <el-form :model="searchForm" inline> |
| | | <el-form-item label="任务名称"> |
| | | <el-input v-model="searchForm.name" placeholder="请输入任务名称" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="所属部门"> |
| | | <el-select |
| | | v-model="searchForm.deptId" |
| | | placeholder="请选择部门" |
| | | clearable |
| | | > |
| | | <el-tree-select |
| | | v-model="searchForm.deptId" |
| | | :data="deptTreeData" |
| | | node-key="id" |
| | | :props="{ |
| | | label: 'name', |
| | | children: 'children' |
| | | }" |
| | | check-strictly |
| | | clearable |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="周期"> |
| | | <el-select v-model="searchForm.status" placeholder="请选择状态" clearable> |
| | | <el-option label="日" value="日" /> |
| | | <el-option label="周" value="周" /> |
| | | <el-option label="月" value="月" /> |
| | | <el-option label="年" value="年" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务状态"> |
| | | <el-select v-model="searchForm.status" placeholder="请选择状态" clearable> |
| | | <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务时间"> |
| | | <el-date-picker |
| | | v-model="searchForm.dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="任务算法"> |
| | | <el-select v-model="searchForm.status" placeholder="请选择状态" clearable> |
| | | <el-option label="识别火情" value="日" /> |
| | | <el-option label="识别车辆" value="周" /> |
| | | <el-option label="识别船只" value="月" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | | import { getDictionary, deptsByAreaCode, getDockInfo } from '@/api/home/common'; |
| | | |
| | | |
| | | const searchForm = reactive({ |
| | | name: '', |
| | | job_info_num: '', |
| | | status: '', |
| | | dateRange: [] |
| | | }); |
| | | const statusOptions = [ |
| | | { label: '待执行', value: 1 }, |
| | | { label: '执行中', value: 2 }, |
| | | { label: '已完成', value: 3 }, |
| | | { label: '已取消', value: 4 }, |
| | | { label: '执行失败', value: 5 } |
| | | ]; |
| | | |
| | | // 部门以及机巢 |
| | | const deptTreeData = ref([]); |
| | | |
| | | const emit = defineEmits(['search']); |
| | | |
| | | const handleSearch = () => { |
| | | emit('search', { |
| | | ...searchForm, |
| | | begin_time: searchForm.dateRange[0], |
| | | end_time: searchForm.dateRange[1] |
| | | }); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | searchForm.name = ''; |
| | | searchForm.job_info_num = ''; |
| | | searchForm.status = ''; |
| | | searchForm.dateRange = []; |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 请求字典字段 |
| | | const requestDictionary = () => { |
| | | getDictionary('SF,HYLB').then((res) => { |
| | | if (res.data.code !== 0) { |
| | | // 处理数据 |
| | | console.log('111111',res.data) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 处理部门数据为树形结构 |
| | | const handleDeptData = (data) => { |
| | | const buildTree = (items, parentId = 0) => { |
| | | const result = []; |
| | | for (const item of items) { |
| | | if (item.parent_id === parentId) { |
| | | const children = buildTree(items, item.id); |
| | | if (children.length) { |
| | | item.children = children; |
| | | } |
| | | result.push(item); |
| | | } |
| | | } |
| | | return result; |
| | | }; |
| | | return buildTree(data); |
| | | }; |
| | | // 部门信息 |
| | | const getDeptsByAreaCode = () => { |
| | | deptsByAreaCode().then((res) => { |
| | | if (res.data.code !== 0) { |
| | | deptTreeData.value = res.data; |
| | | // 处理数据 |
| | | console.log('22222',res.data) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 机巢信息 |
| | | const requestDockInfo = () => { |
| | | getDockInfo().then((res) => { |
| | | if (res.data.code !== 0) { |
| | | // 处理数据 |
| | | console.log('33333',res.data) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | |
| | | onMounted(() => { |
| | | requestDictionary(); |
| | | deptsByAreaCode(); |
| | | requestDockInfo(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .search-box { |
| | | position: absolute; |
| | | top: 120px; |
| | | left: 450px; |
| | | width: calc(100% - 400px - 400px - 100px); |
| | | height:60px; |
| | | color: #fff; |
| | | background: rgba(31, 62, 122, 0.35); |
| | | padding: 10px 20px; |
| | | |
| | | :deep(.el-form) { |
| | | --el-text-color-regular: #fff; |
| | | |
| | | .el-form-item { |
| | | margin-bottom: 0; |
| | | margin-right: 20px; |
| | | |
| | | .el-form-item__label { |
| | | color: #fff; |
| | | } |
| | | |
| | | .el-input, |
| | | .el-select, |
| | | .el-date-editor { |
| | | width: 200px; |
| | | --el-input-bg-color: transparent; |
| | | --el-input-border-color: rgba(255, 255, 255, 0.3); |
| | | --el-input-text-color: #fff; |
| | | --el-input-placeholder-color: rgba(255, 255, 255, 0.5); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 任务统计表格 --> |
| | | <template> |
| | | <SearchBox></SearchBox> |
| | | <div class="task-intermediate-content"> |
| | | <el-table :data="jobListData" style="width: 100%" height="calc(100vh - 180px)"> |
| | | <el-table-column label="序号" width="60"> |
| | | <template #default="scope"> |
| | | {{ (jobListParams.page - 1) * jobListParams.limit + scope.$index + 1 }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="job_info_num" label="任务编号" /> |
| | | <el-table-column prop="name" label="任务名称" /> |
| | | <el-table-column prop="dept_name" label="所属部门" /> |
| | | <el-table-column prop="device_names" label="所属机巢" /> |
| | | <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> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="industry_type_str" label="任务类型" /> |
| | | <el-table-column prop="event_number" label="关联事件" /> |
| | | <el-table-column prop="begin_time" label="任务时间" /> |
| | | <el-table-column prop="creator_name" label="创建人" /> |
| | | <el-table-column label="操作" > |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="handleDetail(scope.row)">查看</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="pagination"> |
| | | <el-pagination |
| | | v-model:current-page="jobListParams.page" |
| | | v-model:page-size="jobListParams.limit" |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import SearchBox from '../SearchBox.vue'; |
| | | import { jobList } from '@/api/home/task'; |
| | | |
| | | const jobListParams = reactive({ |
| | | page: 1, |
| | | limit: 10, |
| | | }); |
| | | const jobListData = ref([]); |
| | | const total = ref(0); |
| | | |
| | | // 获取任务列表 |
| | | const getJobList = () => { |
| | | jobList({current:1,size:10}).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | jobListData.value = res.data.data.records; |
| | | total.value = res.data.data.total; |
| | | }); |
| | | }; |
| | | // 状态文字 |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | 1: '待执行', |
| | | 2: '执行中', |
| | | 3: '已完成', |
| | | 4: '已取消', |
| | | 5: '执行失败' |
| | | }; |
| | | return statusMap[status] || '未知'; |
| | | }; |
| | | |
| | | // 状态标签类型 |
| | | const getStatusType = (status) => { |
| | | const typeMap = { |
| | | 1: 'info', |
| | | 2: 'warning', |
| | | 3: 'success', |
| | | 4: '', |
| | | 5: 'danger' |
| | | }; |
| | | return typeMap[status] || ''; |
| | | }; |
| | | |
| | | // 查看详情 |
| | | const handleDetail = (row) => { |
| | | console.log('查看详情', row); |
| | | }; |
| | | |
| | | // 分页大小改变 |
| | | const handleSizeChange = (val) => { |
| | | jobListParams.limit = val; |
| | | getJobList(); |
| | | }; |
| | | |
| | | // 页码改变 |
| | | const handleCurrentChange = (val) => { |
| | | jobListParams.page = val; |
| | | getJobList(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getJobList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-intermediate-content { |
| | | position: absolute; |
| | | top: 190px; |
| | | width: calc(100% - 400px - 400px - 100px); |
| | | left: 450px; |
| | | height: 770px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | |
| | | :deep(.el-table) { |
| | | background-color: transparent; |
| | | --el-table-tr-bg-color: transparent; |
| | | --el-table-border-color: rgba(255, 255, 255, 0.1); |
| | | --el-table-header-bg-color: rgba(31, 62, 122, 0.5); |
| | | --el-table-header-text-color: #fff; |
| | | --el-table-text-color: #fff; |
| | | .el-table__body tr:hover > td { |
| | | background-color: rgba(31, 62, 122, 0.3) !important; |
| | | } |
| | | } |
| | | |
| | | .pagination { |
| | | padding: 20px 0; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | |
| | | :deep(.el-pagination) { |
| | | --el-pagination-bg-color: transparent; |
| | | --el-pagination-text-color: #fff; |
| | | --el-pagination-button-color: #fff; |
| | | --el-pagination-hover-color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 业务统计 --> |
| | | <template> |
| | | <common-title title="行业统计" :style="{ marginLeft: pxToRem(14) }"></common-title> |
| | | <div class="task-industry"> |
| | | <div class="chart" ref="chartRef"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import * as echarts from 'echarts'; |
| | | import { industryJobNumPieChart } from '@/api/home/task'; |
| | | const chartRef = ref(null); |
| | | let chart = null; |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: '{b}: {c} ({d}%)' |
| | | }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | | left: 'center', |
| | | bottom: '5%', |
| | | textStyle: { |
| | | color: '#fff', |
| | | fontSize: 12 |
| | | }, |
| | | itemWidth: 10, |
| | | itemHeight: 10, |
| | | itemGap: 10, |
| | | formatter: function(name) { |
| | | let data = option.series[0].data; |
| | | let total = 0; |
| | | let tarValue = 0; |
| | | for (let i = 0; i < data.length; i++) { |
| | | total += data[i].value; |
| | | if (data[i].name === name) { |
| | | tarValue = data[i].value; |
| | | } |
| | | } |
| | | let percentage = ((tarValue / total) * 100).toFixed(1); |
| | | return `${name} ${percentage}%`; |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '行业统计', |
| | | type: 'pie', |
| | | radius: '60%', |
| | | center: ['35%', '50%'], |
| | | itemStyle: { |
| | | borderRadius: 4, |
| | | borderColor: 'rgba(255,255,255,0.2)', |
| | | borderWidth: 1 |
| | | }, |
| | | label: { |
| | | show: true, |
| | | position: 'inside', |
| | | formatter: '{c}', |
| | | fontSize: 12, |
| | | color: '#fff' |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | emphasis: { |
| | | scale: true, |
| | | scaleSize: 10 |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | // 获取行业统计数据 |
| | | const getIndustryJobNumPieChart = () => { |
| | | industryJobNumPieChart().then(res => { |
| | | if (res.data.code !== 0) return; |
| | | const data = res.data.data.map(item => ({ |
| | | name: item.name, |
| | | value: item.value, |
| | | itemStyle: { |
| | | color: getRandomColor() |
| | | } |
| | | })); |
| | | option.series[0].data = data; |
| | | chart.setOption(option); |
| | | }); |
| | | }; |
| | | |
| | | // 生成随机颜色 |
| | | const getRandomColor = () => { |
| | | const colors = ['#1890FF', '#36CBCB', '#4ECB73', '#FBD437', '#F2637B', '#975FE5']; |
| | | return colors[Math.floor(Math.random() * colors.length)]; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | chart = echarts.init(chartRef.value); |
| | | getIndustryJobNumPieChart(); |
| | | |
| | | window.addEventListener('resize', () => { |
| | | chart?.resize(); |
| | | }); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | window.removeEventListener('resize', chart?.resize); |
| | | chart?.dispose(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-industry { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | margin-left: 29px; |
| | | padding: 16px 16px; |
| | | width: 340px; |
| | | height: 400px; |
| | | 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; |
| | | .chart { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="task-left"> |
| | | <TaskTotal /> |
| | | <TaskIndustry /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import TaskTotal from './TaskTotal.vue'; |
| | | import TaskIndustry from './TaskIndustry.vue'; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-left { |
| | | // width: 300px; |
| | | position: relative; |
| | | top: 20px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 任务统计 --> |
| | | <template> |
| | | <common-title title="任务统计" :style="{ marginLeft: pxToRem(14) }"></common-title> |
| | | <div class="task-total"> |
| | | <div class="card" v-for="item in list"> |
| | | <div> |
| | | <div class="value">{{ item.value }}</div> |
| | | <div class="name">{{item.name}}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { pxToRem } from '@/utils/rem'; |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import { totalJobNum, jobStatistics } from "@/api/home/task"; |
| | | |
| | | const list = ref([ |
| | | { name: '总任务数', value: '1888'}, |
| | | { name: '计划执行', value: '18'}, |
| | | { name: '执行中', value: '999'}, |
| | | { name: '待执行', value: '8888'}, |
| | | { name: '已执行', value: '666'}, |
| | | { name: '执行失败', value: '2222'}, |
| | | ]); |
| | | |
| | | // 获取任务统计总数 |
| | | const getTotalJobNum = () => { |
| | | totalJobNum().then((res) => { |
| | | if (res.data.code !== 0) returen; |
| | | list.value[0].value = res.data.data; |
| | | }); |
| | | }; |
| | | // 获取其他任务统计 |
| | | const getJobStatistics = () => { |
| | | jobStatistics().then((res) => { |
| | | if (res.data.code !== 0) returen; |
| | | list.value[1].value = res.data.data.planned_executions; |
| | | list.value[2].value = res.data.data.running_num; |
| | | list.value[3].value = res.data.data.pending_executions; |
| | | list.value[4].value = res.data.data.executed; |
| | | list.value[5].value = res.data.data.failed_executions; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTotalJobNum(); |
| | | getJobStatistics(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-total { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | margin-left: 29px; |
| | | padding: 16px 16px; |
| | | width: 340px; |
| | | height: 400px; |
| | | 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; |
| | | margin-bottom: 12px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | grid-template-rows: repeat(3, 1fr); |
| | | gap: 20px; |
| | | padding: 20px; |
| | | .card { |
| | | /* position: absolute; |
| | | top: 8px; |
| | | right: 10px; |
| | | width: 200px; */ |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | justify-content: flex-start; |
| | | line-height: 22px; |
| | | padding: 0 10px 10px 0; |
| | | color: #ffffff; |
| | | .name { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | |
| | | } |
| | | |
| | | .value { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 任务事件统计 --> |
| | | <template> |
| | | <common-title title="任务事件统计"></common-title> |
| | | <div class="task-event"> |
| | | <div class="chart" ref="chartRef"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import * as echarts from 'echarts'; |
| | | import { jobEventBar } from '@/api/home/task'; |
| | | import dayjs from 'dayjs'; |
| | | |
| | | // 日期 |
| | | const currenDate = dayjs().format('YYYY-MM-DD'); |
| | | const newTime = ref([currenDate, currenDate]); |
| | | // 图表 |
| | | const chartRef = ref(null); |
| | | let chart = null; |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['任务', '事件'], |
| | | textStyle: { |
| | | color: '#fff' |
| | | }, |
| | | bottom: '5%' |
| | | }, |
| | | grid: { |
| | | top: '15%', |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '15%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#fff', |
| | | interval: 0, |
| | | rotate: 30 |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: 'rgba(255, 255, 255, 0.1)' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '任务', |
| | | type: 'bar', |
| | | barWidth: '20%', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#1EE7E7' }, |
| | | { offset: 1, color: 'rgba(30, 231, 231, 0.1)' } |
| | | ]) |
| | | } |
| | | }, |
| | | { |
| | | name: '事件', |
| | | type: 'bar', |
| | | barWidth: '20%', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#0070FF' }, |
| | | { offset: 1, color: 'rgba(0, 112, 255, 0.1)' } |
| | | ]) |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | // 获取行业统计数据 |
| | | const getJobEventBar = (value,date_enum) => { |
| | | jobEventBar({date_enum}).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | option.xAxis.data = res.data.data.map(item => item.name); |
| | | option.series[0].data = res.data?.data.map(item => item.data[0].value); |
| | | option.series[1].data = res.data?.data.map(item => item.data[1].value); |
| | | chart.setOption(option); |
| | | }); |
| | | }; |
| | | |
| | | // 生成随机颜色 |
| | | const getRandomColor = () => { |
| | | const colors = ['#1890FF', '#36CBCB', '#4ECB73', '#FBD437', '#F2637B', '#975FE5']; |
| | | return colors[Math.floor(Math.random() * colors.length)]; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | chart = echarts.init(chartRef.value); |
| | | getJobEventBar(newTime.value, 'CURRENT_YEAR'); |
| | | |
| | | window.addEventListener('resize', () => { |
| | | chart?.resize(); |
| | | }); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | window.removeEventListener('resize', chart?.resize); |
| | | chart?.dispose(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-event { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | margin-left: 29px; |
| | | padding: 16px 16px; |
| | | width: 340px; |
| | | height: 400px; |
| | | 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; |
| | | .chart { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="task-right"> |
| | | <TaskTime /> |
| | | <TaskEvent /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import TaskTime from './TaskTime.vue'; |
| | | import TaskEvent from './TaskEvent.vue'; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .task-right { |
| | | position: absolute; |
| | | top: 122px; |
| | | right: 31px; |
| | | width: 404px; |
| | | |
| | | .titleBox { |
| | | width: 404px; |
| | | height: 43px; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 任务事件统计 --> |
| | | <template> |
| | | <common-title title="任务时间统计"></common-title> |
| | | <div class="task-time"> |
| | | <div class="chart" ref="chartRef"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import CommonTitle from '@/components/CommonTitle.vue'; |
| | | import * as echarts from 'echarts'; |
| | | import { jobNumBar } from '@/api/home/task'; |
| | | import dayjs from 'dayjs'; |
| | | |
| | | // 日期 |
| | | const currenDate = dayjs().format('YYYY-MM-DD'); |
| | | const newTime = ref([currenDate, currenDate]); |
| | | |
| | | const chartRef = ref(null); |
| | | let chart = null; |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | grid: { |
| | | top: '15%', |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#fff', |
| | | interval: 0, |
| | | rotate: 30 |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: 'rgba(255, 255, 255, 0.1)' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#fff' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | type: 'bar', |
| | | barWidth: '40%', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#1EE7E7' }, |
| | | { offset: 1, color: 'rgba(30, 231, 231, 0.1)' } |
| | | ]) |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | // 获取任务时间统计数据 |
| | | const getJobNumBar = (value,date_enum) => { |
| | | jobNumBar({date_enum}).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | option.xAxis.data = res.data.data.map(item => item.name); |
| | | option.series[0].data = res.data.data.map(item => item.value); |
| | | chart.setOption(option); |
| | | }); |
| | | }; |
| | | |
| | | |
| | | onMounted(() => { |
| | | chart = echarts.init(chartRef.value); |
| | | getJobNumBar(newTime.value, 'CURRENT_YEAR'); |
| | | |
| | | window.addEventListener('resize', () => { |
| | | chart?.resize(); |
| | | }); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | window.removeEventListener('resize', chart?.resize); |
| | | chart?.dispose(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-time { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | margin-left: 29px; |
| | | padding: 16px 16px; |
| | | width: 340px; |
| | | height: 400px; |
| | | 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; |
| | | .chart { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | </style> |