update: 通知管理,视频中心所有页面表格撑满屏幕

This commit is contained in:
JiangQiming 2023-03-30 17:06:04 +08:00
parent 8239b2c308
commit f960e2df76
8 changed files with 1093 additions and 1029 deletions

View File

@ -2,149 +2,153 @@
<template> <template>
<page-container> <page-container>
<pro-search :columns="columns" target="media" @search="handleSearch" /> <pro-search :columns="columns" target="media" @search="handleSearch" />
<FullPage>
<JProTable <JProTable
ref="listRef" ref="listRef"
model="table" model="table"
:columns="columns" :columns="columns"
:request="(e:any) => CascadeApi.queryBindChannel(route?.query.id as string, e)" :request="(e:any) => CascadeApi.queryBindChannel(route?.query.id as string, e)"
:defaultParams="{ :defaultParams="{
pageSize: 10, pageSize: 10,
sorts: [{ name: 'name', order: 'desc' }], sorts: [{ name: 'name', order: 'desc' }],
}" }"
:params="params" :params="params"
:rowSelection="{ :rowSelection="{
selectedRowKeys: _selectedRowKeys, selectedRowKeys: _selectedRowKeys,
onChange: onSelectChange, onChange: onSelectChange,
}" }"
@cancelSelect="_selectedRowKeys = []" @cancelSelect="_selectedRowKeys = []"
:pagination="{ :pagination="{
showSizeChanger: true, showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'], pageSizeOptions: ['10', '20', '50', '100'],
}" }"
> >
<template #headerTitle> <template #headerTitle>
<h3>通道列表</h3> <h3>通道列表</h3>
</template> </template>
<template #rightExtraRender> <template #rightExtraRender>
<j-space>
<j-button type="primary" @click="bindVis = true">
绑定通道
</j-button>
<j-popconfirm
title="确认解绑?"
@confirm="handleMultipleUnbind"
>
<j-button> 批量解绑 </j-button>
</j-popconfirm>
</j-space>
</template>
<template #gbChannelIdHeader="title">
<j-tooltip
title="国标级联有16位、20位两种格式。在当前页面修改不会修改视频设备-通道页面中的国标ID"
>
<j-space> <j-space>
<span>{{ title }}</span> <j-button type="primary" @click="bindVis = true">
<AIcon type="InfoCircleOutlined" /> 绑定通道
</j-space>
</j-tooltip>
</template>
<template #channelId="slotProps">
<j-space>
<Ellipsis style="width: 150px">
{{ slotProps.gbChannelId }}
</Ellipsis>
<j-popover
v-model:visible="slotProps.popVis"
trigger="click"
>
<template #title>
<div class="header">
<span>编辑国标ID</span>
<AIcon
type="CloseOutlined"
@click="handleClose(slotProps)"
/>
</div>
</template>
<template #content>
<div class="simple-form">
<j-input
v-model:value="gbID"
@change="validField(slotProps)"
placeholder="请输入国标ID"
/>
<div
class="error"
v-if="valid && !valid?.passed"
>
<!-- {{ valid?.reason }} -->
该国标ID在同一设备下已存在
</div>
</div>
<j-button
type="primary"
@click="handleSave(slotProps)"
:loading="loading"
style="width: 100%"
>
保存
</j-button>
</template>
<j-button type="link" @click="slotProps.popVis = true">
<AIcon type="EditOutlined" />
</j-button> </j-button>
</j-popover>
</j-space>
</template>
<template #status="slotProps">
<j-space>
<j-badge
:status="
slotProps.status.value === 'online'
? 'success'
: 'error'
"
:text="slotProps.status.text"
></j-badge>
</j-space>
</template>
<template #action="slotProps">
<j-space :size="16">
<j-tooltip
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
v-bind="i.tooltip"
>
<j-popconfirm <j-popconfirm
v-if="i.popConfirm" title="确认解绑?"
v-bind="i.popConfirm" @confirm="handleMultipleUnbind"
:disabled="i.disabled"
> >
<j-button <j-button> 批量解绑 </j-button>
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></j-button>
</j-popconfirm> </j-popconfirm>
<j-button </j-space>
style="padding: 0" </template>
type="link" <template #gbChannelIdHeader="title">
v-else <j-tooltip
@click="i.onClick && i.onClick(slotProps)" title="国标级联有16位、20位两种格式。在当前页面修改不会修改视频设备-通道页面中的国标ID"
>
<j-space>
<span>{{ title }}</span>
<AIcon type="InfoCircleOutlined" />
</j-space>
</j-tooltip>
</template>
<template #channelId="slotProps">
<j-space>
<Ellipsis style="width: 150px">
{{ slotProps.gbChannelId }}
</Ellipsis>
<j-popover
v-model:visible="slotProps.popVis"
trigger="click"
> >
<template #title>
<div class="header">
<span>编辑国标ID</span>
<AIcon
type="CloseOutlined"
@click="handleClose(slotProps)"
/>
</div>
</template>
<template #content>
<div class="simple-form">
<j-input
v-model:value="gbID"
@change="validField(slotProps)"
placeholder="请输入国标ID"
/>
<div
class="error"
v-if="valid && !valid?.passed"
>
<!-- {{ valid?.reason }} -->
该国标ID在同一设备下已存在
</div>
</div>
<j-button
type="primary"
@click="handleSave(slotProps)"
:loading="loading"
style="width: 100%"
>
保存
</j-button>
</template>
<j-button <j-button
type="link"
@click="slotProps.popVis = true"
>
<AIcon type="EditOutlined" />
</j-button>
</j-popover>
</j-space>
</template>
<template #status="slotProps">
<j-space>
<j-badge
:status="
slotProps.status.value === 'online'
? 'success'
: 'error'
"
:text="slotProps.status.text"
></j-badge>
</j-space>
</template>
<template #action="slotProps">
<j-space :size="16">
<j-tooltip
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
v-bind="i.tooltip"
>
<j-popconfirm
v-if="i.popConfirm"
v-bind="i.popConfirm"
:disabled="i.disabled" :disabled="i.disabled"
>
<j-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></j-button>
</j-popconfirm>
<j-button
style="padding: 0" style="padding: 0"
type="link" type="link"
><AIcon :type="i.icon" v-else
/></j-button> @click="i.onClick && i.onClick(slotProps)"
</j-button> >
</j-tooltip> <j-button
</j-space> :disabled="i.disabled"
</template> style="padding: 0"
</JProTable> type="link"
><AIcon :type="i.icon"
/></j-button>
</j-button>
</j-tooltip>
</j-space>
</template>
</JProTable>
</FullPage>
<BindChannel v-model:visible="bindVis" @submit="listRef.reload()" /> <BindChannel v-model:visible="bindVis" @submit="listRef.reload()" />
</page-container> </page-container>

View File

@ -5,139 +5,146 @@
target="media-cascade" target="media-cascade"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="listRef" ref="listRef"
:columns="columns" :columns="columns"
:request="(e:any) => lastValueFrom(e)" :request="(e:any) => lastValueFrom(e)"
:defaultParams="{ :defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }], sorts: [{ name: 'createTime', order: 'desc' }],
}" }"
:params="params" :params="params"
:gridColumn="2" :gridColumn="2"
> >
<template #headerTitle> <template #headerTitle>
<PermissionButton <PermissionButton
type="primary" type="primary"
@click="handleAdd" @click="handleAdd"
hasPermission="media/Cascade:add" hasPermission="media/Cascade:add"
>
<template #icon><AIcon type="PlusOutlined" />新增</template>
</PermissionButton>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
:actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:showStatus="true"
:status="slotProps.status?.value"
:statusText="slotProps.status?.text"
:statusNames="{
enabled: 'success',
disabled: 'error',
}"
>
<template #img>
<slot name="img">
<img
:src="
getImage('/device/instance/device-card.png')
"
/>
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<p>通道数量{{ slotProps.count || 0 }}</p>
<Ellipsis>
<j-badge
:text="`sip:${slotProps.sipConfigs[0]?.sipId}@${slotProps.sipConfigs[0]?.hostAndPort}`"
:status="
slotProps.status?.value === 'enabled'
? 'success'
: 'error'
"
/>
</Ellipsis>
</template>
<template #actions="item">
<PermissionButton
:disabled="item.disabled"
:popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="'media/Cascade:' + item.key"
>
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item?.text }}</span>
</template>
</PermissionButton>
</template>
</CardBox>
</template>
<template #sipId="slotProps">
{{ slotProps.sipConfigs[0]?.sipId }}
</template>
<template #publicHost="slotProps">
{{ slotProps.sipConfigs[0]?.publicHost }}
</template>
<template #count="slotProps">
{{ slotProps.count || 0 }}
</template>
<template #status="slotProps">
<j-badge
:text="slotProps.status?.text"
:status="
slotProps.status?.value === 'enabled'
? 'success'
: 'error'
"
/>
</template>
<template #onlineStatus="slotProps">
<j-badge
:text="slotProps.onlineStatus?.text"
:status="
slotProps.onlineStatus?.value === 'online'
? 'success'
: 'error'
"
/>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
> >
<PermissionButton <template #icon
:danger="i.key === 'delete'" ><AIcon type="PlusOutlined" />新增</template
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'media/Cascade:' + i.key"
> >
<template #icon><AIcon :type="i.icon" /></template> </PermissionButton>
</PermissionButton> </template>
</template> <template #card="slotProps">
</j-space> <CardBox
</template> :value="slotProps"
</JProTable> :actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:showStatus="true"
:status="slotProps.status?.value"
:statusText="slotProps.status?.text"
:statusNames="{
enabled: 'success',
disabled: 'error',
}"
>
<template #img>
<slot name="img">
<img
:src="
getImage(
'/device/instance/device-card.png',
)
"
/>
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<p>通道数量{{ slotProps.count || 0 }}</p>
<Ellipsis>
<j-badge
:text="`sip:${slotProps.sipConfigs[0]?.sipId}@${slotProps.sipConfigs[0]?.hostAndPort}`"
:status="
slotProps.status?.value === 'enabled'
? 'success'
: 'error'
"
/>
</Ellipsis>
</template>
<template #actions="item">
<PermissionButton
:disabled="item.disabled"
:popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="'media/Cascade:' + item.key"
>
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item?.text }}</span>
</template>
</PermissionButton>
</template>
</CardBox>
</template>
<template #sipId="slotProps">
{{ slotProps.sipConfigs[0]?.sipId }}
</template>
<template #publicHost="slotProps">
{{ slotProps.sipConfigs[0]?.publicHost }}
</template>
<template #count="slotProps">
{{ slotProps.count || 0 }}
</template>
<template #status="slotProps">
<j-badge
:text="slotProps.status?.text"
:status="
slotProps.status?.value === 'enabled'
? 'success'
: 'error'
"
/>
</template>
<template #onlineStatus="slotProps">
<j-badge
:text="slotProps.onlineStatus?.text"
:status="
slotProps.onlineStatus?.value === 'online'
? 'success'
: 'error'
"
/>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<PermissionButton
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'media/Cascade:' + i.key"
>
<template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</FullPage>
<Publish v-model:visible="publishVis" :data="currentData" /> <Publish v-model:visible="publishVis" :data="currentData" />
</page-container> </page-container>

View File

@ -24,101 +24,109 @@
target="channel" target="channel"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="listRef" ref="listRef"
model="table" model="table"
:columns="columns" :columns="columns"
:request="(e:any) => ChannelApi.list(e, route?.query.id as string)" :request="(e:any) => ChannelApi.list(e, route?.query.id as string)"
:defaultParams="{ :defaultParams="{
pageSize: 10, pageSize: 10,
sorts: [{ name: 'notifyTime', order: 'desc' }], sorts: [{ name: 'notifyTime', order: 'desc' }],
}" }"
:params="params" :params="params"
:pagination="{ :pagination="{
showSizeChanger: true, showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'], pageSizeOptions: ['10', '20', '50', '100'],
}" }"
> >
<template #headerTitle> <template #headerTitle>
<j-tooltip <j-tooltip
v-if="route?.query.type === 'gb28181-2016'" v-if="route?.query.type === 'gb28181-2016'"
title="接入方式为GB/T28281时不支持新增" title="接入方式为GB/T28281时不支持新增"
>
<j-button type="primary" disabled> 新增 </j-button>
</j-tooltip>
<PermissionButton
type="primary"
@click="handleAdd"
hasPermission="media/Device:add"
>
<template #icon
><AIcon type="PlusOutlined" />新增</template
> >
</PermissionButton> <j-button type="primary" disabled>
</template> 新增
<template #status="slotProps"> </j-button>
<j-space> </j-tooltip>
<j-badge <PermissionButton
:status=" v-else
slotProps.status.value === 'online' type="primary"
? 'success' @click="handleAdd"
: 'error' hasPermission="media/Device:add"
"
:text="slotProps.status.text"
></j-badge>
</j-space>
</template>
<template #action="slotProps">
<j-space>
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
> >
<PermissionButton <template #icon
v-if=" ><AIcon type="PlusOutlined" />新增</template
i.key !== 'play' && i.key !== 'backPlay'
"
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'media/Device:' + i.key"
> >
<template #icon </PermissionButton>
><AIcon :type="i.icon" </template>
/></template> <template #status="slotProps">
</PermissionButton> <j-space>
<!-- 回放/播放不要权限控制 --> <j-badge
<template v-else> :status="
<j-tooltip :key="i.key" v-bind="i.tooltip"> slotProps.status.value === 'online'
<j-button ? 'success'
style="padding: 0px" : 'error'
type="link" "
@click=" :text="slotProps.status.text"
i.onClick && ></j-badge>
i.onClick(slotProps) </j-space>
" </template>
<template #action="slotProps">
<j-space>
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<PermissionButton
v-if="
i.key !== 'play' &&
i.key !== 'backPlay'
"
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'media/Device:' + i.key"
>
<template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton>
<!-- 回放/播放不要权限控制 -->
<template v-else>
<j-tooltip
:key="i.key"
v-bind="i.tooltip"
> >
<j-button <j-button
:disabled="i.disabled" style="padding: 0px"
style="padding: 0"
type="link" type="link"
@click="
i.onClick &&
i.onClick(slotProps)
"
> >
<AIcon :type="i.icon" /> <j-button
:disabled="i.disabled"
style="padding: 0"
type="link"
>
<AIcon :type="i.icon" />
</j-button>
</j-button> </j-button>
</j-button> </j-tooltip>
</j-tooltip> </template>
</template> </template>
</template> </j-space>
</j-space> </template>
</template> </JProTable>
</JProTable> </FullPage>
</div> </div>
</div> </div>

View File

@ -1,186 +1,191 @@
<!-- 回放 --> <!-- 回放 -->
<template> <template>
<page-container> <page-container>
<div class="playback-warp"> <FullPage>
<!-- 播放器/进度条 --> <div class="playback-warp">
<div class="playback-left"> <!-- 播放器/进度条 -->
<LivePlayer <div class="playback-left">
ref="player" <LivePlayer
autoplay ref="player"
:url="url" autoplay
className="playback-media" :url="url"
:live="type === 'local'" className="playback-media"
:on-play=" :live="type === 'local'"
() => { :on-play="
isEnded = false; () => {
playStatus = 1; isEnded = false;
} playStatus = 1;
"
:on-pause="
() => {
playStatus = 2;
}
"
:on-ended="
() => {
playStatus = 0;
if (playTimeNode && isEnded) {
isEnded = true;
playTimeNode.onNextPlay();
} }
} "
" :on-pause="
:on-error=" () => {
() => { playStatus = 2;
playStatus = 0; }
} "
" :on-ended="
:on-time-update=" () => {
(e: any) => { playStatus = 0;
playTime = e; if (playTimeNode && isEnded) {
} isEnded = true;
" playTimeNode.onNextPlay();
/> }
<TimeLine }
ref="playTimeNode" "
:type="type" :on-error="
:data="historyList" () => {
:date-time="time" playStatus = 0;
:on-change="handleTimeLineChange" }
:play-status="playStatus" "
:play-time="playNowTime + playTime * 1000" :on-time-update="
:local-to-server="cloudTime" (e: any) => {
/> playTime = e;
</div> }
<div class="playback-right"> "
<j-spin :spinning="loading">
<j-tooltip placement="topLeft">
<template #title>
<div>云端存储在服务器中</div>
<div>本地存储在设备本地</div>
</template>
<div>类型: <AIcon type="QuestionCircleOutlined" /></div>
</j-tooltip>
<RadioCard
layout="horizontal"
:options="[
{
label: '云端',
value: 'cloud',
logo: getImage('/media/cloud.png'),
},
{
label: '本地',
value: 'local',
logo: getImage('/local.png'),
disabled: deviceType === 'fixed-media',
},
]"
:checkStyle="true"
v-model="type"
/> />
<div class="playback-calendar"> <TimeLine
<j-calendar ref="playTimeNode"
v-model:value="time" :type="type"
:fullscreen="false" :data="historyList"
:disabledDate=" :date-time="time"
(currentDate: Dayjs) => currentDate > dayjs(new Date()) :on-change="handleTimeLineChange"
" :play-status="playStatus"
@change="handlePanelChange" :play-time="playNowTime + playTime * 1000"
:local-to-server="cloudTime"
/>
</div>
<div class="playback-right">
<j-spin :spinning="loading">
<j-tooltip placement="topLeft">
<template #title>
<div>云端存储在服务器中</div>
<div>本地存储在设备本地</div>
</template>
<div>
类型: <AIcon type="QuestionCircleOutlined" />
</div>
</j-tooltip>
<RadioCard
layout="horizontal"
:options="[
{
label: '云端',
value: 'cloud',
logo: getImage('/media/cloud.png'),
},
{
label: '本地',
value: 'local',
logo: getImage('/local.png'),
disabled: deviceType === 'fixed-media',
},
]"
:checkStyle="true"
v-model="type"
/> />
</div> <div class="playback-calendar">
<div <j-calendar
class="playback-list" v-model:value="time"
:class="{ 'no-list': !historyList.length }" :fullscreen="false"
> :disabledDate="
<j-empty (currentDate: Dayjs) => currentDate > dayjs(new Date())
v-if="!historyList.length" "
description="暂无数据" @change="handlePanelChange"
/> />
<j-list </div>
v-else <div
class="playback-list-items" class="playback-list"
itemLayout="horizontal" :class="{ 'no-list': !historyList.length }"
:dataSource="historyList"
> >
<template #renderItem="{ item }"> <j-empty
<j-list-item> v-if="!historyList.length"
<template #actions> description="暂无数据"
<j-tooltip />
key="play-btn" <j-list
:title=" v-else
(item.startTime || class="playback-list-items"
item.mediaStartTime) === itemLayout="horizontal"
playNowTime && :dataSource="historyList"
playStatus === 1 >
? '暂停' <template #renderItem="{ item }">
: '播放' <j-list-item>
" <template #actions>
> <j-tooltip
<a key="play-btn"
@click=" :title="
handlePlay( (item.startTime ||
item.startTime || item.mediaStartTime) ===
item.mediaStartTime, playNowTime &&
) playStatus === 1
? '暂停'
: '播放'
" "
> >
<AIcon <a
:type=" @click="
(item.startTime || handlePlay(
item.mediaStartTime) === item.startTime ||
playNowTime && item.mediaStartTime,
playStatus === 1 )
? 'PauseCircleOutlined' "
: 'PlayCircleOutlined' >
<AIcon
:type="
(item.startTime ||
item.mediaStartTime) ===
playNowTime &&
playStatus === 1
? 'PauseCircleOutlined'
: 'PlayCircleOutlined'
"
/>
</a>
</j-tooltip>
<j-tooltip
key="download"
:title="
type !== 'local'
? '下载录像文件'
: item.isServer
? '查看'
: '下载到云端'
"
>
<IconNode
:type="type"
:item="item"
:on-cloud-view="cloudView"
:on-down-load="
() =>
downloadClick(item)
" "
/> />
</a> </j-tooltip>
</j-tooltip> </template>
<j-tooltip
key="download"
:title="
type !== 'local'
? '下载录像文件'
: item.isServer
? '查看'
: '下载到云端'
"
>
<IconNode
:type="type"
:item="item"
:on-cloud-view="cloudView"
:on-down-load="
() => downloadClick(item)
"
/>
</j-tooltip>
</template>
<div> <div>
{{ {{
dayjs( dayjs(
item.startTime || item.startTime ||
item.mediaStartTime, item.mediaStartTime,
).format('HH:mm:ss') ).format('HH:mm:ss')
}} }}
~ ~
{{ {{
dayjs( dayjs(
item.endTime || item.endTime ||
item.mediaEndTime, item.mediaEndTime,
).format('HH:mm:ss') ).format('HH:mm:ss')
}} }}
</div> </div>
</j-list-item> </j-list-item>
</template> </template>
<div></div> <div></div>
</j-list> </j-list>
</div> </div>
</j-spin> </j-spin>
</div>
</div> </div>
</div> </FullPage>
</page-container> </page-container>
</template> </template>
@ -216,7 +221,7 @@ const deviceType = ref('');
/** /**
* 查询本地视频 * 查询本地视频
* @param date * @param date
*/ */
const queryLocalRecords = async (date: Dayjs) => { const queryLocalRecords = async (date: Dayjs) => {
playStatus.value = 0; playStatus.value = 0;

View File

@ -5,146 +5,159 @@
target="notice-config" target="notice-config"
@search="handleSearch" @search="handleSearch"
/> />
<JProTable <FullPage>
ref="listRef" <JProTable
:columns="columns" ref="listRef"
:request="DeviceApi.list" :columns="columns"
:defaultParams="{ :request="DeviceApi.list"
sorts: [{ name: 'createTime', order: 'desc' }], :defaultParams="{
}" sorts: [{ name: 'createTime', order: 'desc' }],
:params="params" }"
:gridColumn="4" :params="params"
> :gridColumn="4"
<template #headerTitle> >
<PermissionButton <template #headerTitle>
type="primary" <PermissionButton
@click="handleAdd" type="primary"
hasPermission="media/Device:add" @click="handleAdd"
> hasPermission="media/Device:add"
<template #icon><AIcon type="PlusOutlined" />新增</template>
</PermissionButton>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
:actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:showStatus="true"
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{ online: 'processing', offline: 'error' }"
>
<template #img>
<slot name="img">
<img :src="getImage('/device-media.png')" />
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<j-row>
<j-col :span="12">
<div class="card-item-content-text">厂商</div>
<div>{{ slotProps.manufacturer }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
通道数量
</div>
<div>{{ slotProps.channelNumber }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">型号</div>
<div>{{ slotProps.model }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
接入方式
</div>
<div>
{{ providerType[slotProps.provider] }}
</div>
</j-col>
</j-row>
</template>
<template #actions="item">
<PermissionButton
:disabled="item.disabled"
:popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="
'media/Device:' +
(item.key !== 'updateChannel'
? item.key
: 'update')
"
>
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item?.text }}</span>
</template>
</PermissionButton>
</template>
</CardBox>
</template>
<template #channelNumber="slotProps">
{{ slotProps.channelNumber || 0 }}
</template>
<template #provider="slotProps">
{{ providerType[slotProps.provider] }}
</template>
<template #productId="slotProps">
{{ getProductName(slotProps.productId) }}
</template>
<template #state="slotProps">
<j-badge
:text="slotProps.state?.text"
:status="
slotProps.state?.value === 'online'
? 'success'
: 'error'
"
/>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
> >
<PermissionButton <template #icon
:danger="i.key === 'delete'" ><AIcon type="PlusOutlined" />新增</template
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="
'media/Device:' +
(i.key !== 'updateChannel' &&
i.key !== 'viewDevice'
? i.key
: 'update')
"
> >
<template #icon><AIcon :type="i.icon" /></template> </PermissionButton>
</PermissionButton> </template>
</template> <template #card="slotProps">
</j-space> <CardBox
</template> :value="slotProps"
</JProTable> :actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:showStatus="true"
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{
online: 'processing',
offline: 'error',
}"
>
<template #img>
<slot name="img">
<img :src="getImage('/device-media.png')" />
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<j-row>
<j-col :span="12">
<div class="card-item-content-text">
厂商
</div>
<div>{{ slotProps.manufacturer }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
通道数量
</div>
<div>{{ slotProps.channelNumber }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
型号
</div>
<div>{{ slotProps.model }}</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
接入方式
</div>
<div>
{{ providerType[slotProps.provider] }}
</div>
</j-col>
</j-row>
</template>
<template #actions="item">
<PermissionButton
:disabled="item.disabled"
:popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="
'media/Device:' +
(item.key !== 'updateChannel'
? item.key
: 'update')
"
>
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item?.text }}</span>
</template>
</PermissionButton>
</template>
</CardBox>
</template>
<template #channelNumber="slotProps">
{{ slotProps.channelNumber || 0 }}
</template>
<template #provider="slotProps">
{{ providerType[slotProps.provider] }}
</template>
<template #productId="slotProps">
{{ getProductName(slotProps.productId) }}
</template>
<template #state="slotProps">
<j-badge
:text="slotProps.state?.text"
:status="
slotProps.state?.value === 'online'
? 'success'
: 'error'
"
/>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<PermissionButton
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="
'media/Device:' +
(i.key !== 'updateChannel' &&
i.key !== 'viewDevice'
? i.key
: 'update')
"
>
<template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</FullPage>
</page-container> </page-container>
</template> </template>

View File

@ -1,23 +1,28 @@
<template> <template>
<page-container> <page-container>
<j-card class="splitScreen"> <FullPage>
<div class="split-screen"> <j-card class="splitScreen">
<LeftTree @onSelect="mediaStart" /> <div class="split-screen">
<div class="right-content"> <LeftTree @onSelect="mediaStart" />
<ScreenPlayer <div class="right-content">
ref="player" <ScreenPlayer
:id="deviceId" ref="player"
:channelId="channelId" :id="deviceId"
:onMouseUp="(id, cId) => channelApi.ptzStop(id, cId)" :channelId="channelId"
:onMouseDown=" :onMouseUp="
(id, cId, type) => channelApi.ptzTool(id, cId, type) (id, cId) => channelApi.ptzStop(id, cId)
" "
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)" :onMouseDown="
showScreen (id, cId, type) =>
/> channelApi.ptzTool(id, cId, type)
"
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)"
showScreen
/>
</div>
</div> </div>
</div> </j-card>
</j-card> </FullPage>
</page-container> </page-container>
</template> </template>
@ -32,8 +37,8 @@ const player = ref();
/** /**
* 获取视频链接 * 获取视频链接
* @param dId * @param dId
* @param cId * @param cId
*/ */
const getMediaUrl = (dId: string, cId: string): string => { const getMediaUrl = (dId: string, cId: string): string => {
return channelApi.ptzStart(dId, cId, 'mp4'); return channelApi.ptzStart(dId, cId, 'mp4');
@ -41,7 +46,7 @@ const getMediaUrl = (dId: string, cId: string): string => {
/** /**
* 点击左侧摄像头, 播放对应视频 * 点击左侧摄像头, 播放对应视频
* @param e * @param e
*/ */
const mediaStart = (e: { cId: string; dId: string }) => { const mediaStart = (e: { cId: string; dId: string }) => {
channelId.value = e.cId; channelId.value = e.cId;

View File

@ -6,185 +6,198 @@
target="notice-config" target="notice-config"
@search="handleSearch" @search="handleSearch"
/> />
<JProTable <FullPage>
ref="configRef" <JProTable
:columns="columns" ref="configRef"
:request="ConfigApi.list" :columns="columns"
:defaultParams="{ :request="ConfigApi.list"
sorts: [{ name: 'createTime', order: 'desc' }], :defaultParams="{
}" sorts: [{ name: 'createTime', order: 'desc' }],
:params="params" }"
:gridColumn="3" :params="params"
> :gridColumn="3"
<template #headerTitle> >
<j-space> <template #headerTitle>
<PermissionButton <j-space>
type="primary"
@click="handleAdd"
hasPermission="notice/Config:add"
>
新增
</PermissionButton>
<j-upload
name="file"
accept=".json"
:showUploadList="false"
:before-upload="beforeUpload"
>
<PermissionButton hasPermission="notice/Config:import">
导入
</PermissionButton>
</j-upload>
<j-popconfirm
title="确认导出?"
ok-text="确定"
cancel-text="取消"
@confirm="handleExport"
>
<PermissionButton hasPermission="notice/Config:export">
导出
</PermissionButton>
</j-popconfirm>
</j-space>
</template>
<template #card="slotProps">
<CardBox
:showStatus="false"
:statusNames="{}"
:value="slotProps"
:actions="getActions(slotProps, 'card')"
>
<template #img>
<slot name="img">
<img
:src="
getLogo(slotProps.type, slotProps.provider)
"
class="logo"
/>
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<j-row>
<j-col :span="12">
<div class="card-item-content-text">
通知方式
</div>
<div>
{{ getMethodTxt(slotProps.type) }}
</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">说明</div>
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</j-col>
</j-row>
</template>
<template #actions="item">
<j-tooltip
v-bind="item.tooltip"
:title="item.disabled && item.tooltip.title"
>
<j-dropdown
placement="bottomRight"
v-if="item.key === 'others'"
>
<j-button>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</j-button>
<template #overlay>
<j-menu>
<j-menu-item
v-for="(o, i) in item.children"
:key="i"
>
<PermissionButton
type="link"
@click="o.onClick"
:hasPermission="`notice/Config:${o.key}`"
>
<template #icon>
<AIcon :type="o.icon" />
</template>
<span>{{ o.text }}</span>
</PermissionButton>
</j-menu-item>
</j-menu>
</template>
</j-dropdown>
<j-popconfirm
v-else-if="item.key === 'delete'"
v-bind="item.popConfirm"
:disabled="item.disabled"
>
<PermissionButton
:disabled="item.disabled"
:hasPermission="`notice/Config:${item.key}`"
>
<template #icon>
<AIcon type="DeleteOutlined" />
</template>
</PermissionButton>
</j-popconfirm>
<template v-else>
<PermissionButton
:disabled="item.disabled"
@click="item.onClick"
:hasPermission="`notice/Config:${item.key}`"
>
<template #icon>
<AIcon :type="item.icon" />
</template>
<span>{{ item.text }}</span>
</PermissionButton>
</template>
</j-tooltip>
</template>
</CardBox>
</template>
<template #type="slotProps">
<span> {{ getMethodTxt(slotProps.type) }}</span>
</template>
<template #provider="slotProps">
<span>
{{ getProviderTxt(slotProps.type, slotProps.provider) }}
</span>
</template>
<template #description="slotProps">
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<PermissionButton <PermissionButton
:danger="i.key === 'delete'" type="primary"
:disabled="i.disabled" @click="handleAdd"
:popConfirm="i.popConfirm" hasPermission="notice/Config:add"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'notice/Config:' + i.key"
> >
<template #icon><AIcon :type="i.icon" /></template> 新增
</PermissionButton> </PermissionButton>
</template> <j-upload
</j-space> name="file"
</template> accept=".json"
</JProTable> :showUploadList="false"
:before-upload="beforeUpload"
>
<PermissionButton
hasPermission="notice/Config:import"
>
导入
</PermissionButton>
</j-upload>
<j-popconfirm
title="确认导出?"
ok-text="确定"
cancel-text="取消"
@confirm="handleExport"
>
<PermissionButton
hasPermission="notice/Config:export"
>
导出
</PermissionButton>
</j-popconfirm>
</j-space>
</template>
<template #card="slotProps">
<CardBox
:showStatus="false"
:statusNames="{}"
:value="slotProps"
:actions="getActions(slotProps, 'card')"
>
<template #img>
<slot name="img">
<img
:src="
getLogo(
slotProps.type,
slotProps.provider,
)
"
class="logo"
/>
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
{{ slotProps.name }}
</h3>
<j-row>
<j-col :span="12">
<div class="card-item-content-text">
通知方式
</div>
<div>
{{ getMethodTxt(slotProps.type) }}
</div>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
说明
</div>
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</j-col>
</j-row>
</template>
<template #actions="item">
<j-tooltip
v-bind="item.tooltip"
:title="item.disabled && item.tooltip.title"
>
<j-dropdown
placement="bottomRight"
v-if="item.key === 'others'"
>
<j-button>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</j-button>
<template #overlay>
<j-menu>
<j-menu-item
v-for="(o, i) in item.children"
:key="i"
>
<PermissionButton
type="link"
@click="o.onClick"
:hasPermission="`notice/Config:${o.key}`"
>
<template #icon>
<AIcon :type="o.icon" />
</template>
<span>{{ o.text }}</span>
</PermissionButton>
</j-menu-item>
</j-menu>
</template>
</j-dropdown>
<j-popconfirm
v-else-if="item.key === 'delete'"
v-bind="item.popConfirm"
:disabled="item.disabled"
>
<PermissionButton
:disabled="item.disabled"
:hasPermission="`notice/Config:${item.key}`"
>
<template #icon>
<AIcon type="DeleteOutlined" />
</template>
</PermissionButton>
</j-popconfirm>
<template v-else>
<PermissionButton
:disabled="item.disabled"
@click="item.onClick"
:hasPermission="`notice/Config:${item.key}`"
>
<template #icon>
<AIcon :type="item.icon" />
</template>
<span>{{ item.text }}</span>
</PermissionButton>
</template>
</j-tooltip>
</template>
</CardBox>
</template>
<template #type="slotProps">
<span> {{ getMethodTxt(slotProps.type) }}</span>
</template>
<template #provider="slotProps">
<span>
{{ getProviderTxt(slotProps.type, slotProps.provider) }}
</span>
</template>
<template #description="slotProps">
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<PermissionButton
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'notice/Config:' + i.key"
>
<template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</FullPage>
<Debug v-model:visible="debugVis" :data="currentConfig" /> <Debug v-model:visible="debugVis" :data="currentConfig" />
<Log v-model:visible="logVis" :data="currentConfig" /> <Log v-model:visible="logVis" :data="currentConfig" />

View File

@ -6,189 +6,198 @@
target="notice-config" target="notice-config"
@search="handleSearch" @search="handleSearch"
/> />
<JProTable <FullPage>
ref="configRef" <JProTable
:columns="columns" ref="configRef"
:request="TemplateApi.list" :columns="columns"
:defaultParams="{ :request="TemplateApi.list"
sorts: [{ name: 'createTime', order: 'desc' }], :defaultParams="{
}" sorts: [{ name: 'createTime', order: 'desc' }],
:params="params" }"
:gridColumn="3" :params="params"
> :gridColumn="3"
<template #headerTitle> >
<j-space> <template #headerTitle>
<PermissionButton <j-space>
type="primary"
@click="handleAdd"
hasPermission="notice/Template:add"
>
新增
</PermissionButton>
<j-upload
name="file"
accept=".json"
:showUploadList="false"
:before-upload="beforeUpload"
>
<PermissionButton <PermissionButton
hasPermission="notice/Template:import" type="primary"
@click="handleAdd"
hasPermission="notice/Template:add"
> >
导入 新增
</PermissionButton> </PermissionButton>
</j-upload> <j-upload
<j-popconfirm name="file"
title="确认导出?" accept=".json"
ok-text="确定" :showUploadList="false"
cancel-text="取消" :before-upload="beforeUpload"
@confirm="handleExport" >
<PermissionButton
hasPermission="notice/Template:import"
>
导入
</PermissionButton>
</j-upload>
<j-popconfirm
title="确认导出?"
ok-text="确定"
cancel-text="取消"
@confirm="handleExport"
>
<PermissionButton
hasPermission="notice/Template:export"
>
导出
</PermissionButton>
</j-popconfirm>
</j-space>
</template>
<template #card="slotProps">
<CardBox
:showStatus="false"
:value="slotProps"
:actions="getActions(slotProps, 'card')"
:statusNames="{}"
> >
<PermissionButton <template #img>
hasPermission="notice/Template:export" <slot name="img">
> <img
导出 :src="
</PermissionButton> getLogo(
</j-popconfirm> slotProps.type,
</j-space> slotProps.provider,
</template> )
<template #card="slotProps"> "
<CardBox class="logo"
:showStatus="false" />
:value="slotProps" </slot>
:actions="getActions(slotProps, 'card')" </template>
:statusNames="{}" <template #content>
> <h3 class="card-item-content-title">
<template #img> {{ slotProps.name }}
<slot name="img"> </h3>
<img <j-row>
:src=" <j-col :span="12">
getLogo(slotProps.type, slotProps.provider) <div class="card-item-content-text">
" 通知方式
class="logo" </div>
/> <div>
</slot> {{ getMethodTxt(slotProps.type) }}
</template> </div>
<template #content> </j-col>
<h3 class="card-item-content-title"> <j-col :span="12">
{{ slotProps.name }} <div class="card-item-content-text">
</h3> 说明
<j-row> </div>
<j-col :span="12"> <Ellipsis>
<div class="card-item-content-text"> {{ slotProps.description }}
通知方式 </Ellipsis>
</div> </j-col>
<div> </j-row>
{{ getMethodTxt(slotProps.type) }} </template>
</div> <template #actions="item">
</j-col> <j-tooltip
<j-col :span="12"> v-bind="item.tooltip"
<div class="card-item-content-text">说明</div> :title="item.disabled && item.tooltip.title"
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</j-col>
</j-row>
</template>
<template #actions="item">
<j-tooltip
v-bind="item.tooltip"
:title="item.disabled && item.tooltip.title"
>
<j-dropdown
placement="bottomRight"
v-if="item.key === 'others'"
> >
<j-button> <j-dropdown
<AIcon :type="item.icon" /> placement="bottomRight"
<span>{{ item.text }}</span> v-if="item.key === 'others'"
</j-button>
<template #overlay>
<j-menu>
<j-menu-item
v-for="(o, i) in item.children"
:key="i"
>
<PermissionButton
type="link"
@click="o.onClick"
:hasPermission="`notice/Template:${o.key}`"
>
<template #icon>
<AIcon :type="o.icon" />
</template>
<span>{{ o.text }}</span>
</PermissionButton>
</j-menu-item>
</j-menu>
</template>
</j-dropdown>
<j-popconfirm
v-else-if="item.key === 'delete'"
v-bind="item.popConfirm"
:disabled="item.disabled"
>
<PermissionButton
:disabled="item.disabled"
:hasPermission="`notice/Template:${item.key}`"
> >
<template #icon> <j-button>
<AIcon type="DeleteOutlined" />
</template>
</PermissionButton>
</j-popconfirm>
<template v-else>
<PermissionButton
:disabled="item.disabled"
@click="item.onClick"
:hasPermission="`notice/Template:${item.key}`"
>
<template #icon>
<AIcon :type="item.icon" /> <AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</j-button>
<template #overlay>
<j-menu>
<j-menu-item
v-for="(o, i) in item.children"
:key="i"
>
<PermissionButton
type="link"
@click="o.onClick"
:hasPermission="`notice/Template:${o.key}`"
>
<template #icon>
<AIcon :type="o.icon" />
</template>
<span>{{ o.text }}</span>
</PermissionButton>
</j-menu-item>
</j-menu>
</template> </template>
<span>{{ item.text }}</span> </j-dropdown>
</PermissionButton> <j-popconfirm
</template> v-else-if="item.key === 'delete'"
</j-tooltip> v-bind="item.popConfirm"
</template> :disabled="item.disabled"
</CardBox> >
</template> <PermissionButton
<template #type="slotProps"> :disabled="item.disabled"
<span> {{ getMethodTxt(slotProps.type) }}</span> :hasPermission="`notice/Template:${item.key}`"
</template> >
<template #provider="slotProps"> <template #icon>
<span> <AIcon type="DeleteOutlined" />
{{ getProviderTxt(slotProps.type, slotProps.provider) }} </template>
</span> </PermissionButton>
</template> </j-popconfirm>
<template #description="slotProps"> <template v-else>
<Ellipsis> <PermissionButton
{{ slotProps.description }} :disabled="item.disabled"
</Ellipsis> @click="item.onClick"
</template> :hasPermission="`notice/Template:${item.key}`"
<template #action="slotProps"> >
<j-space :size="16"> <template #icon>
<template <AIcon :type="item.icon" />
v-for="i in getActions(slotProps, 'table')" </template>
:key="i.key" <span>{{ item.text }}</span>
> </PermissionButton>
<PermissionButton </template>
:danger="i.key === 'delete'" </j-tooltip>
:disabled="i.disabled" </template>
:popConfirm="i.popConfirm" </CardBox>
:tooltip="{ </template>
...i.tooltip, <template #type="slotProps">
}" <span> {{ getMethodTxt(slotProps.type) }}</span>
@click="i.onClick" </template>
type="link" <template #provider="slotProps">
style="padding: 0px" <span>
:hasPermission="'notice/Template:' + i.key" {{ getProviderTxt(slotProps.type, slotProps.provider) }}
</span>
</template>
<template #description="slotProps">
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</template>
<template #action="slotProps">
<j-space :size="16">
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
> >
<template #icon><AIcon :type="i.icon" /></template> <PermissionButton
</PermissionButton> :danger="i.key === 'delete'"
</template> :disabled="i.disabled"
</j-space> :popConfirm="i.popConfirm"
</template> :tooltip="{
</JProTable> ...i.tooltip,
}"
@click="i.onClick"
type="link"
style="padding: 0px"
:hasPermission="'notice/Template:' + i.key"
>
<template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</FullPage>
<Debug v-model:visible="debugVis" :data="currentConfig" /> <Debug v-model:visible="debugVis" :data="currentConfig" />
<Log v-model:visible="logVis" :data="currentConfig" /> <Log v-model:visible="logVis" :data="currentConfig" />