Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>10.0.9</Version>
<Version>10.0.10</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ public partial class HikVisionWebPlugin
/// </summary>
public bool IsStartRecord { get; private set; }

/// <summary>
/// 获得 当前是否为分屏状态
/// </summary>
public bool IsMultipleWindowType { get; private set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand Down Expand Up @@ -204,7 +209,7 @@ public async Task GetChannelList()
/// <returns></returns>
public async Task StartRealPlay(int streamType, int channelId)
{
if (IsLogin && !IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && !IsRealPlaying))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider extracting the repeated IsMultipleWindowType-related conditions into dedicated helper properties and using those at call sites to centralize the rules and simplify each method.

You can reduce the added complexity by centralizing the new IsMultipleWindowType logic into helper properties so the rules live in one place instead of being duplicated across many methods.

For example:

private bool CanStartRealPlay => IsMultipleWindowType || (IsLogin && !IsRealPlaying);
private bool CanStopRealPlay  => IsMultipleWindowType || IsRealPlaying;
private bool CanControlPlayback => IsMultipleWindowType || (IsLogin && IsRealPlaying);

Then use these in the call sites:

public async Task StartRealPlay(int streamType, int channelId)
{
    if (!CanStartRealPlay)
    {
        return;
    }

    IsRealPlaying = await InvokeAsync<bool?>("startRealPlay", Id, streamType, channelId) ?? false;
    if (IsRealPlaying)
    {
        await TriggerStartRealPlay();
    }
}
public async Task StopRealPlay()
{
    if (!CanStopRealPlay)
    {
        return;
    }

    await InvokeVoidAsync("stopRealPlay", Id);
    IsRealPlaying = false;
    IsStartRecord = false;
    await TriggerStopRealPlay();
}
public async Task<bool> OpenSound()
{
    var ret = false;
    if (CanControlPlayback)
    {
        var code = await InvokeAsync<int>("openSound", Id);
        ret = code == 100;
        IsOpenSound = ret;
    }
    return ret;
}

Apply CanControlPlayback similarly to CloseSound, SetVolume, CapturePictureAndDownload, CapturePicture, StartRecord, and StopRecord.

This keeps all the multi-window vs. login/playback rules in one place, makes future behavior changes safer (only update the properties), and simplifies the public methods without changing any functionality.

Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is already true, potentially allowing operations on an unauthenticated or invalid session. The condition should be: (IsLogin && !IsRealPlaying) || (IsMultipleWindowType && IsLogin) to ensure login state is always checked.

Suggested change
if (IsMultipleWindowType || (IsLogin && !IsRealPlaying))
if ((IsLogin && !IsRealPlaying) || (IsMultipleWindowType && IsLogin))

Copilot uses AI. Check for mistakes.
{
IsRealPlaying = await InvokeAsync<bool?>("startRealPlay", Id, streamType, channelId) ?? false;
if (IsRealPlaying)
Expand All @@ -228,7 +233,7 @@ private async Task TriggerStartRealPlay()
/// <returns></returns>
public async Task StopRealPlay()
{
if (IsRealPlaying)
if (IsMultipleWindowType || IsRealPlaying)
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsRealPlaying is false, potentially allowing stop operations when nothing is playing. The condition should be: IsRealPlaying || (IsMultipleWindowType && IsRealPlaying) to ensure proper state checking.

Suggested change
if (IsMultipleWindowType || IsRealPlaying)
if (IsRealPlaying)

Copilot uses AI. Check for mistakes.
{
await InvokeVoidAsync("stopRealPlay", Id);
IsRealPlaying = false;
Expand Down Expand Up @@ -289,7 +294,7 @@ public async Task TriggerGetChannelList(HikVisionChannel channel)
public async Task<bool> OpenSound()
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing sound operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Suggested change
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
if (IsLogin && IsRealPlaying)

Copilot uses AI. Check for mistakes.
{
var code = await InvokeAsync<int>("openSound", Id);
ret = code == 100;
Expand All @@ -305,7 +310,7 @@ public async Task<bool> OpenSound()
public async Task<bool> CloseSound()
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing sound operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
var code = await InvokeAsync<int>("closeSound", Id);
ret = code == 100;
Expand All @@ -322,7 +327,7 @@ public async Task<bool> CloseSound()
public async Task<bool> SetVolume(int value)
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing volume operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
var code = await InvokeAsync<int>("setVolume", Id, Math.Max(0, Math.Min(100, value)));
ret = code == 100;
Expand All @@ -337,7 +342,7 @@ public async Task<bool> SetVolume(int value)
public async Task<bool> CapturePictureAndDownload(string? fileName = null, CancellationToken token = default)
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing capture operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
ret = await InvokeAsync<bool>("capturePictureAndDownload", token, Id, fileName);
}
Expand All @@ -351,7 +356,7 @@ public async Task<bool> CapturePictureAndDownload(string? fileName = null, Cance
public async Task<bool> CapturePicture(string? fileName = null, CancellationToken token = default)
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing capture operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
ret = await InvokeAsync<bool>("capturePicture", token, Id, fileName);
}
Expand All @@ -365,7 +370,7 @@ public async Task<bool> CapturePicture(string? fileName = null, CancellationToke
public async Task<bool> StartRecord()
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing record operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
ret = await InvokeAsync<bool>("startRecord", Id);
IsStartRecord = ret;
Expand All @@ -380,7 +385,7 @@ public async Task<bool> StartRecord()
public async Task<bool> StopRecord()
{
var ret = false;
if (IsLogin && IsRealPlaying)
if (IsMultipleWindowType || (IsLogin && IsRealPlaying))
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for controlling method calls using IsMultipleWindowType is problematic. When IsMultipleWindowType is true, the condition passes even if IsLogin is false or IsRealPlaying is false, potentially allowing stop record operations on an unauthenticated or non-playing session. The condition should be: (IsLogin && IsRealPlaying) || (IsMultipleWindowType && IsLogin && IsRealPlaying) to ensure proper state checking.

Copilot uses AI. Check for mistakes.
{
ret = await InvokeAsync<bool>("stopRecord", Id);
if (ret)
Expand All @@ -390,4 +395,15 @@ public async Task<bool> StopRecord()
}
return ret;
}

/// <summary>
/// 更改视口数量方法
/// </summary>
/// <param name="iWndType">画面分割类型 1- 1*1,2- 2*2,3- 3*3,4- 4*4 (最大显示数值为4*4分割,数字超过4返回16分割)</param>
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation comment is unclear about the behavior when iWndType exceeds 4. The comment states "数字超过4返回16分割" (numbers exceeding 4 return 16 splits), but it's not clear if the function returns false or if it defaults to a 4x4 layout. Consider clarifying the exact behavior and return value in this edge case.

Suggested change
/// <param name="iWndType">画面分割类型 1- 1*1,2- 2*2,3- 3*3,4- 4*4 (最大显示数值为4*4分割,数字超过4返回16分割)</param>
/// <param name="iWndType">画面分割类型。支持的值:1 = 1×1,2 = 2×2,3 = 3×3,4 = 4×4。传入其它值将原样传递给底层插件,由其决定实际分割效果和返回值。</param>

Copilot uses AI. Check for mistakes.
/// <returns></returns>
public async Task<bool> ChangeWindowNum(string iWndType)
{
IsMultipleWindowType = iWndType != "1";
return await InvokeAsync<bool>("changeWndNum", Id, iWndType);
}
Comment on lines +404 to +408
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing input validation for the iWndType parameter. The function should validate that iWndType is one of the expected values ("1", "2", "3", "4", "12", "21") before calling the API. Invalid values could lead to unexpected behavior or errors from the WebVideoCtrl API.

Copilot uses AI. Check for mistakes.
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { init as initVision, login as loginVision, logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload, startRecord, stopRecord, dispose as disposeVision } from '../hikvision.js';
import { init as initVision, login as loginVision, logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload, startRecord, stopRecord, changeWndNum, dispose as disposeVision } from '../hikvision.js';
import Data from '../../BootstrapBlazor/modules/data.js';

export async function init(id, invoke) {
Expand All @@ -8,7 +8,8 @@ export async function init(id, invoke) {
}

Data.set(id, {
invoke
invoke,
iWndIndex: 0
});

const inited = await initVision(id);
Expand All @@ -29,7 +30,7 @@ export async function login(id, ip, port, userName, password, loginType) {
return logined;
}

export { logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload, startRecord, stopRecord }
export { logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload, startRecord, stopRecord, changeWndNum }

export function dispose(id) {
disposeVision(id);
Expand Down
35 changes: 28 additions & 7 deletions src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ export async function init(id) {
return false;
}

const result = await initWindow(id);
const vision = Data.get(id);
const result = await initWindow(id, iWndIndex => vision.iWndIndex = iWndIndex);
if (result.inited === false) {
return false;
}

const vision = Data.get(id);
vision.iWndIndex = result.iWndIndex;
vision.inited = true;

const observer = new IntersectionObserver(() => {
Expand Down Expand Up @@ -103,14 +101,14 @@ const removePlugin = () => {
}
}

const initWindow = id => {
const result = { inited: null, iWndIndex: -1 };
const initWindow = (id, cb) => {
const result = { inited: null };
WebVideoCtrl.I_InitPlugin({
szBasePath: './_content/BootstrapBlazor.HikVision',
bWndFull: true,
iWndowType: 1,
cbSelWnd: function (xmlDoc) {
result.iWndIndex = parseInt(getTagNameFirstValue(xmlDoc, "SelectWnd"));
cb(parseInt(getTagNameFirstValue(xmlDoc, "SelectWnd")));
},
cbDoubleClickWnd: function (iWndIndex, bFullScreen) {

Expand Down Expand Up @@ -553,6 +551,29 @@ export async function stopRecord(id) {
});
}

export async function changeWndNum(id, iWndType) {
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function naming is inconsistent. The JavaScript function is named 'changeWndNum' (lowercase 'change') while the comment at line 129 uses Chinese characters suggesting "更改视口数量" (Change viewport number). Consider using 'ChangeWndNum' (PascalCase) to match the naming convention of other exported methods like 'StartRealPlay', 'StopRealPlay', etc., or ensure consistency across all layers.

Suggested change
export async function changeWndNum(id, iWndType) {
export async function ChangeWndNum(id, iWndType) {

Copilot uses AI. Check for mistakes.
const vision = Data.get(id);
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter 'vision' is retrieved but never used in the function. Consider removing this unused variable declaration to improve code clarity.

Suggested change
const vision = Data.get(id);

Copilot uses AI. Check for mistakes.
if (!iWndType) {
iWndType = "1";
}

let ret = false;
try {
if ("1*2" === iWndType || "2*1" === iWndType) {
await WebVideoCtrl.I_ArrangeWindow(iWndType);
}
else {
const iType = parseInt(iWndType, 10);
await WebVideoCtrl.I_ChangeWndNum(iType);
}
ret = true;
}
catch (oError) {
console.log(oError);
}
return ret;
}

export function dispose(id) {
const vision = Data.get(id);
const { realPlaying, logined, observer } = vision;
Expand Down