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>
<page-container>
<pro-search :columns="columns" target="media" @search="handleSearch" />
<JProTable
ref="listRef"
model="table"
:columns="columns"
:request="(e:any) => CascadeApi.queryBindChannel(route?.query.id as string, e)"
:defaultParams="{
pageSize: 10,
sorts: [{ name: 'name', order: 'desc' }],
}"
:params="params"
:rowSelection="{
selectedRowKeys: _selectedRowKeys,
onChange: onSelectChange,
}"
@cancelSelect="_selectedRowKeys = []"
:pagination="{
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
}"
>
<template #headerTitle>
<h3>通道列表</h3>
</template>
<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"
>
<FullPage>
<JProTable
ref="listRef"
model="table"
:columns="columns"
:request="(e:any) => CascadeApi.queryBindChannel(route?.query.id as string, e)"
:defaultParams="{
pageSize: 10,
sorts: [{ name: 'name', order: 'desc' }],
}"
:params="params"
:rowSelection="{
selectedRowKeys: _selectedRowKeys,
onChange: onSelectChange,
}"
@cancelSelect="_selectedRowKeys = []"
:pagination="{
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
}"
>
<template #headerTitle>
<h3>通道列表</h3>
</template>
<template #rightExtraRender>
<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 type="link" @click="slotProps.popVis = true">
<AIcon type="EditOutlined" />
<j-button type="primary" @click="bindVis = true">
绑定通道
</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"
title="确认解绑?"
@confirm="handleMultipleUnbind"
>
<j-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></j-button>
<j-button> 批量解绑 </j-button>
</j-popconfirm>
<j-button
style="padding: 0"
type="link"
v-else
@click="i.onClick && i.onClick(slotProps)"
</j-space>
</template>
<template #gbChannelIdHeader="title">
<j-tooltip
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
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"
>
<j-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></j-button>
</j-popconfirm>
<j-button
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></j-button>
</j-button>
</j-tooltip>
</j-space>
</template>
</JProTable>
v-else
@click="i.onClick && i.onClick(slotProps)"
>
<j-button
:disabled="i.disabled"
style="padding: 0"
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()" />
</page-container>

View File

@ -5,139 +5,146 @@
target="media-cascade"
@search="handleSearch"
/>
<JProTable
ref="listRef"
:columns="columns"
:request="(e:any) => lastValueFrom(e)"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="2"
>
<template #headerTitle>
<PermissionButton
type="primary"
@click="handleAdd"
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"
<FullPage>
<JProTable
ref="listRef"
:columns="columns"
:request="(e:any) => lastValueFrom(e)"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="2"
>
<template #headerTitle>
<PermissionButton
type="primary"
@click="handleAdd"
hasPermission="media/Cascade:add"
>
<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="PlusOutlined" />新增</template
>
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</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
: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" />
</page-container>

View File

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

View File

@ -1,186 +1,191 @@
<!-- 回放 -->
<template>
<page-container>
<div class="playback-warp">
<!-- 播放器/进度条 -->
<div class="playback-left">
<LivePlayer
ref="player"
autoplay
:url="url"
className="playback-media"
:live="type === 'local'"
:on-play="
() => {
isEnded = false;
playStatus = 1;
}
"
:on-pause="
() => {
playStatus = 2;
}
"
:on-ended="
() => {
playStatus = 0;
if (playTimeNode && isEnded) {
isEnded = true;
playTimeNode.onNextPlay();
<FullPage>
<div class="playback-warp">
<!-- 播放器/进度条 -->
<div class="playback-left">
<LivePlayer
ref="player"
autoplay
:url="url"
className="playback-media"
:live="type === 'local'"
:on-play="
() => {
isEnded = false;
playStatus = 1;
}
}
"
:on-error="
() => {
playStatus = 0;
}
"
:on-time-update="
(e: any) => {
playTime = e;
}
"
/>
<TimeLine
ref="playTimeNode"
:type="type"
:data="historyList"
:date-time="time"
:on-change="handleTimeLineChange"
:play-status="playStatus"
: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"
"
:on-pause="
() => {
playStatus = 2;
}
"
:on-ended="
() => {
playStatus = 0;
if (playTimeNode && isEnded) {
isEnded = true;
playTimeNode.onNextPlay();
}
}
"
:on-error="
() => {
playStatus = 0;
}
"
:on-time-update="
(e: any) => {
playTime = e;
}
"
/>
<div class="playback-calendar">
<j-calendar
v-model:value="time"
:fullscreen="false"
:disabledDate="
(currentDate: Dayjs) => currentDate > dayjs(new Date())
"
@change="handlePanelChange"
<TimeLine
ref="playTimeNode"
:type="type"
:data="historyList"
:date-time="time"
:on-change="handleTimeLineChange"
:play-status="playStatus"
: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-list"
:class="{ 'no-list': !historyList.length }"
>
<j-empty
v-if="!historyList.length"
description="暂无数据"
/>
<j-list
v-else
class="playback-list-items"
itemLayout="horizontal"
:dataSource="historyList"
<div class="playback-calendar">
<j-calendar
v-model:value="time"
:fullscreen="false"
:disabledDate="
(currentDate: Dayjs) => currentDate > dayjs(new Date())
"
@change="handlePanelChange"
/>
</div>
<div
class="playback-list"
:class="{ 'no-list': !historyList.length }"
>
<template #renderItem="{ item }">
<j-list-item>
<template #actions>
<j-tooltip
key="play-btn"
:title="
(item.startTime ||
item.mediaStartTime) ===
playNowTime &&
playStatus === 1
? '暂停'
: '播放'
"
>
<a
@click="
handlePlay(
item.startTime ||
item.mediaStartTime,
)
<j-empty
v-if="!historyList.length"
description="暂无数据"
/>
<j-list
v-else
class="playback-list-items"
itemLayout="horizontal"
:dataSource="historyList"
>
<template #renderItem="{ item }">
<j-list-item>
<template #actions>
<j-tooltip
key="play-btn"
:title="
(item.startTime ||
item.mediaStartTime) ===
playNowTime &&
playStatus === 1
? '暂停'
: '播放'
"
>
<AIcon
:type="
(item.startTime ||
item.mediaStartTime) ===
playNowTime &&
playStatus === 1
? 'PauseCircleOutlined'
: 'PlayCircleOutlined'
<a
@click="
handlePlay(
item.startTime ||
item.mediaStartTime,
)
"
>
<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
key="download"
:title="
type !== 'local'
? '下载录像文件'
: item.isServer
? '查看'
: '下载到云端'
"
>
<IconNode
:type="type"
:item="item"
:on-cloud-view="cloudView"
:on-down-load="
() => downloadClick(item)
"
/>
</j-tooltip>
</template>
</j-tooltip>
</template>
<div>
{{
dayjs(
item.startTime ||
item.mediaStartTime,
).format('HH:mm:ss')
}}
~
{{
dayjs(
item.endTime ||
item.mediaEndTime,
).format('HH:mm:ss')
}}
</div>
</j-list-item>
</template>
<div></div>
</j-list>
</div>
</j-spin>
<div>
{{
dayjs(
item.startTime ||
item.mediaStartTime,
).format('HH:mm:ss')
}}
~
{{
dayjs(
item.endTime ||
item.mediaEndTime,
).format('HH:mm:ss')
}}
</div>
</j-list-item>
</template>
<div></div>
</j-list>
</div>
</j-spin>
</div>
</div>
</div>
</FullPage>
</page-container>
</template>

View File

@ -5,146 +5,159 @@
target="notice-config"
@search="handleSearch"
/>
<JProTable
ref="listRef"
:columns="columns"
:request="DeviceApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="4"
>
<template #headerTitle>
<PermissionButton
type="primary"
@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"
<FullPage>
<JProTable
ref="listRef"
:columns="columns"
:request="DeviceApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="4"
>
<template #headerTitle>
<PermissionButton
type="primary"
@click="handleAdd"
hasPermission="media/Device:add"
>
<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="PlusOutlined" />新增</template
>
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
</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
: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>
</template>

View File

@ -1,23 +1,28 @@
<template>
<page-container>
<j-card class="splitScreen">
<div class="split-screen">
<LeftTree @onSelect="mediaStart" />
<div class="right-content">
<ScreenPlayer
ref="player"
:id="deviceId"
:channelId="channelId"
:onMouseUp="(id, cId) => channelApi.ptzStop(id, cId)"
:onMouseDown="
(id, cId, type) => channelApi.ptzTool(id, cId, type)
"
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)"
showScreen
/>
<FullPage>
<j-card class="splitScreen">
<div class="split-screen">
<LeftTree @onSelect="mediaStart" />
<div class="right-content">
<ScreenPlayer
ref="player"
:id="deviceId"
:channelId="channelId"
:onMouseUp="
(id, cId) => channelApi.ptzStop(id, cId)
"
:onMouseDown="
(id, cId, type) =>
channelApi.ptzTool(id, cId, type)
"
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)"
showScreen
/>
</div>
</div>
</div>
</j-card>
</j-card>
</FullPage>
</page-container>
</template>

View File

@ -6,185 +6,198 @@
target="notice-config"
@search="handleSearch"
/>
<JProTable
ref="configRef"
:columns="columns"
:request="ConfigApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="3"
>
<template #headerTitle>
<j-space>
<PermissionButton
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"
>
<FullPage>
<JProTable
ref="configRef"
:columns="columns"
:request="ConfigApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="3"
>
<template #headerTitle>
<j-space>
<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"
type="primary"
@click="handleAdd"
hasPermission="notice/Config:add"
>
<template #icon><AIcon :type="i.icon" /></template>
新增
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
<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
: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" />
<Log v-model:visible="logVis" :data="currentConfig" />

View File

@ -6,189 +6,198 @@
target="notice-config"
@search="handleSearch"
/>
<JProTable
ref="configRef"
:columns="columns"
:request="TemplateApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="3"
>
<template #headerTitle>
<j-space>
<PermissionButton
type="primary"
@click="handleAdd"
hasPermission="notice/Template:add"
>
新增
</PermissionButton>
<j-upload
name="file"
accept=".json"
:showUploadList="false"
:before-upload="beforeUpload"
>
<FullPage>
<JProTable
ref="configRef"
:columns="columns"
:request="TemplateApi.list"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="3"
>
<template #headerTitle>
<j-space>
<PermissionButton
hasPermission="notice/Template:import"
type="primary"
@click="handleAdd"
hasPermission="notice/Template:add"
>
导入
新增
</PermissionButton>
</j-upload>
<j-popconfirm
title="确认导出?"
ok-text="确定"
cancel-text="取消"
@confirm="handleExport"
<j-upload
name="file"
accept=".json"
:showUploadList="false"
:before-upload="beforeUpload"
>
<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
hasPermission="notice/Template:export"
>
导出
</PermissionButton>
</j-popconfirm>
</j-space>
</template>
<template #card="slotProps">
<CardBox
:showStatus="false"
:value="slotProps"
:actions="getActions(slotProps, 'card')"
:statusNames="{}"
>
<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'"
<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-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/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}`"
<j-dropdown
placement="bottomRight"
v-if="item.key === 'others'"
>
<template #icon>
<AIcon type="DeleteOutlined" />
</template>
</PermissionButton>
</j-popconfirm>
<template v-else>
<PermissionButton
:disabled="item.disabled"
@click="item.onClick"
:hasPermission="`notice/Template:${item.key}`"
>
<template #icon>
<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/Template:${o.key}`"
>
<template #icon>
<AIcon :type="o.icon" />
</template>
<span>{{ o.text }}</span>
</PermissionButton>
</j-menu-item>
</j-menu>
</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/Template:' + i.key"
</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>
<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" />
</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"
>
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</j-space>
</template>
</JProTable>
<PermissionButton
:danger="i.key === 'delete'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...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" />
<Log v-model:visible="logVis" :data="currentConfig" />