299 lines
11 KiB
C#
299 lines
11 KiB
C#
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.2,1234 => 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;
|
||
}
|
||
}
|
||
}
|