| | |
| | | <template> |
| | | <div class="right"> |
| | | <div>工单列表</div> |
| | | <div class="event-overviewdetail-right" :class="{ isMore }"> |
| | | <CommonTitle title="事件概况" :style="{width: isMore?pxToRem(820):pxToRem(404)}" /> |
| | | |
| | | <div> |
| | | <div class="content"> |
| | | <img class="leftArrow" :class="isMore?'rightArrow':''" :src="isMore ? rightArrowImg : leftArrowImg" @click="leftArrowFun" alt="" /> |
| | | |
| | | <el-date-picker |
| | | class="ztzf-date-picker" |
| | | v-model="timeArr" |
| | | type="daterange" |
| | | value-format="YYYY-MM-DD" |
| | | :value-format="timeFormat" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | @change="change" |
| | | disabled |
| | | @change="timeChange" |
| | | /> |
| | | <el-select v-model="params.device_sn" placeholder="请选择" size="large" filterable clearable> |
| | | <el-option |
| | | v-for="item in deviceList" |
| | | :label="item.nickname" |
| | | :value="item.device_sn" |
| | | :key="item.device_sn" |
| | | /> |
| | | |
| | | <el-select |
| | | class="ztzf-select" |
| | | :style="{ width: pxToRem(174) }" |
| | | v-model="params.device_sn" |
| | | placeholder="机巢" |
| | | filterable |
| | | clearable |
| | | @change="getList" |
| | | > |
| | | <el-option v-for="item in deviceList" :label="item.nickname" :value="item.device_sn" :key="item.device_sn" /> |
| | | </el-select> |
| | | |
| | | <el-select |
| | | class="ztzf-select" |
| | | :style="{ width: pxToRem(174) }" |
| | | v-model="params.word_order_type" |
| | | placeholder="请选择" |
| | | size="large" |
| | | placeholder="工单类型" |
| | | filterable |
| | | clearable |
| | | @change="getList" |
| | | > |
| | | <el-option |
| | | v-for="item in workOrderType" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | :key="item.dictKey" |
| | | /> |
| | | <el-option v-for="item in workOrderType" :label="item.dictValue" :value="item.dictKey" :key="item.dictKey" /> |
| | | </el-select> |
| | | <div> |
| | | <div v-for="item in statusList"> |
| | | <div>{{ item.name }}</div> |
| | | <div>{{ item.num || 0 }}</div> |
| | | |
| | | <div class="statusList"> |
| | | <div |
| | | class="statusItem" |
| | | v-for="item in isMore ? statusList : statusList.filter(i => i.few)" |
| | | @click="statusClick(item)" |
| | | :class="{ active: item.active }" |
| | | > |
| | | <img class="statusItemImg" :src="item.img" alt="" /> |
| | | <div class="statusItemInfo"> |
| | | <div class="statusItemName">{{ item.name }}</div> |
| | | <div class="statusItemNum" :style="{ color:item.color }">{{ item.num || 0 }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-checkbox-group v-model="params.SFType"> |
| | | <el-checkbox v-for="item in SFDictList" :label="item.dictValue":value="item.dictKey" :key="item.dictKey"/> |
| | | <el-checkbox-group v-show="isMore" v-model="params.event_keys" @change="getList"> |
| | | <el-checkbox v-for="item in eventList" :value="item.status" :key="item.dictKey"> |
| | | <template #default> |
| | | <span class="eventListItemCheckboxName">{{ item.name }}</span> |
| | | <span class="eventListItemCheckboxNum">({{ item.value }})</span> |
| | | </template> |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | |
| | | <div class="eventList"> |
| | | <div class="eventListItem" v-for="item in list"> |
| | | <img |
| | | class="eventListItemImg" |
| | | :src="getSmallImg(item.photo_url)" |
| | | alt="" |
| | | @click="getFindImgHistory(item)" |
| | | /> |
| | | <div class="eventListItemPosition" :title="item.address" @click="positioning(item)"> |
| | | <img :src="positioningImg" alt="" title="点击定位" /> |
| | | <!-- <div class="address">{{ item.address }}</div> --> |
| | | </div> |
| | | <div class="eventListItemText"> |
| | | <div class="eventListItemName">{{ item.event_name }}</div> |
| | | <div class="eventListItemTime">{{ dayjs(item.create_time).format('MM/DD HH:mm') }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="pagination"> |
| | | <el-pagination |
| | | class="ztzf-pagination" |
| | | background |
| | | v-model:current-page="params.current" |
| | | v-model:page-size="params.size" |
| | | layout="total, prev, pager, next" |
| | | :total="total" |
| | | @change="pageChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="image-list" v-if="isShowBigImg" :style="{ right: isMore?pxToRem(840):pxToRem(460) }"> |
| | | <div class="title"> |
| | | <img @click="isShowBigImg=false" src="@/assets/images/home/useEventOperate/close.png" alt=""> |
| | | </div> |
| | | <div class="content"> |
| | | <img :src="clickImgSrc" alt=""> |
| | | </div> |
| | | <div class="card"> |
| | | <div v-for="(item,index) in imageList"> |
| | | <div class="time-top" :class="index===selectedImgIndex?'active':''" @click="clickWeekTime(item,index)">{{ item.create_time_str }}</div> |
| | | <div class="time-point"> |
| | | <img v-if="index===selectedImgIndex" src="@/assets/images/home/useEventOperate/point-active.png" alt=""> |
| | | <img v-else src="@/assets/images/home/useEventOperate/point.png" alt=""> |
| | | </div> |
| | | <div class="time-bottom">{{ item.create_time }}</div> |
| | | </div> |
| | | <div class="time-line"></div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | | import status0Img from '@/assets/images/home/eventOverviewDetail/status0.png' |
| | | import status1Img from '@/assets/images/home/eventOverviewDetail/status1.png' |
| | | import status2Img from '@/assets/images/home/eventOverviewDetail/status2.png' |
| | | import status3Img from '@/assets/images/home/eventOverviewDetail/status3.png' |
| | | import status4Img from '@/assets/images/home/eventOverviewDetail/status4.png' |
| | | import status5Img from '@/assets/images/home/eventOverviewDetail/status5.png' |
| | | import positioningImg from '@/assets/images/home/eventOverviewDetail/positioning.png' |
| | | import leftArrowImg from '@/assets/images/home/eventOverviewDetail/leftArrow.png' |
| | | import rightArrowImg from '@/assets/images/home/eventOverviewDetail/rightArrow.png' |
| | | |
| | | import dayjs from 'dayjs' |
| | | import { selectDevicePage } from '@/api/home/machineNest' |
| | | import { getMultipleDictionary } from '@/api/system/dictbiz' |
| | | import { getEventStatusNum } from '@/api/home/event' |
| | | import { getEvenNum, getEventPage, getEventStatusNum, findImgHistory } from '@/api/home/event' |
| | | import cesiumOperation from '@/utils/cesium-tsa' |
| | | import CommonTitle from '@/components/CommonTitle.vue' |
| | | import { pxToRem } from '@/utils/rem' |
| | | import { useStore } from 'vuex' |
| | | |
| | | const store = useStore() |
| | | // const eventTimeRange = computed(() => store.state.home.eventTimeRange) |
| | | const timeFormat = 'YYYY-MM-DD HH:mm:ss' |
| | | const today = dayjs().format(timeFormat) |
| | | const oneWeekAgo = dayjs().subtract(7, 'day').format(timeFormat) |
| | | const timeArr = ref([oneWeekAgo, today]) |
| | | // const oneWeekAgo = dayjs().subtract(7, 'day').format(timeFormat) |
| | | // const timeArr = ref([oneWeekAgo, today]) |
| | | const startOfWeek = dayjs().startOf('week').add(1, 'day').format(timeFormat) |
| | | const endOfWeek = dayjs().endOf('week').add(1, 'day').format(timeFormat) |
| | | const timeArr = ref([startOfWeek, endOfWeek]) |
| | | const deviceList = ref([]) |
| | | |
| | | const total = ref(0) |
| | | const params = ref({ |
| | | device_sn: '', |
| | | word_order_type: '', |
| | | SFType:[] |
| | | start_date: timeArr.value[0], |
| | | end_date: timeArr.value[1], |
| | | device_sn: undefined, |
| | | word_order_type: undefined, |
| | | status: undefined, |
| | | event_keys: [], |
| | | current: 1, |
| | | size: 8, |
| | | }) |
| | | |
| | | const getSmallImg = (url) => { |
| | | return url ? url.substring(0, url.lastIndexOf('.')) + '_small' + url.substring(url.lastIndexOf('.')) : '' |
| | | } |
| | | |
| | | const isMore = ref(false) |
| | | const leftArrowFun = () => { |
| | | isMore.value = !isMore.value |
| | | params.value.size = isMore.value ? 16 : 8 |
| | | params.value.current = 1 |
| | | // 下半部分隐藏 右侧隐藏 |
| | | store.commit('setHideBottomIcon', !isMore.value) |
| | | getList() |
| | | } |
| | | |
| | | const statusClick = row => { |
| | | params.value.status = row.id || undefined |
| | | statusList.value = statusList.value.map(item => ({ |
| | | ...item, |
| | | active: item.name === row.name, |
| | | })) |
| | | getList() |
| | | } |
| | | |
| | | const getDeviceList = async () => { |
| | | const res = await selectDevicePage({ current: 1, size: 99999, type: 1 }) |
| | | deviceList.value = res.data?.data?.records || [] |
| | | } |
| | | |
| | | // 工单类型 |
| | | const workOrderType = ref([]) |
| | | const SFDictList = ref([]) |
| | | const getDictList = () => { |
| | | getMultipleDictionary('WORK_ORDER_TYPE,SF').then(res => { |
| | | workOrderType.value = res.data.data?.['WORK_ORDER_TYPE'] || [] |
| | | SFDictList.value = res.data.data?.['SF'] || [] |
| | | }) |
| | | } |
| | | const { flyTo } = cesiumOperation() |
| | | const longitudeOffset = ref(0); |
| | | const positioning = row => { |
| | | const longitude = Number(row.longitude) |
| | | const latitude = Number(row.latitude) |
| | | flyTo({ longitude: longitude, latitude:latitude + 0.0002 }, 1, 1000); |
| | | } |
| | | |
| | | const statusList = ref([]) |
| | | // 事件状态+数量 |
| | | const statusList = ref([ |
| | | { name: '全部状态', img: status0Img, id: undefined,few: true, color: '#FFD509' }, |
| | | { name: '待审核', img: status1Img, id: 2, color: '#8CFEA7' }, |
| | | { name: '待处理', img: status2Img, id: 0, few: true, color: '#FF7411' }, |
| | | { name: '处理中', img: status3Img, id: 3, few: true, color: '#FFC398' }, |
| | | { name: '已完成', img: status4Img, id: 4, few: true, color: '#AFD9FB' }, |
| | | { name: '待分拨', img: status5Img, id: 1, color: '#11C4FF' }, |
| | | ]) |
| | | |
| | | const getEventStatusNumFun = () => { |
| | | const [start_date, end_date] = timeArr.value |
| | | getEventStatusNum({ start_date, end_date }).then(res => { |
| | | statusList.value = res.data?.data || [] |
| | | const list = res.data?.data || [] |
| | | statusList.value = statusList.value.map(item => { |
| | | const find = list.find(item1 => item.id === item1.id) || {} |
| | | return { |
| | | ...item, |
| | | ...find, |
| | | } |
| | | }) |
| | | statusList.value[0].active = true |
| | | }) |
| | | } |
| | | |
| | | const change = value => {} |
| | | // 事件+数量 |
| | | const eventList = ref([]) |
| | | const getEventList = () => { |
| | | const [start_date, end_date] = timeArr.value |
| | | getEvenNum({ start_date, end_date }).then(res => { |
| | | eventList.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | const timeChange = value => { |
| | | const [start_date, end_date] = timeArr.value |
| | | params.value.start_date = start_date |
| | | params.value.end_date = end_date |
| | | // 提交数据,更新聚合 |
| | | store.commit('setEventTimeRang', timeArr.value); |
| | | // 重置 |
| | | getEventStatusNumFun() |
| | | getEventList() |
| | | params.value.status = undefined |
| | | params.value.event_keys = undefined |
| | | getList() |
| | | } |
| | | |
| | | const pageChange = val => { |
| | | params.value.current = val |
| | | getList() |
| | | } |
| | | |
| | | const list = ref([]) |
| | | const getList = () => { |
| | | const pageParams = { |
| | | current: params.value.current, |
| | | size: params.value.size, |
| | | } |
| | | getEventPage(params.value, pageParams).then(res => { |
| | | const resData = res.data.data |
| | | list.value = (resData?.records || []) |
| | | total.value = resData.total |
| | | }) |
| | | } |
| | | const isShowBigImg = ref(false) |
| | | const imageList = ref([]); |
| | | const clickImgSrc = ref(''); |
| | | const selectedImgIndex = ref(0); |
| | | // 点击图片放大 显示详细信息 |
| | | const getFindImgHistory = (item) => { |
| | | // 下半部分隐藏 右侧隐藏 |
| | | isShowBigImg.value = true |
| | | store.commit('setHideBottomIcon', false) |
| | | findImgHistory(item.id).then((res) => { |
| | | if (res.data.code !== 0) return |
| | | imageList.value = res.data.data |
| | | clickImgSrc.value = res.data.data[0]?.url; |
| | | }) |
| | | positioning(item); |
| | | } |
| | | // 点击周期 |
| | | const clickWeekTime = (item,index) => { |
| | | clickImgSrc.value = item.url |
| | | selectedImgIndex.value = index |
| | | } |
| | | |
| | | const getDateRange = unit => { |
| | | if (unit === 'today') { |
| | | return [dayjs().format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]; |
| | | } |
| | | return [dayjs().startOf(unit).format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf(unit).format('YYYY-MM-DD HH:mm:ss')]; |
| | | }; |
| | | |
| | | // 监听事件时间范围变化 |
| | | watch(() => store.state.home.eventTimeType, (newVal) => { |
| | | timeArr.value = getDateRange(newVal); |
| | | const [start_date, end_date] = getDateRange(newVal); |
| | | params.value.start_date = start_date |
| | | params.value.end_date = end_date |
| | | getEventStatusNumFun() |
| | | getEventList() |
| | | getList() |
| | | }, { immediate: false,deep: true }) |
| | | |
| | | onMounted(() => { |
| | | getDeviceList() |
| | | getDictList() |
| | | getEventStatusNumFun() |
| | | getEventList() |
| | | getList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .right { |
| | | .event-overviewdetail-right { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 88px; |
| | | color: black; |
| | | right: 36px; |
| | | top: 122px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | height: 900px; |
| | | width: 400px; |
| | | background: white; |
| | | align-items: end; |
| | | height: 922px; |
| | | width: 405px; |
| | | font-size: 18px; |
| | | z-index: 10; |
| | | |
| | | &.isMore { |
| | | width: 808px; |
| | | |
| | | .content { |
| | | width: 792px; |
| | | padding-left: 44px; |
| | | } |
| | | } |
| | | |
| | | .content { |
| | | width: 390px; |
| | | height: 877px; |
| | | background: linear-gradient( |
| | | 270deg, |
| | | rgba(31, 62, 122, 0) 0%, |
| | | rgba(31, 62, 122, 0.35) 21%, |
| | | #1f3e7a 100%); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-content: start; |
| | | flex-wrap: wrap; |
| | | padding: 7px 13px 0 11px; |
| | | gap: 16px; |
| | | |
| | | .leftArrow { |
| | | position: absolute; |
| | | left: -11px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .rightArrow { |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 30px; |
| | | transform: translateY(-50%); |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .statusList { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .statusItem { |
| | | // width: 95px; |
| | | height: 44px; |
| | | display: flex; |
| | | flex: 1; |
| | | justify-content: center; |
| | | position: relative; |
| | | cursor: pointer; |
| | | // margin-right: 4px; |
| | | |
| | | &.active { |
| | | background: linear-gradient( 180deg, rgba(19,80,141,0) 0%, rgba(22,56,91,0.48) 48%, #053462 98%, #259DFF 98%, #259DFF 98%); |
| | | } |
| | | |
| | | .statusItemImg { |
| | | width: 34px; |
| | | height: 34px; |
| | | margin-right: 1px; |
| | | } |
| | | |
| | | .statusItemInfo { |
| | | .statusItemName { |
| | | // width: 59px; |
| | | height: 17px; |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | line-height: 17px; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .statusItemNum { |
| | | width: 32px; |
| | | height: 16px; |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: #ffd509; |
| | | line-height: 16px; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-checkbox-group { |
| | | :deep() { |
| | | .el-checkbox { |
| | | height: 20px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .el-checkbox__inner { |
| | | background: transparent; |
| | | width: 18px; |
| | | height: 18px; |
| | | border: 1px solid #3194ef; |
| | | } |
| | | |
| | | .el-checkbox__label { |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | line-height: 17px; |
| | | |
| | | .eventListItemCheckboxNum { |
| | | color: #ffa500; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .eventList { |
| | | width: 100%; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | // justify-content: space-between; |
| | | gap: 20px 10px; |
| | | |
| | | .eventListItem { |
| | | width: 175px; |
| | | height: 140px; |
| | | position: relative; |
| | | cursor: pointer; |
| | | |
| | | .eventListItemImg { |
| | | width: 174px; |
| | | height: 116px; |
| | | border-radius: 4px 4px 4px 4px; |
| | | margin-bottom: 7px; |
| | | } |
| | | |
| | | .eventListItemPosition { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 116px; |
| | | width: 174px; |
| | | height: 20px; |
| | | transform: translateY(-100%); |
| | | background: rgba(22, 22, 22, 0.68); |
| | | border-radius: 0 0 4px 4px; |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | line-height: 17px; |
| | | color: #51a8ff; |
| | | cursor: pointer; |
| | | padding-right: 5px; |
| | | display: flex; |
| | | justify-content: end; |
| | | |
| | | img { |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | .address { |
| | | display: inline-block; |
| | | width: 60px; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | } |
| | | } |
| | | |
| | | .eventListItemText { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | line-height: 17px; |
| | | |
| | | .eventListItemTime { |
| | | font-family: Segoe UI, Segoe UI; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #96a3cc; |
| | | line-height: 17px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pagination { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | .image-list { |
| | | border: 1px solid red; |
| | | position: absolute; |
| | | z-index: 1; |
| | | right: 460px; |
| | | top: 122px; |
| | | width: 540px; |
| | | height: 420px; |
| | | background: #0F1929; |
| | | // box-shadow: inset 0px -50px 50px 0px rgba(27,148,255,0.13); |
| | | // border-radius: 0px 0px 0px 0px; |
| | | border: 2px solid; |
| | | border-image: linear-gradient(180deg, rgba(81, 168, 255, 0), rgba(48, 111, 202, 1), rgba(255, 255, 255, 1), rgba(27, 148, 255, 1)) 2 2; |
| | | .title { |
| | | position: absolute; |
| | | text-align: right; |
| | | right: 12px; |
| | | // top: 12px; |
| | | img { |
| | | width: 10px; |
| | | height: 10px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .content { |
| | | img { |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 10px 10px 10px 10px; |
| | | } |
| | | } |
| | | .card { |
| | | background: linear-gradient( 180deg, rgba(13,30,70,0.72) 0%, #142E6B 100%); |
| | | padding: 0px 10px 0px 10px; |
| | | color: #BECBEA; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | position: absolute; |
| | | bottom: 0px; |
| | | width: 100%; |
| | | .time-top { |
| | | width: 50px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | text-align: center; |
| | | color: #ffffff; |
| | | background: linear-gradient( 180deg, rgba(13,30,70,0.72) 0%, #142E6B 100%); |
| | | border: 1px solid #0054D3; |
| | | cursor: pointer; |
| | | } |
| | | .active { |
| | | background: linear-gradient( 180deg, rgba(13,48,131,0.72) 0%, #023DC8 100%); |
| | | border: 1px solid; |
| | | border-image: linear-gradient(180deg, rgba(0, 84, 211, 1), rgba(146, 186, 245, 1)) 1 1; |
| | | } |
| | | .time-point { |
| | | text-align: center; |
| | | img { |
| | | width: 8px; |
| | | height: 12px; |
| | | } |
| | | } |
| | | .time-line { |
| | | position: absolute; |
| | | background: linear-gradient( 82deg, rgba(23,40,79,0) 0%, #576D9F 17%, #576D9F 86%, rgba(23,40,79,0) 100%); |
| | | height: 2px; |
| | | top: 38px; |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | </style> |