hi-ucs/front/src/views/home/infrastructurePage.vue

2885 lines
82 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 基础设施 -->
<template>
<div class="infrastructrueBox">
<!-- 选项卡 -->
<div class="infrastructrue-tab">
<div v-for="(item, index) in tabList" :key="index" class="tabBox">
<b class="leftType">{{ item.title }}</b>
<el-button
@click="nullClick"
v-if="item.title == '视频标签'"
type="small"
>
清空
</el-button>
<span
v-for="itemContent in item.content"
:key="itemContent"
@click="tabClick(index, itemContent)"
:class="
clickList[index].content.indexOf(itemContent.labelName) != -1 ||
clickList[index].content.indexOf(itemContent) != -1
? 'down'
: ''
"
>
{{ itemContent.labelName || itemContent }}
</span>
</div>
</div>
<div v-if="!room" class="roomBox">
<div class="leftMake">
<div
class="leftTop"
@click="roomResults"
:class="roomYuyue ? 'roomBackground' : 'nullBackground'"
>
会议室预约
</div>
<div
class="leftBottom"
@click="result"
:class="roomResult ? 'roomBackground' : 'nullBackground'"
>
预约结果
</div>
</div>
<div class="roomSearch">
<span>会议室搜索</span>
<div class="searchInput">
<a-input-search
v-model:value="roomInput"
placeholder="请输入关键词"
enter-button="搜索"
size="large"
@search="onSearch"
/>
<a-button
style="width: 0.8rem; height: 0.36rem; margin-left: 0.7rem"
@click="reSetSearch"
>
重置
</a-button>
</div>
</div>
<div v-if="roomYuyue">
<div class="roomTableList">
<span>会议室列表</span>
<div class="roomTime">
<span>可用时间查询</span>
<a-space direction="vertical" class="roomSpace">
<a-date-picker
v-model:value="roomCerateDate"
placeholder="开始日期"
value-format="YYYY-MM-DD"
:disabled-date="disabledDate"
/>
<a-time-picker
v-model:value="roomCreateTime"
placeholder="开始时间"
value-format="HH:mm:ss"
:disabledHours="disabledStartHours"
:disabledMinutes="disabledStartMinutes"
:disabledSeconds="disabledStartSeconds"
/>
<a-time-picker
v-model:value="roomEndTime"
placeholder="结束时间"
value-format="HH:mm:ss"
:disabledHours="disabledEndHours"
:disabledMinutes="disabledEndMinutes"
:disabledSeconds="disabledEndSeconds"
/>
</a-space>
</div>
</div>
<div class="roomItem" v-for="item in roomList" :key="item.id">
<div class="leftImg">
<img :src="item.pic == null ? hys : `${item.pic}`" alt="" />
</div>
<div class="rightContent">
<div class="topContent">{{ item.name }}</div>
<div class="centerContent">
<span>房间号:{{ item.num }}</span>
<span>可容纳人数:{{ item.capacity }}人</span>
<span>面积:{{ item.area }}m²</span>
</div>
<div class="bottonmContent">
<a-tooltip>
<template #title>{{ item.description }}</template>
<span>{{ item.description }}</span>
</a-tooltip>
<!-- <a-tooltip>
{{ item.description }}
</a-tooltip> -->
</div>
</div>
<a-button
style="
margin-left: 0.8rem;
background: #e1edfa;
color: #0087ff;
border: none;
border-radius: 0.06rem;
"
@click="appointment(item)"
>
预约
</a-button>
</div>
<a-pagination
v-model:current="roomPage"
v-model:pageSize="roomLimit"
show-quick-jumper
:total="roomTotal"
:page-size-options="pageSizeOptions"
@change="onRoomChange"
@showSizeChange="onShowSizeChange"
show-size-changer
/>
</div>
<div v-if="roomResult" style="display: grid">
<a-table
:columns="columnsRomm"
:data-source="dataRoom"
:filterMultiple="false"
:align="center"
:pagination="false"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'bookDate'">
<span>
{{ record.bookDate }} {{ record.startTime }}-{{
record.endTime
}}
</span>
</template>
<template v-if="column.key === 'state'">
<span>
{{
record.state == 2
? '通过'
: record.state == 1
? '审核中'
: '不通过'
}}
</span>
</template>
<template v-if="column.key === 'action'">
<a @click="look(record)">查看详情</a>
</template>
</template>
</a-table>
<a-pagination
v-model:current="roomPage"
v-model:pageSize="roomLimit"
show-quick-jumper
:total="roomTotal"
:page-size-options="pageSizeOptionsChengguo"
@change="onRoomChangeChengguo"
@showSizeChange="onShowSizeChangeChengguo"
show-size-changer
/>
</div>
<a-modal
v-model:visible="visibleRoom"
width="10rem"
title="预约详情"
:body-style="bodystyle"
class="modalClass"
:footer="null"
>
<div class="modalResult" style="margin-bottom: 0.05rem">预约结果</div>
<div
style="
width: 100%;
height: 0.01rem;
border-top: 1px solid #ccc;
transform: scaleY(0.5);
"
></div>
<div
class="modalExamine"
style="display: flex; flex-direction: column; margin-top: 0.2rem"
>
<span style="margin-bottom: 0.2rem">
审核结果:{{
lookData.state == 2
? '通过'
: lookData.state == 1
? '审核中'
: '不通过'
}}
</span>
<span style="width: 8rem; margin-bottom: 0.3rem">
审核意见:{{ lookData.auditViem }}
</span>
</div>
<div class="modalYuyue" style="margin-bottom: 0.05rem">预约信息</div>
<div
style="
width: 100%;
height: 0.01rem;
border-top: 1px solid #ccc;
transform: scaleY(0.5);
"
></div>
<div class="modalTime" style="margin-top: 0.2rem">
<div>
预约时段:{{ lookData.bookDate }} {{ lookData.startTime }}-{{
lookData.endTime
}}
</div>
<div
class="modalContent"
style="
width: 7.5rem;
display: flex;
justify-content: space-between;
margin: 0.15rem 0 0.15rem 0;
"
>
<span>预约人:{{ lookData.name }}</span>
<span>联系方式:{{ lookData.phone }}</span>
<span>预约部门:{{ lookData.dept }}</span>
</div>
</div>
<div style="width: 8rem; margin-bottom: 0.3rem">
使用事项:{{ lookData.matter }}
</div>
</a-modal>
<a-modal
v-model:visible="appointmentRoom"
title="会议室预约"
width="10rem"
@ok="handleOk"
:body-style="bodystyle"
class="appModal"
:footer="null"
>
<a-form
:model="formState"
name="basic"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
:labelAlign="labelPosition"
>
<a-row>
<a-col :span="8">
<a-form-item
name="bookDate"
label="预约日期"
v-bind="validateInfos.bookDate"
@blur="validate('create', { trigger: 'blur' }).catch(() => {})"
>
<a-date-picker
style="width: 72%"
v-model:value="formState.bookDate"
value-format="YYYY-MM-DD"
:disabled-date="disabledDate"
@change="handleChange"
/>
</a-form-item>
<div
:class="roomDateList[0] != null ? 'jinggaoD' : 'jinggaoNull'"
>
<div class="imgJinggao"></div>
<span style="color: #da2a13; font-size: 0.12rem">
当日会议室可用时段:{{ roomDateList[0] }}
</span>
</div>
</a-col>
<a-col :span="8">
<a-form-item
name="startTime"
label="预约时段"
v-bind="validateInfos.startTime"
style="display: flex"
>
<a-time-picker
v-model:value="formState.startTime"
placeholder="开始时间"
value-format="HH:mm:ss"
:disabledHours="disabledTimeHours"
:disabledMinutes="disabledTimeMinutes"
:disabledSeconds="disabledTimeSeconds"
/>
</a-form-item>
</a-col>
<a-col :span="8">
<a-time-picker
v-model:value="formState.endTime"
placeholder="结束时间"
value-format="HH:mm:ss"
:disabledHours="disabledTimeEndHours"
:disabledMinutes="disabledTimeEndMinutes"
:disabledSeconds="disabledTimeEndSeconds"
/>
</a-col>
</a-row>
<a-row style="margin-top: 0.4rem">
<a-col :span="8">
<a-form-item
name="name"
label="预约人"
v-bind="validateInfos.name"
>
<a-input v-model:value="formState.name" style="width: 72%" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item name="phone" label="联系电话">
<a-input v-model:value="formState.phone" style="width: 72%" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item
name="dept"
label="预约部门"
v-bind="validateInfos.dept"
>
<a-input v-model:value="formState.dept" style="width: 72%" />
</a-form-item>
</a-col>
</a-row>
<a-row style="margin-top: 0.4rem">
<a-col :span="24">
<a-form-item
name="matter"
v-bind="validateInfos.matter"
label="使用事项"
class="introduction"
>
<a-textarea v-model:value="formState.matter" />
</a-form-item>
</a-col>
</a-row>
<a-row style="margin-top: 0.4rem">
<a-col :span="24">
<a-form-item
name="uploadRoom"
label="附件上传"
class="introduction"
>
<a-upload
:max-count="1"
accept=".doc,.docx,pdf"
v-model:file-list="fileList"
:action="`${apiURL}/upload`"
@remove="handleRemove"
@change="roomUpload"
>
<a-button>
<upload-outlined>选择上传附件</upload-outlined>
</a-button>
<span>
支持doc、docx、PDF等格式支撑材料上传文件大小不超过100M
</span>
</a-upload>
</a-form-item>
</a-col>
</a-row>
<a-form-item
:wrapper-col="{ span: 14, offset: 4 }"
style="text-align: center; margin-top: 0.4rem"
>
<a-button @click="appointmentRoom = false" type="primary" danger>
取消
</a-button>
<a-button
style="margin-left: 10px"
type="primary"
@click="onSubmit"
>
提交
</a-button>
</a-form-item>
</a-form>
</a-modal>
</div>
<div v-if="room">
<!-- 地图 -->
<div class="map-contain" v-if="showMap">
<video-surveillance></video-surveillance>
</div>
<!-- 功能行 -->
<div class="infrastructrue-content" v-if="!wrjFlag">
<!-- 表格数据统计 -->
<div class="contentNum">
<p v-if="selectType !== '视频会议' && isXiHaiAn">
备选
<span>{{ pagination.total || 0 }}</span>
</p>
<p v-if="selectType !== '视频会议' && isXiHaiAn">
已选
<span>{{ selectedRowKeys.length }}</span>
</p>
</div>
<!-- 右侧 -->
<div class="contentRight">
<div class="searchInput" v-if="isXiHaiAn">
<a-input-search
v-model:value="mapSearchParam.cameraName"
placeholder="请输入关键词"
enter-button="搜索"
size="large"
@change="(e) => getCamera(true, e.target.value)"
/>
<a-button
type="primary"
style="width: 0.8rem; height: 0.36rem; margin-left: 0.7rem"
@click="clean"
>
重置
</a-button>
</div>
<i></i>
<!-- 批量预览 -->
<a-button
type="primary"
@click="batchPreview"
class="buttonAdd"
v-if="isXiHaiAn"
>
批量预览
</a-button>
<!-- 添加至申购车 -->
<a-button
v-if="isXiHaiAn"
type="primary"
@click="addShoppingCart"
class="buttonAdd"
>
添加至申购车
</a-button>
<a
style="
display: inline-block;
width: 100px;
height: 36px;
line-height: 36px;
text-align: center;
background: #0558e1;
border-radius: 5px;
font-size: 14px;
color: #fff;
"
v-if="selectType == '视频会议'"
href="/static/download/金宏视频会议系统参会终端(10.1.101.504)_20200211.rar"
>
客户端下载
</a>
<!-- 一键申请 -->
<a-button
v-if="isXiHaiAn"
type="primary"
@click="apply"
class="buttonAdd"
>
一键申请
</a-button>
<a-button v-else type="primary" @click="goToWeb" class="buttonAdd">
<template v-if="selectType == '视频会议'">一键组会</template>
<template v-else>我要申请{{ selectType }}</template>
</a-button>
</div>
</div>
<!-- 表格 -->
<div
class="infrastructrue-table"
v-if="!wrjFlag && selectType !== '视频会议' && isXiHaiAn"
>
<a-table
class="ant-table-striped"
:dataSource="dataSource"
:columns="columns"
:scroll="{ y: tableHeight }"
rowKey="channelId"
:rowClassName="
(record, index) => (index % 2 === 1 ? 'table-striped' : null)
"
:pagination="pagination"
@change="handleTableChange"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onSelect: onSelectChange,
onSelectAll: onSelectAll,
}"
:loading="loadingCamera"
>
<template #bodyCell="{ column, record }">
<template v-if="isXiHaiAn && column.dataIndex === 'status'">
<span>{{ statusText[record.status] || '' }}</span>
</template>
<template v-if="column.dataIndex === 'operation'">
<!-- 离线 -->
<a v-if="record.status != 1" class="disabled-text">预览</a>
<a-tooltip v-else placement="top">
<template #title>请申请后在我的申请中观看视频!</template>
<a
@click="
openVideo(
record.channelCode ||
record.channelId ||
record.channelCode.channelId,
record
)
"
>
预览
</a>
</a-tooltip>
</template>
</template>
</a-table>
</div>
<div
class="infrastructrue-table"
v-if="!wrjFlag && selectType == '视频会议'"
>
<a-table
class="ant-table-striped"
:dataSource="meetingList"
:columns="meetingColumns"
:scroll="{ y: tableHeight }"
rowKey="key"
:rowClassName="
(record, index) => (index % 2 === 1 ? 'table-striped' : null)
"
:pagination="meetingPagination"
:row-selection="{
selectedRowKeys: meetingSelect.data,
onChange: meetingOnSelectChange,
}"
@change="handleMeeting"
></a-table>
</div>
<!-- 西海岸-无人机、单兵设备 -->
<div class="infrastructrue-table" v-else-if="isXiHaiAn && wrjFlag">
<a-table
class="ant-table-striped"
:dataSource="dataSource2"
:columns="columns2"
:scroll="{ y: tableHeight }"
rowKey="channelId"
:rowClassName="
(record, index) => (index % 2 === 1 ? 'table-striped' : null)
"
:pagination="pagination"
@change="handleTableChange"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'operation'">
<a-button
@click="goToApply(record)"
type="link"
:disabled="record.state != 1"
>
申请
</a-button>
<a-button @click="showWrj(record)" type="link">详情</a-button>
</template>
</template>
</a-table>
</div>
<!-- 单个预览弹窗 -->
<a-modal
wrapClassName="single-preview-modal"
v-model:visible="visible"
:width="960"
destroyOnClose
>
<!-- title="视频预览" -->
<template #title>
<span>视频预览</span>
<span style="color: #ff4d4f; margin-left: 10px">
{{ `(请申请后在我的申请中观看视频)` }}
</span>
</template>
<template #footer></template>
<div style="width: 100%; display: flex; justify-content: center">
<div
style="width: 100%; height: 100%; position: relative"
v-show="isXiHaiAn"
>
<!-- 西海岸--预览视频--遮罩 todo-->
<div class="video-cover" @click="videoShowMsg"></div>
<div class="waterMark waterMark-left-top">
{{ userInfo.usernameShow }}
</div>
<div class="waterMark waterMark-right-top">
{{ userInfo.realNameShow }}
</div>
<div class="waterMark waterMark-left-bottom">
{{ userInfo.usernameShow }}
</div>
<div class="waterMark waterMark-right-bottom">
{{ userInfo.realNameShow }}
</div>
<vue3VideoPlay v-bind="options" />
</div>
</div>
</a-modal>
<!-- 图片预览 -->
<a-modal
wrapClassName="single-preview-modal"
v-model:visible="picVisible"
title="图片预览"
:width="960"
destroyOnClose
>
<template #footer></template>
<div style="width: 100%; display: flex; justify-content: center">
<a-image :src="options.src" />
</div>
</a-modal>
<!-- 批量预览图片弹窗 -->
<a-modal
wrapClassName="batch-preview-modal"
v-model:visible="batchPicVisible"
title="图片批量预览"
:width="1060"
destroyOnClose
@cancel="videoClean"
>
<template #footer></template>
<div class="batch-video">
<div
v-for="item in videoList"
:key="item.id"
style="width: 100%; height: 100%"
>
<a-image
width="500px"
height="281px"
:src="item.options.src"
fallback="data:image/png;base64,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"
/>
</div>
</div>
<a-pagination
v-model:current="current"
:total="videoTotal"
defaultPageSize="4"
:showSizeChanger="false"
@change="batchPicturePreview"
show-less-items
/>
</a-modal>
<!-- 批量预览视频弹窗 -->
<a-modal
wrapClassName="batch-preview-modal"
v-model:visible="batchVisible"
title="视频批量预览"
:width="1060"
destroyOnClose
@cancel="videoClean"
>
<template #footer></template>
<div class="batch-video">
<div
v-for="(item, index) in videoList"
:key="item.id"
style="width: 100%; height: 100%; position: relative"
>
<!-- 批量预览视频--遮罩 -->
<div
class="batch-video-cover"
@click="videoShowMsg(index)"
v-show="isXiHaiAn"
></div>
<div
class="batch-waterMark batch-waterMark-left-top"
v-show="isXiHaiAn"
>
{{ userInfo.usernameShow }}
</div>
<div
class="batch-waterMark batch-waterMark-right-top"
v-show="isXiHaiAn"
>
{{ userInfo.realNameShow }}
</div>
<div
class="batch-waterMark batch-waterMark-left-bottom"
v-show="isXiHaiAn"
>
{{ userInfo.usernameShow }}
</div>
<div
class="batch-waterMark batch-waterMark-right-bottom"
v-show="isXiHaiAn"
>
{{ userInfo.realNameShow }}
</div>
<p></p>
<vue3VideoPlay v-bind="item.options" />
</div>
</div>
<a-pagination
v-model:current="current"
:total="videoTotal"
defaultPageSize="4"
:showSizeChanger="false"
@change="batchPreview"
show-less-items
/>
</a-modal>
<a-modal
wrapClassName="wrj"
v-model:visible="wrjVisible"
:width="1000"
:title="wrjName + '详情'"
@ok="wrjVisible = false"
>
<template #footer></template>
<div v-for="(db, key) in wrjData" :key="key">
<template v-if="typeof db == 'object'">
<div
style="
font-size: 20px;
font-weight: 600;
margin: 10px 0;
text-align: center;
"
>
{{ db.attrType || '--' }}
</div>
<template v-if="db.attrValue">
<div
style="padding: 0 30px"
v-for="(value, key2) in JSON.parse(db.attrValue)"
:key="value"
>
{{ key2 + '' + value }}
</div>
</template>
</template>
</div>
</a-modal>
</div>
</div>
</template>
<script setup>
import VideoSurveillance from '@/views/home/videoSurveillance'
import { useRouter } from 'vue-router'
import { message, Upload } from 'ant-design-vue'
import {
ref,
reactive,
onMounted,
defineProps,
watch,
defineComponent,
nextTick,
defineExpose,
computed,
} from 'vue'
import { getUser, getEnkeUsers } from '@/api/home'
import { initiateMeet } from '@/api/file'
import {
getCameraByParentId,
getStreamByChannelCode,
getCameraAllLabel,
selectByChannelCode,
} from '@/api/videoSurveillance'
import { getCameraByCondition } from '@/api/file'
import {
sgcInsert,
xhaAddCart,
getRoomSearch,
getDate,
setSubmit,
getYuyue,
getSoldierList,
getMaxApplyNum,
} from '@/api/home'
import mybus from '@/myplugins/mybus'
import dayjs from 'dayjs'
import { Form } from 'ant-design-vue'
import moment from 'moment'
import { useStore } from 'vuex'
const store = useStore()
const username = store.getters['user/username']
const props = defineProps({
// 模糊查
searchValue: { type: String, default: '' },
searchType: { type: String, default: '' },
})
const current = ref(1)
const videoTotal = ref(0)
const router = useRouter()
const whoShow1 = ref(whoShow)
const isXiHaiAn = whoShow1.value.itShowXiHaiAn
const options = reactive({
width: '912px', //播放器宽度
height: '513px', //播放器高度
color: '#409eff', //主题色
title: '', //视频名称
src: '', //视频源
type: 'm3u8', // 视频源类型
muted: false, //静音
webFullScreen: false,
speedRate: ['0.75', '1.0', '1.25', '1.5', '2.0'], //播放倍速
autoPlay: isXiHaiAn ? false : true, //自动播放
loop: false, //循环播放
mirror: false, //镜像画面
ligthOff: false, //关灯模式
volume: 0.3, //默认音量大小
control: isXiHaiAn ? false : true, //是否显示控制
controlBtns: isXiHaiAn
? []
: [
'audioTrack',
'quality',
'speedRate',
'volume',
'setting',
'pip',
'pageFullScreen',
'fullScreen',
], //显示所有按钮,
})
const meetingList = ref([])
const meetingPagination = ref({
total: 0,
current: 1,
pageSize: 5, //每页中显示5条数据
showSizeChanger: false,
})
const meetingSelect = reactive({ data: [] })
const meetingSelectOld = reactive({ data: [] })
const meetingOnSelectChange = (selectedRowKeys) => {
console.log(
'selectedRowKeys changed: ',
selectedRowKeys,
meetingSelect.data
)
meetingSelect.data = selectedRowKeys
meetingSelectOld.data[meetingPagination.value.current - 1] =
meetingSelect.data
}
const videoList = ref([])
const initMeeting = () => {
let str = '青岛市一网统揽项目组/'
// meetingSelect.data.map((val) => (str += val + '/'))
meetingSelectOld.data.map((val) => {
val.map((data) => (str += data + '/'))
})
initiateMeet(str).then((res) => {
console.log('组会=========>', res)
})
}
// 获取会议列表
const meetingColumns = ref([
{
title: '视频会议用户名称',
dataIndex: 'hostName',
key: 'hostName',
},
])
const getMeetingList = () => {
getEnkeUsers({
page: meetingPagination.value.current,
limit: meetingPagination.value.pageSize,
}).then((res) => {
meetingList.value = []
res.data.data.list.map((val) => {
val.key = val.hostName
})
meetingList.value = res.data.data.list
meetingPagination.value.total = res.data.data.total
meetingSelect.data =
meetingSelectOld.data[meetingPagination.value.current - 1]
console.log('会议列表=============>', res.data.data)
})
}
const hys = ref(require('@/assets/home/hys.png'))
getMeetingList()
const handleMeeting = (pag, filters, sorter) => {
console.log(pag, filters, sorter)
meetingPagination.value.current = pag.current
getMeetingList()
}
let visible = ref(false) // 视频预览
let picVisible = ref(false) // 图片预览
let batchVisible = ref(false) // 视频批量预览
let batchPicVisible = ref(false) // 图片批量预览
const jcssType = ref(router.currentRoute.value.query.type)
const pagination = ref({
total: 0,
current: 1,
pageSize: 10, //每页中显示10条数据
showSizeChanger: true,
pageSizeOptions: ['10', '30', '50', '100', '1000'], //每页中显示的数据
})
//会议室变量区域=======
const paginationRoom = ref({
total: 0,
current: 1,
pageSize: 10, //每页中显示10条数据
showSizeChanger: true,
pageSizeOptions: ['5', '10', '15', '20'], //每页中显示的数据
})
const formState = reactive({
roomId: '',
bookDate: '', //日期
startTime: '', //开始时间
endTime: '', //结束时间
name: '',
phone: '',
dept: '',
matter: '',
file: '',
roomName: '',
})
const fileList = ref([])
const useForm = Form.useForm
const roomInput = ref('')
let roomStr = router.currentRoute.value.query.str
if (roomStr) {
roomInput.value = roomStr
}
const rulesRef = reactive({
bookDate: [
{
type: 'string',
required: true,
message: '请选择日期',
},
],
startTime: [
{
type: 'string',
required: true,
message: '请选择时间段',
},
],
name: [
{
required: true,
message: '请输入预约人',
},
],
matter: [{ min: 1, max: 500, required: true, message: '可输入500字内容' }],
dept: [
{
required: true,
message: '请输入部门',
},
],
})
const { resetFields, validateInfos, validate } = useForm(formState, rulesRef)
const mapSearchParam = ref({
// 地图搜索初始化数据
parentId: '',
cameraName: '',
checkStatus: '1',
pageNum: pagination.value.current,
pageSize: pagination.value.pageSize,
gpsX: '',
gpsY: '',
radius: '',
labelCodes: [],
})
const showMap = ref(true)
const room = ref(true)
const roomResult = ref(true)
const roomYuyue = ref(true)
const visibleRoom = ref(false)
const appointmentRoom = ref(false)
const labelPosition = ref('left')
const apiURL = window.SITE_CONFIG.apiURL
const roomList = ref([])
const roomPage = ref(1)
const roomLimit = ref(5)
const roomTotal = ref(0)
const pageSizeOptions = ref(['5', '10', '20', '50'])
const pageSizeOptionsChengguo = ref(['5', '10', '20', '50'])
const dateId = ref(null)
const roomDateList = ref([])
//开始时间---结束时间
const roomCerateDate = ref('')
const roomCreateTime = ref('')
const roomEndTime = ref('')
const roomModalCreateTime = ref('')
const roomModalEndTime = ref('')
const lookData = ref({})
// console.log('模糊查传递', props.searchValue)
if (props.searchValue) {
mapSearchParam.value.cameraName = props.searchValue
}
if (props.searchType) {
tabClick(0, props.searchType.value)
}
// 消息列表页面
let formPage = router.currentRoute.value.query.formPage || ''
// 设施类型--无人机和单兵设备
let facilitiesType = router.currentRoute.value.query.facilitiesType || ''
onMounted(() => {
// 获取用户信息
handleUser()
if (jcssType.value) {
tabClick(0, jcssType.value)
if (jcssType.value == '视频资源') {
getCamera()
}
} else {
if (isXiHaiAn) {
if (facilitiesType) {
tabClick(0, facilitiesType)
} else {
let _obj = {
title: '视频标签',
content: ['视频资源'],
}
clickList.value.push(_obj)
tabClick(0, '视频资源')
}
} else {
// 默认选中
if (formPage && formPage == 'noticePage') {
tabClick(0, '城市云脑会客厅')
roomYuyue.value = false
roomResult.value = true
onSearch()
} else {
tabClick(0, '城市云脑会客厅')
}
}
}
mybus.off('getListByParentId')
mybus.on('getListByParentId', (parentId) => {
mapSearchParam.value.parentId = parentId
getCamera()
})
mybus.off('changeRoomInput')
mybus.on('changeRoomInput', (val) => {
console.log('更改=======》')
roomInput.value = val
onSearch()
})
mybus.off('getListByMap')
mybus.on('getListByMap', (param) => {
mapSearchParam.value.gpsX = param.gpsX
mapSearchParam.value.gpsY = param.gpsY
mapSearchParam.value.radius = param.radius
mapSearchParam.value.type = param.type
mapSearchParam.value.borderPolygonList = param.borderPolygonList
mapSearchParam.value.pageSize = param.type != 0 ? 20000 : 10
selectedRowKeys.value = [] //清空选中的点位
selectedList.value = []
dataSource.value = param.dataSource
pagination.value.total = param.total
})
//点位点击
mybus.off('pointMarkerClick')
mybus.on('pointMarkerClick', (point) => {
console.log('pointMarkerClick->point', selectedList.value, point)
let check = false //是否勾选
if (selectedList.value && selectedList.value.length > 0) {
selectedList.value.forEach((ele) => {
if (ele.channelCode == point.data.channelCode) {
check = true
}
})
}
let pointData = new Proxy(point.data, point)
onSelectChange(pointData, !check, '', '', 'proxy')
})
})
const selectedList = ref([])
const selectedRowKeys = ref([])
const tabList = ref([
{
title: '设施类型',
content: isXiHaiAn
? ['视频资源']
: username == 'admin'
? ['城市云脑会客厅', '视频资源', '政务云资源', '视频会议']
: ['城市云脑会客厅', '视频资源', '政务云资源'],
},
])
let clickList = ref([]) //存储点击的tab
if (!isXiHaiAn) {
tabList.value.push({
title: '城市云脑会客厅',
content: [],
})
}
const wrjVisible = ref(false)
const wrjName = ref('')
const wrjData = ref([])
// 单兵、无人机-详情
const showWrj = (data) => {
wrjName.value = data.wrjName
wrjData.value = data.deviceAttrDTOList || []
wrjVisible.value = true
}
const goToWrj = (data) => {
window.open(data.url)
}
// 西海岸-无人机、单兵设备申请
const goToApply = (data) => {
console.log(data, dept)
let arr = [
{
arr: [
{
description: data.description,
resourceId: data.id,
resourceName: data.wrjName,
type: data.type,
},
],
deptId: dept.deptId || data.deptId || '',
deptName: dept.deptName,
},
]
localStorage.setItem('applyList', JSON.stringify(arr))
router.push({
path: '/apply',
})
}
if (whoShow1.value.itShowXiHaiAn) {
tabList.value[0].content.push('无人机')
tabList.value[0].content.push('单兵设备')
}
// 单个预览,当前点击数据
const rowClickData = ref(null)
// 打开视频预览
const openVideo = (id, item) => {
rowClickData.value = item
// 单个预览
if (item && item.status != 1) {
return
// return message.warning('当前设备离线, 不可预览!')
}
console.log('打开视频', id)
const param = {
key: id,
}
getStreamByChannelCode(param).then((res) => {
console.log(res)
visible.value = true
//options.src = res.data.data
options.src ="wss://10.134.135.45:6014/proxy/10.10.20.15:559/openUrl/0kIF7La"
})
// // 视频测试--勿删
// visible.value = true
// options.src = 'http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8'
}
// 打开图片预览
const openPicture = (id) => {
console.log('打开图片', id)
const param = {
channelCode: id,
}
selectByChannelCode(param).then((res) => {
console.log(res)
if (res.data.data && res.data.data[0].picUrl) {
options.src = res.data.data[0].picUrl
picVisible.value = true
} else {
message.warning('该点位暂无预览图片!')
}
})
}
//初始化数据
const init = () => {
tabList.value.map((item) => {
let params = {
title: item.title,
content: [],
}
clickList.value.push(params)
})
mybus.off('tranferToList')
mybus.on('tranferToList', () => {
console.log('获取到的列表数据')
})
}
init()
//点击会议室左侧切换
const result = () => {
roomYuyue.value = false
roomResult.value = true
chengguoSearch()
}
const chengguoSearch = () => {
let query = {
page: roomPage.value,
limit: roomLimit.value,
roomName: roomInput.value,
}
getYuyue(query).then(({ data: res }) => {
dataRoom.value = res.data.list
roomTotal.value = res.data.total
})
}
const roomResults = () => {
roomYuyue.value = true
roomResult.value = false
}
// 查看详情
const look = (row) => {
visibleRoom.value = true
lookData.value = row
}
// 搜索
const onSearch = (searchValue) => {
let newQuery = JSON.parse(JSON.stringify(router.currentRoute.value.query))
newQuery.str = roomInput.value
router
.replace({
query: newQuery,
})
.then(() => {})
mybus.emit('changeSearchValue', roomInput.value)
searchData()
chengguoSearch()
}
//重置
const reSetSearch = () => {
roomInput.value = ''
searchData()
chengguoSearch()
}
// 时间选择器限制----可用时间查询
//获取不可选择的日期
const disabledDate = (current) => {
const time = moment().endOf('day').subtract(1, 'days')
return current && current < time
}
//获取不可选择的小时
const disabledStartHours = () => {
if (roomEndTime.value) {
let hours = []
let hour = roomEndTime.value.substr(0, 2)
for (let i = hour; i < 24; i++) {
hours.push(i)
}
return hours
}
}
//获取不可选择的分钟
const disabledStartMinutes = (selectedHour) => {
if (roomEndTime.value) {
let minutes = []
let hour = roomEndTime.value.substr(0, 2)
let minute = roomEndTime.value.substr(3, 2)
if (selectedHour == hour) {
for (let i = minute; i < 60; i++) {
minutes.push(i)
}
}
return minutes
}
}
//获取不可选择的秒
const disabledStartSeconds = (selectedHour, selectedMinute) => {
if (roomEndTime.value) {
let seconds = []
let hour = roomEndTime.value.substr(0, 2)
let minute = roomEndTime.value.substr(3, 2)
let second = roomEndTime.value.substr(6, 2)
if (selectedHour == hour && selectedMinute.value == minute) {
for (let i = second - 1; i < 60; i++) {
seconds.push(i)
}
}
return seconds
}
}
//获取不可选择的小时
const disabledEndHours = () => {
if (roomCreateTime.value) {
let hours = []
let hour = roomCreateTime.value.substr(0, 2)
for (let i = 0; i < hour; i++) {
hours.push(i)
}
return hours
}
}
//获取不可选择的分钟
const disabledEndMinutes = (selectedHour) => {
if (roomCreateTime.value) {
let minutes = []
let hour = roomCreateTime.value.substr(0, 2)
let minute = roomCreateTime.value.substr(3, 2)
if (selectedHour == hour) {
for (let i = 0; i < minute; i++) {
minutes.push(i)
}
}
return minutes
}
}
//获取不可选择的秒
const disabledEndSeconds = (selectedHour, selectedMinute) => {
if (roomCreateTime.value) {
let seconds = []
let hour = roomCreateTime.value.substr(0, 2)
let minute = roomCreateTime.value.substr(3, 2)
let second = roomCreateTime.value.substr(6, 2)
if (selectedHour == hour && selectedMinute.value == minute) {
for (let i = 0; i <= second; i++) {
seconds.push(i)
}
}
return seconds
}
}
// 时间选择器限制----会议室预约时段
//获取不可选择的小时
const disabledTimeHours = () => {
if (formState.endTime) {
let hours = []
let hour = formState.endTime.substr(0, 2)
for (let i = hour; i < 24; i++) {
hours.push(i)
}
return hours
}
}
//获取不可选择的分钟
const disabledTimeMinutes = (selectedHour) => {
if (formState.endTime) {
let minutes = []
let hour = formState.endTime.substr(0, 2)
let minute = formState.endTime.substr(3, 2)
if (selectedHour == hour) {
for (let i = minute; i < 60; i++) {
minutes.push(i)
}
}
return minutes
}
}
//获取不可选择的秒
const disabledTimeSeconds = (selectedHour, selectedMinute) => {
if (formState.endTime) {
let seconds = []
let hour = formState.endTime.substr(0, 2)
let minute = formState.endTime.substr(3, 2)
let second = formState.endTime.substr(6, 2)
if (selectedHour == hour && selectedMinute.value == minute) {
for (let i = second - 1; i < 60; i++) {
seconds.push(i)
}
}
return seconds
}
}
//获取不可选择的小时
const disabledTimeEndHours = () => {
if (formState.startTime) {
let hours = []
let hour = formState.startTime.substr(0, 2)
for (let i = 0; i < hour; i++) {
hours.push(i)
}
return hours
}
}
//获取不可选择的分钟
const disabledTimeEndMinutes = (selectedHour) => {
if (formState.startTime) {
let minutes = []
let hour = formState.startTime.substr(0, 2)
let minute = formState.startTime.substr(3, 2)
if (selectedHour == hour) {
for (let i = 0; i < minute; i++) {
minutes.push(i)
}
}
return minutes
}
}
//获取不可选择的秒
const disabledTimeEndSeconds = (selectedHour, selectedMinute) => {
if (formState.startTime) {
let seconds = []
let hour = formState.startTime.substr(0, 2)
let minute = formState.startTime.substr(3, 2)
let second = formState.startTime.substr(6, 2)
if (selectedHour == hour && selectedMinute.value == minute) {
for (let i = 0; i <= second; i++) {
seconds.push(i)
}
}
return seconds
}
}
//分页
const onRoomChange = (pageNumber) => {
roomPage.value = pageNumber
searchData()
}
const onShowSizeChange = (current, pageSize) => {
roomLimit.value = pageSize
searchData()
}
const onRoomChangeChengguo = (pageNumber) => {
roomPage.value = pageNumber
chengguoSearch()
}
const onShowSizeChangeChengguo = (current, pageSize) => {
roomLimit.value = pageSize
chengguoSearch()
}
//预约
const appointment = (item) => {
dateId.value = item.id
formState.roomId = item.id
formState.roomName = item.name
appointmentRoom.value = true
}
//预约弹框 选择日期
const handleChange = (i) => {
let query = {
date: i, //查询的riqi
roomId: dateId.value, //会议室主键
}
getDate(query).then(({ data: res }) => {
roomDateList.value = res.data
})
}
const columnsRomm = [
{
title: '会议室名称',
dataIndex: 'roomName',
align: 'center',
},
{
title: '预约时段',
key: 'bookDate',
align: 'center',
},
{
title: '预约状态',
key: 'state',
align: 'center',
},
{
title: '预约详情',
key: 'action',
align: 'center',
},
]
const dataRoom = ref([])
const bodystyle = {
paddingTop: 0,
borderBottom: 0,
}
const handleOk = (e) => {
console.log(e)
}
//文件上传成功回调
const roomUpload = (response) => {
if (response.file.response !== undefined) {
fileList.value = response.fileList
formState.file = response.file.response.data
}
}
//提交预约
const onSubmit = () => {
validate()
.then(() => {
setSubmit(formState).then(({ data: res }) => {
appointmentRoom.value = false
rulesRef.bookDate = []
rulesRef.startTime = []
rulesRef.name = []
rulesRef.matter = []
rulesRef.phone = []
rulesRef.dept = []
formState.roomId = ''
formState.bookDate = ''
formState.startTime = '' //开始时间
formState.endTime = '' //结束时间
formState.name = ''
formState.phone = ''
formState.dept = ''
formState.matter = ''
formState.file = ''
fileList.value = []
searchData()
})
})
.catch((err) => {
console.log('error', err)
})
}
//会议室查询接口
const searchData = () => {
let query = {
bookDate: roomCerateDate.value, // 预约开始时间 年月日
startTime: roomCreateTime.value, //预约开始时 间时分秒
endTime: roomEndTime.value, // 预约结束时间
name: roomInput.value, //会议室名称
page: roomPage.value, //页码
limit: roomLimit.value, //每页条数
}
getRoomSearch(query).then(({ data: res }) => {
roomList.value = res.data.list
roomTotal.value = res.data.total
})
}
const emits = defineEmits(['add'])
const selectType = ref('政务云资源')
//表格的高度
let tableHeight = ref('600')
//tab切换点击事件
const tabClick = (indexFather, name) => {
selectedRowKeys.value = []
selectedList.value = []
if (clickList.value[indexFather].content.indexOf(name) != -1) {
if (name == '视频资源') {
room.value = true
tableHeight.value = 330
showMap.value = true
if (tabList.value[1]) {
tabList.value[1].title = '视频标签'
}
selectType.value = '视频资源'
console.log('444------------>', 444)
} else if (name == '政务云资源') {
room.value = true
tableHeight.value = 600
showMap.value = false
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
if (tabList.value[1]) {
tabList.value[1].title = '政务云资源分类'
}
selectType.value = '政务云资源'
} else if (name == '感知资源') {
room.value = true
tableHeight.value = 330
showMap.value = true
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
selectType.value = '感知资源'
} else if (name == '城市云脑会客厅') {
} else if (name == '视频会议') {
room.value = true
tableHeight.value = 600
showMap.value = false
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
if (tabList.value[1]) {
tabList.value[1].title = ''
}
selectType.value = '视频会议'
}
clickList.value[indexFather].content.splice(
clickList.value[indexFather].content.indexOf(name),
1
)
} else {
if (name == '视频资源') {
selectType.value = '视频资源'
wrjFlag.value = false
tableHeight.value = 330
showMap.value = true
if (tabList.value[1]) {
tabList.value[1].content = []
tabList.value[1].title = '视频标签'
}
if (clickList.value[1]) {
clickList.value[1].content = []
}
clickList.value[indexFather].content[0] = name
dataSource.value = []
dataSource2.value = []
room.value = true
getCameraAllLabel().then((res) => {
res.data.data.forEach((val) => {
if (tabList.value[1]) {
tabList.value[1].content.push({
labelCode: val.labelCode,
labelName: val.labelName,
})
}
})
})
// 改变查询摄像头接口的labelCode数组
mapSearchParam.value.labelCodes = []
if (clickList.value[1]) {
clickList.value[1].content.map((item) => {
mapSearchParam.value.labelCodes.push(item.labelCode)
})
}
mapSearchParam.value.gpsX = ''
mapSearchParam.value.gpsY = ''
mapSearchParam.value.radius = ''
mapSearchParam.value.type = ''
mapSearchParam.value.labelCodes = mapSearchParam.value.labelCodes + ''
emits('add', 1)
getCamera()
} else if (name == '政务云资源') {
selectType.value = '政务云资源'
tableHeight.value = 600
showMap.value = false
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
if (clickList.value[1]) {
clickList.value[1].content = []
}
clickList.value[indexFather].content[0] = name
if (tabList.value[1]) {
tabList.value[1].title = '政务云资源分类'
tabList.value[1].content = [
'云主机',
'算力主机',
'对象存储',
'堡垒机',
'防火墙',
'网闸',
'负载均衡',
'公网IP',
]
}
room.value = true
wrjFlag.value = false
emits('add', 2)
} else if (name == '视频会议') {
selectType.value = '视频会议'
tableHeight.value = 600
showMap.value = false
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
if (clickList.value[1]) {
clickList.value[1].content = []
}
clickList.value[indexFather].content[0] = name
if (tabList.value[1]) {
tabList.value[1].title = ''
tabList.value[1].content = []
}
room.value = true
wrjFlag.value = false
// emits('add', 2)
} else if (name == '感知资源') {
selectType.value = '感知资源'
tableHeight.value = 330
showMap.value = true
if (clickList.value[1]) {
clickList.value[1].content = []
}
pagination.value.total = 0
clickList.value[indexFather].content[0] = name
if (tabList.value[1]) {
tabList.value[1].content = []
tabList.value[1].title = '感知资源分类'
}
dataSource.value = []
dataSource2.value = []
room.value = true
wrjFlag.value = false
emits('add', 3)
} else if (name == '无人机') {
pagination.value.current = 1
getSoldierData(indexFather, name)
} else if (name == '单兵设备') {
pagination.value.current = 1
getSoldierData(indexFather, name)
} else if (name == '城市云脑会客厅') {
showMap.value = false
dataSource.value = []
dataSource2.value = []
pagination.value.total = 0
if (clickList.value[1]) {
clickList.value[1].content = []
}
clickList.value[indexFather].content[0] = name
if (tabList.value[1]) {
tabList.value[1].content = []
tabList.value[1].title = ''
}
wrjFlag.value = true
room.value = false
roomYuyue.value = true
roomResult.value = false
emits('add', 6)
searchData()
} else {
if (clickList.value[indexFather]) {
clickList.value[indexFather].content.push(name)
}
}
}
// 改变查询摄像头接口的labelCode数组
mapSearchParam.value.labelCodes = []
if (clickList.value[1]) {
clickList.value[1].content.map((item) => {
mapSearchParam.value.labelCodes.push(item.labelCode)
})
}
console.log('选中的标签code', mapSearchParam.value)
mapSearchParam.value.labelCodes = mapSearchParam.value.labelCodes + ''
if (name == '政务云资源' || name == '视频会议' || name == '感知资源') {
dataSource.value = []
dataSource2.value = []
console.log('视频会议=========>', dataSource, columns)
pagination.value.total = 0
} else {
if (name !== '无人机' && name !== '单兵设备') {
getCamera()
}
}
}
// 无人机、单兵设备状态
const wrjStateObj = {
0: '待审批',
1: '未申请',
2: '通过',
3: '未通过',
}
// 获取无人机、单兵设备
const getSoldierData = (indexFather, name) => {
room.value = true
tableHeight.value = 600
showMap.value = false
dataSource.value = []
dataSource2.value = []
if (clickList.value[1]) {
clickList.value[1].content = []
}
clickList.value[indexFather].content[0] = name
console.log(
'clickList.value[indexFather].content[0]------------>',
clickList.value[indexFather].content[0]
)
if (tabList.value[1]) {
tabList.value[1].title = ''
tabList.value[1].content = []
}
wrjFlag.value = true
let _params = {
type: name,
page: pagination.value.current,
limit: pagination.value.pageSize,
}
getSoldierList(_params)
.then((res) => {
console.log('res---获取无人机、单兵设备--------->', res)
if (res.data.code !== 0) {
return message.error(res.data.msg)
}
let { list = [], total = 0 } = res.data.data
pagination.value.total = total
if (name == '无人机') {
list.map((wrj) => {
dataSource2.value.push({
wrjName: wrj.name,
wrjState: wrjStateObj[wrj.state],
url: wrj.url,
details: wrj.details,
...wrj,
})
})
}
if (name == '单兵设备') {
list.map((db) => {
dataSource2.value.push({
wrjName: db.name,
wrjState: wrjStateObj[db.state],
details: db.details,
type: db.type,
...db,
})
})
}
})
.catch((err) => {
message.error(err)
})
}
// 打开视频批量预览
const batchPreview = async function (page) {
if (page.layerX) {
page = 1
}
if (selectedList.value.length > 0) {
videoTotal.value = selectedList.value.length
const arr = JSON.parse(JSON.stringify(selectedList.value))
let start = (page - 1) * 4
let list = []
list = arr.splice(start, 4)
const length = list.length
videoList.value = []
for (let index = 0; index < length; index++) {
const param = {
key: list[index].channelId,
}
let ob = {
options: {
width: '512px', //播放器宽度
height: '288px', //播放器高度
color: '#409eff', //主题色
title: '', //视频名称
src: '', //视频源
type: 'm3u8', // 视频源类型
muted: false, //静音
webFullScreen: false,
speedRate: ['0.75', '1.0', '1.25', '1.5', '2.0'], //播放倍速
autoPlay: isXiHaiAn ? false : true, //自动播放
loop: false, //循环播放
mirror: false, //镜像画面
ligthOff: false, //关灯模式
volume: 0.3, //默认音量大小
control: isXiHaiAn ? false : true, //是否显示控制
controlBtns: isXiHaiAn
? []
: [
'audioTrack',
'quality',
'speedRate',
'volume',
'setting',
'pip',
'pageFullScreen',
'fullScreen',
], //显示所有按钮,
},
}
await getStreamByChannelCode(param).then((res) => {
// 视频测试
// ob.options.src = 'http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8'
ob.options.src = res.data.data
console.log('监测ob的变化', ob)
videoList.value.push(ob)
})
}
batchVisible.value = true
} else {
message.error('请选择需要预览的数据')
}
}
// 打开图片批量预览
const batchPicturePreview = async function (page) {
if (page.layerX) {
page = 1
}
if (selectedList.value.length > 0) {
videoTotal.value = selectedList.value.length
const arr = JSON.parse(JSON.stringify(selectedList.value))
let start = (page - 1) * 4
let list = []
list = arr.splice(start, 4)
const length = list.length
videoList.value = []
for (let index = 0; index < length; index++) {
const param = {
channelCode: list[index].channelId,
}
let ob = {
options: {
src: '', //图片源
},
}
selectByChannelCode(param).then((res) => {
ob.options.src = (res.data.data && res.data.data[0].picUrl) || ''
videoList.value.push(ob)
})
}
batchPicVisible.value = true
} else {
message.error('请选择需要预览的数据')
}
}
// 清空
const nullClick = () => {
if (clickList.value[1]) {
clickList.value[1].content = []
}
mapSearchParam.value.labelCodes = ''
getCamera()
}
// 重置
const clean = () => {
mapSearchParam.value.cameraName = ''
selectedList.value = []
selectedRowKeys.value = []
videoList.value = []
pagination.value.current = 1
mapSearchParam.value.pageNum = 1
mapSearchParam.value.type = 0
pagination.value.pageSize = 10
getCamera()
}
const videoClean = () => {
//视频预览弹窗关闭后不清除选中行
videoList.value = []
current.value = 1
}
// 改变批量预览的分页
const changePage = (page) => {}
// 一键申请
const dept = reactive({})
if (infrastructure) {
dept.deptId = infrastructure.deptId || ''
dept.deptName = infrastructure.deptName || ''
}
// 西海岸--判断设备最大数量个数
const judegNumber = () => {
return new Promise((resolve, reject) => {
getMaxApplyNum(selectedRowKeys.value.length)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
const apply = async () => {
if (selectedRowKeys.value.length != 0) {
// 判断最大数量
let maxNumRes = await judegNumber()
if (maxNumRes.data.code != 0) {
return
}
let arr = [
{
arr: [
{
description: '',
note1: JSON.stringify(selectedList.value),
resourceId: '1522550195055828996',
resourceName: '摄像头列表',
type: '基础设施',
},
],
deptId: dept.deptId,
deptName: dept.deptName,
},
]
console.log('一键申请', arr)
localStorage.setItem('applyList', JSON.stringify(arr))
router.push({
path: '/apply',
})
} else {
message.error('请选择需要申请的数据')
}
}
const goToWeb = () => {
switch (selectType.value) {
case '政务云资源':
window.open('http://15.72.183.88:8760/yzy/login')
break
case '视频资源':
window.open('http://15.72.183.88:8860/video')
break
case '视频会议':
initMeeting()
break
default:
break
}
}
const wrjFlag = ref(false)
// 西海岸-视频资源loading
const loadingCamera = ref(false)
const getCamera = (flag, str) => {
loadingCamera.value = true
if (flag) {
mapSearchParam.value.cameraName = str
}
console.log('初始化调用')
console.log(
'不选左侧树的时候不调用接口',
mapSearchParam.value,
selectType.value
)
if (!whoShow1.value.itShowXiHaiAn) {
if (selectType.value == '视频资源') {
getCameraByParentId(mapSearchParam.value)
.then((res) => {
console.log('res--查询摄像头---------->', res)
loadingCamera.value = false
dataSource.value = res.data.data
pagination.value.total = res.data.count
})
.catch((err) => {
loadingCamera.value = false
message.error(err)
})
} else {
loadingCamera.value = false
}
} else {
let params = {
regionId:
mapSearchParam.value.parentId || '70be8c5b664f4bcf869d82f2e8335051',
pageNum: mapSearchParam.value.pageNum,
pageSize: mapSearchParam.value.pageSize,
longitude: mapSearchParam.value.gpsX || '',
latitude: mapSearchParam.value.gpsY || '',
radius: mapSearchParam.value.radius || '',
name: mapSearchParam.value.cameraName,
type: mapSearchParam.value.type,
borderPolygonList: mapSearchParam.value.borderPolygonList || [],
}
// todo-临时放开
// if (
// params.regionId === '70be8c5b664f4bcf869d82f2e8335051' &&
// !params.name &&
// !params.longitude
// ) {
// params.status = ''
// }
let paramsFather = ''
let i = 1
for (var key in params) {
if (params[key] === '') {
delete params[key]
} else {
if (i != 1) {
paramsFather += `&${key}=` + params[key]
i += 1
} else if (i == 1) {
paramsFather += `${key}=` + params[key]
i += 1
}
}
}
getCameraByCondition(params)
.then((res) => {
console.log('res--查询摄像头---------->', res)
loadingCamera.value = false
dataSource.value = res.data.data
pagination.value.total = res.data.count
})
.catch((err) => {
loadingCamera.value = false
message.error(err)
})
}
}
defineExpose({
getCamera,
})
//加入申购车
const addShoppingCart = () => {
if (selectedList.value.length > 0) {
let _arr = []
selectedList.value.map((v) => {
_arr.push({
delFlag: '0',
resourceId: v.idtCameraChannel,
note1: [v],
})
})
xhaAddCart(_arr).then((res) => {
if (res.data.code !== 0) {
return message.error(res.data.msg)
}
message.success('添加申购车成功!')
mybus.emit('getSgcNum')
})
} else {
message.error('请选择需要添加申购车的数据')
}
}
// 表格
const dataSource = ref([])
const dataSource2 = ref([])
const statusText = ref({
0: '离线',
1: '在线',
})
const columns = ref([
{
title: '名称',
dataIndex: 'channelName',
key: 'channelName',
},
{
title: '归属',
dataIndex: 'managementUnitName',
width: '60%',
key: 'managementUnitName',
},
{
title: '操作',
dataIndex: 'operation',
width: '10%',
key: 'channelId',
},
])
// 西海岸--状态展示
if (isXiHaiAn) {
columns.value.splice(2, 0, {
title: '状态',
dataIndex: 'status',
width: '10%',
key: 'status',
})
}
const columns2 = ref([
{
title: '名称',
dataIndex: 'wrjName',
key: 'wrjName',
align: 'center',
},
{
title: '申请状态',
dataIndex: 'wrjState',
width: '60%',
key: 'wrjState',
align: 'center',
},
{
title: '操作',
dataIndex: 'operation',
width: '20%',
key: 'wrjName',
align: 'center',
},
])
const onSelectChange = (
record,
selected,
selectedRows,
nativeEvent,
type
) => {
record = JSON.parse(JSON.stringify(record))
if (selected) {
if (selectedRowKeys.value.length == 1000) {
message.warning('最多只能添加1000个摄像头')
} else {
selectedList.value.push(record)
selectedRowKeys.value.push(record.channelCode || record.channelId)
}
} else {
selectedList.value.forEach((ele, index) => {
if (ele.channelCode == record.channelCode) {
selectedList.value.splice(index, 1)
}
})
selectedRowKeys.value.splice(
selectedRowKeys.value.indexOf(record.channelCode || record.channelId),
1
)
}
mybus.emit('selectTablePoint', selectedList.value)
console.log('已选中======================>', selectedList.value)
}
const onSelectChange2 = (
record,
selected,
selectedRows,
nativeEvent,
type
) => {
console.log(
'已选中======================>',
record,
selected,
selectedRows,
nativeEvent,
type
)
if (selected) {
selectedRowKeys.value.push(record.name)
selectedRows.value.push(record.name)
} else {
selectedRowKeys.value.splice(
selectedRowKeys.value.indexOf(record.name),
1
)
selectedRows.value.splice(selectedRowKeys.value.indexOf(record.name), 1)
}
}
const onSelectAll = (selected, selectedRows, changeRows) => {
if (selected) {
changeRows.map((val) => {
selectedList.value.push(val)
selectedRowKeys.value.push(val.channelCode || val.channelId)
})
if (selectedRowKeys.value.length > 1000) {
message.warning('最多只能添加1000个摄像头')
changeRows.map((val) => {
selectedList.value.forEach((ele, index) => {
if (ele.channelCode == record.channelCode) {
selectedList.value.splice(index, 1)
}
})
selectedRowKeys.value.splice(
selectedRowKeys.value.indexOf(val.channelCode || val.channelId),
1
)
})
}
} else {
changeRows.map((val) => {
selectedList.value = selectedList.value.filter(
(item) => item.idtCameraChannel !== val.idtCameraChannel
)
selectedRowKeys.value.splice(
selectedRowKeys.value.indexOf(val.channelCode || val.channelId),
1
)
})
}
console.log('heiheiheiehiehei', selected, selectedRows, changeRows)
mybus.emit('selectTablePoint', selectedList.value)
}
const onSelectAll2 = (selected, selectedRows, changeRows) => {
console.log(selected, selectedRows, changeRows)
if (selected) {
} else {
}
}
// 切换tab
const handleTableChange = (val) => {
pagination.value.current = val.current
pagination.value.pageSize = val.pageSize
mapSearchParam.value.pageNum = val.current
mapSearchParam.value.pageSize = val.pageSize
let _arr =
clickList.value.filter(
(v) => v.content.includes('单兵设备') || v.content.includes('无人机')
) || []
let _tab_name = _arr[0] && _arr[0].content && _arr[0].content[0]
// 无人机、单兵设备
if (_tab_name) {
getSoldierData(0, _tab_name)
} else {
getCamera()
}
}
// 视频预览 提示
const videoShowMsg = (index) => {
let itemData = null
if (index) {
itemData = selectedList.value[index]
}
let msg = '请申请后在我的申请中观看视频!'
if (
(itemData && itemData.status != 1) ||
(rowClickData.value && rowClickData.value.status != 1)
) {
msg = '当前视频离线不可预览!'
} else {
msg = '请申请后在我的申请中观看视频!'
}
message.warning(msg)
}
// 获取用户信息
const userInfo = ref(null)
const handleUser = () => {
getUser()
.then((res) => {
if (res.data.code != 0) {
return message.warning(res.data.msg)
}
userInfo.value = res.data.data || {}
userInfo.value.usernameShow =
'西海岸能力超市' +
(userInfo.value.deptName || '') +
(userInfo.value.username || '')
userInfo.value.realNameShow =
'西海岸能力超市' +
(userInfo.value.deptName || '') +
(userInfo.value.realName || '')
})
.catch((err) => {
message.warning(err)
})
}
</script>
<style lang="less" scoped>
.infrastructrueBox {
padding: 0.2rem;
background: #ffffff;
border-bottom: 0.01rem solid rgba(150, 144, 144, 0.3);
.infrastructrue-tab {
span {
display: inline-block;
height: 0.24rem;
font-size: 0.14rem;
line-height: 0.24rem;
border: 0;
border-radius: 0.12rem;
margin-left: 0.1rem;
text-align: center;
color: #666666;
cursor: pointer;
padding: 0 0.08rem;
}
.leftType {
margin: 0.2rem 0;
margin-right: 0.06rem;
}
.down {
background: #0087ff;
color: #ffffff;
}
.tabBox {
padding-bottom: 0.16rem;
}
}
.infrastructrue-content {
display: flex;
justify-content: space-between;
padding: 0.14rem 0.2rem 0.1rem;
background: #ffffff;
.contentNum {
position: relative;
display: flex;
p {
color: #666666;
padding: 0;
margin: 0;
span {
color: #0087ff;
font-size: 0.2rem;
font-weight: 500;
}
}
p:first-of-type {
padding-right: 0.16rem;
margin-right: 0.16rem;
}
.boundary {
position: absolute;
left: 0.9rem;
top: 0.07rem;
display: block;
width: 0.02rem;
border-radius: 0.01rem;
height: 0.2rem;
background: rgba(150, 144, 144, 0.3);
}
}
.contentRight {
position: relative;
display: flex;
justify-content: space-between;
.boundary {
position: absolute;
left: 3.74rem;
top: 0.07rem;
display: block;
width: 0.02rem;
border-radius: 0.01rem;
height: 0.2rem;
background: rgba(150, 144, 144, 0.3);
}
.searchInput {
display: flex;
margin-right: 0.2rem;
.ant-input-search {
max-width: 4rem;
}
:deep(.ant-input) {
width: 2rem;
height: 0.36rem;
font-size: 0.14rem;
color: #b2b2b2;
background: #f5f5f5;
}
:deep(.ant-input-group-addon) {
display: inline-block;
margin-left: 0.1rem;
.ant-input-search-button {
width: 0.8rem;
height: 0.36rem;
background: #0558e1;
border-radius: 0.04rem;
font-size: 0.14rem;
}
}
:deep(.ant-btn) {
background: #0558e1;
border-radius: 0.04rem;
}
}
.buttonAdd {
background: #0558e1;
border-radius: 0.04rem;
height: 0.36rem;
border-color: #0558e1;
margin-left: 0.1rem;
}
}
}
.infrastructrue-table {
.ant-table-striped :deep(.table-striped) td {
background-color: #fafafa;
}
}
.map-contain {
// width: 9.46rem;
height: 4.1rem;
margin-left: 0.16rem;
position: relative;
}
}
.roomBackground {
background: #0058e1;
color: #ffffff;
}
.nullBackground {
background: #f3f5f9;
color: #0087ff;
}
:deep(.ant-form-item-control-input-content) {
margin-left: 0.15rem;
}
:deep(.ant-col) {
.ant-form-item {
margin-bottom: 0;
}
}
.jinggaoD {
display: flex;
align-items: center;
}
.jinggaoNull {
display: none;
}
.imgJinggao {
width: 0.2rem;
height: 0.2rem;
background: url('~@/assets/home/jingao.png') no-repeat;
background-size: 100%;
}
.introduction {
width: unset;
button {
height: 30px;
width: 120px;
border: 1px solid #bbd3ef;
border-radius: 6px;
background: #edf4fc;
color: #0087ff;
font-size: 14px;
}
:deep(.ant-form-item-control) {
margin-left: -2.1rem;
}
}
.roomBox {
.leftMake {
float: left;
margin-left: -1rem;
margin-top: -0.5rem;
font-size: 0.2rem;
cursor: pointer;
.leftTop {
width: 0.6rem;
height: 1.75rem;
border-top-left-radius: 0.08rem;
border-bottom-left-radius: 0.08rem;
padding: 0.13rem;
text-align: center;
}
.leftBottom {
width: 0.6rem;
height: 1.75rem;
border-top-left-radius: 0.08rem;
border-bottom-left-radius: 0.08rem;
padding: 0.2rem 0.13rem 0.1rem 0.1rem;
text-align: center;
}
}
.roomSearch {
display: flex;
align-items: center;
.searchInput {
display: flex;
margin-right: 0.2rem;
margin-left: 0.2rem;
// .ant-input-search {
// max-width: 4rem;
// }
:deep(.ant-input) {
width: 2rem;
height: 0.36rem;
font-size: 0.14rem;
color: #b2b2b2;
background: #f5f5f5;
}
:deep(.ant-input-group-addon) {
display: inline-block;
margin-left: 0.1rem;
.ant-input-search-button {
width: 0.8rem;
height: 0.36rem;
background: #0558e1;
border-radius: 0.06rem;
font-size: 0.14rem;
}
}
:deep(.ant-btn) {
border-radius: 0.06rem;
}
}
}
.roomTableList {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0.4rem 0 0.2rem 0;
.roomTime {
display: flex;
align-items: center;
:deep(.ant-space-vertical) {
flex-direction: inherit;
margin-left: 0.2rem;
}
}
}
.roomItem {
width: 10.3rem;
height: 2rem;
border-top: 1px #d5d4d4 solid;
display: flex;
align-items: center;
.leftImg {
width: 2.4rem;
height: 1.75rem;
margin: 0 0.3rem 0 0.15rem;
// background: url('~@/assets/home/yyzy_square.png') no-repeat;
background-size: 100%;
img {
width: 100%;
height: 100%;
}
}
.rightContent {
height: 1.75rem;
width: 5.8rem;
.topContent {
font-size: 0.2rem;
color: #000;
font-weight: 600;
}
.centerContent {
display: flex;
justify-content: space-between;
font-size: 0.14rem;
margin: 0.15rem 0 0.2rem 0;
}
.bottonmContent {
width: 100%;
overflow: hidden; //超出隐藏
text-overflow: ellipsis; //超出文本设置为...
display: -webkit-box; //将div1转换为盒子模型
-webkit-line-clamp: 3; //设置div1的文本为2行
-webkit-box-orient: vertical; //从顶部向底部垂直布置子元素
}
}
}
:deep(.ant-pagination) {
float: right;
}
:deep(.ant-pagination) {
text-align: end;
}
}
:deep(.ant-table-thead > tr > th) {
color: #5580f7 !important;
font-size: 16px !important;
font-weight: 600 !important;
}
</style>
<style lang="less">
.wrj {
.ant-modal-body {
height: 700px !important;
overflow-y: auto;
}
}
.modalClass {
.ant-modal-body {
height: 4rem !important;
overflow-y: scroll !important;
}
.ant-modal-title {
font-weight: 600;
}
.ant-modal-content {
.ant-modal-header {
border-bottom: 0 !important;
}
}
}
.appModal {
.ant-modal-body {
height: 4.8rem !important;
overflow-y: scroll !important;
}
.ant-modal-title {
font-weight: 600;
}
.ant-modal-content {
.ant-modal-header {
border-bottom: 0 !important;
}
}
}
.single-preview-modal {
.ant-modal-header {
background: url(~@/assets/home/video-background.png) no-repeat;
background-size: cover;
}
.ant-modal-title {
font-size: 0.16rem;
font-weight: 500;
color: #ffffff;
}
.anticon {
color: #ffffff;
}
}
.batch-preview-modal {
.batch-video {
width: 100%;
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
justify-content: center;
grid-row-gap: 10px;
grid-column-gap: 10px;
}
.ant-pagination-item-link {
background-color: #5580f7;
}
.ant-modal-header {
background: url(~@/assets/home/video-background.png) no-repeat;
background-size: cover;
}
.ant-modal-title {
font-size: 0.16rem;
font-weight: 500;
color: #ffffff;
}
.anticon {
color: #ffffff;
}
}
/*禁用video的controls要慎重不要轻易隐藏掉会导致点击视频不能播放*/
video::-webkit-media-controls {
display: none !important;
}
.video-cover {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
background: transparent;
z-index: 99999999;
cursor: pointer;
}
.batch-video-cover {
position: absolute;
left: 0;
top: 0;
background: transparent;
height: 288px;
z-index: 99999999;
width: 512px;
margin-top: 14px;
cursor: pointer;
}
.waterMark {
position: absolute;
z-index: 99999999;
color: #0058e1;
font-size: 22px;
font-weight: bold;
opacity: 0.4;
transform: rotate(-25deg);
width: 470px;
}
// 左上
.waterMark-left-top {
left: 50px;
top: 100px;
text-align: left;
}
// 右上
.waterMark-right-top {
right: 50px;
top: 100px;
text-align: right;
}
// 左下
.waterMark-left-bottom {
left: 50px;
bottom: 100px;
text-align: left;
}
// 右下
.waterMark-right-bottom {
right: 50px;
bottom: 100px;
text-align: right;
}
// 批量
.batch-waterMark {
position: absolute;
z-index: 99999999;
color: #0058e1;
font-size: 14px;
opacity: 0.4;
transform: rotate(-25deg);
width: 200px;
}
// 左上
.batch-waterMark-left-top {
left: 30px;
top: 50px;
text-align: left;
}
// 右上
.batch-waterMark-right-top {
text-align: right;
right: 30px;
top: 80px;
}
// 左下
.batch-waterMark-left-bottom {
left: 30px;
bottom: 50px;
text-align: left;
}
// 右下
.batch-waterMark-right-bottom {
right: 20px;
bottom: 30px;
text-align: right;
}
.disabled-text {
cursor: not-allowed;
opacity: 0.5;
color: #666666;
&:hover {
color: #666666;
}
}
</style>