Merge remote-tracking branch 'origin/master'
| | |
| | | |
| | | import DevicePopUpBox from '@/hooks/components/DevicePopUpBox.vue' |
| | | import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue' |
| | | |
| | | // 图标 |
| | | import offlineImg from '@/assets/images/home/useEventOperate/offline.png' |
| | | import onlineImg from '@/assets/images/home/useEventOperate/eventSingle.png' |
| | | import { render } from 'vue' |
| | | import { useStore } from 'vuex' |
| | | import { getCenterPoint } from '@/utils/cesium/mapUtil' |
| | |
| | | * 机巢聚合功能 |
| | | */ |
| | | |
| | | let arrColor = ["rgb(15,176,255)", "rgb(18,76,154)", "#40C4E4", "#42B2BE", "rgb(51,176,204)", "#8CB7E5", "rgb(0,244,188)", "#139FF0"] |
| | | let arrColor = [ |
| | | 'rgb(15,176,255)', |
| | | 'rgb(18,76,154)', |
| | | '#40C4E4', |
| | | '#42B2BE', |
| | | 'rgb(51,176,204)', |
| | | '#8CB7E5', |
| | | 'rgb(0,244,188)', |
| | | '#139FF0', |
| | | ] |
| | | |
| | | let index = 0 |
| | | function getColor () { |
| | | return arrColor[++index % arrColor.length] |
| | | } |
| | | |
| | | export const useMapAggregation = type => { |
| | | export const useMapAggregation = (type, status) => { |
| | | const { flyTo } = cesiumOperation() |
| | | |
| | | const singleImg = type === 'device' ? uavImg : eventSingle |
| | | const singleImg = type === 'device' ? onlineImg : eventSingle |
| | | const offlinesingleImg = type === 'device' ? offlineImg : eventSingle |
| | | const mergeImg = type === 'device' ? aggregationImg : eventAggregationImg |
| | | const MapPopUpBox = type === 'device' ? DevicePopUpBox : EventPopUpBox |
| | | const styleTransform = type === 'device' ? 'translateY(-50%)' : 'translate(-50%,-110%)' |
| | |
| | | const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode) |
| | | const selectedAreaCode = computed(() => store.state.user.selectedAreaCode) |
| | | |
| | | |
| | | const eventTimeType = computed(() => store.state.home.eventTimeType) |
| | | const eventTimeRang = computed(() => store.state.home.eventTimeRang) |
| | | |
| | |
| | | })) |
| | | |
| | | let saveParams = { area_code: '', date_enum: 'CURRENT_WEEK' } |
| | | |
| | | |
| | | // 确定缩放比例 |
| | | const determineScaling = () => { |
| | |
| | | // 获取设备聚合 |
| | | function getDeviceCount (areaCode) { |
| | | return getDeviceRegionCount({ areaCode }).then(res => { |
| | | return (res?.data?.data || []) |
| | | return res?.data?.data || [] |
| | | }) |
| | | } |
| | | // 获取设备散点 |
| | | function getDeviceList (areaCode) { |
| | | return getDeviceRegion({ areaCode }).then(res => { |
| | | |
| | | return (res?.data?.data || []).map(i => ({ ...i, type })) |
| | | |
| | | |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | const getOutLine = async (jsonPathPre, hierarchy) => { |
| | | const parentGJson = await getFiler(`${defaultDir}${jsonPathPre}/index.json`) |
| | | let features = parentGJson.features.find( |
| | | item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1]) |
| | | ) |
| | | let features = parentGJson.features.find(item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1])) |
| | | return { type: 'FeatureCollection', features: [features] } |
| | | } |
| | | |
| | |
| | | if (!areaCode) return |
| | | saveParams.area_code = areaCode |
| | | const list = type === 'device' ? await getDeviceCount(areaCode) : await getMapEventCount(saveParams) |
| | | const splashedList = type === 'device' |
| | | const splashedList = |
| | | type === 'device' |
| | | ? await getDeviceList(areaCode) |
| | | : eventList.map(i => ({ eventId: i.id, latitude: Number(i.latitude), longitude: Number(i.longitude), type: 'event' })) |
| | | : eventList.map(i => ({ |
| | | eventId: i.id, |
| | | latitude: Number(i.latitude), |
| | | longitude: Number(i.longitude), |
| | | type: 'event', |
| | | })) |
| | | const hierarchy = convertToHierarchy(areaCode.slice(0, 6)) |
| | | const jsonPath = hierarchy.join('/') |
| | | const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/') |
| | |
| | | const outlineGJson = await getOutLine(jsonPathPre, hierarchy) |
| | | scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson)) |
| | | const [longitude, latitude] = outlineGJson.features[0].properties.centroid |
| | | const height = scalingJudgment[(hierarchy.length - 3) * (-1)].height |
| | | const height = scalingJudgment[(hierarchy.length - 3) * -1].height |
| | | setCenterPosition({ longitude, latitude, height }) |
| | | flyTo({ longitude, latitude }, 0, height) |
| | | } |
| | | |
| | | const userAreaPosition = computed(() => store.state.home.userAreaPosition) |
| | | |
| | | const setCenterPosition = (position) => { |
| | | const setCenterPosition = position => { |
| | | store.commit('setCurrentAreaPosition', position) |
| | | if (!userAreaPosition.value.longitude) { |
| | | store.commit('setUserAreaPosition', position) |
| | | } |
| | | } |
| | | |
| | | watch(combinedValues, async (newValue, oldValue) => { |
| | | watch( |
| | | combinedValues, |
| | | async (newValue, oldValue) => { |
| | | if (newValue.singleUavHome?.device_sn) { |
| | | clearMapEntity() |
| | | return |
| | |
| | | } |
| | | |
| | | if (newValue.eventTimeRang) { |
| | | saveParams = { area_code: newValue.selectedAreaCode, start_date: newValue.eventTimeRang[0], end_date: newValue.eventTimeRang[1] } |
| | | saveParams = { |
| | | area_code: newValue.selectedAreaCode, |
| | | start_date: newValue.eventTimeRang[0], |
| | | end_date: newValue.eventTimeRang[1], |
| | | } |
| | | } |
| | | |
| | | needFly = true |
| | |
| | | //散点机巢 |
| | | function splashed (row) { |
| | | row.splashedList.forEach((item, index) => { |
| | | |
| | | viewer.entities.add({ |
| | | id: `aggregation-splashed-${index}`, |
| | | position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude), |
| | |
| | | pixelOffset: new Cesium.Cartesian2(0, -9), |
| | | }, |
| | | billboard: { |
| | | image: new Cesium.ConstantProperty(singleImg), |
| | | // singleImg |
| | | image: new Cesium.ConstantProperty(()=>{ |
| | | return item.status ==="OFFLINE" ? offlinesingleImg:singleImg |
| | | }), |
| | | width: 24, |
| | | height: 24, |
| | | }, |
| | |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(arrColor[randomInt]), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3 |
| | | alphaPower: 1.3, |
| | | }) |
| | | |
| | | entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || 1) * 500 |
| | |
| | | }), |
| | | }, |
| | | |
| | | polygon |
| | | polygon, |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 聚合机巢 |
| | | const aggregation = (item) => { |
| | | const aggregation = item => { |
| | | if (!item.gJson) return |
| | | const featuresList = item.gJson.features.map(item1 => { |
| | | // const {lng,lat} = getCenterPoint(item1.geometry.coordinates[0][0]) |
| | |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(getColor()), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3 |
| | | alphaPower: 1.3, |
| | | }) |
| | | |
| | | const randomInt = Math.floor(Math.random() * 8) + 1 |
| | |
| | | entity.polygon.outline = false // 显示边框 |
| | | }) |
| | | |
| | | needFly && viewer.flyTo(dataSource, { |
| | | needFly && |
| | | viewer.flyTo(dataSource, { |
| | | offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-60), 0), |
| | | duration: 0.5, |
| | | }) |
| | |
| | | let clickTargets = viewer.scene.drillPick(click.position).map(item => item.id) |
| | | if (!clickTargets.length) return |
| | | |
| | | console.log(clickTargets, 11111) |
| | | // console.log(clickTargets, 11111) |
| | | |
| | | let deviceAggregationFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'deviceAggregation') |
| | | let deviceFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'device') |
| | | let deviceAggregationFind = findTypeItem( |
| | | clickTargets, |
| | | item => item?.properties?.customData?._value?.data?.type === 'deviceAggregation' |
| | | ) |
| | | let deviceFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'device') |
| | | // "event" |
| | | let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'event') |
| | | let eventFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'event') |
| | | // let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'eventAggregation') |
| | | currentEntity = deviceAggregationFind || deviceFind || eventFind |
| | | |
| | |
| | | actions: {}, |
| | | mutations: { |
| | | setTaskSearchParams: (state, data) => { |
| | | console.log(data) |
| | | // setStore({ name: 'taskSearchParams', content: data }) |
| | | state.taskSearchParams = data; |
| | | }, |
| | | }, |
| | |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="任务算法:" v-if="isExpand"> |
| | | <TaskAlgorithmBusiness :setWidth="200" :showAlgorithm="true" @algorithmChange="algorithmChange"/> |
| | | <TaskAlgorithmBusiness :setWidth="186" :showAlgorithm="true" @algorithmChange="algorithmChange"/> |
| | | </el-form-item> |
| | | <el-form-item label="所属部门:" v-if="isExpand"> |
| | | <el-select class="ztzf-select" v-model="searchForm.create_dept" placeholder="请选择部门" clearable> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务类型:" v-if="isExpand"> |
| | | <TaskAlgorithmBusiness :setWidth="200" :showBusiness="true" @businessChange="businessChange"/> |
| | | <TaskAlgorithmBusiness :setWidth="186" :showBusiness="true" @businessChange="businessChange"/> |
| | | </el-form-item> |
| | | <div class="more" v-if="isExpand" @click="toggleExpand">收起</div> |
| | | <div class="more" v-else @click="toggleExpand">更多</div> |
| | |
| | | ai_types: [], // 算法类型 |
| | | area_code: '', // 区域code |
| | | create_dept: '', // 创建部门 |
| | | date_enum: '', // 日期枚举,可用值:TODAY,CURRENT_WEEK,CURRENT_MONTH,CURRENT_YEAR |
| | | date_enum: 'TODAY', // 日期枚举,可用值:TODAY,CURRENT_WEEK,CURRENT_MONTH,CURRENT_YEAR |
| | | device_sn: '', // 设备编号 |
| | | end_date: null, // 结束时间 |
| | | industry_type: '', // 行业key |
| | |
| | | ]; |
| | | |
| | | const emit = defineEmits(['search','addTask']); |
| | | |
| | | const handleSearch = () => { |
| | | // 提交至store |
| | | let params = { |
| | | ...searchForm, |
| | | start_date: dateRange.value.length ? `${dateRange.value[0]} 00:00:00` : null, |
| | | end_date: dateRange.value.length ? `${dateRange.value[1]} 23:59:59` : null |
| | | } |
| | | store.commit('setTaskSearchParams', params); |
| | | emit('search', params); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | dateRange.value = null; |
| | | Object.keys(searchForm).forEach(key => { |
| | | searchForm[key] = ''; |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 新增任务 |
| | | const addTask = () => { |
| | | emit('addTask'); |
| | | }; |
| | | |
| | | const algorithmChange = (val) => { |
| | | searchForm.ai_types = val; |
| | |
| | | }; |
| | | const deptChange = (value) => { |
| | | // 处理机巢数据 |
| | | searchForm.device_sn = ''; |
| | | machineData.value = ''; |
| | | machineData.value = deptTreeData.value.find(item => item.area_code === value)?.devices || []; |
| | | // 所属部门重新请求值 |
| | |
| | | // model.value = dateRanges[item]; |
| | | // emit('change', dateRanges[item],timeListEnum[index]); |
| | | searchForm.date_enum = timeListEnum[index]; |
| | | handleSearch(); |
| | | }; |
| | | // 搜索 |
| | | const handleSearch = () => { |
| | | if (!dateRange.value) { dateRange.value = []; } |
| | | // 提交至store |
| | | let params = { |
| | | ...searchForm, |
| | | start_date: dateRange.value.length ? `${dateRange?.value[0]} 00:00:00` : null, |
| | | end_date: dateRange.value.length ? `${dateRange?.value[1]} 23:59:59` : null |
| | | } |
| | | store.commit('setTaskSearchParams', params); |
| | | emit('search', params); |
| | | }; |
| | | // 重置 |
| | | const handleReset = () => { |
| | | dateRange.value = []; |
| | | Object.keys(searchForm).forEach(key => { |
| | | searchForm[key] = ''; |
| | | }); |
| | | searchForm.ai_types = []; |
| | | searchForm.date_enum = 'TODAY'; |
| | | checked.value = 'today'; |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 新增任务 |
| | | const addTask = () => { |
| | | emit('addTask'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // requestDictionary(); |
| | | getDeptsByAreaCode(); |
| | | requestDockInfo(); |
| | | // 查询一次 |
| | | handleSearch(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | :width="pxToRem(1500)" |
| | | :close-on-click-modal="false" |
| | | :destroy-on-close="true" |
| | | @close="cancel" |
| | | > |
| | | <!-- <el-divider content-position="left">新建任务</el-divider> --> |
| | | <div class="task-contain"> |
| | |
| | | |
| | | // 添加监听 |
| | | watch(() => store.state.task.taskSearchParams, (newVal) => { |
| | | console.log(newVal, '1111'); |
| | | if (newVal) { |
| | | getJobEventBar(newVal); |
| | | } |
| | |
| | | <!-- 任务算法统计 --> |
| | | <template> |
| | | <div class="task-industry"> |
| | | <div class="title">任务算法统计</div> |
| | | <div class="title">任务算法类型</div> |
| | | <div class="chart" ref="chartRef"></div> |
| | | </div> |
| | | </template> |
| | |
| | | roseType: 'radius', |
| | | radius: ['20%', '70%'], |
| | | center: ['50%', '45%'], |
| | | data: [ |
| | | { name: '国土类', value: 0, itemStyle: { color: '#3D7FFF' } }, |
| | | { name: '城管类', value: 0, itemStyle: { color: '#8277E9' } }, |
| | | { name: '消防类', value: 0, itemStyle: { color: '#FFB77E' } }, |
| | | { name: '林业类', value: 0, itemStyle: { color: '#44D7B6' } }, |
| | | { name: '公安类', value: 0, itemStyle: { color: '#62F4FF' } } |
| | | ], |
| | | data: [], |
| | | // [ |
| | | // { name: '国土类', value: 0, itemStyle: { color: '#3D7FFF' } }, |
| | | // { name: '城管类', value: 0, itemStyle: { color: '#8277E9' } }, |
| | | // { name: '消防类', value: 0, itemStyle: { color: '#FFB77E' } }, |
| | | // { name: '林业类', value: 0, itemStyle: { color: '#44D7B6' } }, |
| | | // { name: '公安类', value: 0, itemStyle: { color: '#62F4FF' } } |
| | | // ], |
| | | label: { |
| | | show: true, |
| | | position: 'outside', |
| | |
| | | const getIndustryJobNumPieChart = (value) => { |
| | | industryJobNumPieChart(value).then(res => { |
| | | if (res.data.code !== 0) return; |
| | | option.series[0].data.forEach(item => { |
| | | const matchData = res.data.data.find(d => d.name === item.name); |
| | | if (matchData) { |
| | | item.value = matchData.value; |
| | | } |
| | | }); |
| | | option.series[0].data = res.data.data; |
| | | // forEach(item => { |
| | | // const matchData = res.data.data.find(d => d.name === item.name); |
| | | // if (matchData) { |
| | | // item.value = matchData.value; |
| | | // } |
| | | // }); |
| | | chart.value.setOption(option); |
| | | }); |
| | | }; |
| | | |
| | | |
| | | // 获取行业统计数据 |
| | | // 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.value.setOption(option); |
| | | // }); |
| | | // }; |
| | | |
| | | // 添加监听 |
| | | watch(() => store.state.task.taskSearchParams, (newVal) => { |
| | | console.log(newVal, '2222'); |
| | | if (newVal) { |
| | | getIndustryJobNumPieChart(newVal); |
| | | } |
| | |
| | | <!-- 关联算法和综合业务 --> |
| | | <template> |
| | | <div class="task-algorithm" v-if="showAlgorithm"> |
| | | <el-select class="ztzf-select" :style="{ width:setWidth +'px' }" v-model="ai_types" multiple collapse-tags collapse-tags-tooltip placeholder="请选择算法" clearable @change="handleAlgorithmChange"> |
| | | <el-select class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="ai_types" multiple collapse-tags collapse-tags-tooltip placeholder="请选择算法" clearable @change="handleAlgorithmChange"> |
| | | <el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </div> |
| | | <div class="task-business" v-if="showBusiness"> |
| | | <el-select class="ztzf-select" :style="{ width:setWidth +'px' }" v-model="industry_type" placeholder="请选择类型" clearable @change="handleBusinessChange"> |
| | | <el-select class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="industry_type" placeholder="请选择类型" clearable @change="handleBusinessChange"> |
| | | <el-option v-for="item in taskBusiness" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </div> |
| | |
| | | |
| | | <script setup> |
| | | |
| | | import { getMultipleDictionary } from '@/api/system/dictbiz' |
| | | import { getMultipleDictionary } from '@/api/system/dictbiz'; |
| | | import { pxToRem } from '@/utils/rem' |
| | | |
| | | // 接收父组件传参 |
| | | const props = defineProps({ |
| | |
| | | default: false |
| | | }, |
| | | setWidth: { |
| | | type: String, |
| | | type: Number, |
| | | default: '100%' |
| | | } |
| | | }); |