Files
FATrace/FATrace.Com/NVRCom.cs
2026-05-15 17:17:08 +08:00

299 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Globalization;
namespace FATrace.Com
{
/// <summary>
/// NVR 公共的类
/// </summary>
public class NVRCom
{
private static string[] SplitCodeParts(string code)
{
if (string.IsNullOrWhiteSpace(code)) return Array.Empty<string>();
var normalized = code.Trim()
.Replace('', ',')
.Replace('', ',')
.Replace(';', ',');
// 优先使用逗号分隔,避免 SolidBeveBatch 中包含空格导致被错误切分
if (normalized.Contains(','))
{
return normalized
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Trim())
.ToArray();
}
// 无逗号时回退到按空白分隔
return normalized
.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Trim())
.ToArray();
}
/// <summary>
/// 获取视频名称
/// </summary>
/// <param name="configKey"></param>
/// <returns></returns>
public static string GetVideoPathName(string basePath, string Code)
{
// 清洗非法文件名字符,避免保存失败
string safeCode = Code;
try
{
var invalid = System.IO.Path.GetInvalidFileNameChars();
safeCode = new string(Code.Where(c => !invalid.Contains(c)).ToArray());
if (string.IsNullOrWhiteSpace(safeCode)) safeCode = DateTime.Now.ToString("yyyy-MM-dd HHmmss");
}
catch { }
return $"{basePath}\\{safeCode}.mp4";
}
/// <summary>
/// 获取视频名称
/// </summary>
/// <returns></returns>
public static string GetVideoName(string Code)
{
string safeCode = Code;
try
{
var invalid = System.IO.Path.GetInvalidFileNameChars();
safeCode = new string(Code.Where(c => !invalid.Contains(c)).ToArray());
if (string.IsNullOrWhiteSpace(safeCode)) safeCode = DateTime.Now.ToString("yyyy-MM-dd HHmmss");
}
catch { }
return $"{safeCode}.mp4";
}
/// <summary>
/// 解析条码
/// </summary>
/// <returns></returns>
public static (string RawCode, string Batch, string Weight) ParseCode(string Code)
{
if (string.IsNullOrWhiteSpace(Code))
{
return (string.Empty, string.Empty, string.Empty);
}
try
{
var parts = SplitCodeParts(Code);
// 新二维码固定 7 段RawCode,Batch,SolidBeveBatch,Weight,ShelfLife,Region,DayCount
if (parts.Length != 7)
{
return (string.Empty, string.Empty, string.Empty);
}
string rawCode = parts.Length > 0 ? parts[0] : string.Empty;
// 批号:通常为 8 位日期 yyyyMMdd保留前 8 位数字
string batch = string.Empty;
if (parts.Length > 1)
{
var digits = new string(parts[1].Where(char.IsDigit).ToArray());
if (digits.Length >= 8) batch = digits.Substring(0, 8);
else batch = digits; // 若不足 8 位,原样返回可供上层判定
}
// 重量3/4 位数字最后一位为小数位802 => 80.2g)。
string weight = string.Empty;
var weightIndex = 3;
if (parts.Length > 3)
{
var digits = new string(parts[weightIndex].Where(char.IsDigit).ToArray());
if (digits.Length >= 2)
{
// 在最后一位前插入小数点,如 802 => 80.21234 => 123.4
weight = string.Concat(digits.AsSpan(0, digits.Length - 1), ".", digits.AsSpan(digits.Length - 1));
}
else if (digits.Length == 1)
{
weight = "0." + digits; // 兜底1 位数字视为 0.x
}
}
return (rawCode, batch, weight);
}
catch
{
return (string.Empty, string.Empty, string.Empty);
}
}
public static ParsedCodeInfo ParseCodeFull(string code)
{
var result = new ParsedCodeInfo();
if (string.IsNullOrWhiteSpace(code)) return result;
result.Code = code;
try
{
var parts = SplitCodeParts(code);
// 新二维码固定 7 段RawCode,Batch,SolidBeveBatch,Weight,ShelfLife,Region,DayCount
if (parts.Length != 7)
{
return result;
}
result.RawCode = parts.Length > 0 ? parts[0] : string.Empty;
if (parts.Length > 1)
{
var digits = new string(parts[1].Where(char.IsDigit).ToArray());
result.Batch = digits.Length >= 8 ? digits.Substring(0, 8) : digits;
}
// 新二维码7段第3段为固体饮料批次
result.SolidBeveBatch = parts[2];
var weightIndex = 3;
if (parts.Length > 3)
{
var digits = new string(parts[weightIndex].Where(char.IsDigit).ToArray());
string weightStr = string.Empty;
if (digits.Length >= 2)
{
weightStr = string.Concat(digits.AsSpan(0, digits.Length - 1), ".", digits.AsSpan(digits.Length - 1));
}
else if (digits.Length == 1)
{
weightStr = "0." + digits;
}
if (!string.IsNullOrWhiteSpace(weightStr))
{
if (decimal.TryParse(weightStr, NumberStyles.Any, CultureInfo.InvariantCulture, out var w))
result.Weight = w;
}
}
var shelfLifeIndex = 4;
if (parts.Length > 4)
{
var digits = new string(parts[shelfLifeIndex].Where(char.IsDigit).ToArray());
if (int.TryParse(digits, out var m)) result.ShelfLifeMonths = m;
}
var regionIndex = 5;
if (parts.Length > 5)
{
var digits = new string(parts[regionIndex].Where(char.IsDigit).ToArray());
result.RegionCode = digits;
result.RegionName = digits == "01" ? "国内" : (digits == "02" ? "日本" : "未知");
}
var countIndex = 6;
if (parts.Length > 6)
{
var digits = new string(parts[countIndex].Where(char.IsDigit).ToArray());
if (int.TryParse(digits, out var c)) result.Count = c;
}
}
catch { }
return result;
}
/// <summary>
/// 兼容解析条码(用于 OEMApp 这类流程后段应用:现场可能存在历史 6 段条码)。
/// 新条码7段RawCode,Batch,SolidBeveBatch,Weight,ShelfLife,Region,DayCount
/// 旧条码6段RawCode,Batch,Weight,ShelfLife,Region,DayCount不包含 SolidBeveBatch
/// </summary>
public static ParsedCodeInfo ParseCodeFullCompat(string code)
{
var result = new ParsedCodeInfo();
if (string.IsNullOrWhiteSpace(code)) return result;
result.Code = code;
try
{
var parts = SplitCodeParts(code);
if (parts.Length != 7 && parts.Length != 6)
{
return result;
}
result.RawCode = parts.Length > 0 ? parts[0] : string.Empty;
if (parts.Length > 1)
{
var digits = new string(parts[1].Where(char.IsDigit).ToArray());
result.Batch = digits.Length >= 8 ? digits.Substring(0, 8) : digits;
}
var isNew7 = parts.Length == 7;
if (isNew7)
{
// 新条码7段第3段为固体饮料批次
result.SolidBeveBatch = parts[2];
}
else
{
// 旧条码6段不包含固体饮料批次
result.SolidBeveBatch = string.Empty;
}
var weightIndex = isNew7 ? 3 : 2;
if (parts.Length > weightIndex)
{
var digits = new string(parts[weightIndex].Where(char.IsDigit).ToArray());
string weightStr = string.Empty;
if (digits.Length >= 2)
{
weightStr = string.Concat(digits.AsSpan(0, digits.Length - 1), ".", digits.AsSpan(digits.Length - 1));
}
else if (digits.Length == 1)
{
weightStr = "0." + digits;
}
if (!string.IsNullOrWhiteSpace(weightStr))
{
if (decimal.TryParse(weightStr, NumberStyles.Any, CultureInfo.InvariantCulture, out var w))
result.Weight = w;
}
}
var shelfLifeIndex = isNew7 ? 4 : 3;
if (parts.Length > shelfLifeIndex)
{
var digits = new string(parts[shelfLifeIndex].Where(char.IsDigit).ToArray());
if (int.TryParse(digits, out var m)) result.ShelfLifeMonths = m;
}
var regionIndex = isNew7 ? 5 : 4;
if (parts.Length > regionIndex)
{
var digits = new string(parts[regionIndex].Where(char.IsDigit).ToArray());
result.RegionCode = digits;
result.RegionName = digits == "01" ? "国内" : (digits == "02" ? "日本" : "未知");
}
var countIndex = isNew7 ? 6 : 5;
if (parts.Length > countIndex)
{
var digits = new string(parts[countIndex].Where(char.IsDigit).ToArray());
if (int.TryParse(digits, out var c)) result.Count = c;
}
}
catch { }
return result;
}
}
}