@@ -23,6 +23,7 @@ | |||
"vite-plugin-svg-icons": "^2.0.1", | |||
"vue": "^3.2.16", | |||
"vue-router": "^4.0.14", | |||
"vue3-video-play": "^1.3.1-beta.6", | |||
"vuedraggable": "^4.1.0" | |||
}, | |||
"devDependencies": { |
@@ -4,7 +4,7 @@ import { defAxios as request } from '@/utils/http' | |||
* @description: 获取巡检机场 | |||
* @return {*} | |||
*/ | |||
export function airportList(params) { | |||
export function airportList (params) { | |||
return request({ | |||
url: '/inspection/airport', | |||
method: 'GET', | |||
@@ -16,7 +16,7 @@ export function airportList(params) { | |||
* @description: 获取航线 | |||
* @return {*} | |||
*/ | |||
export function airportLine(id) { | |||
export function airportLine (id) { | |||
return request({ | |||
url: `/inspection/airport/line/${id}`, | |||
method: 'GET' | |||
@@ -28,7 +28,7 @@ export function airportLine(id) { | |||
* @param {*} id 机场id | |||
* @return {*} | |||
*/ | |||
export function airportWeather(id) { | |||
export function airportWeather (id) { | |||
return request({ | |||
url: `/inspection/airport/weather/${id}`, | |||
method: 'GET' | |||
@@ -40,7 +40,7 @@ export function airportWeather(id) { | |||
* @param {*} id 机场id | |||
* @return {*} | |||
*/ | |||
export function airportTrack(id) { | |||
export function airportTrack (id) { | |||
return request({ | |||
url: `/inspection/track/${id}`, | |||
method: 'GET' | |||
@@ -52,10 +52,52 @@ export function airportTrack(id) { | |||
* @param {*} id 机场id | |||
* @return {*} | |||
*/ | |||
export function missionLive(id) { | |||
export function missionLive (id) { | |||
return request({ | |||
url: `/mission/live/${id}`, | |||
method: 'GET' | |||
}) | |||
} | |||
/** | |||
* @description:获取机场详细信息 | |||
* @param id 机场id | |||
*/ | |||
export function getAirportInfo (data) { | |||
return request({ | |||
url: `/index/getAirportDetail`, | |||
method: 'POST', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:获取任务列表接口 | |||
* @param page 页数 | |||
* @param limit 每页显示数 | |||
*/ | |||
export function getMissionList (data) { | |||
return request({ | |||
url: `/index/getMissionList`, | |||
method: 'POST', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:获取问题多选类型 | |||
* | |||
*/ | |||
export function getQuestionType () { | |||
return request({ | |||
url: `/question/type`, | |||
method: 'GET' | |||
}) | |||
} | |||
/** | |||
* @description:获取问题列表数据 | |||
*/ | |||
export function getQuestionList (data) { | |||
return request({ | |||
url: `/index/getQuestionList`, | |||
method: 'POST', | |||
data | |||
}) | |||
} |
@@ -149,3 +149,17 @@ export function questionAnalyze(id) { | |||
method: 'GET' | |||
}) | |||
} | |||
/** | |||
* 新的接口 | |||
* 获取问题列表(限制200条) | |||
* @param {startTime} 开始时间 | |||
* @param {endTime} 结束时间 | |||
*/ | |||
export function getQuestions(params) { | |||
return request({ | |||
url: '/index/getQuestionList', | |||
method: 'POST', | |||
params | |||
}) | |||
} |
@@ -71,6 +71,7 @@ export default { | |||
const res = await airportList({ page: 1, limit: 60 }) | |||
if (res.code === 0) { | |||
data.airOptionsAll = res.data | |||
// console.log(data.airOptionsAll) | |||
data.airOptions = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
data.videoForm.airportId = res.data[0].id | |||
getAirportInfo(res.data[0].id) |
@@ -0,0 +1,234 @@ | |||
<template> | |||
<div class="content"> | |||
<table> | |||
<tr> | |||
<th class="title">机场名称:</th> | |||
<th>机场A</th> | |||
</tr> | |||
<tr> | |||
<th class="title">机场状态:</th> | |||
<th>正常</th> | |||
</tr> | |||
<tr> | |||
<th class="title">可选挂载:</th> | |||
<th>高清相机、多光谱相机、喊话器</th> | |||
</tr> | |||
</table> | |||
<div class="deviceInfo"> | |||
<div | |||
v-for="(item,index) in indicatorList" | |||
:key="index" | |||
class="item" | |||
> | |||
<img :src="item.icon"> | |||
<div class="value">{{ item.indicatorValue }}</div> | |||
<div class="name">{{ item.indicatorName }}</div> | |||
</div> | |||
</div> | |||
<div class="monitorList"> | |||
<div class="innerMonitor"> | |||
<div class="monitorName">机场内部监控</div> | |||
<img src="../../../assets/images/webScreen.png" @click="videoShowStyle"> | |||
<videoPlay | |||
v-bind="innerMonitorOptions" | |||
style="z-index:1" | |||
/> | |||
</div> | |||
<div class="innerMonitor"> | |||
<div class="monitorName">机场外部监控</div> | |||
<img src="../../../assets/images/webScreen.png" @click="outerVideoShowStyle"> | |||
<videoPlay | |||
v-bind="outsideMonitorOptions" | |||
style="z-index:1" | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { reactive, toRefs, watch } from 'vue' | |||
import { getAirportInfo } from '@/api/dashboard/index.js' | |||
import 'vue3-video-play/dist/style.css' | |||
import { videoPlay } from 'vue3-video-play' | |||
export default { | |||
name: 'OneMap', | |||
components: { videoPlay }, | |||
props: { | |||
data: { | |||
type: Object, | |||
default: () => { } | |||
} | |||
}, | |||
setup(props) { | |||
const data = reactive({ | |||
detail: props.data, | |||
indicatorList: [ | |||
{ icon: new URL('../../../assets/images/wind.png', import.meta.url).href, indicatorValue: '3m/s', indicatorName: '风速' }, | |||
{ icon: new URL('../../../assets/images/north.png', import.meta.url).href, indicatorValue: '正北', indicatorName: '风向' }, | |||
{ icon: new URL('../../../assets/images/atmosPressure.png', import.meta.url).href, indicatorValue: '0.1Mpa', indicatorName: '大气压力' }, | |||
{ icon: new URL('../../../assets/images/airHumidity.png', import.meta.url).href, indicatorValue: '25rh', indicatorName: '空气湿度' }, | |||
{ icon: new URL('../../../assets/images/rainfall.png', import.meta.url).href, indicatorValue: '5ml', indicatorName: '降雨量' }, | |||
{ icon: new URL('../../../assets/images/airTemperature.png', import.meta.url).href, indicatorValue: '25°C', indicatorName: '空气温度' }], | |||
innerMonitorOptions: { | |||
width: '256px', | |||
height: '198px', | |||
controls: false, | |||
src: '', | |||
webFullScreen: false | |||
}, | |||
outsideMonitorOptions: { | |||
width: '256px', | |||
height: '198px', | |||
controls: false, | |||
src: '', | |||
webFullScreen: false | |||
} | |||
}) | |||
watch(() => props.data, (value) => { | |||
if (value) { | |||
// console.log(props.data) | |||
data.detail = props.data | |||
data.innerMonitorOptions.src = data.detail.internalMonitorUrl | |||
data.outsideMonitorOptions.src = data.detail.externalMonitorUrl | |||
getAirportInfo({ | |||
airportId: data.detail.id | |||
}) | |||
.then(res => { | |||
if (res.code === 0) { | |||
// console.log('机场详情') | |||
data.indicatorList.map((item, index) => { | |||
switch (index) { | |||
case 0: | |||
item.indicatorValue = res.data.wspd | |||
break | |||
case 1: | |||
item.indicatorValue = res.data.wdir | |||
break | |||
case 2: | |||
item.indicatorValue = res.data.hpa | |||
break | |||
case 3: | |||
item.indicatorValue = res.data.hum | |||
break | |||
case 5: | |||
item.indicatorValue = res.data.tmp | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
}) | |||
const videoShowStyle = () => { | |||
data.innerMonitorOptions.webFullScreen = !data.innerMonitorOptions.webFullScreen | |||
} | |||
const outerVideoShowStyle = () => { | |||
data.outsideMonitorOptions.webFullScreen = !data.outsideMonitorOptions.webFullScreen | |||
} | |||
return { | |||
...toRefs(data), | |||
videoShowStyle, | |||
outerVideoShowStyle | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.map-container { | |||
width: 100vw; | |||
height: 100vh; | |||
} | |||
.layer-management { | |||
height: calc(100vh - 84%); | |||
position: absolute; | |||
width: 100px; | |||
/* margin-right: 10px; */ | |||
left: 100px; | |||
top: 100px; | |||
background-color: rgba(0, 0, 0, 0.6); | |||
} | |||
.content { | |||
box-sizing: border-box; | |||
padding: 25px 5px; | |||
} | |||
table { | |||
width: 100%; | |||
height: 90px; | |||
font-size: 15px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
border-collapse: collapse; | |||
background: #2c2c2c; | |||
.title { | |||
color: #8b8b8b; | |||
} | |||
} | |||
table, | |||
td, | |||
th { | |||
border: 1px solid #707070; | |||
color: white; | |||
font-weight: 400; | |||
} | |||
.deviceInfo { | |||
margin-top: 5px; | |||
width: 100%; | |||
height: 83px; | |||
background: #2c2c2c; | |||
display: flex; | |||
justify-content: space-between; | |||
.item { | |||
color: white; | |||
display: flex; | |||
justify-content: center; | |||
flex-direction: column; | |||
align-items: center; | |||
.value { | |||
font-size: 14px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
color: #ffffff; | |||
} | |||
.name { | |||
font-size: 15px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
color: #8b8b8b; | |||
} | |||
} | |||
} | |||
.monitorList { | |||
margin-top: 10px; | |||
display: flex; | |||
justify-content: space-around; | |||
.innerMonitor { | |||
position: relative; | |||
width: 256px; | |||
height: 198px; | |||
.monitorName { | |||
position: absolute; | |||
bottom: 8px; | |||
left: 10px; | |||
font-size: 14px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
color: #ffffff; | |||
z-index: 100; | |||
} | |||
img { | |||
position: absolute; | |||
right: 10px; | |||
bottom: 8px; | |||
z-index: 100; | |||
} | |||
} | |||
} | |||
</style> | |||
@@ -0,0 +1,874 @@ | |||
<template> | |||
<div | |||
class="map-container" | |||
:="getMapOptions" | |||
/> | |||
<!-- <div class="layer-management"> | |||
<div class="list-manage"> | |||
<p>列表</p> | |||
<n-switch v-model:value="listShow" /> | |||
</div> | |||
<div class="air-manage"> | |||
<p>机场</p> | |||
<n-switch v-model:value="airShow" | |||
@update:value="airShowHide" /> | |||
</div> | |||
</div> --> | |||
<div | |||
id="airOverlay" | |||
class="airport-overlay" | |||
> | |||
<span | |||
id="closeAir" | |||
class="close-overlay" | |||
@click="hideAirInfo" | |||
>x</span> | |||
<air-info :data="airDetail" /> | |||
</div> | |||
<div | |||
v-show="problemPopupShow" | |||
id="problemOverlay" | |||
class="problem-overlay" | |||
> | |||
<span | |||
class="close-overlay" | |||
@click="hideProblemInfo" | |||
>x</span> | |||
<problem-info :detail="problemDetail" /> | |||
</div> | |||
<div | |||
v-show="false" | |||
class="task-question" | |||
> | |||
<n-card style="margin-bottom: 16px"> | |||
<n-tabs | |||
type="line" | |||
animated | |||
> | |||
<!-- <n-tab-pane name="task" tab="任务"> | |||
任务 | |||
</n-tab-pane> --> | |||
<n-tab-pane | |||
name="question" | |||
tab="问题" | |||
> | |||
<n-date-picker | |||
:on-update:formatted-value="abc" | |||
:default-formatted-value="efg" | |||
type="daterange" | |||
:default-value="[Date.now() - 6.048e8, Date.now()]" | |||
:is-date-disabled="disablePreviousDate" | |||
/> | |||
<!-- <n-checkbox-group :value="cities" @update:value="handleUpdateValue"> | |||
<n-space style="display: block;"> | |||
<n-checkbox value="Beijing" label="北京" /> | |||
<n-checkbox value="Shanghai" label="上海" /> | |||
<n-checkbox value="Guangzhou" label="广州" /> | |||
<n-checkbox value="Shenzen" label="深圳" /> | |||
</n-space> | |||
</n-checkbox-group> --> | |||
</n-tab-pane> | |||
</n-tabs> | |||
</n-card> | |||
</div> | |||
<div | |||
v-show="listChecked" | |||
class="menu" | |||
> | |||
<div class="tabBar"> | |||
<span | |||
:class="[tabIndex==1?'checkedColor':'uncheckedColor']" | |||
style="margin-right:97px" | |||
@click="showTask" | |||
>任务</span> | |||
<span | |||
:class="[tabIndex==1?'uncheckedColor':'checkedColor']" | |||
@click="showProblem" | |||
>问题</span> | |||
</div> | |||
<div | |||
v-if="tabIndex==1" | |||
class="listDetail" | |||
> | |||
<ul> | |||
<li | |||
v-for="(item,index) in taskList" | |||
:key="index" | |||
style="display:flex;font-size:14px" | |||
> | |||
<div style="width:145px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ item.taskName }}</div> | |||
<div style="42px">{{ item.statusInfo }}</div> | |||
<!-- <div v-if="item.status==1" | |||
@click="performTask(item)">立即执行</div> --> | |||
<!-- <n-button v-if="item.status==1" | |||
@click="handleConfirm">立即执行</n-button> --> | |||
<n-popconfirm | |||
v-if="item.status==1" | |||
@positive-click="handlePositiveClick(item)" | |||
@negative-click="handleNegativeClick" | |||
> | |||
<template #trigger> | |||
<span style="color:#22D33D">立即执行</span> | |||
</template> | |||
是否立即开始执行任务? | |||
</n-popconfirm> | |||
<div | |||
v-else | |||
style="color:#1890FF" | |||
@click="liveShow(item)" | |||
>直播</div> | |||
</li> | |||
</ul> | |||
<n-pagination | |||
v-model:page="page" | |||
:page-count="pageCount" | |||
:page-slot="7" | |||
style="color:#FFFFFF;position:absolute;bottom:10px;left:10px" | |||
/> | |||
</div> | |||
<div | |||
v-else | |||
class="listDetail" | |||
> | |||
<n-date-picker | |||
:on-update:formatted-value="abc" | |||
:default-formatted-value="efg" | |||
type="daterange" | |||
:default-value="[Date.now() - 6.048e8, Date.now()]" | |||
:is-date-disabled="disablePreviousDate" | |||
style="margin-bottom:15px" | |||
/> | |||
<!-- 多选框 --> | |||
<n-checkbox-group | |||
v-model:value="problemTypeSelected" | |||
@update:value="handleProblemTypeValue" | |||
> | |||
<div | |||
v-for="(item,index) in problemTypeList" | |||
:key="index" | |||
> | |||
<n-checkbox | |||
:value="item.content" | |||
:label="item.content" | |||
style="color:#FFFFFF" | |||
/> | |||
</div> | |||
</n-checkbox-group> | |||
</div> | |||
</div> | |||
<div class="menuControl"> | |||
<div | |||
style="border-bottom:1px solid rgba(1122,112,112,0.65)" | |||
class="item" | |||
> | |||
<div @click="showList"> | |||
<img | |||
v-if="listChecked==true" | |||
src="../../../assets/images/listChecked.png" | |||
> | |||
<img | |||
v-else | |||
src="../../../assets/images/listUnchecked.png" | |||
> | |||
</div> | |||
<span :style="{'color':listChecked?'#1890FF':'#666666'}">列表</span> | |||
</div> | |||
<div class="item"> | |||
<div @click="showAirportList"> | |||
<img | |||
v-if="airportSelected==true" | |||
src="../../../assets/images/airportChecked.png" | |||
> | |||
<img | |||
v-else | |||
src="../../../assets/images/airportUnchecked.png" | |||
> | |||
</div> | |||
<span :style="{'color':airportSelected?'#1890FF':'#666666'}">机场</span> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { Map, View, Feature, Overlay } from 'ol' | |||
import { useRouter } from 'vue-router' | |||
import { XYZ, Vector as VectorSource } from 'ol/source' | |||
import TileLayer from 'ol/layer/Tile.js' | |||
import WMTS from 'ol/source/WMTS.js' | |||
import TileWMS from 'ol/source/TileWMS.js' | |||
import WMTSTileGrid from 'ol/tilegrid/WMTS.js' | |||
import { Tile, Vector as VectorLayer } from 'ol/layer' | |||
import { transform, fromLonLat } from 'ol/proj' | |||
import { Style, Icon, Text, Fill } from 'ol/style' | |||
import * as control from 'ol/control' | |||
import uav_icon from '@/assets/images/airport.png' | |||
import personnel_icon from '@/assets/images/personnelActivities.png' | |||
import problemSpot_icon from '@/assets/images/problemSpot.png' | |||
import deadTree_icon from '@/assets/images/deadTree.png' | |||
import fireHazard_icon from '@/assets/images/fireHazard.png' | |||
import { reactive, toRefs, onMounted, computed, ref, watch } from 'vue' | |||
import { Point } from 'ol/geom' | |||
import { airportList, getMissionList, getQuestionType, getQuestionList } from '@/api/dashboard/index.js' | |||
import { getQuestions } from '@/api/task/index.js' | |||
import { gcj02towgs84 } from '@/utils/coordinate-util.js' | |||
import AirInfo from './AirInfo.vue' | |||
import ProblemInfo from './ProblemInfo.vue' | |||
import { startOfDay } from 'date-fns/esm' | |||
import { useMessage, useDialog } from 'naive-ui' | |||
import { implement } from '@/api/task/index.js' | |||
import { get as getProjection } from 'ol/proj.js' | |||
import { getTopLeft, getWidth } from 'ol/extent.js' | |||
const projection = getProjection('EPSG:4326') | |||
const projectionExtent = projection.getExtent() | |||
const size = getWidth(projectionExtent) / 256 | |||
const resolutions = new Array(19) | |||
const matrixIds = new Array(19) | |||
for (let z = 0; z < 19; ++z) { | |||
// generate resolutions and matrixIds arrays for this WMTS | |||
resolutions[z] = size / Math.pow(2, z) | |||
matrixIds[z] = z | |||
} | |||
var message = useMessage() | |||
export default { | |||
name: 'OneMap', | |||
components: { AirInfo, ProblemInfo }, | |||
props: { | |||
id: { | |||
type: String, | |||
default: 'map' | |||
} | |||
}, | |||
setup(props) { | |||
const router = useRouter() | |||
const dialog = useDialog() | |||
const data = reactive({ | |||
map: null, | |||
// 机场数组 | |||
airportsAll: [], | |||
// 机场显隐 | |||
airShow: true, | |||
// 机场要素集 | |||
airFeatures: [], | |||
// 机场图层 | |||
airLayer: null, | |||
// 机场信息容器 | |||
airOverlay: null, | |||
// 问题信息容器 | |||
problemOverlay: null, | |||
// 机场细节信息 | |||
airDetail: {}, | |||
// 问题细节信息 | |||
problemDetail: {}, | |||
listShow: false, | |||
// 时间范围是一周前至今天 | |||
efg: '', | |||
listIcon: new URL('../../../assets/images/listChecked.png', import.meta.url).href, | |||
airportIcon: new URL('../../../assets/images/airportChecked.png', import.meta.url).href, | |||
listFontStyle: { | |||
'color': '#666666' | |||
}, | |||
airportFontStyle: { | |||
'color': '#1890FF' | |||
}, | |||
problemPopupShow: false, | |||
tabIndex: 1, | |||
page: ref(1), | |||
pageCount: 0, | |||
taskList: [], | |||
range: (['2012-09-10', '2022-09-10']), | |||
problemTypeSelected: null, | |||
problemTypeList: [], | |||
listChecked: false, | |||
airportSelected: false, | |||
problemLayerList: [] | |||
}) | |||
watch(() => data.page, (newValue, oldValue) => { | |||
if (newValue !== oldValue) { | |||
initTaskList() | |||
} | |||
}) | |||
const getMapOptions = computed(() => { | |||
return { | |||
id: props.id | |||
} | |||
}) | |||
const initMap = () => { | |||
// 天地图影像图 | |||
const tdtImgMap = | |||
new Tile({ | |||
visible: true, | |||
source: new XYZ({ | |||
url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=f634525a82da65f715d168d7ba1899c0' | |||
}) | |||
}) | |||
var wmsSource = new Tile({ | |||
source: new TileWMS({ | |||
url: 'https://geoserver.t-aaron.com:4080/geoserver/jiangning/wms', | |||
params: { 'LAYERS': 'jiangning:town' } | |||
}) | |||
}) | |||
data.map = new Map({ | |||
// 地图容器 | |||
target: props.id, | |||
view: new View({ | |||
center: transform([118.773136, 31.828065], 'EPSG:4326', 'EPSG:3857'), | |||
zoom: 11, | |||
maxZoom: 17 | |||
}), | |||
layers: [ | |||
tdtImgMap | |||
], | |||
controls: control.defaults({ | |||
attribution: false, | |||
rotate: false, | |||
zoom: false | |||
}) | |||
}) | |||
data.map.addLayer(wmsSource) | |||
wmsSource.setOpacity(0.3) | |||
} | |||
/** | |||
* @description: 获取机场数据 | |||
* @param {*} res | |||
* @return {*} | |||
*/ | |||
const loadAirport = (async function() { | |||
const res = await airportList({ page: 1, limit: 100 }) | |||
if (res.code === 0) { | |||
data.airportsAll = res.data | |||
showAirport() | |||
} | |||
})() | |||
/** | |||
* @description:分页器改变时改变任务列表信息 | |||
*/ | |||
const changePage = (v) => { | |||
} | |||
/** | |||
* 展示机场 | |||
*/ | |||
const showAirport = () => { | |||
if (data.airportsAll.length > 0) { | |||
for (let i = 0; i < data.airportsAll.length; i++) { | |||
const airport = data.airportsAll[i] | |||
const lngLat = gcj02towgs84(parseFloat(airport.longitude), parseFloat(airport.latitude)) | |||
const feature = new Feature({ | |||
geometry: new Point(fromLonLat(lngLat)) | |||
}) | |||
// 要素设置样式 | |||
feature.setStyle( | |||
new Style({ | |||
image: new Icon({ | |||
src: uav_icon | |||
}), | |||
text: new Text({ | |||
// 文字内容 | |||
text: airport.name, | |||
// 位置 | |||
textAlign: 'center', | |||
// 基准线 | |||
textBaseline: 'top', | |||
offsetY: 30, | |||
// 文字样式 | |||
font: 'normal 20px Microsoft YaHei', | |||
backgroundFill: new Fill({ | |||
color: '#1890FF' | |||
}), | |||
padding: [3, 6, 3, 6], | |||
// 文字颜色 | |||
fill: new Fill({ | |||
color: '#fff' | |||
}) | |||
}) | |||
}) | |||
) | |||
// 要素设置id | |||
feature.setId(airport.id) | |||
// 要素设置属性 | |||
feature.setProperties({ | |||
id: airport.id, | |||
code: airport.code, | |||
name: airport.name, | |||
// 设置类别 | |||
type: 'airport', | |||
coordinate: fromLonLat(lngLat), | |||
// 机场外部监控地址 | |||
externalMonitorUrl: airport.externalMonitorUrl, | |||
// 机场内部监控地址 | |||
internalMonitorUrl: airport.internalMonitorUrl | |||
}) | |||
data.airFeatures.push(feature) | |||
} | |||
} | |||
data.airLayer = new VectorLayer({ | |||
source: new VectorSource({ | |||
features: data.airFeatures | |||
}), | |||
visible: data.airShow | |||
}) | |||
data.map.addLayer(data.airLayer) | |||
// 机场信息覆盖物 | |||
data.airOverlay = new Overlay({ | |||
id: 'air_overlay', | |||
element: document.getElementById('airOverlay'), | |||
autoPan: true, | |||
offset: [10, 10] | |||
}) | |||
// 点击事件 | |||
data.map.on('click', (evt) => { | |||
showAirInfo(evt) | |||
}) | |||
// console.log(new Date().getFullYear()) | |||
} | |||
/** | |||
* 展示机场信息 | |||
* @param {} e | |||
*/ | |||
const showAirInfo = (e) => { | |||
// 防止冒泡 | |||
e.stopPropagation() | |||
// 点击位置的经纬度 | |||
var feature = data.map.forEachFeatureAtPixel(e.pixel, (feature) => { | |||
return feature | |||
}) | |||
if (feature) { | |||
// 要素类别为机场 | |||
if (feature.getProperties().type === 'airport') { | |||
data.airDetail = feature.getProperties() | |||
// 为了overlay位置更加精确 | |||
const coord = feature.getProperties().coordinate | |||
data.airOverlay.setPosition(coord) | |||
data.map.addOverlay(data.airOverlay) | |||
} | |||
if (feature.getProperties().typeName) { | |||
data.problemDetail = feature.getProperties() | |||
// console.log(data.problemDetail, '详情') | |||
const coord = feature.getProperties().coordinate | |||
data.problemOverlay.setPosition(coord) | |||
data.problemPopupShow = true | |||
data.map.addOverlay(data.problemOverlay) | |||
// data.problemOverlay.setPosition(coord) | |||
// data.map.addOverlay(data.problemOverlay) | |||
} | |||
} | |||
} | |||
/** | |||
* 关闭展示机场信息 | |||
*/ | |||
const hideAirInfo = () => { | |||
if (data.map.getOverlayById('air_overlay')) { | |||
data.airDetail = {} | |||
data.map.removeOverlay(data.airOverlay) | |||
} | |||
} | |||
/** | |||
* 关闭显示问题图层信息 | |||
*/ | |||
const hideProblemInfo = () => { | |||
if (data.map.getOverlayById('problem_overlay')) { | |||
data.problemDetail = {} | |||
data.problemPopupShow = false | |||
data.map.removeOverlay(data.problemOverlay) | |||
} | |||
} | |||
/** | |||
* 显示问题信息 | |||
*/ | |||
const showProblem = () => { | |||
data.tabIndex = 0 | |||
} | |||
/** | |||
* 显示任务列表信息 | |||
*/ | |||
const showTask = () => { | |||
data.tabIndex = 1 | |||
} | |||
/** | |||
* 机场图层控制显隐 | |||
* @param { } value | |||
*/ | |||
const airShowHide = (isShow) => { | |||
data.airLayer.setVisible(isShow) | |||
if (!isShow) { | |||
hideAirInfo() | |||
} | |||
} | |||
/** | |||
* @description:执行任务 | |||
*/ | |||
const performTask = (item) => { | |||
// console.log(router, '路径') | |||
router.push({ path: '/taskManage/all', query: { rowInfo: JSON.stringify(item) }}) | |||
} | |||
const abc = (value) => { | |||
getQuestionList({ | |||
startTime: value[0], | |||
endTime: value[1] | |||
}).then(res => { | |||
if (res.code === 0) { | |||
const arr = res.data | |||
var resArr = [] | |||
var narr = [] | |||
for (var i = 0; i < arr.length; i++) { | |||
var n = resArr.indexOf(arr[i].typeName) | |||
if (n == -1) { | |||
resArr.push(arr[i].typeName) | |||
narr.push({ 'name': arr[i].typeName, fraction: [arr[i]] }) | |||
} else { | |||
narr[n].fraction.push(arr[i]) | |||
} | |||
} | |||
// 添加问题图层 | |||
addproblemLayer(narr) | |||
} | |||
}) | |||
} | |||
// 添加问题图层 | |||
const addproblemLayer = (narr) => { | |||
data.problemOverlay = new Overlay({ | |||
id: 'problem_overlay', | |||
element: document.getElementById('problemOverlay'), | |||
autoPan: true, | |||
offset: [10, 10] | |||
}) | |||
narr.map((item) => { | |||
const Features = [] | |||
if (item.fraction.length > 0) { | |||
item.fraction.map((iitem) => { | |||
const problem = iitem | |||
const lngLat = gcj02towgs84(parseFloat(problem.lng), parseFloat(problem.lat)) | |||
const feature = new Feature({ | |||
geometry: new Point(fromLonLat(lngLat)) | |||
}) | |||
let icon | |||
switch (iitem.typeName) { | |||
case '林场问题图斑': | |||
icon = problemSpot_icon | |||
break | |||
case '病死树': | |||
icon = deadTree_icon | |||
break | |||
case '人员活动': | |||
icon = personnel_icon | |||
break | |||
case '火灾隐患': | |||
icon = fireHazard_icon | |||
} | |||
// 要素设置样式 | |||
feature.setStyle( | |||
new Style({ | |||
image: new Icon({ | |||
src: icon | |||
}) | |||
}) | |||
) | |||
// 要素设置id | |||
feature.setId(problem.questionId) | |||
// 要素设置属性 | |||
problem.coordinate = fromLonLat(lngLat) | |||
feature.setProperties(problem) | |||
Features.push(feature) | |||
}) | |||
// 添加图层 | |||
const layer = new VectorLayer({ | |||
source: new VectorSource({ | |||
features: Features | |||
}), | |||
visible: false | |||
}) | |||
const obj = { type: item.name, layer: layer } | |||
data.problemLayerList.push(obj) | |||
data.map.addLayer(layer) | |||
} | |||
}) | |||
} | |||
/** | |||
* 初始化任务列表信息 | |||
* | |||
*/ | |||
const initTaskList = () => { | |||
getMissionList({ | |||
page: data.page, | |||
limit: 12 | |||
}).then(res => { | |||
if (res.code === 0) { | |||
data.taskList = res.data.records | |||
data.taskList.map((item) => { | |||
const arr = item.executionStartTime.split(/[ ]+/)// 以空格分开 | |||
item.taskName = arr[0] + item.name | |||
switch (item.status) { | |||
case 1: | |||
item.statusInfo = '待执行' | |||
break | |||
case 2: | |||
item.statusInfo = '执行中' | |||
break | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
/** | |||
* 获取问题多选类型 | |||
*/ | |||
const initProblemType = () => { | |||
getQuestionType().then(res => { | |||
if (res.code === 0) { | |||
data.problemTypeList = res.data | |||
} | |||
}) | |||
} | |||
/** | |||
* @description:是否展示列表 | |||
*/ | |||
const showList = () => { | |||
data.listChecked = !data.listChecked | |||
} | |||
/** | |||
* | |||
*/ | |||
const handleProblemTypeValue = (value) => { | |||
data.problemLayerList.map((item) => { | |||
const a = value.indexOf(item.type) | |||
if (a == -1) { | |||
item.layer.setVisible(false) | |||
} else { | |||
item.layer.setVisible(true) | |||
} | |||
}) | |||
} | |||
/** | |||
* @description:是否显示机场 | |||
*/ | |||
const showAirportList = () => { | |||
data.airportSelected = !data.airportSelected | |||
data.airLayer.setVisible(data.airportSelected) | |||
if (!data.airportSelected) { | |||
hideAirInfo() | |||
} | |||
} | |||
/** | |||
* 展示直播视频 | |||
*/ | |||
const liveShow = (rowInfo) => { | |||
router.push({ path: '/taskManage/all', query: { rowInfo: JSON.stringify(rowInfo) }}) | |||
} | |||
onMounted(() => { | |||
initMap() | |||
initTaskList() | |||
initProblemType() | |||
}) | |||
return { | |||
...toRefs(data), | |||
getMapOptions, | |||
loadAirport, | |||
showProblem, | |||
showTask, | |||
airShowHide, | |||
hideAirInfo, | |||
changePage, | |||
showList, | |||
disablePreviousDate(ts, type, range) { | |||
const d = 864e5 | |||
// return ts > Date.now() | |||
if (type === 'start' && range !== null) { | |||
return startOfDay(range[1]).valueOf() - startOfDay(ts).valueOf() >= d * 8 | |||
} | |||
if (type === 'end' && range !== null) { | |||
return startOfDay(ts).valueOf() - startOfDay(range[0]).valueOf() >= d * 8 | |||
} | |||
return ts > Date.now() | |||
}, | |||
abc, | |||
showAirportList, | |||
handleProblemTypeValue, | |||
hideProblemInfo, | |||
performTask, | |||
handleConfirm() { | |||
dialog.warning({ | |||
title: '警告', | |||
content: '你确定?', | |||
positiveText: '确定', | |||
negativeText: '不确定', | |||
onPositiveClick: () => { | |||
message.success('确定') | |||
}, | |||
onNegativeClick: () => { | |||
message.error('不确定') | |||
} | |||
}) | |||
}, | |||
handlePositiveClick(row) { | |||
$message.info('机场设备开始自检,请稍等') | |||
implement(row.id) | |||
.then(res => { | |||
if (res.code === 0) { | |||
$message.info('操作成功') | |||
} | |||
}) | |||
}, | |||
handleNegativeClick() { | |||
}, | |||
liveShow | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.map-container { | |||
width: 100vw; | |||
height: 100vh; | |||
} | |||
.layer-management { | |||
height: calc(100vh - 84%); | |||
position: absolute; | |||
width: 100px; | |||
/* margin-right: 10px; */ | |||
left: 100px; | |||
top: 100px; | |||
background-color: rgba(0, 0, 0, 0.6); | |||
} | |||
.layer-management p { | |||
color: #fff; | |||
} | |||
.airport-overlay { | |||
width: 530px; | |||
height: 430px; | |||
background-color: rgba(0, 0, 0, 0.5); | |||
} | |||
.problem-overlay { | |||
width: 530px; | |||
background-color: rgba(0, 0, 0, 0.5); | |||
} | |||
.close-overlay { | |||
width: 28px; | |||
height: 28px; | |||
position: relative; | |||
color: #fff; | |||
font-size: 20px; | |||
cursor: pointer; | |||
float: right; | |||
text-align: center; | |||
line-height: 28px; | |||
} | |||
/* 任务-问题面板 */ | |||
.task-question { | |||
width: 500px; | |||
height: 800px; | |||
position: absolute; | |||
top: 100px; | |||
right: 140px; | |||
} | |||
.menu { | |||
position: absolute; | |||
top: 64px; | |||
right: 90px; | |||
width: 355px; | |||
height: 428px; | |||
background: #000000; | |||
box-sizing: border-box; | |||
padding: 5px; | |||
.tabBar { | |||
height: 35px; | |||
width: 100%; | |||
font-size: 15px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
display: flex; | |||
justify-content: center; | |||
.checkedColor { | |||
color: #1890ff; | |||
} | |||
.uncheckedColor { | |||
color: #ffffff; | |||
} | |||
} | |||
.listDetail { | |||
width: 345px; | |||
height: 383px; | |||
background: #2c2c2c; | |||
font-size: 14px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
color: #ffffff; | |||
position: relative; | |||
box-sizing: border-box; | |||
padding: 10px 19px; | |||
ul { | |||
li { | |||
display: flex; | |||
justify-content: space-between; | |||
padding: 8px 2px; | |||
margin-bottom: 15px; | |||
} | |||
} | |||
} | |||
} | |||
// 列表机场控制显隐菜单 | |||
.menuControl { | |||
position: absolute; | |||
top: 200px; | |||
right: 40px; | |||
background: #ffffff; | |||
box-shadow: 2px 2px 2px 1px rgba(31, 31, 31, 0.38); | |||
border-radius: 2px; | |||
width: 40px; | |||
.item { | |||
width: 100%; | |||
height: 60px; | |||
font-size: 14px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: center; | |||
align-items: center; | |||
} | |||
} | |||
:deep(.n-pagination-item) { | |||
color: #ffffff !important; | |||
} | |||
:deep(.n-checkbox__label) { | |||
color: #ffffff !important; | |||
} | |||
:deep(.n-pagination | |||
.n-pagination-item.n-pagination-item--disabled.n-pagination-item--button) { | |||
background-color: rgba(0, 0, 0, 0) !important; | |||
} | |||
</style> |
@@ -0,0 +1,138 @@ | |||
<template> | |||
<div class="content"> | |||
<table> | |||
<tr> | |||
<th class="title">问题类型:</th> | |||
<td>{{ detail.typeName }}</td> | |||
</tr> | |||
<tr> | |||
<th class="title">任务名称:</th> | |||
<td>{{ detail.missionName }}</td> | |||
</tr> | |||
<tr> | |||
<th class="title">巡检时间:</th> | |||
<td>{{ detail.inspectionTime }}</td> | |||
</tr> | |||
<tr> | |||
<th class="title">问题图片:</th> | |||
<td> | |||
<img | |||
v-for="(item,index) in fileImageList" | |||
:key="index" | |||
:src="item.src" | |||
> | |||
</td> | |||
</tr> | |||
<tr v-show="detail.handlerResult"> | |||
<th class="title">处理后描述:</th> | |||
<td>{{ detail.handlerResult }}</td> | |||
</tr> | |||
<tr v-show="detail.handlerImage"> | |||
<th class="title">处理后图片:</th> | |||
<td> | |||
<img | |||
v-for="(item,index) in handlerImageList" | |||
:key="index" | |||
:src="item.src" | |||
> | |||
</td> | |||
</tr> | |||
<tr> | |||
<th class="title">处理人:</th> | |||
<td>{{ detail.handlerUserName }}</td> | |||
</tr> | |||
<tr v-show="detail.handlerTime"> | |||
<th class="title">处理时间:</th> | |||
<td>{{ detail.handlerTime }}</td> | |||
</tr> | |||
</table> | |||
</div> | |||
</template> | |||
<script> | |||
import { reactive, toRefs, watch, onMounted } from 'vue' | |||
export default { | |||
props: { | |||
detail: { | |||
type: Object, | |||
default: () => { } | |||
} | |||
}, | |||
setup(props) { | |||
const data = reactive({ | |||
detail: props.detail, | |||
fileImageList: [], | |||
handlerImageList: [] | |||
}) | |||
watch(() => props.detail, (value) => { | |||
if (value) { | |||
// console.log(value) | |||
// console.log(props.detail) | |||
const fileImageList = value.fileMarkerUrl.split(',') | |||
data.fileImageList = [] | |||
fileImageList.map((item) => { | |||
const obj = {} | |||
obj.src = new URL(item, import.meta.url).href | |||
data.fileImageList.push(obj) | |||
}) | |||
data.handlerImageList = [] | |||
if (value.handlerImage) { | |||
const handlerImageStr = value.handlerImage.split(',') | |||
handlerImageStr.map((item) => { | |||
const obj = {} | |||
obj.src = new URL(item, import.meta.url).href | |||
data.handlerImageList.push(obj) | |||
}) | |||
// console.log(data.handlerImageList, '444') | |||
} | |||
} | |||
}) | |||
return { | |||
...toRefs(data) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang='scss' scoped> | |||
.content { | |||
box-sizing: border-box; | |||
padding: 25px 5px; | |||
} | |||
table { | |||
width: 100%; | |||
height: 90px; | |||
font-size: 15px; | |||
font-family: Noto Sans SC-Regular, Noto Sans SC; | |||
font-weight: 400; | |||
border-collapse: collapse; | |||
background: #2c2c2c; | |||
img { | |||
width: 56px; | |||
height: 56px; | |||
margin: 5px 0; | |||
} | |||
.title { | |||
color: #8b8b8b; | |||
} | |||
td { | |||
box-sizing: border-box; | |||
padding-left: 11px; | |||
display: flex; | |||
align-items: center; | |||
} | |||
// td { | |||
// padding: 5px 11px; | |||
// display: flex; | |||
// } | |||
} | |||
table, | |||
td, | |||
th { | |||
border: 1px solid #707070; | |||
color: white; | |||
font-weight: 400; | |||
} | |||
</style> |
@@ -0,0 +1,56 @@ | |||
<template> | |||
<div class="dashboard__main"> | |||
<div class="dashboard__top"> | |||
<TaskCard /> | |||
<VideoCard /> | |||
</div> | |||
<div class="dishboard__bottom"> | |||
<AirCard /> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { useRouter } from 'vue-router' | |||
import TaskCard from './components/TaskCard.vue' | |||
import VideoCard from './components/VideoCard.vue' | |||
import AirCard from './components/AirCard.vue' | |||
export default { | |||
name: 'HomePage', | |||
components: { TaskCard, VideoCard, AirCard }, | |||
setup(props) { | |||
const router = useRouter() | |||
function toSystem() { | |||
router.push({ path: '/login' }) | |||
} | |||
return { | |||
toSystem | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.dashboard__main{ | |||
height: calc(100vh - 80px); | |||
.dashboard__top{ | |||
display: flex; | |||
height: 50%; | |||
.n-card{ | |||
overflow: hidden; | |||
&:first-child{ | |||
width: 50%; | |||
margin-right: 20px; | |||
} | |||
} | |||
} | |||
.dishboard__bottom{ | |||
display: flex; | |||
height: calc(50% - 20px); | |||
margin-top: 20px; | |||
} | |||
.n-card{ | |||
border-radius: 10px; | |||
} | |||
} | |||
</style> | |||
@@ -1,23 +1,15 @@ | |||
<template> | |||
<div class="dashboard__main"> | |||
<div class="dashboard__top"> | |||
<TaskCard /> | |||
<VideoCard /> | |||
</div> | |||
<div class="dishboard__bottom"> | |||
<AirCard /> | |||
</div> | |||
<div> | |||
<OneMap /> | |||
</div> | |||
</template> | |||
<script> | |||
import { useRouter } from 'vue-router' | |||
import TaskCard from './components/TaskCard.vue' | |||
import VideoCard from './components/VideoCard.vue' | |||
import AirCard from './components/AirCard.vue' | |||
import OneMap from './components/OneMap.vue' | |||
export default { | |||
name: 'HomePage', | |||
components: { TaskCard, VideoCard, AirCard }, | |||
components: { OneMap }, | |||
setup(props) { | |||
const router = useRouter() | |||
function toSystem() { |
@@ -54,6 +54,7 @@ export default { | |||
status: 1, | |||
...res | |||
} | |||
console.log(_params) | |||
return await getQuestionList(_params) | |||
} | |||
@@ -1,7 +1,13 @@ | |||
<template> | |||
<div> | |||
<n-card> | |||
<HeadSearch ref="searchRef" :info="search" @search="handleSearch" @reset="handleSearch" @change="handleChange" /> | |||
<HeadSearch | |||
ref="searchRef" | |||
:info="search" | |||
@search="handleSearch" | |||
@reset="handleSearch" | |||
@change="handleChange" | |||
/> | |||
<DataTable | |||
ref="tableRef" | |||
:columns="columns" | |||
@@ -10,7 +16,10 @@ | |||
size="large" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary" @click="handleModal"> 新建 </n-button> | |||
<n-button | |||
type="primary" | |||
@click="handleModal" | |||
> 新建 </n-button> | |||
<!-- <n-popconfirm | |||
negative-text="取消" | |||
positive-text="确认" | |||
@@ -27,13 +36,28 @@ | |||
</div> | |||
<!-- 新增、编辑弹窗 --> | |||
<TaskModal v-if="modalShow" v-model:visible="modalShow" :type="modalType" :data="rowData" @reload="handleSearch" /> | |||
<TaskModal | |||
v-if="modalShow" | |||
v-model:visible="modalShow" | |||
:type="modalType" | |||
:data="rowData" | |||
@reload="handleSearch" | |||
/> | |||
<!-- 直播抽屉 --> | |||
<LiveDrawer v-model:visible="liveDrawer" :data="rowData" /> | |||
<LiveDrawer | |||
v-model:visible="liveDrawer" | |||
:data="rowData" | |||
/> | |||
<!-- 轨迹回放 --> | |||
<DemandDrawer v-model:visible="demandDrawer" :data="rowData" /> | |||
<DemandDrawer | |||
v-model:visible="demandDrawer" | |||
:data="rowData" | |||
/> | |||
<!-- 问题核实 --> | |||
<VerifyDrawer v-model:visible="verifyDrawer" :data="rowData" /> | |||
<VerifyDrawer | |||
v-model:visible="verifyDrawer" | |||
:data="rowData" | |||
/> | |||
</template> | |||
@@ -46,13 +70,15 @@ import TaskModal from './components/TaskModal.vue' | |||
import LiveDrawer from './components/LiveDrawer.vue' | |||
import DemandDrawer from './components/DemandDrawer.vue' | |||
import VerifyDrawer from './components/VerifyDrawer.vue' | |||
import { reactive, ref, unref, toRefs, onUnmounted } from 'vue' | |||
import { reactive, ref, unref, toRefs, onUnmounted, onMounted } from 'vue' | |||
import { getTaskList } from '@/api/task/index.js' | |||
import { useRoute } from 'vue-router' | |||
export default { | |||
name: 'TaskAll', | |||
components: { HeadSearch, DataTable, TaskModal, LiveDrawer, DemandDrawer, VerifyDrawer }, | |||
setup() { | |||
const route = useRoute() | |||
const rowInfo = route.query.rowInfo | |||
getAirOptions() | |||
const searchRef = ref() | |||
const data = reactive({ | |||
@@ -93,7 +119,12 @@ export default { | |||
searchRef.value.setFormValue({ inspectionLine: null }) | |||
} | |||
} | |||
onMounted(() => { | |||
if (rowInfo) { | |||
data.rowData = rowInfo | |||
data.liveDrawer = true | |||
} | |||
}) | |||
onUnmounted(() => { | |||
data.searchParams = null | |||
}) |
@@ -8,7 +8,7 @@ import { taskDelete, implement } from '@/api/task/index.js' | |||
const tableRef = ref() | |||
const searchParams = ref() | |||
function handleSearch(params) { | |||
function handleSearch (params) { | |||
searchParams.value = { ...params } | |||
tableRef.value.reFetch({ searchParams }) | |||
} | |||
@@ -19,13 +19,13 @@ function handleSearch(params) { | |||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑 | |||
* @return {*} | |||
*/ | |||
function getRowData(row, type) { | |||
function getRowData (row, type) { | |||
data.rowData = row | |||
data.modalType = type | |||
data.modalShow = true | |||
} | |||
function handleRowDelete(row) { | |||
function handleRowDelete (row) { | |||
taskDelete(row.id) | |||
.then(res => { | |||
if (res.code === 0) { | |||
@@ -34,8 +34,9 @@ function handleRowDelete(row) { | |||
}) | |||
} | |||
function handleImplement(row) { | |||
function handleImplement (row) { | |||
$message.info('机场设备开始自检,请稍等') | |||
implement(row.id) | |||
.then(res => { | |||
if (res.code === 0) { | |||
@@ -45,19 +46,19 @@ function handleImplement(row) { | |||
} | |||
/* 直播 */ | |||
function handleTaskLive(row) { | |||
function handleTaskLive (row) { | |||
data.rowData = row | |||
data.liveDrawer = true | |||
} | |||
/* 回放 */ | |||
function handleTaskDemand(row) { | |||
function handleTaskDemand (row) { | |||
data.rowData = row | |||
data.demandDrawer = true | |||
} | |||
/* 问题核实 */ | |||
function handleTaskVerify(row) { | |||
function handleTaskVerify (row) { | |||
data.rowData = row | |||
data.verifyDrawer = true | |||
} | |||
@@ -96,7 +97,7 @@ const data = reactive({ | |||
title: '巡检方式', | |||
key: 'inspectionType', | |||
align: 'center', | |||
render(row) { | |||
render (row) { | |||
return h(TableTags, { | |||
data: row.inspectionType, | |||
filters: TASK_MODE | |||
@@ -117,7 +118,7 @@ const data = reactive({ | |||
title: '任务类型', | |||
key: 'type', | |||
align: 'center', | |||
render(row) { | |||
render (row) { | |||
return h(TableTags, { | |||
data: row.type, | |||
filters: TASK_TYPE | |||
@@ -133,7 +134,7 @@ const data = reactive({ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
render(row) { | |||
render (row) { | |||
return h(TableTags, { | |||
data: row.status, | |||
filters: TASK_STATUS | |||
@@ -146,7 +147,7 @@ const data = reactive({ | |||
align: 'center', | |||
width: 150, | |||
fixed: 'right', | |||
render(row) { | |||
render (row) { | |||
return h(TableAction, { | |||
actions: [ | |||
{ |