Compare commits

...

11 Commits

Author SHA1 Message Date
阿斌
912c5ccef1
Pre Merge pull request !36 from 阿斌/N/A 2025-06-26 06:12:38 +00:00
648540858
5f4d78fe8f
Merge pull request #1900 from xiaoQQya/master
控制台新增国标收流通道列表查看弹窗
2025-06-26 14:09:27 +08:00
xiaoQQya
2b66404a2a fix: 修复国标收流列表播放按钮 loading 不生效问题 2025-06-26 13:24:15 +08:00
xiaoQQya
380c42040f fix: 修复国标收流列表关闭再打开时未刷新数据问题 2025-06-26 12:53:22 +08:00
xiaoQQya
1c25f2f190 feat: 新增国标收流通道列表查看 2025-06-26 11:46:14 +08:00
lin
d9b750dc50 补充丢失的文件 2025-06-26 11:05:39 +08:00
lin
d507d075b1 补充丢失的文件 2025-06-26 11:05:34 +08:00
648540858
592b1799e7
Merge pull request #1897 from xiaoQQya/master
修复登录页背景图加载失败问题
2025-06-26 07:05:05 +08:00
xiaoQQya
8c7b8eaeba perf: 登录状态持久化 2025-06-25 10:20:48 +08:00
xiaoQQya
6659779d91 fix: 修复登录页背景图加载失败问题 2025-06-25 10:19:57 +08:00
阿斌
da98101aac
update src/main/resources/civilCode.csv.
行政规划错误。江苏南通海门市,修改为海门区,浙江杭州删除下城区、江干区,新增钱塘区,临平区

Signed-off-by: 阿斌 <38912748@qq.com>
2024-12-15 08:58:42 +00:00
15 changed files with 263 additions and 30 deletions

View File

@ -21,6 +21,12 @@ public class DeviceChannel extends CommonGBChannel {
@Schema(description = "数据库自增ID")
private int id;
@Schema(description = "父设备编码")
private String parentDeviceId;
@Schema(description = "父设备名称")
private String parentName;
@MessageElementForCatalog("DeviceID")
@Schema(description = "编码")
private String deviceId;

View File

@ -113,6 +113,19 @@ public class DeviceQuery {
return deviceChannelService.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count);
}
@GetMapping("/streams")
@Operation(summary = "分页查询存在流的通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "page", description = "当前页", required = true)
@Parameter(name = "count", description = "每页查询数量", required = true)
@Parameter(name = "query", description = "查询内容")
public PageInfo<DeviceChannel> streamChannels(int page, int count,
@RequestParam(required = false) String query) {
if (ObjectUtils.isEmpty(query)) {
query = null;
}
return deviceChannelService.queryChannels(query, true, null, null, true, page, count);
}
@Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true)

View File

@ -86,10 +86,11 @@ public interface DeviceChannelMapper {
int update(DeviceChannel channel);
@SelectProvider(type = DeviceChannelProvider.class, method = "queryChannels")
List<DeviceChannel> queryChannels(@Param("dataDeviceId") int dataDeviceId, @Param("civilCode") String civilCode,
List<DeviceChannel> queryChannels(@Param("dataDeviceId") Integer dataDeviceId, @Param("civilCode") String civilCode,
@Param("businessGroupId") String businessGroupId, @Param("parentChannelId") String parentChannelId,
@Param("query") String query, @Param("hasSubChannel") Boolean hasSubChannel,
@Param("online") Boolean online, @Param("channelIds") List<String> channelIds);
@Param("query") String query, @Param("queryParent") Boolean queryParent,
@Param("hasSubChannel") Boolean hasSubChannel, @Param("online") Boolean online,
@Param("channelIds") List<String> channelIds, @Param("hasStream") Boolean hasStream);
@SelectProvider(type = DeviceChannelProvider.class, method = "queryChannelsByDeviceDbId")
List<DeviceChannel> queryChannelsByDeviceDbId(@Param("dataDeviceId") int dataDeviceId);

View File

@ -20,6 +20,8 @@ public class DeviceChannelProvider {
" dc.gps_time,\n" +
" dc.stream_identification,\n" +
" dc.channel_type,\n" +
" d.device_id as parent_device_id,\n" +
" coalesce(d.custom_name, d.name) as parent_name,\n" +
" coalesce(dc.gb_device_id, dc.device_id) as device_id,\n" +
" coalesce(dc.gb_name, dc.name) as name,\n" +
" coalesce(dc.gb_manufacturer, dc.manufacturer) as manufacturer,\n" +
@ -55,13 +57,17 @@ public class DeviceChannelProvider {
" coalesce(dc.gb_svc_space_support_mod, dc.svc_space_support_mod) as svc_space_support_mod,\n" +
" coalesce(dc.gb_svc_time_support_mode,dc.svc_time_support_mode) as svc_time_support_mode\n" +
" from " +
" wvp_device_channel dc "
" wvp_device_channel dc " +
" left join wvp_device d on d.id = dc.data_device_id "
;
}
public String queryChannels(Map<String, Object> params ){
StringBuilder sqlBuild = new StringBuilder();
sqlBuild.append(getBaseSelectSql());
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value + " and dc.data_device_id = #{dataDeviceId} ");
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value);
if (params.get("dataDeviceId") != null) {
sqlBuild.append(" AND dc.data_device_id = #{dataDeviceId} ");
}
if (params.get("businessGroupId") != null ) {
sqlBuild.append(" AND coalesce(dc.gb_business_group_id, dc.business_group_id)=#{businessGroupId} AND coalesce(dc.gb_parent_id, dc.parent_id) is null");
}else if (params.get("parentChannelId") != null ) {
@ -73,8 +79,15 @@ public class DeviceChannelProvider {
}
if (params.get("query") != null && !ObjectUtils.isEmpty(params.get("query"))) {
sqlBuild.append(" AND (coalesce(dc.gb_device_id, dc.device_id) LIKE concat('%',#{query},'%') escape '/'" +
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%') escape '/')")
;
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%') escape '/'");
if (params.get("queryParent") != null && (Boolean) params.get("queryParent")) {
sqlBuild.append(" OR d.device_id LIKE concat('%',#{query},'%') escape '/'");
sqlBuild.append(" OR coalesce(d.custom_name, d.name) LIKE concat('%',#{query},'%') escape '/'");
}
sqlBuild.append(")");
}
if (params.get("hasStream") != null && (Boolean) params.get("hasStream")) {
sqlBuild.append(" AND dc.stream_id IS NOT NULL");
}
if (params.get("online") != null && (Boolean)params.get("online")) {
sqlBuild.append(" AND coalesce(gb_status, status) = 'ON'");
@ -101,7 +114,7 @@ public class DeviceChannelProvider {
}
sqlBuild.append(" )");
}
sqlBuild.append(" ORDER BY device_id");
sqlBuild.append(" ORDER BY d.device_id, dc.device_id");
return sqlBuild.toString();
}

View File

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
@ -104,6 +101,7 @@ public interface IDeviceChannelService {
PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean channelType, Boolean online, int page, int count);
PageInfo<DeviceChannel> queryChannels(String query, Boolean queryParent, Boolean channelType, Boolean online, Boolean hasStream, int page, int count);
List<Device> queryDeviceWithAsMessageChannel();

View File

@ -696,7 +696,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
.replaceAll("%", "/%")
.replaceAll("_", "/_");
}
List<DeviceChannel> all = channelMapper.queryChannels(deviceDbId, civilCode, businessGroupId, parentId, query, channelType, online,null);
List<DeviceChannel> all = channelMapper.queryChannels(deviceDbId, civilCode, businessGroupId, parentId, query, false, channelType, online, null, null);
return new PageInfo<>(all);
}
@ -717,7 +717,19 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
.replaceAll("_", "/_");
}
PageHelper.startPage(page, count);
List<DeviceChannel> all = channelMapper.queryChannels(device.getId(), null,null, null, query, hasSubChannel, online,null);
List<DeviceChannel> all = channelMapper.queryChannels(device.getId(), null, null, null, query, false, hasSubChannel, online, null, null);
return new PageInfo<>(all);
}
@Override
public PageInfo<DeviceChannel> queryChannels(String query, Boolean queryParent, Boolean hasSubChannel, Boolean online, Boolean hasStream, int page, int count) {
PageHelper.startPage(page, count);
if (query != null) {
query = query.replaceAll("/", "//")
.replaceAll("%", "/%")
.replaceAll("_", "/_");
}
List<DeviceChannel> all = channelMapper.queryChannels(null, null, null, null, query, queryParent, hasSubChannel, online, null, hasStream);
return new PageInfo<>(all);
}

View File

@ -861,7 +861,7 @@
320623,如东县,3206
320681,启东市,3206
320682,如皋市,3206
320684,海门,3206
320684,海门,3206
320685,海安市,3206
3207,连云港市,32
320703,连云区,3207
@ -918,8 +918,6 @@
33,浙江省,
3301,杭州市,33
330102,上城区,3301
330103,下城区,3301
330104,江干区,3301
330105,拱墅区,3301
330106,西湖区,3301
330108,滨江区,3301
@ -927,6 +925,8 @@
330110,余杭区,3301
330111,富阳区,3301
330112,临安区,3301
330113,临平区,3301
330114,钱塘区,3301
330122,桐庐县,3301
330127,淳安县,3301
330182,建德市,3301

1 编号 名称 上级
861 320623 如东县 3206
862 320681 启东市 3206
863 320682 如皋市 3206
864 320684 海门市 海门区 3206
865 320685 海安市 3206
866 3207 连云港市 32
867 320703 连云区 3207
918 33 浙江省
919 3301 杭州市 33
920 330102 上城区 3301
330103 下城区 3301
330104 江干区 3301
921 330105 拱墅区 3301
922 330106 西湖区 3301
923 330108 滨江区 3301
925 330110 余杭区 3301
926 330111 富阳区 3301
927 330112 临安区 3301
928 330113 临平区 3301
929 330114 钱塘区 3301
930 330122 桐庐县 3301
931 330127 淳安县 3301
932 330182 建德市 3301

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -118,6 +118,19 @@ export function queryChannels(deviceId, params) {
})
}
export function queryHasStreamChannels(params) {
const {page, count, query} = params
return request({
method: 'get',
url: `/api/device/query/streams`,
params: {
page: page,
count: count,
query: query
}
})
}
export function deviceRecord(params) {
const { deviceId, channelId, recordCmdStr } = params
return request({

View File

@ -1,17 +1,24 @@
import {
add, changeChannelAudio,
add,
changeChannelAudio,
deleteDevice,
deviceRecord,
queryBasicParam,
queryChannelOne,
queryChannels, queryChannelTree, queryDeviceOne,
queryChannels,
queryChannelTree,
queryDeviceOne,
queryDevices,
queryDeviceSyncStatus, queryDeviceTree,
queryDeviceSyncStatus,
queryDeviceTree,
queryHasStreamChannels,
resetGuard,
setGuard,
subscribeCatalog,
subscribeMobilePosition,
sync, update, updateChannelStreamIdentification,
sync,
update,
updateChannelStreamIdentification,
updateDeviceTransport
} from '@/api/device'
@ -126,6 +133,16 @@ const actions = {
})
})
},
queryHasStreamChannels({commit}, params) {
return new Promise((resolve, reject) => {
queryHasStreamChannels(params).then(response => {
const {data} = response
resolve(data)
}).catch(error => {
reject(error)
})
})
},
deviceRecord({ commit }, params) {
return new Promise((resolve, reject) => {
deviceRecord(params).then(response => {

View File

@ -3,6 +3,7 @@ import Cookies from 'js-cookie'
const TokenKey = 'wvp_token'
const NameKey = 'wvp_username'
const serverIdKey = 'wvp_server_id'
const expires = 30
export function getToken() {
console.log('Getting token...')
@ -10,7 +11,7 @@ export function getToken() {
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
return Cookies.set(TokenKey, token, {expires: expires})
}
export function removeToken() {
@ -22,7 +23,7 @@ export function getName() {
}
export function setName(name) {
return Cookies.set(NameKey, name)
return Cookies.set(NameKey, name, {expires: expires})
}
export function removeName() {
@ -34,7 +35,7 @@ export function getServerId() {
}
export function setServerId(serverId) {
return Cookies.set(serverIdKey, serverId)
return Cookies.set(serverIdKey, serverId, {expires: expires})
}
export function removeServerId() {

View File

@ -1,17 +1,21 @@
<template>
<div id="ConsoleNodeLoad" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
<ve-histogram ref="consoleNodeLoad" :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" :legend-visible="true" />
<ve-histogram ref="consoleNodeLoad" :data="chartData" :extend="extend" :events="events" :settings="chartSettings"
width="100%" height="100%" :legend-visible="true"/>
<HasStreamChannel ref="hasStreamChannel"/>
</div>
</template>
<script>
import veHistogram from 'v-charts/lib/histogram'
import HasStreamChannel from "@/views/dialog/hasStreamChannel";
export default {
name: 'ConsoleNodeLoad',
components: {
veHistogram
veHistogram,
HasStreamChannel
},
data() {
return {
@ -43,6 +47,9 @@ export default {
show: true,
position: 'top'
}
},
events: {
click: this.onClick
}
}
},
@ -56,10 +63,14 @@ export default {
destroyed() {
},
methods: {
setData: function(data) {
setData: function (data) {
this.chartData.rows = data
},
onClick(v) {
if (v.seriesName === "国标收流") {
this.$refs.hasStreamChannel.openDialog();
}
}
}
}
</script>

View File

@ -6,6 +6,7 @@
v-el-drag-dialog
title="视频播放"
top="0"
append-to-body
:close-on-click-modal="false"
:visible.sync="showVideoDialog"
@close="close()"

View File

@ -0,0 +1,147 @@
<template>
<div>
<el-dialog
v-if="showDialog"
v-el-drag-dialog
:visible.sync="showDialog"
title="国标收流列表"
width="70%"
top="5rem"
append-to-body
:close-on-click-modal="false"
>
<el-form :inline="true" size="mini" @submit.native.prevent>
<el-form-item label="搜索">
<el-input
v-model="query"
placeholder="关键字"
prefix-icon="el-icon-search"
clearable
@input="getChannelList"
/>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="channelList" :height="500" stripe>
<el-table-column prop="parentDeviceId" label="设备编号" min-width="180"/>
<el-table-column prop="parentName" label="设备名称" min-width="180"/>
<el-table-column prop="deviceId" label="通道编号" min-width="180"/>
<el-table-column prop="name" label="通道名称" min-width="180"/>
<el-table-column prop="ptzType" label="云台类型" min-width="100">
<template v-slot:default="scope">
<div>{{ scope.row.ptzTypeText }}</div>
</template>
</el-table-column>
<el-table-column label="操作" min-width="120" fixed="right">
<template v-slot:default="scope">
<el-button
size="medium"
icon="el-icon-video-play"
type="text"
:loading="scope.row.playing"
@click="sendDevicePush(scope.row)"
>播放
</el-button>
<el-button
size="medium"
icon="el-icon-switch-button"
type="text"
style="color: #f56c6c"
@click="stopDevicePush(scope.row)"
>停止
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px; text-align: right"
:current-page="currentPage"
:page-size="count"
:page-sizes="[15, 25, 35, 50]"
layout="total, sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="currentChange"
/>
</el-dialog>
<devicePlayer ref="devicePlayer"/>
</div>
</template>
<script>
import devicePlayer from "@/views/dialog/devicePlayer";
import elDragDialog from "@/directive/el-drag-dialog";
export default {
name: "HasStreamChannel",
directives: {elDragDialog},
components: {devicePlayer},
data() {
return {
showDialog: false,
loading: false,
playing: false,
channelList: [],
query: null,
currentPage: 1,
count: 15,
total: 0
}
},
methods: {
openDialog: function () {
this.showDialog = true;
this.getChannelList();
},
getChannelList: function () {
this.loading = true;
this.$store.dispatch("device/queryHasStreamChannels", {
page: this.currentPage,
count: this.count,
query: this.query
}).then((data) => {
this.total = data.total
this.channelList = data.list
}).finally(() => {
this.loading = false
})
},
currentChange: function (val) {
this.currentPage = val
this.getChannelList()
},
handleSizeChange: function (val) {
this.count = val
this.getChannelList()
},
sendDevicePush: function (row) {
const deviceId = row.parentDeviceId
const channelId = row.deviceId
this.$set(row, "playing", true)
this.$store.dispatch("play/play", [deviceId, channelId])
.then((data) => {
this.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
streamInfo: data,
hasAudio: row.hasAudio
})
})
.finally(() => {
this.$set(row, "playing", false)
})
},
stopDevicePush: function (row) {
this.$store.dispatch("play/stop", [row.parentDeviceId, row.deviceId]).then(_ => {
this.getChannelList();
}).catch((error) => {
if (error.response.status === 402) {
this.getChannelList();
} else {
this.$message.error({showClose: true, message: error})
}
})
}
}
}
</script>

View File

@ -61,7 +61,7 @@
</template>
<script>
import { validUsername } from '@/utils/validate'
import {validUsername} from '@/utils/validate'
export default {
name: 'Login',