diff --git a/README.md b/README.md index c1f01f0..55961dd 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,16 @@ ``` 成套报价软件\ 主程序源码(MainForm 拆 14 个 partial;xiangmu/shezhi/ku 子模块窗体) - └ 扒图\ CAD/PDF 扒图窗口 + OCR/PDF 基础设施(唯一权威源,pdfbt 链接共享) -cadbt\ CAD 扒图独立程序(含 CAD-Viewer 网页引擎) -pdfbt\ PDF 扒图独立程序(OCR 等基础设施链接主项目扒图\ 源码) + └ 扒图\ CAD/PDF 扒图窗口 + OCR/PDF 基础设施(唯一权威源) +cadbt\ CAD 网页引擎运行时(node.exe + CAD-Viewer;2026-10-01 独立 cadbt.exe 退役) ai助手\ ZCode 引擎发行包 + 启停脚本(发行包不进 git) 会员服务器\ 肥牛 fnnas 会员服务端 v1.5.1(fpk 工程) tools\ 构建/打包/维护脚本(见下表) release\ 组装产物(仅 setup.iss 进 git) -ghj\ yjktool\ 历史试验小工具 ``` +(已退役:独立 cadbt.exe/pdfbt.exe 扒图程序、ghj/yjktool 试验小工具、cadcj 旧 AutoCAD 插件——扒图功能全部由主程序内嵌窗口承载。) + **数据目录**(运行时,均不进 git):`sjk\bjb\项目<编号>.db` 每项目一库;`sjk\fak.db` 公式库;`sjk\方案库\*.db` 一方案一库;`shezhi\` 用户配置;`xiangmu\` 报表模板。 ## 构建与验证 diff --git a/cadbt/cadbt.sln b/cadbt/cadbt.sln deleted file mode 100644 index 12435b1..0000000 --- a/cadbt/cadbt.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -# SharpDevelop 5.2 -VisualStudioVersion = 12.0.20827.3 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cadbt", "cadbt\cadbt.csproj", "{0A91D57B-B279-4672-9440-78088D022EB1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0A91D57B-B279-4672-9440-78088D022EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0A91D57B-B279-4672-9440-78088D022EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0A91D57B-B279-4672-9440-78088D022EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0A91D57B-B279-4672-9440-78088D022EB1}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/cadbt/cadbt/CadBridge.cs b/cadbt/cadbt/CadBridge.cs deleted file mode 100644 index 48c3421..0000000 --- a/cadbt/cadbt/CadBridge.cs +++ /dev/null @@ -1,213 +0,0 @@ -// ============================================================ -// CadBridge:WinForms 宿主与网页 CAD(CAD-Viewer)之间的互操作桥 -// · 下行(C#→网页):PostMessage 发 startPick/zoomToHandle/deleteHandles/clearHighlight -// · 上行(网页→C#):WebMessageReceived 收 paPicked/entityErased/paExited -// · 扒图结果与实体删除事件以 C# 事件形式提供给 Form3(替代 AutoCAD 版 -// 的 PaTextSelector.BatchTextsPicked 与 Database.ObjectErased) -// ============================================================ -using System; -using System.Collections.Generic; -using System.Web.Script.Serialization; -using Microsoft.Web.WebView2.Core; -using Microsoft.Web.WebView2.WinForms; - -namespace cadbt -{ - public static class CadBridge - { - private static WebView2 _wv; - private static readonly JavaScriptSerializer _json = new JavaScriptSerializer(); - - /// 网页 CAD 是否已挂载(WebView2 已附加)。 - public static bool IsViewerReady - { - get { return _wv != null && _wv.CoreWebView2 != null; } - } - - /// 网页 CAD 中实体被删除(句柄十六进制字符串)。 - public static event Action EntityErased; - - /// 网页 CAD 扒图完成一批(图号/箱号/元件)。 - public static event Action> PaPicked; - - /// 用户按 ESC 退出网页扒图连续模式。 - public static event Action PaExited; - - /// 用户按 F1(焦点在网页或宿主时都触发)——元件两两合并。 - public static event Action F1Requested; - - /// 用户按 F2——元件三个一组合并。 - public static event Action F2Requested; - - /// 用户按 F3——元件四个一组合并。 - public static event Action F3Requested; - - /// 触发 F1 请求(消息过滤器等宿主侧来源调用)。 - public static void RaiseF1() - { - if (F1Requested != null) F1Requested(); - } - - /// 触发 F2 请求(消息过滤器等宿主侧来源调用)。 - public static void RaiseF2() - { - if (F2Requested != null) F2Requested(); - } - - /// 触发 F3 请求(消息过滤器等宿主侧来源调用)。 - public static void RaiseF3() - { - if (F3Requested != null) F3Requested(); - } - - /// 把 WebView2 挂到桥上(在控件初始化完成后调用一次)。 - public static void Attach(WebView2 wv) - { - if (_wv == wv) return; - if (_wv != null) _wv.WebMessageReceived -= OnMessage; - _wv = wv; - if (_wv != null) _wv.WebMessageReceived += OnMessage; - } - - private static void OnMessage(object sender, CoreWebView2WebMessageReceivedEventArgs e) - { - try - { - if (e.TryGetWebMessageAsString() != null) return; // 只处理 JSON 消息 - } - catch { } - try - { - var msg = _json.Deserialize>(e.WebMessageAsJson); - if (msg == null || !msg.ContainsKey("type")) return; - string type = msg["type"] as string; - - if (type == "paPicked") - { - int mode = Convert.ToInt32(msg["mode"]); - var results = new List(); - var arr = msg["results"] as System.Collections.ArrayList; - if (arr != null) - { - foreach (Dictionary item in arr) - { - results.Add(new MyApp.PaTextResult - { - Text = Convert.ToString(item["text"]) ?? "", - FrameHandle = Convert.ToString(item["frameHandle"]) ?? "", - TextHandle = Convert.ToString(item["textHandle"]) ?? "" - }); - } - } - // WebMessageReceived 在 UI 线程触发,可直接调用 Form3 - if (PaPicked != null) - PaPicked((MyApp.PaMode)mode, results); - } - else if (type == "entityErased") - { - string handle = Convert.ToString(msg["handle"]); - if (!string.IsNullOrWhiteSpace(handle) && EntityErased != null) - EntityErased(handle); - } - else if (type == "paError") - { - string errMsg = Convert.ToString(msg["message"]); - System.Windows.Forms.MessageBox.Show( - "网页 CAD 返回错误:\n" + errMsg, - "扒数据", System.Windows.Forms.MessageBoxButtons.OK, - System.Windows.Forms.MessageBoxIcon.Warning); - } - else if (type == "f1") - { - if (F1Requested != null) F1Requested(); - } - else if (type == "f2") - { - if (F2Requested != null) F2Requested(); - } - else if (type == "f3") - { - if (F3Requested != null) F3Requested(); - } - else if (type == "paExited") - { - if (PaExited != null) PaExited(); - } - } - catch (Exception) - { - // 消息格式异常直接忽略,不影响宿主 - } - } - - private static void Post(object msg) - { - if (!IsViewerReady) return; - try - { - _wv.CoreWebView2.PostWebMessageAsJson(_json.Serialize(msg)); - } - catch { } - } - - /// - /// 发送扒图命令。接受原 CAD 命令名(CADPATU/CADPAXH/CADPAYJ/CADPACL) - /// 或网页命令名(patu/paxh/payj)。 - /// - public static void SendPaCommand(string cmd) - { - if (string.IsNullOrWhiteSpace(cmd)) return; - string c = cmd.Trim().ToUpperInvariant(); - int mode = 0; - if (c == "CADPATU" || c == "PATU") mode = 0; - else if (c == "CADPAXH" || c == "PAXH") mode = 1; - else if (c == "CADPAYJ" || c == "PAYJ") mode = 2; - else if (c == "CADPACL" || c == "PACL") - { - ClearHighlight(); - return; - } - else return; - Post(new { type = "startPick", mode = mode }); - } - - /// 缩放居中到指定 Handle 的实体并高亮(点击表格行定位框)。 - public static void ZoomToFrameHandle(string handle) - { - if (string.IsNullOrWhiteSpace(handle)) return; - Post(new { type = "zoomToHandle", handle = handle }); - } - - /// 批量删除指定 Handle 的实体(删表格行联动删框)。 - public static void DeleteFramesByHandles(IEnumerable handles) - { - if (handles == null) return; - var list = new List(); - foreach (string h in handles) - if (!string.IsNullOrWhiteSpace(h)) list.Add(h); - if (list.Count == 0) return; - Post(new { type = "deleteHandles", handles = list }); - } - - /// - /// 合并蒙版:保留 keep 句柄的蒙版并扩大到所有 removes 蒙版的并集, - /// 被合并行的蒙版从网页 CAD 移除(元件合并时蒙版同步合并)。 - /// - public static void MergeMasks(string keep, System.Collections.Generic.IEnumerable removes) - { - if (string.IsNullOrWhiteSpace(keep)) return; - var list = new List(); - if (removes != null) - foreach (string h in removes) - if (!string.IsNullOrWhiteSpace(h) && h != keep) list.Add(h); - if (list.Count == 0) return; - Post(new { type = "mergeMasks", keep = keep, removes = list }); - } - - /// 清除网页 CAD 中的所有高亮。 - public static void ClearHighlight() - { - Post(new { type = "clearHighlight" }); - } - } -} diff --git a/cadbt/cadbt/DockWindows/CadViewerWindow.Designer.cs b/cadbt/cadbt/DockWindows/CadViewerWindow.Designer.cs deleted file mode 100644 index fb81aee..0000000 --- a/cadbt/cadbt/DockWindows/CadViewerWindow.Designer.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace cadbt.DockWindows -{ - partial class CadViewerWindow - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) components.Dispose(); - base.Dispose(disposing); - } - - #region Designer generated code - - private void InitializeComponent() - { - this.SuspendLayout(); - // - // CadViewerWindow - // - this.Name = "CadViewerWindow"; - this.ResumeLayout(false); - } - - #endregion - } -} diff --git a/cadbt/cadbt/DockWindows/CadViewerWindow.cs b/cadbt/cadbt/DockWindows/CadViewerWindow.cs deleted file mode 100644 index 83d85c9..0000000 --- a/cadbt/cadbt/DockWindows/CadViewerWindow.cs +++ /dev/null @@ -1,187 +0,0 @@ -// ============================================================ -// 停靠窗口:CAD 查看器(中央文档区) -// WebView2 承载网页版 CAD-Viewer(localhost:5173),并挂到 CadBridge。 -// ★ 网页服务自启动:exe 旁 node\node.exe + CAD-Viewer\dist\server.cjs -// (静态产物零依赖,客户机无需 Node 环境/pnpm dev;主程序同款端口探测模式) -// ============================================================ -using System; -using System.Diagnostics; -using System.IO; -using System.Net.Sockets; -using System.Windows.Forms; -using Microsoft.Web.WebView2.WinForms; - -namespace cadbt.DockWindows -{ - /// 停靠窗口:网页 CAD 查看器(DockState.Document)。 - public partial class CadViewerWindow : WeifenLuo.WinFormsUI.Docking.DockContent - { - private WebView2 _webView; - private Label _hint; - - /// 静态服务进程句柄(退出时杀进程树)。 - private static Process _serverProcess; - - public CadViewerWindow() - { - InitializeComponent(); - Text = "CAD 查看器"; - TabText = "CAD 查看器"; - FormClosed += (s, e) => 停止网页服务(); - LoadViewer(); - } - - /// CAD 网页服务端口(与 server.cjs 一致)。 - private const int 服务端口 = 5173; - - private async void LoadViewer() - { - try - { - _webView = new WebView2(); - _webView.Dock = DockStyle.Fill; - Controls.Add(_webView); - await _webView.EnsureCoreWebView2Async(null); - CadBridge.Attach(_webView); - - // ★ 禁用浏览器快捷键(F5/Ctrl+R/Ctrl+F 等):刷新会丢掉所有扒图蒙版 - _webView.CoreWebView2.Settings.AreBrowserAcceleratorKeysEnabled = false; - - // ★ 先确保静态服务在线(复刻主程序 StartPriceWebView 的探测+拉起模式) - 启动网页服务(); - - // 服务不可达时给用户明确提示 - _webView.CoreWebView2.NavigationCompleted += (s, e) => - { - if (!e.IsSuccess && _hint == null) - ShowLoadHint("无法连接网页 CAD 服务(端口 " + 服务端口 + ")。\r\n请确认 cadbt\\node\\node.exe 与 cadbt\\CAD-Viewer\\dist 目录完整,然后点击\"重新加载\"。"); - }; - _webView.CoreWebView2.Navigate("http://localhost:" + 服务端口 + "/"); - } - catch (Exception ex) - { - ShowLoadHint("WebView2 初始化失败: " + ex.Message + "\r\n请确认系统已安装 Microsoft Edge WebView2 运行时。"); - } - } - - /// 启动 CAD 网页静态服务(端口已通=复用;不通=node server.cjs 后台拉起)。 - private void 启动网页服务() - { - try - { - if (端口已通()) return; // 上次实例或手动 dev server 已在服务 - - string baseDir = AppDomain.CurrentDomain.BaseDirectory; - string nodeExe = Path.Combine(baseDir, "node", "node.exe"); - // dist 与 server.cjs 同目录;找不到时尝试上一级 CAD-Viewer 结构(开发机) - // 安装布局: {app}\cadbt\CAD-Viewer\dist\ (make_package 已展平 packages 层) - string serverScript = Path.Combine(baseDir, "CAD-Viewer", "dist", "server.cjs"); - if (!File.Exists(serverScript)) - { - // 开发机回退: bin\Debug 上两级 = cadbt\cadbt\,保留 monorepo 原始层级 - serverScript = Path.GetFullPath(Path.Combine(baseDir, @"..\..\CAD-Viewer\packages\cad-viewer-example\dist\server.cjs")); - } - - if (!File.Exists(nodeExe) || !File.Exists(serverScript)) - { - WriteDiag("[CAD服务] 缺少 node.exe 或 server.cjs: node=" + nodeExe + " script=" + serverScript); - return; - } - - var psi = new ProcessStartInfo - { - FileName = nodeExe, - Arguments = "\"" + Path.GetFullPath(serverScript) + "\"", - WorkingDirectory = Path.GetDirectoryName(Path.GetFullPath(serverScript)), - UseShellExecute = false, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - }; - _serverProcess = Process.Start(psi); - WriteDiag("[CAD服务] 已启动 node PID=" + (_serverProcess == null ? "?" : _serverProcess.Id.ToString())); - - // 等端口就绪(最多 8 秒) - for (int i = 0; i < 40; i++) - { - System.Threading.Thread.Sleep(200); - if (端口已通()) { WriteDiag("[CAD服务] 端口就绪, 耗时 " + (i + 1) * 200 + "ms"); return; } - } - WriteDiag("[CAD服务] 端口 8 秒未就绪(继续导航,由 NavigationCompleted 提示)"); - } - catch (Exception ex) { WriteDiag("[CAD服务] 启动异常: " + ex.Message); } - } - - /// 快速探测本机端口。 - private static bool 端口已通() - { - try - { - using (var client = new TcpClient()) - { - var ar = client.BeginConnect("127.0.0.1", 服务端口, null, null); - bool ok = ar.AsyncWaitHandle.WaitOne(400); - if (ok && client.Connected) { client.EndConnect(ar); return true; } - } - } - catch { } - return false; - } - - /// 退出清理:杀 node 静态服务进程树(taskkill /T 覆盖可能的子进程)。 - private void 停止网页服务() - { - try - { - if (_serverProcess != null && !_serverProcess.HasExited) - { - int pid = _serverProcess.Id; - Process.Start(new ProcessStartInfo("taskkill", "/PID " + pid + " /T /F") - { - CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden - }); - WriteDiag("[CAD服务] 已停止 PID=" + pid); - } - _serverProcess = null; - } - catch (Exception ex) { WriteDiag("[CAD服务] 停止异常: " + ex.Message); } - } - - /// 简单诊断日志(logs\cad服务.log)。 - private static void WriteDiag(string msg) - { - try - { - string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"); - Directory.CreateDirectory(dir); - File.AppendAllText(Path.Combine(dir, "cad服务.log"), - DateTime.Now.ToString("HH:mm:ss.fff") + " " + msg + Environment.NewLine); - } - catch { } - } - - private void ShowLoadHint(string text) - { - if (_hint != null) return; - _hint = new Label(); - _hint.Dock = DockStyle.Fill; - _hint.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - _hint.Text = text; - var reload = new Button(); - reload.Text = "重新加载"; - reload.Dock = DockStyle.Bottom; - reload.Click += (s, e) => - { - Controls.Remove(_hint); - _hint.Dispose(); - _hint = null; - 启动网页服务(); - if (_webView != null && _webView.CoreWebView2 != null) - _webView.CoreWebView2.Navigate("http://localhost:" + 服务端口 + "/"); - }; - Controls.Add(reload); - Controls.Add(_hint); - _hint.BringToFront(); - } - - } -} diff --git a/cadbt/cadbt/DockWindows/QuoteWindow.Designer.cs b/cadbt/cadbt/DockWindows/QuoteWindow.Designer.cs deleted file mode 100644 index 8b5f4f7..0000000 --- a/cadbt/cadbt/DockWindows/QuoteWindow.Designer.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace cadbt.DockWindows -{ - partial class QuoteWindow - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) components.Dispose(); - base.Dispose(disposing); - } - - #region Designer generated code - - private void InitializeComponent() - { - this.SuspendLayout(); - // - // QuoteWindow - // - this.Name = "QuoteWindow"; - this.ResumeLayout(false); - } - - #endregion - } -} diff --git a/cadbt/cadbt/DockWindows/QuoteWindow.cs b/cadbt/cadbt/DockWindows/QuoteWindow.cs deleted file mode 100644 index b6a572f..0000000 --- a/cadbt/cadbt/DockWindows/QuoteWindow.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ============================================================ -// 停靠窗口:报价插件工具栏(左侧) -// 把 cadcj 的 Form3 报价界面作为子控件嵌入(TopLevel=false)。 -// ============================================================ -using System.Windows.Forms; - -namespace cadbt.DockWindows -{ - /// 停靠窗口:报价插件工具栏(DockState.DockLeft)。 - public partial class QuoteWindow : WeifenLuo.WinFormsUI.Docking.DockContent - { - public QuoteWindow() - { - InitializeComponent(); - Text = "报价工具"; - TabText = "报价工具"; - - var form = new MyApp.Form3(); - form.TopLevel = false; - form.FormBorderStyle = FormBorderStyle.None; - form.Dock = DockStyle.Fill; - Controls.Add(form); - form.Show(); - } - } -} diff --git a/cadbt/cadbt/MainForm.Designer.cs b/cadbt/cadbt/MainForm.Designer.cs deleted file mode 100644 index e7da564..0000000 --- a/cadbt/cadbt/MainForm.Designer.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace cadbt -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.dockSurface1 = new Smart.CustomComponents.DockSurface(); - Smart.CustomComponents.DockWindows.DockWindowItem dockWindowItem1 = new Smart.CustomComponents.DockWindows.DockWindowItem(); - Smart.CustomComponents.DockWindows.DockWindowItem dockWindowItem2 = new Smart.CustomComponents.DockWindows.DockWindowItem(); - this.SuspendLayout(); - // - // dockSurface1 - // - dockWindowItem1.ClassName = "QuoteWindow"; - dockWindowItem1.Title = "报价工具"; - dockWindowItem1.DockState = WeifenLuo.WinFormsUI.Docking.DockState.DockLeft; - dockWindowItem1.DefaultWidth = 440; - dockWindowItem1.ShowCloseButton = false; - this.dockSurface1.DockWindows.Add(dockWindowItem1); - dockWindowItem2.ClassName = "CadViewerWindow"; - dockWindowItem2.Title = "CAD 查看器"; - dockWindowItem2.DockState = WeifenLuo.WinFormsUI.Docking.DockState.Document; - dockWindowItem2.ShowCloseButton = false; - this.dockSurface1.DockWindows.Add(dockWindowItem2); - this.dockSurface1.Dock = System.Windows.Forms.DockStyle.Fill; - this.dockSurface1.Location = new System.Drawing.Point(0, 0); - this.dockSurface1.Name = "dockSurface1"; - this.dockSurface1.Size = new System.Drawing.Size(1184, 661); - this.dockSurface1.TabIndex = 0; - // - // MainForm - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1184, 661); - this.Controls.Add(this.dockSurface1); - this.Name = "MainForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "cadbt - 报价工具 + 网页 CAD"; - this.ResumeLayout(false); - this.PerformLayout(); - } - - private Smart.CustomComponents.DockSurface dockSurface1; - } -} diff --git a/cadbt/cadbt/MainForm.DockWindows.cs b/cadbt/cadbt/MainForm.DockWindows.cs deleted file mode 100644 index 31695ef..0000000 --- a/cadbt/cadbt/MainForm.DockWindows.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 本文件由『生成停靠窗口代码』自动生成格式参考手写,集合变更后请同步刷新。 -using System; -using WeifenLuo.WinFormsUI.Docking; - -namespace cadbt -{ - public partial class MainForm - { - void CreateDockWindows_dockSurface1() - { - var dockSurface1 = this.dockSurface1 as Smart.CustomComponents.DockSurface; - if (dockSurface1 == null) return; - dockSurface1.EnsureDefaultTheme(); // 必须:Show 前保证有效主题 - - var quote = new cadbt.DockWindows.QuoteWindow(); - quote.CloseButtonVisible = false; - quote.TabText = "报价工具"; - quote.Text = "报价工具"; - quote.Show(dockSurface1, DockState.DockLeft); - - var viewer = new cadbt.DockWindows.CadViewerWindow(); - viewer.CloseButtonVisible = false; - viewer.TabText = "CAD 查看器"; - viewer.Text = "CAD 查看器"; - viewer.Show(dockSurface1, DockState.Document); - } - } -} diff --git a/cadbt/cadbt/MainForm.cs b/cadbt/cadbt/MainForm.cs deleted file mode 100644 index 8c6ddb3..0000000 --- a/cadbt/cadbt/MainForm.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 由SharpDevelop创建。 - * 用户: 099978 - * 日期: 2026-09-04 - * 时间: 12:24 - * - * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 - */ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; - -namespace cadbt -{ - /// - /// Description of MainForm. - /// - public partial class MainForm : Form - { - public MainForm() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - CreateDockWindows_dockSurface1(); - - // ★ 全局 F1 过滤器:焦点在任何 WinForms 控件上都触发元件合并 - // (焦点在网页时由网页端转发,两路都汇聚到 CadBridge.F1Requested) - Application.AddMessageFilter(new F1MessageFilter()); - FormClosed += (s, e) => Application.RemoveMessageFilter(f1Filter); - } - - private readonly F1MessageFilter f1Filter = new F1MessageFilter(); - - /// 把 F1 按键(0x70)转成 CadBridge.F1Requested,不拦截按键本身。 - private class F1MessageFilter : IMessageFilter - { - public bool PreFilterMessage(ref Message m) - { - const int WM_KEYDOWN = 0x0100; - if (m.Msg == WM_KEYDOWN && (int)m.WParam == 0x70) - { - try { CadBridge.RaiseF1(); } catch { } - } - else if (m.Msg == WM_KEYDOWN && (int)m.WParam == 0x71) - { - try { CadBridge.RaiseF2(); } catch { } - } - else if (m.Msg == WM_KEYDOWN && (int)m.WParam == 0x72) - { - try { CadBridge.RaiseF3(); } catch { } - } - return false; - } - } - } -} diff --git a/cadbt/cadbt/Plugin/Form3.cs b/cadbt/cadbt/Plugin/Form3.cs deleted file mode 100644 index a1e5f87..0000000 --- a/cadbt/cadbt/Plugin/Form3.cs +++ /dev/null @@ -1,6794 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Drawing; -using System.IO; -using System.Windows.Forms; -using Microsoft.Win32; -using Zuby.ADGV; - -namespace MyApp -{ - /// - /// Form3 的交互逻辑(CAD 2018 插件报价窗口)。 - /// 功能与主项目报价页面一致:项目表 + 图号/箱号/元件三级联动 + 公式重算 + 右键菜单 + 项目导出。 - /// UI 布局定义见 Form3.ui.cs。数据库独立存放在 cadcj\sjk\ 目录。 - /// - public partial class Form3 - { - // ============================================================ - // 数据库路径与表名常量(独立于主项目,存放在 cadcj\sjk\ 下) - // ============================================================ - - private const string ProjectsDbPath = @"sjk\advancedDataGridView6Table.db"; - private const string ProjectsTableName = "advancedDataGridView6Table"; - private const string QuoteDbDir = @"sjk\bjb"; - private const string TuhaoTableName = "advancedDataGridView9Table"; - private const string ProjectInfoTableName = "项目信息"; - private const string IndexTableName = "表索引"; - - private const string CadRegPath = @"SOFTWARE\Autodesk\AutoCAD\R22.0\ACAD-1001:804\Apps\CADCJ"; - - /// - /// 插件所在目录(cadcj)。优先从注册表读取 CAD 自动加载的 DLL 路径(最可靠), - /// 然后尝试 CodeBase / Location,最后兜底 BaseDirectory(可能是 CAD 目录,会报错)。 - /// - private static readonly string _baseDir = GetPluginBaseDir(); - - private static string GetPluginBaseDir() - { - // ★ 方案0(2026-09-04 standalone 版):exe 所在目录即数据根 - // (cadbt 独立运行,不再依赖 AutoCAD 注册表定位——旧 cadcj 注册表残留在 - // 退役机器上会把数据库指向已删除的目录) - try - { - var baseDir = AppDomain.CurrentDomain.BaseDirectory; - if (!string.IsNullOrEmpty(baseDir) && Directory.Exists(baseDir)) - { - WriteDebugLog("[GetPluginBaseDir] BaseDirectory 成功: " + baseDir); - return baseDir; - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] BaseDirectory 异常: " + ex.Message); } - - // ★ 方案2:CodeBase(不受 shadow copy 影响) - try - { - var codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase; - WriteDebugLog("[GetPluginBaseDir] CodeBase=" + codeBase); - if (!string.IsNullOrEmpty(codeBase)) - { - var localPath = new Uri(codeBase).LocalPath; - var dir = Path.GetDirectoryName(localPath); - if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) - { - WriteDebugLog("[GetPluginBaseDir] CodeBase方案成功: " + dir); - return dir; - } - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] CodeBase方案异常: " + ex.Message); } - - // ★ 方案3:Location - try - { - var loc = System.Reflection.Assembly.GetExecutingAssembly().Location; - WriteDebugLog("[GetPluginBaseDir] Location=" + loc); - if (!string.IsNullOrEmpty(loc)) - { - var dir = Path.GetDirectoryName(loc); - if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) - { - WriteDebugLog("[GetPluginBaseDir] Location方案成功: " + dir); - return dir; - } - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] Location方案异常: " + ex.Message); } - - // ★ 方案4(最后兜底):BaseDirectory(CAD 目录,数据库会找不到) - var fallback = AppDomain.CurrentDomain.BaseDirectory; - WriteDebugLog("[GetPluginBaseDir] ⚠ 兜底BaseDirectory=" + fallback + " (数据库会找不到!)"); - return fallback; - } - - private static void WriteDebugLog(string msg) - { - try - { - var logDir = Path.Combine( - Path.GetDirectoryName( - new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath), - "sjk"); - if (!Directory.Exists(logDir)) logDir = Path.GetTempPath(); - var logPath = Path.Combine(logDir, "form3_path_debug.log"); - File.AppendAllText(logPath, - "[" + DateTime.Now.ToString("HH:mm:ss") + "] " + msg + Environment.NewLine); - } - catch { } - } - - // ============================================================ - // 当前层级选中状态(联动核心) - // ============================================================ - - private string _currentProjectId = ""; - private string _currentTuhao = ""; - private string _currentXianghao = ""; - private bool _isReloading = false; - private bool _isRecalculating = false; - private DateTime _lastRecalcTime = DateTime.MinValue; - - // 价格显示格式化配置(每个项目独立,随项目信息表加载) - private string _单台小数位文本 = "保留2位小数"; - private string _单台取整方式 = "不取整"; - private string _项目小数位文本 = "保留2位小数"; - private string _项目取整方式 = "不取整"; - - // 当前各表的内存数据(用于关闭/切换时回写数据库) - private DataTable _tuhaoTable; - private DataTable _xianghaoTable; - private DataTable _yuanjianTable; - - // 内存缓存:切换图号/箱号时不丢编辑,点保存才写库 - private Dictionary _xianghaoCache = new Dictionary(); - private Dictionary _yuanjianCache = new Dictionary(); - - // 右键菜单组件(运行时创建,不在设计器 XML 里) - private ContextMenuStrip _menuTuhao; - private ContextMenuStrip _menuXianghao; - private ContextMenuStrip _menuYuanjian; - - private static readonly string[] ProjectInfoColumns = - { - "项目编号", "项目名称", "客户名称", "客户地址", - "联系人", "联系电话", "项目日期", "备注", - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话", - "单台小数位", "单台取整方式", "项目小数位", "项目取整方式" - }; - - /// 公式计算列集合(只包含程序算出来的价格列)。 - private static readonly HashSet s_公式列集合 = - new HashSet(StringComparer.OrdinalIgnoreCase) - { - "表价", "采购单价", "采购价", "报出单价", "报出价", - "单台成本", "成本价", "单台报出", "利润", - "单价", "总价", "成本总价", "毛利", - "成本总价", "报出总价", "利润" - }; - - /// 构造函数:初始化 UI 并绑定事件。 - public Form3() - { - InitializeComponent(); - - // ★ 立即创建数据库(不依赖 Load 事件,UserControl 嵌入 PaletteSet 时 Load 可能延迟) - try - { - Log("[Form3] _baseDir = " + _baseDir); - Log("[Form3] ProjectsDbPath = " + GetDbFullPath(ProjectsDbPath)); - EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); - Log("[Form3] 数据库创建/验证成功"); - } - catch (System.Exception ex) - { - Log("[Form3] 数据库创建失败: " + ex.Message); - } - - // ★ 诊断:后续初始化步骤逐步打点(定位面板空白问题) - try - { - Log("[Form3.init] 开始双缓冲设置"); - EnableDoubleBuffered(this.advancedDataGridView6); - EnableDoubleBuffered(this.advancedDataGridView9); - EnableDoubleBuffered(this.advancedDataGridView4); - EnableDoubleBuffered(this.advancedDataGridView5); - Log("[Form3.init] 双缓冲完成"); - - ApplyReadOnlyColumns(this.advancedDataGridView6, new string[] { - "项目编号", "项目名称", "客户名称", "客户地址", "联系人", "联系电话", - "项目日期", "箱柜台数", "成本总价", "报出总价", "利润", "利润率", "备注" - }); - ApplyReadOnlyColumns(this.advancedDataGridView9, new string[] { - "序号", "箱柜数量", "单价", "总价", "成本总价", "毛利", "毛利率" - }); - ApplyReadOnlyColumns(this.advancedDataGridView4, new string[] { - "序号", "单台成本", "成本价", "单台报出", "报出价", "利润", "利润率", "毛利率" - }); - ApplyReadOnlyColumns(this.advancedDataGridView5, new string[] { - "序号", "采购单价", "采购价", "报出单价", "报出价" - }); - Log("[Form3.init] 只读列完成"); - - // 工具栏按钮事件 - this.toolStripButton1.Click += toolStripButton1_Click; - this.toolStripButton5.Click += toolStripButton5_Click; - this.toolStripButton6.Click += toolStripButton6_Click; - this.toolStripButton2.Click += (s, e) => SendCadPaCommand("CADPATU"); - this.toolStripButton3.Click += (s, e) => SendCadPaCommand("CADPAXH"); - this.toolStripButton4.Click += (s, e) => SendCadPaCommand("CADPAYJ"); - this.toolStripButton7.Click += (s, e) => ShowDeepSeekSettings(); - Log("[Form3.init] 工具栏事件完成"); - - this.button28.Click += button28_Click; - this.advancedDataGridView6.CellDoubleClick += advancedDataGridView6_CellDoubleClick; - - this.advancedDataGridView9.SelectionChanged += advancedDataGridView9_SelectionChanged; - this.advancedDataGridView4.SelectionChanged += advancedDataGridView4_SelectionChanged; - this.advancedDataGridView5.SelectionChanged += advancedDataGridView5_SelectionChanged; - - this.advancedDataGridView9.CellClick += Grid_CellClick_Zoom; - this.advancedDataGridView4.CellClick += Grid_CellClick_Zoom; - this.advancedDataGridView5.CellClick += Grid_CellClick_Zoom; - - this.advancedDataGridView5.CellValueChanged += Yuanjian_CellValueChanged; - this.advancedDataGridView4.CurrentCellDirtyStateChanged += Grid_DirtyStateChanged; - this.advancedDataGridView4.CellValueChanged += Xianghao_CellValueChanged; - this.advancedDataGridView9.CurrentCellDirtyStateChanged += Grid_DirtyStateChanged; - this.advancedDataGridView9.CellValueChanged += Tuhao_CellValueChanged; - - this.advancedDataGridView5.CellEndEdit += Grid_CellEndEdit; - this.advancedDataGridView4.CellEndEdit += Grid_CellEndEdit; - this.advancedDataGridView9.CellEndEdit += Grid_CellEndEdit; - - this.advancedDataGridView5.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView4.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView9.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView6.DataError += (s, e) => { e.Cancel = true; }; - - this.advancedDataGridView9.MouseDown += Grid_MouseDown_KeepMultiSelect; - this.advancedDataGridView4.MouseDown += Grid_MouseDown_KeepMultiSelect; - this.advancedDataGridView5.MouseDown += Grid_MouseDown_KeepMultiSelect; - - this.advancedDataGridView9.KeyDown += Grid_KeyDown_Delete; - this.advancedDataGridView4.KeyDown += Grid_KeyDown_Delete; - this.advancedDataGridView5.KeyDown += Grid_KeyDown_Delete; - Log("[Form3.init] 表格事件完成"); - - BuildContextMenus(); - Log("[Form3.init] 右键菜单完成"); - - this.Disposed += Form3_Disposed; - - this.Load += (s, e) => - { - try - { - EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); - ReloadProjectsFromDatabase(); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - this.advancedDataGridView9.DataSource = null; - this.advancedDataGridView4.DataSource = null; - this.advancedDataGridView5.DataSource = null; - Log("[Form3.Load] 初始化完成"); - } - catch (System.Exception ex) - { - Log("[Form3.Load] 初始化异常: " + ex.Message); - } - - try - { - // 网页 CAD 桥:订阅实体删除事件(用户在网页里删框时联动删行) - cadbt.CadBridge.EntityErased -= Database_ObjectErased; - cadbt.CadBridge.EntityErased += Database_ObjectErased; - // 网页 CAD 桥:订阅扒图结果事件(框选完成立即插入表格) - cadbt.CadBridge.PaPicked -= OnPaTextsPicked; - cadbt.CadBridge.PaPicked += OnPaTextsPicked; - // 网页 CAD 桥:F1/F2 元件合并(焦点在网页时按键由网页转发) - cadbt.CadBridge.F1Requested -= OnF1FromBridge; - cadbt.CadBridge.F1Requested += OnF1FromBridge; - cadbt.CadBridge.F2Requested -= OnF2FromBridge; - cadbt.CadBridge.F2Requested += OnF2FromBridge; - cadbt.CadBridge.F3Requested -= OnF3FromBridge; - cadbt.CadBridge.F3Requested += OnF3FromBridge; - } - catch (System.Exception ex) - { - Log("[Form3.Load] 订阅CadBridge事件失败: " + ex.Message); - } - }; - Log("[Form3.init] 构造函数全部完成 ✓"); - } - catch (System.Exception ex) - { - Log("[Form3.init] ⚠ 初始化异常: " + ex.ToString()); - } - } - - /// - /// ★ 网页 CAD 中实体被删除时触发。如果删除的是 __CADCJ_PA_FRAME 图层上的扒图框, - /// 通过 Handle 查找当前项目下的图号表/箱号表/元件表对应行,同步删除。 - /// - private void Database_ObjectErased(string handle) - { - try - { - if (string.IsNullOrWhiteSpace(handle)) return; - // ★ 如果正在通过表格删除(_isReloading=true),跳过网页 CAD 事件触发的删除 - // 避免表格删除和 CAD 事件删除互相干扰导致蒙版/数据不一致 - if (_isReloading) return; - - Log("[ObjectErased] 触发! Handle=" + handle); - - this.BeginInvoke((Action)(() => - { - try - { - // 再次检查(异步执行时状态可能已变化) - if (_isReloading) { Log("[ObjectErased] _isReloading=true,跳过"); return; } - DeleteRowsByFrameHandle(handle); - } - catch (System.Exception ex) - { - Log("[ObjectErased.BeginInvoke] 异常: " + ex.Message); - } - })); - } - catch (System.Exception ex) - { - Log("[ObjectErased] 异常: " + ex.Message); - } - } - - /// - /// 根据框Handle在当前项目的图号表/箱号表/元件表中删除对应数据行。 - /// - private void DeleteRowsByFrameHandle(string frameHandle) - { - if (string.IsNullOrWhiteSpace(frameHandle)) return; - if (string.IsNullOrWhiteSpace(_currentProjectId)) { Log("[DeleteRowsByFrameHandle] _currentProjectId 为空,放弃"); return; } - _isReloading = true; - try - { - string dbPath = GetQuoteDbPath(_currentProjectId); - if (!File.Exists(dbPath)) { Log("[DeleteRowsByFrameHandle] 数据库不存在: " + dbPath); return; } - - bool deleted = false; - string deletedTuhao = null; - string deletedXianghao = null; - // ★ 收集级联删除的框Handle(图号→箱号→元件,删除数据时同步删蒙版) - var cascadeFrames = new List(); - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - - // 1) 图号表 - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT 图号 FROM " + TuhaoTableName + " WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - using (var reader = sel.ExecuteReader()) - { - if (reader.Read()) - { - deletedTuhao = reader.IsDBNull(0) ? "" : reader.GetString(0); - Log("[DeleteRowsByFrameHandle] 命中图号表: " + deletedTuhao); - } - } - } - if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - // ★ 删除图号前,先收集该图号下所有箱号和元件的框Handle(级联删蒙版) - CollectFrameHandlesForTuhao(_currentProjectId, deletedTuhao, cascadeFrames); - DeleteTuhao(_currentProjectId, deletedTuhao); - deleted = true; - } - - if (!deleted) - { - // 2) 箱号表:通过表索引找到所有箱号表,逐个查 - List allXhTables = new List(); - using (var selIdx = new System.Data.SQLite.SQLiteCommand( - "SELECT 实际表名, 图号 FROM 表索引 WHERE 类型='箱号';", conn)) - using (var rIdx = selIdx.ExecuteReader()) - { - while (rIdx.Read()) - { - string realTbl = rIdx.IsDBNull(0) ? "" : rIdx.GetString(0); - string th = rIdx.IsDBNull(1) ? "" : rIdx.GetString(1); - if (!string.IsNullOrWhiteSpace(realTbl)) - allXhTables.Add(realTbl + "|" + th); - } - } - Log("[DeleteRowsByFrameHandle] 箱号表数量: " + allXhTables.Count); - foreach (string info in allXhTables) - { - string[] parts = info.Split('|'); - string realTbl = parts[0]; - string th = parts.Length > 1 ? parts[1] : ""; - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT 箱号 FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - using (var reader = sel.ExecuteReader()) - { - if (reader.Read()) - { - deletedTuhao = th; - deletedXianghao = reader.IsDBNull(0) ? "" : reader.GetString(0); - Log("[DeleteRowsByFrameHandle] 命中箱号表: 图号=" + th + " 箱号=" + deletedXianghao); - break; - } - } - } - if (!string.IsNullOrWhiteSpace(deletedXianghao)) break; - } - if (!string.IsNullOrWhiteSpace(deletedXianghao)) - { - // ★ 删除箱号前,先收集该箱号下元件表的框Handle(级联删蒙版) - CollectFrameHandlesForXianghao(_currentProjectId, deletedTuhao, deletedXianghao, cascadeFrames); - DeleteXianghao(_currentProjectId, deletedTuhao, deletedXianghao); - deleted = true; - } - } - - if (!deleted) - { - // 3) 元件表:通过表索引找到所有元件表,逐个查 - List allYjTables = new List(); - using (var selIdx = new System.Data.SQLite.SQLiteCommand( - "SELECT 实际表名, 图号, 箱号 FROM 表索引 WHERE 类型='元件';", conn)) - using (var rIdx = selIdx.ExecuteReader()) - { - while (rIdx.Read()) - { - string realTbl = rIdx.IsDBNull(0) ? "" : rIdx.GetString(0); - string th = rIdx.IsDBNull(1) ? "" : rIdx.GetString(1); - string xh = rIdx.IsDBNull(2) ? "" : rIdx.GetString(2); - if (!string.IsNullOrWhiteSpace(realTbl)) - allYjTables.Add(realTbl + "|" + th + "|" + xh); - } - } - Log("[DeleteRowsByFrameHandle] 元件表数量: " + allYjTables.Count + " 查找Handle=" + frameHandle); - foreach (string info in allYjTables) - { - string[] parts = info.Split('|'); - string realTbl = parts[0]; - string th = parts.Length > 1 ? parts[1] : ""; - string xh = parts.Length > 2 ? parts[2] : ""; - // ★ 先列出该表所有的框Handle,排查是否真的写进去了 - using (var selAll = new System.Data.SQLite.SQLiteCommand( - "SELECT 序号, 框Handle FROM \"" + realTbl + "\";", conn)) - using (var rAll = selAll.ExecuteReader()) - { - while (rAll.Read()) - { - string s = rAll.IsDBNull(0) ? "" : rAll.GetString(0); - string h = rAll.IsDBNull(1) ? "" : rAll.GetString(1); - Log(" [元件表 " + realTbl + "] 序号=" + s + " 框Handle=[" + h + "]"); - } - } - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - object cnt = sel.ExecuteScalar(); - int matchCount = (cnt != null && cnt != DBNull.Value) ? Convert.ToInt32(cnt) : 0; - if (matchCount > 0) - { - deletedTuhao = th; - deletedXianghao = xh; - Log("[DeleteRowsByFrameHandle] 命中元件表: 图号=" + th + " 箱号=" + xh + " 匹配行数=" + matchCount); - - // ★ 直接用框Handle 删除所有匹配行(解决重复行问题) - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - delCmd.Parameters.AddWithValue("@fh", frameHandle); - int affected = delCmd.ExecuteNonQuery(); - Log("[DeleteRowsByFrameHandle] DELETE 完成,影响行数=" + affected); - } - deleted = true; - break; - } - } - } - } - } - - if (deleted) - { - Log("[DeleteRowsByFrameHandle] 删除成功: Handle=" + frameHandle + " cascadeFrames=" + cascadeFrames.Count); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - // 重新编号(直接操作数据库) - if (!string.IsNullOrWhiteSpace(deletedTuhao) && !string.IsNullOrWhiteSpace(deletedXianghao)) - { - string yjTbl = GetYuanjianTableByIndex(_currentProjectId, deletedTuhao, deletedXianghao); - if (!string.IsNullOrEmpty(yjTbl)) - RenumberTable(_currentProjectId, "\"" + yjTbl + "\""); - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, deletedTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - } - else if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, deletedTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - } - - // ★ 直接在数据库层面重算(不经过内存表,不触发回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - - // ★ 从数据库重新加载到 UI(覆盖内存表,确保 UI 与数据库一致) - if (!string.IsNullOrWhiteSpace(deletedTuhao) && !string.IsNullOrWhiteSpace(deletedXianghao)) - { - if (_currentTuhao == deletedTuhao) - { - ReloadXianghaoByTuhao(_currentProjectId, deletedTuhao); - if (_currentXianghao == deletedXianghao) - ReloadYuanjianByXianghao(_currentProjectId, deletedTuhao, deletedXianghao); - } - } - else if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - ReloadTuhaoByProject(_currentProjectId); - if (_currentTuhao == deletedTuhao) - ReloadXianghaoByTuhao(_currentProjectId, deletedTuhao); - } - - // ★ 删除级联的框实体(图号删除时,其下箱号和元件的蒙版也要删除) - Log("[DeleteRowsByFrameHandle] cascadeFrames 数量: " + cascadeFrames.Count + " 当前Handle=" + frameHandle); - if (cascadeFrames.Count > 0) - { - // ★ 收集后一次性批量删除(排除当前正在删除的 frameHandle,已由 CAD 端删除) - var toDel = new List(); - foreach (string h in cascadeFrames) - { - if (h != frameHandle) toDel.Add(h); - } - if (toDel.Count > 0) - { - Log("[DeleteRowsByFrameHandle] 级联删除框Handle数: " + toDel.Count); - DeleteFramesByHandles(toDel); - } - SaveCurrentDwg(); - Log("[DeleteRowsByFrameHandle] 级联删除完成"); - } - } - } - finally - { - _isReloading = false; - } - } - - /// 重写 OnLoad:在所有 Load 事件订阅者之前确保项目库文件存在。 - protected override void OnLoad(EventArgs e) - { - try { EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); } - catch { } - base.OnLoad(e); - } - - // ============================================================ - // 通用辅助方法 - // ============================================================ - - private void Log(string msg) - { - try - { - string logPath = Path.Combine(_baseDir, "diag.log"); - File.AppendAllText(logPath, - DateTime.Now.ToString("HH:mm:ss.fff") + " " + msg + "\r\n"); - } - catch { } - } - - private string GetDbFullPath(string relativePath) - { - return Path.Combine(_baseDir, relativePath); - } - - private string GetConnString(string dbPath) - { - // ★ busy_timeout=3000:数据库被 CAD 或其他进程短暂占用时等待重试而非卡死; - // Pooling 关闭,避免连接池长期持有文件句柄 - return "Data Source=" + dbPath + ";Version=3;busy_timeout=3000;"; - } - - private string GetQuoteDbPath(string projectId) - { - string safeName = projectId; - char[] invalidChars = Path.GetInvalidFileNameChars(); - foreach (char c in invalidChars) safeName = safeName.Replace(c, '_'); - return GetDbFullPath(QuoteDbDir + @"\项目" + safeName + ".db"); - } - - private static decimal ParseDecimal(object v) - { - if (v == null || v == DBNull.Value) return 0m; - decimal d; - if (decimal.TryParse(v.ToString().Trim(), out d)) return d; - return 0m; - } - - private static DataGridViewColumn FindColumn(DataGridView dgv, string name) - { - if (dgv == null || dgv.Columns == null) return null; - foreach (DataGridViewColumn c in dgv.Columns) - { - if (c == null) continue; - if (c.DataPropertyName == name || c.HeaderText == name || c.Name == name) return c; - } - return null; - } - - private static string GetCellString(DataGridViewRow row, string name) - { - if (row == null || row.DataGridView == null) return ""; - DataGridViewColumn col = FindColumn(row.DataGridView, name); - if (col == null) return ""; - object v = row.Cells[col.Index].Value; - return v == null ? "" : v.ToString().Trim(); - } - - private static decimal GetCellDecimal(DataGridViewRow row, string name) - { - return ParseDecimal(GetCellString(row, name)); - } - - private static string GetCellValueAsString(DataGridViewRow row, string colName) - { - if (row == null || row.Cells == null || string.IsNullOrEmpty(colName)) return ""; - DataGridView grid = row.DataGridView; - if (grid != null) - { - foreach (DataGridViewColumn col in grid.Columns) - { - if (col == null) continue; - string key = !string.IsNullOrEmpty(col.DataPropertyName) - ? col.DataPropertyName - : (!string.IsNullOrEmpty(col.HeaderText) ? col.HeaderText : col.Name); - if (key == colName) - { - object v = row.Cells[col.Index].Value; - return v == null ? "" : v.ToString().Trim(); - } - } - } - return ""; - } - - private static void SetCell(DataGridViewRow row, string colName, decimal value) - { - if (row == null || row.DataGridView == null) return; - DataGridViewColumn col = FindColumn(row.DataGridView, colName); - if (col == null) return; - row.Cells[col.Index].Value = value == 0m ? 0d : (double)value; - } - - private static DataGridViewRow GetFirstSelectedRow(DataGridView dgv) - { - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return null; - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - return r; - } - if (dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) return dgv.CurrentRow; - return null; - } - - private static List GetAllSelectedRows(DataGridView dgv) - { - var result = new List(); - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return result; - var seenRows = new HashSet(); - if (dgv.SelectedRows != null) - { - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - if (seenRows.Add(r.Index)) result.Add(r); - } - } - // ★ 总是通过 SelectedCells 补充收集(不再限制 result.Count == 0) - // ADGV 多选时 SelectedRows 可能不完整,SelectedCells 能覆盖所有选中行 - if (dgv.SelectedCells != null) - { - foreach (DataGridViewCell c in dgv.SelectedCells) - { - if (c == null || c.RowIndex < 0) continue; - DataGridViewRow r = dgv.Rows[c.RowIndex]; - if (r == null || r.IsNewRow) continue; - if (seenRows.Add(r.Index)) result.Add(r); - } - } - // 兜底:如果以上都没收集到,取当前行 - if (result.Count == 0 && dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) - { - result.Add(dgv.CurrentRow); - } - return result; - } - - private DataGridViewRow GetFirstSelectedProjectRow() - { - DataGridView dgv = this.advancedDataGridView6; - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return null; - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - return r; - } - if (dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) return dgv.CurrentRow; - return null; - } - - private DataGridViewRow FindProjectRowById(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return null; - DataGridView dgv = this.advancedDataGridView6; - if (dgv == null || dgv.Rows == null) return null; - foreach (DataGridViewRow r in dgv.Rows) - { - if (r == null || r.IsNewRow) continue; - if (GetCellValueAsString(r, "项目编号") == projectId) return r; - } - return null; - } - - private static void SetCurrentCell(DataGridView dgv, int rowIndex, int colIndex = 0) - { - if (dgv == null || dgv.Rows == null || rowIndex < 0 || rowIndex >= dgv.Rows.Count) return; - try - { - if (dgv.Rows[rowIndex].IsNewRow) return; - if (colIndex < 0 || colIndex >= dgv.Columns.Count) colIndex = 0; - dgv.ClearSelection(); - dgv.Rows[rowIndex].Selected = true; - dgv.CurrentCell = dgv.Rows[rowIndex].Cells[colIndex]; - } - catch { } - } - - private void SelectRowByValue(DataGridView dgv, string colName, string value) - { - if (dgv == null || dgv.Rows == null || string.IsNullOrEmpty(value)) return; - try - { - _isReloading = true; - foreach (DataGridViewRow r in dgv.Rows) - { - if (r == null || r.IsNewRow) continue; - if (GetCellValueAsString(r, colName) == value) - { - dgv.ClearSelection(); - r.Selected = true; - dgv.CurrentCell = r.Cells[0]; - return; - } - } - } - catch { } - finally { _isReloading = false; } - } - - private static int GetSelectedRowIndex(DataGridView dgv) - { - if (dgv == null) return -1; - if (dgv.CurrentRow == null || dgv.CurrentRow.IsNewRow) return -1; - return dgv.CurrentRow.Index; - } - - private static string MakeSafeFileName(string s) - { - if (string.IsNullOrEmpty(s)) return "未命名"; - string r = s; - char[] invalid = Path.GetInvalidFileNameChars(); - foreach (char c in invalid) r = r.Replace(c, '_'); - return r; - } - - private static string EscapeJsonString(string s) - { - if (s == null) return ""; - return s.Replace("\\", "\\\\").Replace("\"", "\\\"") - .Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t"); - } - - private string ShowInputDialog(string title, string prompt, string defaultValue) - { - using (var dlg = new Form()) - { - dlg.Text = title; - dlg.StartPosition = FormStartPosition.CenterParent; - dlg.FormBorderStyle = FormBorderStyle.FixedDialog; - dlg.MinimizeBox = false; - dlg.MaximizeBox = false; - dlg.Width = 340; - dlg.Height = 170; - - var lbl = new Label(); - lbl.Text = prompt; - lbl.Left = 12; lbl.Top = 15; - lbl.Width = 300; lbl.Height = 30; - dlg.Controls.Add(lbl); - - var txt = new TextBox(); - txt.Text = defaultValue; - txt.Left = 12; txt.Top = 55; - txt.Width = 300; - dlg.Controls.Add(txt); - - var btnOk = new Button(); - btnOk.Text = "确定"; - btnOk.Left = 210; btnOk.Top = 92; - btnOk.Width = 90; - btnOk.DialogResult = DialogResult.OK; - dlg.Controls.Add(btnOk); - - var btnCancel = new Button(); - btnCancel.Text = "取消"; - btnCancel.Left = 108; btnCancel.Top = 92; - btnCancel.Width = 90; - btnCancel.DialogResult = DialogResult.Cancel; - dlg.Controls.Add(btnCancel); - - dlg.AcceptButton = btnOk; - dlg.CancelButton = btnCancel; - - if (dlg.ShowDialog(this) == DialogResult.OK) return txt.Text; - return ""; - } - } - - /// 开启 DataGridView 的双缓冲(消除闪烁)。 - private static void EnableDoubleBuffered(DataGridView dgv) - { - if (dgv == null) return; - try - { - typeof(DataGridView).InvokeMember("DoubleBuffered", - System.Reflection.BindingFlags.SetProperty | - System.Reflection.BindingFlags.Instance | - System.Reflection.BindingFlags.NonPublic, - null, dgv, new object[] { true }); - } - catch { } - } - - /// 按列名设置只读(运行时按 DataPropertyName/HeaderText 查找)。 - private static void ApplyReadOnlyColumns(DataGridView dgv, string[] colNames) - { - if (dgv == null || colNames == null) return; - foreach (string name in colNames) - { - DataGridViewColumn col = FindColumn(dgv, name); - if (col != null) col.ReadOnly = true; - } - } - - // ============================================================ - // 价格显示格式化 - // ============================================================ - - /// 把"保留2位小数"/"保留整数"等转成 .NET 格式字符串(F0/F2)。 - private static string ToFormatString(string 小数位文本) - { - int n = 解析小数位(小数位文本); - if (n < 0) n = 2; - return "F" + n.ToString(); - } - - private static int 解析小数位(string text) - { - if (string.IsNullOrWhiteSpace(text)) return 2; - string t = text.Trim(); - if (t.Contains("整数")) return 0; - if (t.Contains("1位")) return 1; - if (t.Contains("2位")) return 2; - if (t.Contains("3位")) return 3; - if (t.Contains("4位")) return 4; - return 2; - } - - private void ApplyPriceFormat(DataGridView dgv, string 小数位文本) - { - if (dgv == null || dgv.Columns == null) return; - string fmt = ToFormatString(小数位文本); - foreach (DataGridViewColumn col in dgv.Columns) - { - if (col == null) continue; - string name = !string.IsNullOrEmpty(col.DataPropertyName) - ? col.DataPropertyName : col.HeaderText; - if (string.IsNullOrEmpty(name)) continue; - if (s_公式列集合.Contains(name)) - { - col.DefaultCellStyle.Format = fmt; - } - } - } - - /// 老库兼容:把 DataTable 中公式列的类型从 string 转为 double。 - private static DataTable ConvertFormulaColumnsToDouble(DataTable table) - { - if (table == null || table.Columns.Count == 0) return table; - bool needsConvert = false; - foreach (DataColumn dc in table.Columns) - { - if (s_公式列集合.Contains(dc.ColumnName) && dc.DataType == typeof(string)) - { - needsConvert = true; - break; - } - } - if (!needsConvert) return table; - - var newTable = new DataTable(); - foreach (DataColumn dc in table.Columns) - { - Type t = s_公式列集合.Contains(dc.ColumnName) ? typeof(double) : dc.DataType; - newTable.Columns.Add(dc.ColumnName, t); - } - foreach (DataRow row in table.Rows) - { - var newRow = newTable.NewRow(); - foreach (DataColumn dc in table.Columns) - { - if (s_公式列集合.Contains(dc.ColumnName)) - { - object v = row[dc]; - if (v == null || v == DBNull.Value) newRow[dc.ColumnName] = 0d; - else if (v is double) newRow[dc.ColumnName] = v; - else - { - double d; - newRow[dc.ColumnName] = double.TryParse(v.ToString().Trim(), out d) ? d : 0d; - } - } - else newRow[dc.ColumnName] = row[dc]; - } - newTable.Rows.Add(newRow); - } - newTable.TableName = table.TableName; - return newTable; - } - - // ============================================================ - // 数据库结构维护 - // ============================================================ - - private void EnsureProjectDbExists(string dbPath) - { - string dir = Path.GetDirectoryName(dbPath); - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE IF NOT EXISTS " + ProjectsTableName + " (" + - " 项目编号 TEXT, 项目名称 TEXT, 客户名称 TEXT, 客户地址 TEXT," + - " 联系人 TEXT, 联系电话 TEXT, 项目日期 TEXT, 箱柜台数 REAL," + - " 成本总价 REAL, 报出总价 REAL, 利润 REAL, 利润率 REAL, 备注 TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - EnsureColumns(conn, ProjectsTableName, new[] { - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话" - }); - } - } - - private static void EnsureColumns(System.Data.SQLite.SQLiteConnection conn, string tableName, string[] columns) - { - if (columns == null || columns.Length == 0) return; - var existing = new HashSet(StringComparer.OrdinalIgnoreCase); - using (var infoCmd = new System.Data.SQLite.SQLiteCommand("PRAGMA table_info(" + tableName + ");", conn)) - using (var reader = infoCmd.ExecuteReader()) - { - while (reader.Read()) - { - object nameObj = reader["name"]; - if (nameObj != null && nameObj != DBNull.Value) existing.Add(nameObj.ToString()); - } - } - foreach (string col in columns) - { - if (!existing.Contains(col)) - { - string sql = "ALTER TABLE " + tableName + " ADD COLUMN " + col + " TEXT;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - } - } - - private static List GetProjectTableColumns(System.Data.SQLite.SQLiteConnection conn) - { - var cols = new List(); - try - { - using (var infoCmd = new System.Data.SQLite.SQLiteCommand("PRAGMA table_info(" + ProjectsTableName + ");", conn)) - using (var reader = infoCmd.ExecuteReader()) - { - while (reader.Read()) - { - object nameObj = reader["name"]; - if (nameObj != null && nameObj != DBNull.Value) cols.Add(nameObj.ToString()); - } - } - } - catch { } - return cols; - } - - private void EnsureQuoteDbExists(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - string dir = Path.GetDirectoryName(dbPath); - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sqlTuhao = - "CREATE TABLE IF NOT EXISTS " + TuhaoTableName + " (" + - " 序号 TEXT, 图号 TEXT, 图名 TEXT, 台数 TEXT, 箱柜数量 REAL," + - " 单价 REAL, 总价 REAL, 成本总价 REAL, 毛利 REAL, 毛利率 REAL," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - string sqlIndex = - "CREATE TABLE IF NOT EXISTS 表索引 (" + - " 类型 TEXT, 图号 TEXT, 箱号 TEXT, 实际表名 TEXT" + - ");"; - string sqlProjectInfo = - "CREATE TABLE IF NOT EXISTS " + ProjectInfoTableName + " (" + - " 项目编号 TEXT, 项目名称 TEXT, 客户名称 TEXT, 客户地址 TEXT," + - " 联系人 TEXT, 联系电话 TEXT, 项目日期 TEXT, 备注 TEXT," + - " 成套厂名称 TEXT, 成套厂地址 TEXT, 成套厂联系人 TEXT, 成套厂联系电话 TEXT," + - " 单台小数位 TEXT, 单台取整方式 TEXT, 项目小数位 TEXT, 项目取整方式 TEXT" + - ");"; - foreach (string sql in new[] { sqlTuhao, sqlIndex, sqlProjectInfo }) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - EnsureColumns(conn, ProjectInfoTableName, new[] { - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话", - "单台小数位", "单台取整方式", "项目小数位", "项目取整方式" - }); - // ★ 确保旧库的图号表也有"框Handle"/"文本Handle"列 - EnsureColumns(conn, TuhaoTableName, new[] { "框Handle", "文本Handle" }); - } - } - - // ---------- 箱号表(每个图号一张独立表,表名=图号原名,双引号括起)---------- - - private static string GetXianghaoTableName(string tuhao) - { - if (string.IsNullOrWhiteSpace(tuhao)) return "\"图号箱号表\""; - return "\"" + tuhao.Replace("\"", "\"\"") + "\""; - } - - private void EnsureXianghaoTableExists(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - // 先查表索引,已有则跳过 - string existing = GetXianghaoTableByIndex(projectId, tuhao); - if (!string.IsNullOrEmpty(existing)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - // 用唯一ID做表名,避免图号名含特殊字符 - string realTbl = GetNextTableId(projectId, "箱号"); - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTbl + "\" (" + - " 序号 TEXT, 箱号 TEXT, 型号 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 单台成本 REAL, 成本价 REAL, 单台报出 REAL, 报出价 REAL," + - " 利润 REAL, 利润率 REAL, 毛利率 REAL, 箱柜类型 TEXT, 备注 TEXT, 图纸 TEXT," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - // ★ 注册到表索引,后续 GetXianghaoTableByIndex 才能查到 - AddTableIndex(projectId, "箱号", tuhao, "", realTbl); - } - catch { } - } - - private string GetXianghaoCount(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return "1"; - string realTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(realTbl)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT COUNT(*) FROM \"" + realTbl + "\";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - catch { return "1"; } - } - - // ---------- 元件计数(用于新建元件命名"新元件N")---------- - - private string GetYuanjianCount(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || - string.IsNullOrWhiteSpace(xianghao)) return "1"; - // 查索引表拿该箱号元件表的真实表名 - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(realTbl)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT COUNT(*) FROM \"" + realTbl + "\";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - catch { return "1"; } - } - - // ---------- 元件表(每个箱号一张独立表)---------- - - private static string GetYuanjianTableName(string xianghao) - { - if (string.IsNullOrWhiteSpace(xianghao)) return "\"元件表\""; - return "\"" + xianghao.Replace("\"", "\"\"") + "\""; - } - - private void EnsureYuanjianTableExists(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - // 先查表索引,已有则跳过 - string existing = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (!string.IsNullOrEmpty(existing)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - // 用唯一ID做表名 - string realTbl = GetNextTableId(projectId, "元件"); - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTbl + "\" (" + - " 序号 TEXT, 元件名称 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 表价 REAL, 采购单价 REAL, 采购系数 TEXT, 采购价 REAL," + - " 报出单价 REAL, 报出系数 TEXT, 报出价 REAL," + - " 图纸规格 TEXT, 品牌 TEXT, 系列 TEXT, 类型 TEXT, 备注 TEXT," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - // ★ 注册到表索引(类型=元件,图号,箱号) — 后续 GetYuanjianTableByIndex 才能查到 - AddTableIndex(projectId, "元件", tuhao, xianghao, realTbl); - } - catch { } - } - - // ---------- 表索引(用唯一ID做表名,索引表记录 图号/箱号 → 真实表名)---------- - - private string GetNextTableId(string projectId, string prefix) - { - if (string.IsNullOrWhiteSpace(projectId)) return prefix + "_1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return prefix + "_1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT 实际表名 FROM 表索引 WHERE 实际表名 LIKE @p;"; - int maxN = 0; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@p", prefix + "_%"); - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string t = reader.IsDBNull(0) ? "" : reader.GetString(0); - string numPart = t.StartsWith(prefix + "_") ? t.Substring(prefix.Length + 1) : ""; - int n; - if (int.TryParse(numPart, out n) && n > maxN) maxN = n; - } - } - } - return prefix + "_" + (maxN + 1).ToString(); - } - } - catch { return prefix + "_1"; } - } - - private void AddTableIndex(string projectId, string type, string tuhao, string xianghao, string realTableName) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(realTableName)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "INSERT INTO 表索引 (类型, 图号, 箱号, 实际表名) VALUES (@t, @th, @xh, @real);"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao ?? ""); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - cmd.Parameters.AddWithValue("@real", realTableName); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - private void RemoveTableIndex(string projectId, string type, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "DELETE FROM 表索引 WHERE 类型=@t AND 图号=@th AND 箱号=@xh;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao ?? ""); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - private string GetXianghaoTableByIndex(string projectId, string tuhao) - { - return LookupTableByIndex(projectId, "箱号", tuhao, ""); - } - - private string GetYuanjianTableByIndex(string projectId, string tuhao, string xianghao) - { - return LookupTableByIndex(projectId, "元件", tuhao, xianghao); - } - - private string LookupTableByIndex(string projectId, string type, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return ""; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return ""; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - return LookupTableByIndex(type, tuhao, xianghao, conn); - } - } - catch { return ""; } - } - - private string LookupTableByIndex(string type, string tuhao, string xianghao, System.Data.SQLite.SQLiteConnection conn) - { - if (conn == null || string.IsNullOrWhiteSpace(tuhao)) return ""; - try - { - string sql = "SELECT 实际表名 FROM 表索引 WHERE 类型=@t AND 图号=@th AND 箱号=@xh LIMIT 1;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - object o = cmd.ExecuteScalar(); - return (o == null || o == DBNull.Value) ? "" : o.ToString(); - } - } - catch { return ""; } - } - - private string GetXianghaoTableByIndex(string tuhao, System.Data.SQLite.SQLiteConnection conn) - { - return LookupTableByIndex("箱号", tuhao, "", conn); - } - - private string GetYuanjianTableByIndex(string tuhao, string xianghao, System.Data.SQLite.SQLiteConnection conn) - { - return LookupTableByIndex("元件", tuhao, xianghao, conn); - } - - private void CreateXianghaoTable(string projectId, string realTableName) - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTableName + "\" (" + - " 序号 TEXT, 箱号 TEXT, 箱名 TEXT, 型号 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 单台成本 REAL, 成本价 REAL, 单台报出 REAL, 报出价 REAL," + - " 利润 REAL, 利润率 REAL, 毛利率 REAL, 箱柜类型 TEXT, 备注 TEXT, 图纸 TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - } - catch { } - } - - private void RenumberTable(string projectId, string quotedTableName) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(quotedTableName)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string selSql = "SELECT rowid FROM " + quotedTableName + " ORDER BY rowid;"; - var rowids = new List(); - using (var sel = new System.Data.SQLite.SQLiteCommand(selSql, conn)) - using (var reader = sel.ExecuteReader()) - { - while (reader.Read()) rowids.Add(reader.GetInt64(0)); - } - int newSeq = 1; - foreach (long rowid in rowids) - { - string updSql = "UPDATE " + quotedTableName + " SET 序号 = @seq WHERE rowid = @rid;"; - using (var upd = new System.Data.SQLite.SQLiteCommand(updSql, conn)) - { - upd.Parameters.AddWithValue("@seq", newSeq.ToString()); - upd.Parameters.AddWithValue("@rid", rowid); - upd.ExecuteNonQuery(); - } - newSeq++; - } - } - } - catch { } - } - - // ============================================================ - // 报价库「项目信息」表读写 - // ============================================================ - - private void InsertProjectInfoToQuoteDb(string projectId, Dictionary values) - { - if (string.IsNullOrWhiteSpace(projectId) || values == null) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string delSql = "DELETE FROM " + ProjectInfoTableName + " WHERE 项目编号 = @id;"; - using (var del = new System.Data.SQLite.SQLiteCommand(delSql, conn)) - { - del.Parameters.AddWithValue("@id", projectId); - del.ExecuteNonQuery(); - } - var cols = new List(); - var paras = new List(); - foreach (string c in ProjectInfoColumns) - { - if (values.ContainsKey(c)) { cols.Add(c); paras.Add("@" + c); } - } - if (cols.Count == 0) return; - string sql = "INSERT INTO " + ProjectInfoTableName + " (" + - string.Join(", ", cols.ToArray()) + ") VALUES (" + - string.Join(", ", paras.ToArray()) + ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - foreach (string c in cols) cmd.Parameters.AddWithValue("@" + c, values[c] ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private Dictionary GetProjectInfoFromQuoteDb(string projectId) - { - var info = new Dictionary(); - if (string.IsNullOrWhiteSpace(projectId)) return info; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return info; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string chkSql = "SELECT name FROM sqlite_master WHERE type='table' AND name=@n;"; - using (var chk = new System.Data.SQLite.SQLiteCommand(chkSql, conn)) - { - chk.Parameters.AddWithValue("@n", ProjectInfoTableName); - if (chk.ExecuteScalar() == null) return info; - } - string sql = "SELECT * FROM " + ProjectInfoTableName + " WHERE 项目编号 = @id LIMIT 1;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@id", projectId); - using (var reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - var existCols = new HashSet(StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < reader.FieldCount; i++) existCols.Add(reader.GetName(i)); - foreach (string c in ProjectInfoColumns) - { - if (!existCols.Contains(c)) continue; - object v = reader[c]; - info[c] = (v == null || v == DBNull.Value) ? "" : v.ToString(); - } - } - } - } - } - } - catch { } - return info; - } - - private void LoadPriceFormatConfig(string projectId) - { - _单台小数位文本 = "保留2位小数"; - _单台取整方式 = "不取整"; - _项目小数位文本 = "保留2位小数"; - _项目取整方式 = "不取整"; - try - { - var info = GetProjectInfoFromQuoteDb(projectId); - if (info == null || info.Count == 0) return; - string v; - if (info.TryGetValue("单台小数位", out v) && !string.IsNullOrWhiteSpace(v)) _单台小数位文本 = v; - if (info.TryGetValue("单台取整方式", out v) && !string.IsNullOrWhiteSpace(v)) _单台取整方式 = v; - if (info.TryGetValue("项目小数位", out v) && !string.IsNullOrWhiteSpace(v)) _项目小数位文本 = v; - if (info.TryGetValue("项目取整方式", out v) && !string.IsNullOrWhiteSpace(v)) _项目取整方式 = v; - } - catch { } - } - - // ============================================================ - // 项目库 CRUD - // ============================================================ - - private int InsertProjectToDatabase(Dictionary values) - { - if (values == null || values.Count == 0) return 0; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) - { - EnsureProjectDbExists(dbPath); - if (!File.Exists(dbPath)) - throw new FileNotFoundException("无法创建项目数据库文件: " + dbPath, dbPath); - } - int affected; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var allowed = new HashSet(GetProjectTableColumns(conn), StringComparer.OrdinalIgnoreCase); - var colNames = new List(); - var paramNames = new List(); - foreach (string col in values.Keys) - { - if (allowed.Contains(col)) { colNames.Add(col); paramNames.Add("@" + col); } - } - if (colNames.Count == 0) { affected = 0; } - else - { - string sql = "INSERT INTO " + ProjectsTableName + " (" + - string.Join(", ", colNames.ToArray()) + ") VALUES (" + - string.Join(", ", paramNames.ToArray()) + ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - foreach (string col in colNames) cmd.Parameters.AddWithValue("@" + col, values[col]); - affected = cmd.ExecuteNonQuery(); - } - } - } - string projectId; - values.TryGetValue("项目编号", out projectId); - if (!string.IsNullOrWhiteSpace(projectId)) InsertProjectInfoToQuoteDb(projectId, values); - return affected; - } - - private int DeleteProjectFromDatabase(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return 0; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) throw new FileNotFoundException("找不到项目数据库文件: " + dbPath, dbPath); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "DELETE FROM " + ProjectsTableName + " WHERE 项目编号 = @id;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@id", projectId); - return cmd.ExecuteNonQuery(); - } - } - } - - private void CascadeDeleteByProject(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try { File.Delete(dbPath); } - catch { } - } - - private List> ReadAllProjectsFromDatabase() - { - var list = new List>(); - try - { - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT * FROM " + ProjectsTableName + " ORDER BY rowid;", conn)) - using (var rd = cmd.ExecuteReader()) - { - while (rd.Read()) - { - var dict = new Dictionary(StringComparer.Ordinal); - for (int i = 0; i < rd.FieldCount; i++) - { - object v = rd.GetValue(i); - if (v == null || v == DBNull.Value) v = ""; - dict[rd.GetName(i)] = v; - } - list.Add(dict); - } - } - } - } - catch { } - return list; - } - - private Dictionary ReadProjectMetaData(string pid) - { - var dict = new Dictionary(StringComparer.Ordinal); - try - { - string dbPath = GetDbFullPath(ProjectsDbPath); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT * FROM " + ProjectsTableName + " WHERE 项目编号 = @p LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@p", pid); - using (var rd = cmd.ExecuteReader()) - { - if (!rd.Read()) return null; - for (int i = 0; i < rd.FieldCount; i++) - { - object v = rd.GetValue(i); - if (v == null || v == DBNull.Value) v = ""; - dict[rd.GetName(i)] = v; - } - } - } - } - } - catch { return null; } - return dict; - } - - // ============================================================ - // 图号/箱号/元件 CRUD - // ============================================================ - - private string GetNextSeqNumber(string tableName, string nameCol, string projectId, string tuhao = null) - { - if (string.IsNullOrWhiteSpace(projectId)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql; - if (tuhao == null) - { - sql = "SELECT COUNT(*) FROM " + tableName + ";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - else - { - sql = "SELECT COUNT(*) FROM " + tableName + " WHERE 图号 = @th;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - } - catch { return "1"; } - } - - // ============================================================ - // 扒图号/扒箱号/扒元件:CAD 文本选择交互 - // ============================================================ - - /// - /// 向 CAD 发送扒数据命令,触发框选交互。 - /// ★ 关键:先发 ESC 取消当前可能正在进行的扒图循环,再发新命令 - /// 这样用户从"扒图号"循环里点"扒箱号"也能立即切换 - /// - private void SendCadPaCommand(string cmd) - { - try - { - if (!cadbt.CadBridge.IsViewerReady) - { - MessageBox.Show(this, "网页 CAD 尚未就绪,请先在文档区打开图纸。", - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // 转发到网页 CAD 桥(patu/paxh/payj/pacl 命令) - cadbt.CadBridge.SendPaCommand(cmd); - } - catch (Exception ex) - { - MessageBox.Show(this, "发送扒图命令失败:\n" + ex.Message, - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - /// - /// CAD 选中文本后的回调:把选中的文本批量插入到对应表格。 - /// 由 CadPlugin.ExecutePaCommand 在 UI 线程调用。 - /// - public void OnPaTextsPicked(PaMode mode, List results) - { - if (results == null || results.Count == 0) return; - if (string.IsNullOrWhiteSpace(_currentProjectId)) - { - MessageBox.Show(this, "请先在项目表中双击选择一个项目,再扒数据。", - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - switch (mode) - { - case PaMode.Tuhao: - PaTuhaoInsert(results); - break; - case PaMode.Xianghao: - PaXianghaoInsert(results); - break; - case PaMode.Yuanjian: - PaYuanjianInsert(results); - break; - } - } - - /// 扒图号:把选中文本作为图号批量插入到当前项目,同时保存框Handle。 - /// ★ 重复扒图:如果图号已存在,删除旧框和数据库行(不新增)。 - private void PaTuhaoInsert(List results) - { - string lastInsertedTuhao = null; // ★ 记录最后插入的图号,用于自动选中联动 - try - { - _isReloading = true; - // 先 AcceptChanges,避免 SaveAllQuoteTablesIfDirty 把旧内存表回写 - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - - // ★ 新增框架Handle列表: PaTextSelector刚画的框,如果是重复,需要删除这些新框 - var newFramesToErase = new List(); - int deletedCount = 0; - int inserted = 0; - - foreach (var r in results) - { - if (string.IsNullOrWhiteSpace(r.Text)) continue; - string clean = r.Text.Trim(); - // ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - // 不同位置的相同内容文本 Handle 不同 → 不算重复,正常插入。 - string oldFrame = GetTuhaoFrameHandleByTextHandle(_currentProjectId, clean, r.TextHandle); - if (!string.IsNullOrEmpty(oldFrame)) - { - // ★ 重复(同一个文本再次选中):删除旧框+数据库行+新框 - DeleteTuhao(_currentProjectId, clean); - DeleteFrameByHandle(oldFrame); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - deletedCount++; - } - else - { - InsertTuhao(_currentProjectId, clean, r.FrameHandle, r.TextHandle); - lastInsertedTuhao = clean; // ★ 记录最后插入的图号 - inserted++; - } - } - - // ★ 删除重复图号对应的新框(PaTextSelector已经画出来了,但不需要保留)——批量一次删 - DeleteFramesByHandles(newFramesToErase); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - // 直接在数据库层面重算(不经过内存回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadTuhaoByProject(_currentProjectId); - - // 保存 - try - { - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_tuhaoTable != null) - { - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - _tuhaoTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0 && inserted == 0) - { - Log("[PaTuhaoInsert] 删除了 " + deletedCount + " 条重复图号"); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒图号失败:\n" + ex.Message, - "扒图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒完图号后自动选中刚插入的图号行,联动刷新箱号表 - if (!string.IsNullOrWhiteSpace(lastInsertedTuhao)) - { - _currentTuhao = lastInsertedTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", lastInsertedTuhao); - // 手动联动刷新箱号表(SelectRowByValue 在 _isReloading 下不触发 SelectionChanged) - ReloadXianghaoByTuhao(_currentProjectId, lastInsertedTuhao); - } - } - } - - /// 扒箱号:把选中文本作为箱号批量插入到当前图号,同时保存框Handle。 - /// ★ 重复扒图:如果箱号已存在,删除旧框和数据库行(不新增)。 - private void PaXianghaoInsert(List results) - { - string lastInsertedXianghao = null; // ★ 记录最后插入的箱号,用于自动选中联动 - if (string.IsNullOrWhiteSpace(_currentTuhao)) - { - MessageBox.Show(this, "请先在图号表中选择一个图号,再扒箱号。", - "扒箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - try - { - _isReloading = true; - // 先 AcceptChanges,避免 SaveAllQuoteTablesIfDirty 把旧内存表回写 - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - - var newFramesToErase = new List(); - int deletedCount = 0; - int inserted = 0; - - foreach (var r in results) - { - if (string.IsNullOrWhiteSpace(r.Text)) continue; - string clean = r.Text.Trim(); - // ★ 按"同一个文本实体"判断重复(不同位置的相同内容文本不算重复) - string oldFrame = GetXianghaoFrameHandleByTextHandle(_currentProjectId, _currentTuhao, clean, r.TextHandle); - if (!string.IsNullOrEmpty(oldFrame)) - { - // ★ 重复(同一个文本再次选中):删除旧框+数据库行+新框 - DeleteXianghao(_currentProjectId, _currentTuhao, clean); - DeleteFrameByHandle(oldFrame); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - deletedCount++; - } - else - { - InsertXianghao(_currentProjectId, _currentTuhao, clean, r.FrameHandle, r.TextHandle); - lastInsertedXianghao = clean; // ★ 记录最后插入的箱号 - inserted++; - } - } - - DeleteFramesByHandles(newFramesToErase); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - - try - { - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (_xianghaoTable != null && !string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) - { - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null, true); - _xianghaoTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0 && inserted == 0) - { - Log("[PaXianghaoInsert] 删除了 " + deletedCount + " 条重复箱号"); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒箱号失败:\n" + ex.Message, - "扒箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒完箱号后自动选中刚插入的箱号行,联动刷新元件表 - if (!string.IsNullOrWhiteSpace(lastInsertedXianghao)) - { - _currentXianghao = lastInsertedXianghao; - SelectRowByValue(this.advancedDataGridView4, "箱号", lastInsertedXianghao); - // 手动联动刷新元件表(SelectRowByValue 在 _isReloading 下不触发 SelectionChanged) - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, lastInsertedXianghao); - } - } - } - - /// 扒元件:把选中文本作为【规格】批量插入到当前箱号(写到规格列),同时保存框Handle。 - /// ★ 关键:在单个事务里按 results 顺序依次插入,保证序号连续。 - /// ★ 重复扒图:如果规格已存在,删除旧框+数据库行(不新增)。 - private void PaYuanjianInsert(List results) - { - if (string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先在箱号表中选择一个箱号,再扒元件。", - "扒元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - try - { - _isReloading = true; - // ★ 关键:先 AcceptChanges 清掉内存表的改动标记,避免 SaveAllQuoteTablesIfDirty - // 用旧的内存数据覆盖数据库 - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - EnsureQuoteDbExists(_currentProjectId); - string dbPath = GetQuoteDbPath(_currentProjectId); - EnsureYuanjianTableExists(_currentProjectId, _currentTuhao, _currentXianghao); - string tblName = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (string.IsNullOrEmpty(tblName)) - { - MessageBox.Show("元件表创建失败(表索引未注册),图号=" + _currentTuhao + " 箱号=" + _currentXianghao); - return; - } - - // ★ 确保旧元件表也有"框Handle"/"文本Handle"列 - using (var connEns = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - connEns.Open(); - EnsureColumns(connEns, "\"" + tblName + "\"", new[] { "框Handle", "文本Handle" }); - } - - // 过滤掉空文本,保留原始顺序(同时保留框Handle+文本Handle) - var cleanResults = new List(); - foreach (var r in results) - { - if (!string.IsNullOrWhiteSpace(r.Text)) - { - cleanResults.Add(new PaTextResult - { - Text = r.Text.Trim(), - FrameHandle = r.FrameHandle ?? "", - TextHandle = r.TextHandle ?? "" - }); - } - } - if (cleanResults.Count == 0) return; - - // ★ 判断是否是逆向合并模式(所有result共用同一个框Handle且数量>1) - bool isMergeMode = cleanResults.Count > 1; - string mergeHandle = cleanResults[0].FrameHandle; - if (isMergeMode) - { - foreach (var r in cleanResults) - { - if (r.FrameHandle != mergeHandle) { isMergeMode = false; break; } - } - } - - // ★ 新增:重复检测辅助集合 - // newFramesToErase: PaTextSelector刚画的框,如果是重复项,这些框要删除 - var newFramesToErase = new List(); - // oldFrameHandlesToDelete: 数据库里匹配到的旧框,要删除 - var oldFrameHandlesToDelete = new List(); - // toInsert: 不重复、需要插入的项 - var toInsert = new List(); - // ★ 本地匹配失败的规格(收集后交给 DeepSeek AI 兜底识别) - var aiFailedSpecs = new List(); - int deletedCount = 0; - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - - if (isMergeMode) - { - // ★ 合并模式:所有文本按图纸阅读顺序拼成一个规格 - // (PaTextSelector 已按列分组、列内从上到下排好序,保持此顺序 - // 与库中自然书写顺序一致,如 HD13BX-1500/31 + 1500A) - // 文本Handle串与文本一一对应拼接(同一批文本Handle集合相同即重复)。 - var orderedTexts = new List(); - var orderedHandles = new List(); - foreach (var r in cleanResults) - { - orderedTexts.Add(r.Text); - orderedHandles.Add(r.TextHandle ?? ""); - } - string mergedSpec = string.Join("", orderedTexts.ToArray()); - // ★ Handle串排序后拼接(Handle集合相同即同一批文本,与顺序无关) - var sortedHandles = new List(orderedHandles); - sortedHandles.Sort(StringComparer.Ordinal); - string mergedTextHandle = string.Join("|", sortedHandles.ToArray()); - - // ★ 1. 查"同一批文本实体"的合并规格是否已存在 - // (文本Handle拼接串相同 = 同一批文本再次被选中,才是真重复) - var matchFrames = new List(); - using (var selCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tblName + "\" WHERE 规格=@spec AND 文本Handle=@th;", conn)) - { - selCmd.Parameters.AddWithValue("@spec", mergedSpec); - selCmd.Parameters.AddWithValue("@th", mergedTextHandle); - using (var reader = selCmd.ExecuteReader()) - { - while (reader.Read()) - { - object v = reader["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s) && !matchFrames.Contains(s)) - matchFrames.Add(s); - } - } - } - } - - // ★ 2. 再查:本批每个文本实体是否已作为"独立元件"入库(按文本Handle精确匹配) - var perTextFrames = new List(); - var perTextSpecs = new List(); - foreach (var r in cleanResults) - { - List fhs = GetYuanjianFrameHandlesByTextHandle( - _currentProjectId, _currentTuhao, _currentXianghao, r.Text, r.TextHandle); - foreach (string fh in fhs) - { - if (!perTextFrames.Contains(fh)) perTextFrames.Add(fh); - } - if (fhs.Count > 0 && !perTextSpecs.Contains(r.Text)) perTextSpecs.Add(r.Text); - } - - // ★ 只要匹配到(1.同一批文本的合并规格 或 2.同一文本实体的独立元件) → 执行删除 - bool hitMergeMatch = matchFrames.Count > 0; - bool hitPerTextMatch = perTextSpecs.Count > 0; - - if (hitMergeMatch || hitPerTextMatch) - { - // ★ 删除:同一批文本的合并规格匹配的行(文本Handle+规格双条件) - if (hitMergeMatch) - { - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 规格=@spec AND 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@spec", mergedSpec); - delCmd.Parameters.AddWithValue("@th", mergedTextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - foreach (string fh in matchFrames) - if (!oldFrameHandlesToDelete.Contains(fh)) oldFrameHandlesToDelete.Add(fh); - } - // ★ 删除:同一文本实体的独立元件行(按文本Handle删除) - if (hitPerTextMatch) - { - foreach (var r in cleanResults) - { - if (string.IsNullOrWhiteSpace(r.TextHandle)) continue; - using (var selCmd2 = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - selCmd2.Parameters.AddWithValue("@th", r.TextHandle); - object cnt = selCmd2.ExecuteScalar(); - int n = (cnt != null && cnt != DBNull.Value) ? Convert.ToInt32(cnt) : 0; - if (n > 0) - { - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@th", r.TextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - } - } - } - foreach (string fh in perTextFrames) - if (!oldFrameHandlesToDelete.Contains(fh)) oldFrameHandlesToDelete.Add(fh); - } - // ★ 删除 PaTextSelector 刚画的新合并框 - if (!string.IsNullOrWhiteSpace(mergeHandle)) - if (!newFramesToErase.Contains(mergeHandle)) - newFramesToErase.Add(mergeHandle); - Log("[PaYuanjianInsert] 合并模式:删除重复项 mergedMatch=" + hitMergeMatch - + " perTextMatch=" + hitPerTextMatch + ", 删除行数=" + deletedCount - + ", 删除旧框数=" + oldFrameHandlesToDelete.Count); - } - else - { - // ★ 没有匹配:新增一行(合并规格) - toInsert.Add(new PaTextResult - { - Text = mergedSpec, - FrameHandle = mergeHandle, - TextHandle = mergedTextHandle - }); - } - } - else - { - // ★ 正向模式:每个文本一条记录,按"同一个文本实体"判断是否重复 - foreach (var r in cleanResults) - { - // ★ 按文本Handle精确匹配:同一文本实体才删除, - // 不同位置的相同内容文本(Handle不同)正常插入 - List matchFrames = GetYuanjianFrameHandlesByTextHandle( - _currentProjectId, _currentTuhao, _currentXianghao, r.Text, r.TextHandle); - if (matchFrames.Count > 0) - { - // 重复:按文本Handle删除数据库行 + 旧框 + 新画的框 - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@th", r.TextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - foreach (string fh in matchFrames) oldFrameHandlesToDelete.Add(fh); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - } - else - { - toInsert.Add(r); - } - } - } - - // ★ 写入需要新增的项 - if (toInsert.Count > 0) - { - // 先取当前最大序号(用MAX函数) - int startSeq = 0; - using (var cntCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT COALESCE(MAX(CAST(序号 AS INTEGER)), 0) FROM \"" + tblName + "\";", conn)) - { - object o = cntCmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) startSeq = Convert.ToInt32(o); - } - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 规格, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型, 框Handle, 文本Handle) " + - "VALUES (@seq, @name, @spec, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件', @fh, @th);"; - for (int i = 0; i < toInsert.Count; i++) - { - // ★ 自动匹配元件名称(用户库CSV模糊匹配,匹配不上为空) - string matchedName = MatchSpecName(toInsert[i].Text) ?? ""; - if (matchedName.Length == 0) aiFailedSpecs.Add(toInsert[i].Text); - using (var insCmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - insCmd.Parameters.AddWithValue("@seq", (startSeq + i + 1).ToString()); - insCmd.Parameters.AddWithValue("@name", matchedName); - insCmd.Parameters.AddWithValue("@spec", toInsert[i].Text); - insCmd.Parameters.AddWithValue("@unit", "只"); - insCmd.Parameters.AddWithValue("@shuliang", "1"); - insCmd.Parameters.AddWithValue("@caigou", "1"); - insCmd.Parameters.AddWithValue("@baochu", "1"); - insCmd.Parameters.AddWithValue("@fh", toInsert[i].FrameHandle ?? ""); - insCmd.Parameters.AddWithValue("@th", toInsert[i].TextHandle ?? ""); - insCmd.ExecuteNonQuery(); - } - } - } - } - - // ★ 删除旧框和重复新框——合并成一次批量删除(单事务+单次刷新) - var framesToErase = new List(oldFrameHandlesToDelete); - framesToErase.AddRange(newFramesToErase); - DeleteFramesByHandles(framesToErase); - - // ★ 重新编号(删除后序号可能不连续) - RenumberTable(_currentProjectId, "\"" + tblName + "\""); - - _yuanjianCache.Clear(); - _xianghaoCache.Clear(); - - // 直接在数据库层面重算(不经过内存回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - - // ★ 收集新插入元件的框Handle(finally 里再统一选中, - // 避免被后续 SaveTable/AcceptChanges/表格刷新清掉选中) - foreach (var r in toInsert) - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) - _pendingSelectYuanjianHandles.Add(r.FrameHandle); - - // 保存 - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (_yuanjianTable != null) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0) - { - Log("[PaYuanjianInsert] 删除了 " + deletedCount + " 条重复元件(匹配框:" + oldFrameHandlesToDelete.Count + ")"); - } - - // ★ DeepSeek AI 兜底:本地未匹配到名称的规格,异步提交 AI 识别并回填 - if (aiFailedSpecs.Count > 0) - { - Log("[PaYuanjianInsert] " + aiFailedSpecs.Count + " 条本地未匹配,提交AI识别"); - AiFillMissingNames(aiFailedSpecs, tblName); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒元件失败:\n" + ex.Message, - "扒元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒到的元件行保持选中(供 F1 合并):延迟两拍执行, - // 等保存/刷新/绑定事件链全部走完,否则选中会被冲掉 - if (_pendingSelectYuanjianHandles.Count > 0) - { - var snapshot = new List(_pendingSelectYuanjianHandles); - _pendingSelectYuanjianHandles.Clear(); - BeginInvoke((Action)(() => - { - BeginInvoke((Action)(() => - { - SelectYuanjianRowsByFrameHandles(snapshot); - Log("[PaYuanjianInsert] 已选中 " + snapshot.Count + " 条新元件行(供F1合并)"); - })); - })); - } - } - } - - /// 查询图号是否已存在(避免重复插入)。 - private bool TuhaoExists(string projectId, string tuhao) - { - return !string.IsNullOrEmpty(GetTuhaoFrameHandle(projectId, tuhao)); - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - /// 命中返回旧框Handle(真重复);未命中返回 null(不同位置的相同内容文本,正常插入)。 - /// - private string GetTuhaoFrameHandleByTextHandle(string projectId, string tuhao, string textHandle) - { - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetTuhaoFrameHandle(projectId, tuhao); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧图号表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, TuhaoTableName, new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按内容兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM " + TuhaoTableName + - " WHERE 文本Handle=@th OR (图号=@t AND (文本Handle IS NULL OR 文本Handle='')) LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@t", tuhao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定图号的框Handle(不存在返回null)。 - private string GetTuhaoFrameHandle(string projectId, string tuhao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM " + TuhaoTableName + " WHERE 图号=@t LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@t", tuhao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询箱号是否已存在(避免重复插入)。 - private bool XianghaoExists(string projectId, string tuhao, string xianghao) - { - return !string.IsNullOrEmpty(GetXianghaoFrameHandle(projectId, tuhao, xianghao)); - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - /// 命中返回旧框Handle(真重复);未命中返回 null(不同位置的相同内容文本,正常插入)。 - /// - private string GetXianghaoFrameHandleByTextHandle(string projectId, string tuhao, string xianghao, string textHandle) - { - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetXianghaoFrameHandle(projectId, tuhao, xianghao); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - string tableName = GetQuoteTableName(projectId, tuhao); - if (string.IsNullOrEmpty(tableName)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧箱号表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, "\"" + tableName + "\"", new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按内容兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\"" + - " WHERE 文本Handle=@th OR (箱号=@x AND (文本Handle IS NULL OR 文本Handle='')) LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@x", xianghao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定箱号的框Handle(不存在返回null)。 - private string GetXianghaoFrameHandle(string projectId, string tuhao, string xianghao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - string tableName = GetQuoteTableName(projectId, tuhao); - if (string.IsNullOrEmpty(tableName)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\" WHERE 箱号=@x LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@x", xianghao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定元件规格的所有框Handle(可能有多个重复行,返回List)。 - private List GetYuanjianFrameHandles(string projectId, string tuhao, string xianghao, string spec) - { - var list = new List(); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return list; - string tableName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tableName)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\" WHERE 规格=@s;", conn)) - { - cmd.Parameters.AddWithValue("@s", spec); - using (var rdr = cmd.ExecuteReader()) - { - while (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) list.Add(s); - } - } - } - } - } - } - catch { } - return list; - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle在元件表中是否已入库。 - /// 命中返回旧框Handle列表(真重复);未命中返回空列表(不同位置的相同内容文本,正常插入)。 - /// - private List GetYuanjianFrameHandlesByTextHandle(string projectId, string tuhao, string xianghao, string spec, string textHandle) - { - var list = new List(); - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetYuanjianFrameHandles(projectId, tuhao, xianghao, spec); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return list; - string tableName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tableName)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧元件表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, "\"" + tableName + "\"", new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按规格兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\"" + - " WHERE 文本Handle=@th OR (规格=@s AND (文本Handle IS NULL OR 文本Handle=''));", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@s", spec); - using (var rdr = cmd.ExecuteReader()) - { - while (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) list.Add(s); - } - } - } - } - } - } - catch { } - return list; - } - - // ============================================================ - // 扒元件自动匹配元件名称(用户库CSV模糊匹配) - // · 扫描插件上级目录/自身目录下最新的 用户库_*.csv(GBK编码) - // · 匹配策略:L1归一化相等 → L2包含(60%长度) → L3编辑距离≥0.70 - // · 硬保护:模糊匹配时数字序列必须完全一致(63A 不会配到 100A) - // ============================================================ - - /// 用户库条目:规格 → 元件名称 - private class SpecNameEntry - { - public string Name; - public string NormSpec; // 归一化后的规格 - public string[] Numbers; // 规格中的数字序列(模糊匹配保护用) - public string Skeleton; // 字母骨架(去数字/分隔符/尾部单位,如 DZ47-4P/C80A → DZPC) - } - - private static List _specNameLib = null; - private static string _specLibCsvPath = null; - private static DateTime _specLibCsvTime = DateTime.MinValue; - - /// - /// 确保用户库CSV已加载(取最新修改时间的 用户库_*.csv, - /// 文件时间戳变化时自动重新加载;文件被 Excel 占用时用共享读)。 - /// - private static void EnsureUserLibCsvLoaded() - { - try - { - // 候选目录:上级目录(成套报价软件根目录) + 插件目录自身 - var dirs = new List(); - try - { - var parent = Path.GetDirectoryName(_baseDir); - if (!string.IsNullOrEmpty(parent) && Directory.Exists(parent)) dirs.Add(parent); - } - catch { } - dirs.Add(_baseDir); - - string best = null; - DateTime bestTime = DateTime.MinValue; - foreach (string d in dirs) - { - try - { - string[] files = Directory.GetFiles(d, "用户库*.csv"); - foreach (string f in files) - { - DateTime t = File.GetLastWriteTime(f); - if (best == null || t > bestTime) { best = f; bestTime = t; } - } - } - catch { } - } - if (best == null) return; // 没找到CSV,保持空库 - - // 时间戳没变且已加载 → 不重复加载 - if (_specNameLib != null && - string.Equals(best, _specLibCsvPath, StringComparison.OrdinalIgnoreCase) && - bestTime == _specLibCsvTime) return; - - var lib = new List(); - var prefixRules = new List(); - // ★ 共享读:文件被 Excel 打开也能读 - using (var fs = new FileStream(best, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (var sr = new StreamReader(fs, DetectCsvEncoding(fs))) - { - string line; - bool first = true; - while ((line = sr.ReadLine()) != null) - { - if (string.IsNullOrWhiteSpace(line)) continue; - string[] cols = SplitCsvLine(line); - if (cols.Length < 2) continue; - string name = cols[0].Trim(); - string spec = cols[1].Trim(); - if (first) - { - first = false; - // 跳过表头 - if (name == "元件名称") continue; - } - if (name.Length == 0 || spec.Length == 0) continue; - - // ★ "元件类型"列 = "前缀" 的行是型号前缀规则(不是库条目) - string elemType = cols.Length >= 10 ? cols[9].Trim() : ""; - if (elemType == "前缀") - { - string pfx = spec.ToUpperInvariant(); - if (pfx.Length >= 2) prefixRules.Add(new[] { pfx, name }); - continue; - } - - string normSpec = NormalizeSpec(spec); - lib.Add(new SpecNameEntry - { - Name = name, - NormSpec = normSpec, - // ★ 必须用原始 spec 提取数字(保留空格/符号作数字边界); - // 用 normSpec 会导致 3300 800 粘连成 3300800,数字序列错位 - Numbers = ExtractNumbers(spec), - Skeleton = ExtractSkeleton(spec) - }); - } - } - _specNameLib = lib; - _prefixRules = prefixRules; - _specLibCsvPath = best; - _specLibCsvTime = bestTime; - WriteDebugLog("[用户库匹配] 加载CSV: " + best + " 条数=" + lib.Count + - " 前缀规则=" + prefixRules.Count); - } - catch (Exception ex) { WriteDebugLog("[用户库匹配] 加载CSV异常: " + ex.Message); } - } - - /// 检测CSV编码:有UTF-8 BOM用UTF8,否则按GBK(主程序导出编码)。 - private static System.Text.Encoding DetectCsvEncoding(FileStream fs) - { - try - { - long pos = fs.Position; - int b1 = fs.ReadByte(); - int b2 = fs.ReadByte(); - int b3 = fs.ReadByte(); - fs.Position = pos; - if (b1 == 0xEF && b2 == 0xBB && b3 == 0xBF) return System.Text.Encoding.UTF8; - } - catch { } - return System.Text.Encoding.GetEncoding("GBK"); - } - - /// 按CSV规则拆分一行(支持双引号包裹和转义"")。 - private static string[] SplitCsvLine(string line) - { - var parts = new List(); - var sb = new System.Text.StringBuilder(); - bool inQuotes = false; - for (int i = 0; i < line.Length; i++) - { - char c = line[i]; - if (c == '"') - { - if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { sb.Append('"'); i++; } - else inQuotes = !inQuotes; - } - else if (c == ',' && !inQuotes) - { - parts.Add(sb.ToString()); - sb.Length = 0; - } - else sb.Append(c); - } - parts.Add(sb.ToString()); - return parts.ToArray(); - } - - /// 规格归一化:全角→半角、统一大写、去空白和分隔符号(保留字母/数字/中文)。 - private static string NormalizeSpec(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(s.Length); - foreach (char c0 in s) - { - char c = c0; - // 全角→半角 - if (c >= 0xFF01 && c <= 0xFF5E) c = (char)(c - 0xFEE0); - else if (c == 0x3000) c = ' '; - if (c == ' ' || c == '\t') continue; - if (IsSpecSeparator(c)) continue; - sb.Append(char.ToUpperInvariant(c)); - } - return sb.ToString(); - } - - /// 规格中的分隔符号(归一化时删除;数字提取时作为数字段边界)。 - private static bool IsSpecSeparator(char c) - { - return c == '-' || c == '/' || c == '*' || c == '×' || c == '·' || c == '.' || - c == '、' || c == ',' || c == ',' || c == '(' || c == ')' || c == '(' || - c == ')' || c == '#' || c == '+' || c == '_' || c == ':' || c == ':' || - c == '~' || c == '~'; - } - - /// - /// 轻量归一化(保留分隔符和空格):全角→半角、统一大写。 - /// ★ 用于数字序列提取:分隔符和空格是数字段的天然边界, - /// 先删分隔符会导致 HYM1-63/3300 的 63 和 3300 粘连成 633300; - /// 删空格会导致 3300 800 粘连成 3300800(与 3300,800 数字序列不一致)。 - /// - private static string NormalizeKeepSeparators(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(s.Length); - foreach (char c0 in s) - { - char c = c0; - if (c >= 0xFF01 && c <= 0xFF5E) c = (char)(c - 0xFEE0); - else if (c == 0x3000) c = ' '; - if (c == '\t') c = ' '; // 制表符当空格 - sb.Append(char.ToUpperInvariant(c)); - } - return sb.ToString(); - } - - /// - /// 提取规格中的所有数字序列(在保留分隔符的版本上提取, - /// 如 HYM1-63/3300 63A → ["1","63","3300","63"])。 - /// - private static string[] ExtractNumbers(string spec) - { - var list = new List(); - if (string.IsNullOrEmpty(spec)) return list.ToArray(); - string light = NormalizeKeepSeparators(spec); - var sb = new System.Text.StringBuilder(); - foreach (char c in light) - { - if (c >= '0' && c <= '9') sb.Append(c); - else if (sb.Length > 0) { list.Add(sb.ToString()); sb.Length = 0; } - } - if (sb.Length > 0) list.Add(sb.ToString()); - return list.ToArray(); - } - - /// 两个数字序列是否完全一致。 - private static bool NumbersEqual(string[] a, string[] b) - { - if (a == null || b == null) return false; - if (a.Length != b.Length) return false; - for (int i = 0; i < a.Length; i++) - if (a[i] != b[i]) return false; - return true; - } - - /// - /// 数字序列兼容(子序列检查):短方的数字按顺序都能在长方中找到即通过。 - /// ★ 用于 L2 包含关系:一方文本是另一方的一部分,数字自然也可能少 - /// (如图纸只写 HD13BX-1500/31,库里是 HD13BX-1500/31 1500A)。 - /// ★ 依然防误配:63A vs 100A 时 63 不在对方序列对应位置,拒绝。 - /// - private static bool NumbersCompatible(string[] a, string[] b) - { - if (a == null || b == null) return false; - string[] shorter = a.Length <= b.Length ? a : b; - string[] longer = a.Length <= b.Length ? b : a; - if (longer.Length == 0) return shorter.Length == 0; - int i = 0; - foreach (string n in longer) - { - if (i < shorter.Length && n == shorter[i]) i++; - } - return i == shorter.Length; - } - - /// - /// 数字序列严格相等 + 两种容错(L3 模糊匹配用): - /// 1.粘连拆分:图纸连写导致数字粘连(如 0.66+1500 提取出 661500),拆成两段后对上即通过; - /// 2.壳架容错:图纸把额定电流写进型号段(如 HYW1-2500/3P 2500A,2500出现两次), - /// 库里型号段是壳架等级(HYW1-3200),删掉图纸型号段那个数字后能对上即通过。 - /// ★ 仅当该数字在图纸中出现≥2次才允许删,220V/380V 这类无重复差异依然拒绝。 - /// - private static bool NumbersEqualEx(string[] a, string[] b) - { - if (a == null || b == null) return false; - if (NumbersEqual(a, b)) return true; - // 容错1:粘连拆分 - if (TrySplitAndCompatible(a, b)) return true; - if (TrySplitAndCompatible(b, a)) return true; - // 容错2:壳架(删图纸中重复出现的电流数字之一) - if (TryDropFrameCurrent(a, b)) return true; - if (TryDropFrameCurrent(b, a)) return true; - return false; - } - - /// - /// 壳架容错:seq 中存在出现≥2次的数字 X,删掉其中一次后作为子序列能对上 other。 - /// 典型:图纸 HYW1-2500/3P 2500A(2500×2) vs 库 HYW1-3200/3P 2500A(3200×1,2500×1)。 - /// - private static bool TryDropFrameCurrent(string[] seq, string[] other) - { - for (int i = 0; i < seq.Length; i++) - { - string s = seq[i]; - if (s == null || s.Length < 2) continue; - // 该数字必须在 seq 中出现≥2次(型号段+电流段重复) - int cnt = 0; - foreach (string n in seq) if (n == s) cnt++; - if (cnt < 2) continue; - // 删掉第 i 个,其余保持顺序 - var list = new List(seq.Length - 1); - for (int k = 0; k < seq.Length; k++) - if (k != i) list.Add(seq[k]); - if (NumbersCompatible(list.ToArray(), other)) return true; - } - return false; - } - - /// 把 seq 中某个数字串拆成两段,拆分后作为子序列能对上 other 即返回 true。 - private static bool TrySplitAndCompatible(string[] seq, string[] other) - { - for (int i = 0; i < seq.Length; i++) - { - string s = seq[i]; - if (s == null || s.Length < 2) continue; - for (int cut = 1; cut < s.Length; cut++) - { - var list = new List(seq.Length + 1); - for (int k = 0; k < seq.Length; k++) - { - if (k == i) - { - list.Add(s.Substring(0, cut)); - list.Add(s.Substring(cut)); - } - else list.Add(seq[k]); - } - if (NumbersCompatible(list.ToArray(), other)) return true; - } - } - return false; - } - - /// - /// 提取字母骨架:去数字、去分隔符、去尾部单位词(A/V/kA 等)。 - /// ★ 用于图纸省略壳架等级的场景:DZ47-4P/C80A 与 DZ47-100 4P C80 - /// 骨架同为 DZPC,配合数字子序列保护可安全匹配。 - /// - private static string ExtractSkeleton(string spec) - { - if (string.IsNullOrEmpty(spec)) return ""; - string light = NormalizeKeepSeparators(spec); - var sb = new System.Text.StringBuilder(); - for (int i = 0; i < light.Length; i++) - { - char c = light[i]; - if (c >= 'A' && c <= 'Z') - { - // 单位词必须紧跟在数字后面才有效(如 80A、450V); - // 6L2-V 的 V 前面是分隔符,属于型号的一部分,不能截断 - bool prevIsDigit = i > 0 && light[i - 1] >= '0' && light[i - 1] <= '9'; - if (prevIsDigit && IsTailUnit(light.Substring(i))) break; - sb.Append(c); - } - // 数字、分隔符、中文等其他字符全部跳过 - } - return sb.ToString(); - } - - /// 判断剩余部分是否为纯尾部单位词(如 "A"、"80A" 里的 A、"0~450V" 里的 V)。 - private static bool IsTailUnit(string rest) - { - if (string.IsNullOrEmpty(rest)) return false; - string r = rest.Trim(); - if (r.Length > 2) return false; // 单位最多2字符(HZ/KA/KW/VA) - return r == "A" || r == "V" || r == "W" || r == "VA" || r == "HZ" || r == "KA" || r == "KW"; - } - - /// Levenshtein 编辑距离(滚动数组实现)。 - private static int LevenshteinDistance(string a, string b) - { - if (string.IsNullOrEmpty(a)) return string.IsNullOrEmpty(b) ? 0 : b.Length; - if (string.IsNullOrEmpty(b)) return a.Length; - int n = a.Length, m = b.Length; - int[] prev = new int[m + 1]; - int[] cur = new int[m + 1]; - for (int j = 0; j <= m; j++) prev[j] = j; - for (int i = 1; i <= n; i++) - { - cur[0] = i; - for (int j = 1; j <= m; j++) - { - int cost = (a[i - 1] == b[j - 1]) ? 0 : 1; - int v1 = prev[j] + 1; - int v2 = cur[j - 1] + 1; - int v3 = prev[j - 1] + cost; - cur[j] = Math.Min(v1, Math.Min(v2, v3)); - } - int[] tmp = prev; prev = cur; cur = tmp; - } - return prev[m]; - } - - /// - /// 规格匹配元件名称(模糊): - /// L1 归一化后完全相等 → 直接命中; - /// L2 包含关系(短方长度≥长方60%,数字序列一致); - /// L3 编辑距离相似度≥0.70(数字序列必须完全一致,唯一最高分才命中)。 - /// 都不中返回 null(不硬猜)。 - /// - /// - /// 粘连清洗:扒图可能把相邻文本粘连(如 "0mAVigiC65N-...")。 - /// 若文本开头是"数字+单位(mA/A/V/W)"且后面紧跟大写字母开头的型号, - /// 从型号处截取;否则原样返回。 - /// - private static string CleanLeadingNoise(string spec) - { - if (string.IsNullOrEmpty(spec)) return spec; - string s = spec.Trim(); - - // ★ 先剥"数量×"前缀:如 "3xLMZ1-0.5" → "LMZ1-0.5"、"2×AD16" → "AD16" - // (图纸常在型号前写元件数量,3x=3只) - if (s.Length > 2) - { - char c0 = s[0]; - if (c0 >= '0' && c0 <= '9') - { - int i = 0; - while (i < s.Length && s[i] >= '0' && s[i] <= '9') i++; - if (i < s.Length && (s[i] == 'x' || s[i] == 'X' || s[i] == '×' || s[i] == '*')) - { - int after = i + 1; - if (after < s.Length && s[after] >= 'A' && s[after] <= 'Z') - return s.Substring(after); - } - } - } - - // 找开头最长的"数字(可含小数点)+单位"模式 - int j = 0; - while (j < s.Length && ((s[j] >= '0' && s[j] <= '9') || s[j] == '.')) j++; - if (j == 0 || j >= s.Length) return spec; // 开头不是数字 - // 单位段(1~3个字母) - int u = j; - while (u < s.Length && u - j <= 3 && s[u] >= 'A' && s[u] <= 'z') u++; - if (u == j || u >= s.Length) return spec; // 没有单位或后面没内容 - string unit = s.Substring(j, u - j).ToUpperInvariant(); - if (unit != "MA" && unit != "A" && unit != "V" && unit != "W" && unit != "KW" && unit != "HZ") return spec; - // 单位后必须紧跟大写字母(型号开头) - char next = s[u]; - if (next < 'A' || next > 'Z') return spec; - return s.Substring(u); // 从型号处截取 - } - - // ★ 匹配结果缓存:同一规格文本(一批框选里重复文本很常见)只完整跑一次 L0-L5。 - // L3 会按库逐条算编辑距离(库大时是 CPU 热点),缓存能直接砍掉重复计算。 - private static readonly System.Collections.Generic.Dictionary _specMatchCache = - new System.Collections.Generic.Dictionary(System.StringComparer.Ordinal); - private static readonly object _specMatchCacheLock = new object(); - - /// 规格匹配元件名称(带结果缓存):相同规格文本第二次起直接返回缓存结果。 - private static string MatchSpecName(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string cached; - lock (_specMatchCacheLock) - { - if (_specMatchCache.TryGetValue(spec, out cached)) return cached; - } - string result = MatchSpecNameCore(spec); - lock (_specMatchCacheLock) - { - // 上限保护:超过2万条清空重来(规格文本总量有限,防内存无限增长) - if (_specMatchCache.Count > 20000) _specMatchCache.Clear(); - _specMatchCache[spec] = result; - } - return result; - } - - private static string MatchSpecNameCore(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - - // ★ 粘连清洗:扒图可能把相邻文本粘连(如 "0mAVigiC65N-...")。 - // 若文本前部含"数字+单位(mA/A/V)"后跟已知型号,从型号处截取 - spec = CleanLeadingNoise(spec); - - EnsureUserLibCsvLoaded(); - if (_specNameLib == null || _specNameLib.Count == 0) return null; - - string norm = NormalizeSpec(spec); - if (norm.Length == 0) return null; - string[] nums = ExtractNumbers(spec); - - string result = null; - string via = "none"; - - // L0: 型号前缀规则(本地权威,最优先,覆盖国标型号命名体系) - string ruleName = MatchByPrefixRule(spec); - if (ruleName != null) - { - WriteDebugLog("[用户库匹配] 「" + spec + "」 → " + ruleName + " via L0规则"); - return ruleName; - } - - // L0.5: JB/T 2930 国标类组代号(官方定义:前2位字母=品类代号) - string gbName = MatchByGbCode(spec); - if (gbName != null) - { - WriteDebugLog("[用户库匹配] 「" + spec + "」 → " + gbName + " via L0.5国标"); - return gbName; - } - - // L1: 归一化后完全相等 - foreach (var e in _specNameLib) - { - if (e.NormSpec == norm) { result = e.Name; via = "L1相等"; break; } - } - - // L2: 包含关系(如图纸只写型号主体,库里有完整版) - if (result == null) - { - foreach (var e in _specNameLib) - { - if (e.NormSpec.Length == 0) continue; - bool contains = e.NormSpec.Contains(norm) || norm.Contains(e.NormSpec); - if (!contains) continue; - int shortLen = Math.Min(e.NormSpec.Length, norm.Length); - int longLen = Math.Max(e.NormSpec.Length, norm.Length); - if (longLen == 0 || (double)shortLen / longLen < 0.6) continue; - if (!NumbersCompatible(nums, e.Numbers)) continue; // ★ 数字子序列兼容(允许少,不允许错) - result = e.Name; via = "L2包含"; break; - } - } - - // L3: 编辑距离模糊匹配(字母/符号容错,数字绝对不放过) - if (result == null) - { - string bestName = null; - double bestScore = 0.0; - int bestCount = 0; - foreach (var e in _specNameLib) - { - if (e.NormSpec.Length == 0) continue; - if (!NumbersEqualEx(nums, e.Numbers)) continue; // ★ 数字一致(含粘连拆分容错) - // ★ 长度差剪枝:编辑距离 ≥ 长度差,长度差已超过 0.30×maxLen 时 - // score 必然 < 0.70,直接跳过(编辑距离是 O(m×n),库里条目多时全算是卡顿热点) - int maxLen = Math.Max(norm.Length, e.NormSpec.Length); - if (Math.Abs(norm.Length - e.NormSpec.Length) * 10 > maxLen * 3) continue; - int dist = LevenshteinDistance(norm, e.NormSpec); - double score = 1.0 - (double)dist / maxLen; - if (score >= 0.70) - { - if (score > bestScore + 0.0001) { bestScore = score; bestName = e.Name; bestCount = 1; } - else if (Math.Abs(score - bestScore) <= 0.0001 && bestName != e.Name) bestCount++; - } - } - if (bestCount == 1 && bestName != null) { result = bestName; via = "L3模糊"; } - } - - // L4: 字母骨架匹配(图纸省略壳架等级的场景) - // DZ47-4P/C80A 与 DZ47-100 4P C80:骨架同为 DZPC, - // 且图纸数字 [47,4,80] 是库数字 [47,100,4,80] 的子序列 → 命中 - if (result == null) - { - string skel = ExtractSkeleton(spec); - if (skel.Length >= 3) - { - string bestName = null; - int bestLen = int.MaxValue; - foreach (var e in _specNameLib) - { - if (e.Skeleton == null || e.Skeleton.Length < 3) continue; - if (e.Skeleton != skel) continue; - if (!NumbersCompatible(nums, e.Numbers)) continue; // ★ 数字子序列保护 - // 多条同骨架时取数字数量最接近的 - int diff = Math.Abs(nums.Length - e.Numbers.Length); - if (diff < bestLen) { bestLen = diff; bestName = e.Name; } - } - if (bestName != null) { result = bestName; via = "L4骨架"; } - } - } - - // L5: 大电流启发式(最后兜底) - // 框架级特征:数字≥1600 + 3P/4P + 型号含W(万能式标记) → 万能式/智能断路器 - if (result == null) - { - string sUp = spec.Trim().ToUpperInvariant(); - bool hasBig = false; - foreach (string n in nums) - { - long v; - if (long.TryParse(n, out v) && v >= 1600 && v <= 6300) { hasBig = true; break; } - } - bool hasPole = sUp.Contains("/3P") || sUp.Contains("/4P") || sUp.Contains(" 3P") || sUp.Contains(" 4P") || - sUp.EndsWith("3P") || sUp.EndsWith("4P"); - bool hasW = sUp.IndexOf('W') >= 0; - if (hasBig && hasPole && hasW) - { - // 含 I/E(智能型标记,如 HUWI/CW1I) → 智能断路器 - bool hasSmart = sUp.IndexOf('I') >= 0 || sUp.IndexOf('E') >= 0; - result = hasSmart ? "智能断路器" : "万能式断路器"; - via = "L5大电流启发"; - } - } - - // ★ 匹配日志:输入/归一化/数字序列/结果,失败可从日志直接定位原因 - WriteDebugLog("[用户库匹配] 「" + spec + "」 norm=" + norm + - " nums=[" + string.Join(",", nums) + "] → " + - (result == null ? "(未匹配)" : result + " via " + via)); - return result; - } - - // ============================================================ - // DeepSeek AI 智能匹配(本地匹配失败后的兜底) - // · 设置窗口填 API Key,存插件目录 deepseek.json - // · 扒元件后本地未命中的规格批量提交 AI 识别元器件名称 - // · 结果缓存到 deepseek_cache.json(同规格只问一次) - // · AI 结果回填元件表"元件名称"列 - // ============================================================ - - private string DeepSeekConfigPath { get { return GetDbFullPath("deepseek.json"); } } - private string DeepSeekCachePath { get { return GetDbFullPath("deepseek_cache.json"); } } - - /// DeepSeek 设置(加载/保存 JSON) - private class DeepSeekConfig - { - public string ApiKey = ""; - public string BaseUrl = "https://api.deepseek.com"; - public string Model = "deepseek-v4-flash"; // ★ 支持联网搜索的模型 - public bool Enabled = false; - public bool WebSearch = true; // ★ 联网搜索(罕见型号也能查) - } - - private DeepSeekConfig _dsConfig; - private System.Collections.Hashtable _dsCache; - - private DeepSeekConfig LoadDsConfig() - { - if (_dsConfig != null) return _dsConfig; - var cfg = new DeepSeekConfig(); - try - { - if (File.Exists(DeepSeekConfigPath)) - { - string json = File.ReadAllText(DeepSeekConfigPath, System.Text.Encoding.UTF8); - var map = SimpleJsonParse(json); - if (map.ContainsKey("ApiKey")) cfg.ApiKey = (string)map["ApiKey"] ?? ""; - if (map.ContainsKey("BaseUrl")) cfg.BaseUrl = (string)map["BaseUrl"] ?? "https://api.deepseek.com"; - if (map.ContainsKey("Model")) cfg.Model = (string)map["Model"] ?? "deepseek-v4-flash"; - // ★ 布尔值无引号,解析出的 val 可能带换行/空格前缀,比较前必须 Trim - if (map.ContainsKey("Enabled")) cfg.Enabled = ((string)map["Enabled"] ?? "").Trim() == "true"; - if (map.ContainsKey("WebSearch")) cfg.WebSearch = ((string)map["WebSearch"] ?? "").Trim() != "false"; - // ★ 旧模型(deepseek-chat 不支持联网)自动迁移到 v4 - if (cfg.Model == "deepseek-chat" || cfg.Model == "deepseek-reasoner") cfg.Model = "deepseek-v4-flash"; - } - } - catch { } - _dsConfig = cfg; - return cfg; - } - - private void SaveDsConfig(DeepSeekConfig cfg) - { - try - { - string json = "{\n" + - " \"ApiKey\": \"" + (cfg.ApiKey ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"BaseUrl\": \"" + (cfg.BaseUrl ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"Model\": \"" + (cfg.Model ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"Enabled\": " + (cfg.Enabled ? "true" : "false") + ",\n" + - " \"WebSearch\": " + (cfg.WebSearch ? "true" : "false") + "\n" + - "}"; - File.WriteAllText(DeepSeekConfigPath, json, System.Text.Encoding.UTF8); - _dsConfig = cfg; - } - catch (Exception ex) { Log("[DeepSeek配置] 保存失败: " + ex.Message); } - } - - /// AI 匹配缓存:规格 → 元件名称(未命中/失败也缓存,避免反复请求) - private System.Collections.Hashtable LoadDsCache() - { - if (_dsCache != null) return _dsCache; - var ht = new System.Collections.Hashtable(); - try - { - if (File.Exists(DeepSeekCachePath)) - { - string json = File.ReadAllText(DeepSeekCachePath, System.Text.Encoding.UTF8); - var map = SimpleJsonParse(json); - foreach (System.Collections.DictionaryEntry kv in map) - ht[kv.Key.ToString()] = (kv.Value ?? "").ToString(); - } - } - catch { } - _dsCache = ht; - return ht; - } - - private void SaveDsCache() - { - if (_dsCache == null) return; - try - { - var sb = new System.Text.StringBuilder("{\n"); - bool first = true; - foreach (System.Collections.DictionaryEntry kv in _dsCache) - { - if (!first) sb.Append(",\n"); - sb.Append(" \"" + kv.Key.ToString().Replace("\"", "\\\"") + "\": \"" + - kv.Value.ToString().Replace("\"", "\\\"") + "\""); - first = false; - } - sb.Append("\n}"); - File.WriteAllText(DeepSeekCachePath, sb.ToString(), System.Text.Encoding.UTF8); - } - catch (Exception ex) { Log("[DeepSeek缓存] 保存失败: " + ex.Message); } - } - - /// 极简 JSON 解析(扁平 key:value 结构,支持字符串/数字/布尔值) - private static System.Collections.Hashtable SimpleJsonParse(string json) - { - var ht = new System.Collections.Hashtable(); - if (string.IsNullOrEmpty(json)) return ht; - int depth = 0; bool inStr = false; - var key = new System.Text.StringBuilder(); - var val = new System.Text.StringBuilder(); - bool inKey = true; - for (int i = 0; i < json.Length; i++) - { - char c = json[i]; - if (inStr) - { - if (c == '\\' && i + 1 < json.Length) { val.Append(json[i + 1]); i++; continue; } - if (c == '"') { inStr = false; continue; } - (inKey ? key : val).Append(c); - continue; - } - if (c == '"') { inStr = true; continue; } - if (c == '{' || c == '[') { depth++; continue; } - if (c == '}' || c == ']') - { - // ★ 闭合括号收掉最后一个键值对(布尔值结尾无逗号) - if (depth == 1 && key.Length > 0) - { - ht[key.ToString()] = val.ToString().Trim(); - key.Length = 0; val.Length = 0; inKey = true; - } - depth--; continue; - } - if (c == ':' && depth == 1) { inKey = false; val.Length = 0; continue; } - if (c == ',' && depth == 1) - { - if (key.Length > 0) ht[key.ToString()] = val.ToString().Trim(); - key.Length = 0; val.Length = 0; inKey = true; - continue; - } - // ★ 无引号值(true/false/数字)必须累积,否则解析成空 - if (!inKey && !char.IsWhiteSpace(c)) val.Append(c); - } - if (key.Length > 0) ht[key.ToString()] = val.ToString().Trim(); - return ht; - } - - // ============================================================ - // 电器型号前缀规则(与用户库共用同一个 CSV 数据文件) - // ★ 用户库 CSV 中"元件类型"列 = "前缀" 的行即为前缀规则: - // 隔离开关,HGL,只,1,0,1,1,规则,0,前缀 - // (元件名称列=名称,规格列=型号前缀) - // ★ Excel 里直接编辑用户库即可增删规则,随库自动重载 - // ★ 规则结果与 AI 冲突时,以规则为准(根治 AI 误判) - // ============================================================ - - private static List _prefixRules = new List(); - - /// 内置最小规则集(仅当用户库无任何前缀行时兜底)。 - private static readonly string[,] s_BuiltinPrefixRules = - { - { "HGL", "隔离开关" }, { "DZ47", "小型断路器" }, { "NM1", "塑壳断路器" }, - { "CJX2", "交流接触器" }, { "RT16", "熔断器" }, { "LMZ", "电流互感器" }, - }; - - // ============================================================ - // ★ JB/T 2930 国标类组代号表(低压电器型号编制方法的官方定义) - // 国标型号前2位字母=品类代号:第1位类别+第2位组别。 - // 在前缀规则(L0)之后、CSV 库(L1)之前执行,覆盖所有国标型号。 - // ============================================================ - private static readonly System.Collections.Hashtable s_GbClassCodes = new System.Collections.Hashtable(StringComparer.OrdinalIgnoreCase) - { - // H 刀开关/隔离开关族 - { "HD", "隔离开关" }, // 单投刀开关 - { "HS", "隔离开关" }, // 双投刀开关(转换) - { "HR", "隔离开关" }, // 熔断器式刀开关 - { "HH", "隔离开关" }, // 封闭式负荷开关 - { "HK", "隔离开关" }, // 开启式负荷开关(胶盖闸) - { "HZ", "转换开关" }, // 组合开关 - { "HG", "隔离开关" }, // 熔断器式隔离器(另:HG1/HG13) - // R 熔断器族 - { "RC", "熔断器" }, // 插入式 - { "RL", "熔断器" }, // 螺旋式(RL6/RL8) - { "RM", "熔断器" }, // 密封管式 - { "RS", "快速熔断器" }, // 快速(RS0/RS3) - { "RT", "熔断器" }, // 有填料管式(RT0/RT16/RT18) - { "RX", "熔断器" }, // 限流 - { "RTO", "熔断器" }, - // D 断路器族 - { "DW", "万能式断路器" }, // 框架式(DW15/DW45) - { "DZ", "塑壳断路器" }, // 装置式/塑料外壳(DZ15/DZ20) - { "DX", "小型断路器" }, - { "DM", "塑壳断路器" }, - { "DC", "断路器" }, - // C 接触器族 - { "CJ", "交流接触器" }, // 交流(CJ20/CJX) - { "CZ", "直流接触器" }, // 直流 - { "CG", "接触器" }, // 高压 - { "CP", "接触器" }, // 中频 - { "CS", "接触器" }, // 时间 - // Q 起动器族 - { "QC", "电磁起动器" }, { "QS", "手动起动器" }, { "QX", "星三角起动器" }, - { "QJ", "自耦减压起动器" }, { "QT", "起动器" }, { "QU", "起动器" }, - // J 控制继电器族 - { "JL", "电流继电器" }, { "JR", "热过载继电器" }, { "JS", "时间继电器" }, - { "JT", "通用继电器" }, { "JW", "温度继电器" }, { "JZ", "中间继电器" }, - { "JX", "继电器" }, - // L 主令电器族 - { "LA", "按钮" }, // 按钮(LA38/LA39) - { "LK", "主令控制器" }, { "LT", "主令开关" }, { "LW", "转换开关" }, - { "LX", "行程开关" }, { "LU", "足踏开关" }, { "LS", "主令开关" }, - // Z 电阻/终端族 - { "ZB", "电阻器" }, { "ZG", "电阻器" }, { "ZC", "电阻器" }, - // B 变阻器族 - { "BL", "励磁变阻器" }, { "BP", "频敏变阻器" }, { "BQ", "起动变阻器" }, - { "BT", "变阻器" }, { "BC", "旋臂变阻器" }, - // M 电磁铁族 - { "MQ", "牵引电磁铁" }, { "MZ", "制动电磁铁" }, { "MW", "起重电磁铁" }, - // A 其他族 - { "AD", "指示灯" }, // 信号灯(AD11/AD16 习惯用) - { "AN", "按钮" }, - // P 仪用互感器(行业习惯,P 不在 JB/T2930 主表,单列) - { "LQG", "电流互感器" }, - // 变压器(控制变压器 BK 不在 JB/T2930,行业通用) - { "BK", "控制变压器" }, - }; - - /// - /// ★ 国标类组代号解析:按 JB/T 2930 定义,取型号前2位字母查类组表。 - /// 仅当:①前缀规则未命中 ②开头≥2位字母 ③类组表命中 时返回名称。 - /// 数字开头/单字母/进口品牌型号不适用(返回 null 交给后续层)。 - /// - private static string MatchByGbCode(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string s = spec.Trim(); - // 前2位必须是字母(国标类组代号为2位拼音) - if (s.Length < 3) return null; - if (!((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= 'a' && s[0] <= 'z'))) return null; - if (!((s[1] >= 'A' && s[1] <= 'Z') || (s[1] >= 'a' && s[1] <= 'z'))) return null; - // 第3位应是数字或分隔符(确认是类组代号+设计序号结构,排除品牌词) - if (s.Length > 2) - { - char c2 = s[2]; - bool ok = (c2 >= '0' && c2 <= '9') || c2 == '-' || c2 == ' ' || c2 == '/'; - if (!ok) return null; - } - string code = s.Substring(0, 2).ToUpperInvariant(); - object v = s_GbClassCodes[code]; - return v as string; - } - - /// - /// 按型号前缀规则查元器件名称。 - /// ★ 规则来自用户库 CSV"元件类型=前缀"的行(EnsureUserLibCsvLoaded 时提取), - /// 规则前缀直接与规格开头比对(支持字母+数字混合前缀,如 DZ47/CDM3/CJX2), - /// 最长前缀优先(7→2字符)。 - /// 返回 null 表示无规则。 - /// - private static string MatchByPrefixRule(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string s = spec.Trim().ToUpperInvariant(); - if (s.Length < 2) return null; - - var rules = _prefixRules; - if (rules.Count == 0) - { - // 用户库无前缀行 → 内置兜底 - for (int i = 0; i < s_BuiltinPrefixRules.GetLength(0); i++) - rules.Add(new[] { s_BuiltinPrefixRules[i, 0], s_BuiltinPrefixRules[i, 1] }); - _prefixRules = rules; - } - - for (int plen = 7; plen >= 2; plen--) - { - if (s.Length < plen) continue; - string head = s.Substring(0, plen); - foreach (var rule in rules) - { - if (rule[0].Length != plen || rule[0] != head) continue; - return rule[1]; - } - } - return null; - } - - /// 打开 DeepSeek 设置窗口(运行时创建,不改 ui.cs) - private void ShowDeepSeekSettings() - { - var cfg = LoadDsConfig(); - var form = new System.Windows.Forms.Form(); - form.Text = "DeepSeek AI 匹配设置"; - form.Size = new System.Drawing.Size(420, 260); - form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - form.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - form.MaximizeBox = false; form.MinimizeBox = false; - - var lblKey = new System.Windows.Forms.Label { Text = "API Key:", Location = new System.Drawing.Point(15, 18), AutoSize = true }; - var txtKey = new System.Windows.Forms.TextBox - { - Location = new System.Drawing.Point(80, 15), Size = new System.Drawing.Size(310, 23), - Text = cfg.ApiKey, UseSystemPasswordChar = true - }; - var chkShow = new System.Windows.Forms.CheckBox - { - Text = "显示密钥", Location = new System.Drawing.Point(80, 44), AutoSize = true - }; - chkShow.CheckedChanged += (s2, e2) => txtKey.UseSystemPasswordChar = !chkShow.Checked; - - var lblModel = new System.Windows.Forms.Label { Text = "模型:", Location = new System.Drawing.Point(15, 78), AutoSize = true }; - var cboModel = new System.Windows.Forms.ComboBox - { - Location = new System.Drawing.Point(80, 74), Size = new System.Drawing.Size(180, 23), - DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList - }; - cboModel.Items.Add("deepseek-v4-flash"); - cboModel.Items.Add("deepseek-v4-pro"); - cboModel.Items.Add("deepseek-chat"); - cboModel.SelectedItem = string.IsNullOrEmpty(cfg.Model) ? "deepseek-v4-flash" : cfg.Model; - - var chkEnable = new System.Windows.Forms.CheckBox - { - Text = "启用 AI 匹配(本地匹配失败后自动提交 DeepSeek 识别)", - Location = new System.Drawing.Point(15, 108), AutoSize = true, Checked = cfg.Enabled - }; - - var lblTip = new System.Windows.Forms.Label - { - Text = "提示:AI 结果会缓存到本地,相同规格只请求一次。\nAPI Key 从 platform.deepseek.com 获取。", - Location = new System.Drawing.Point(15, 138), AutoSize = true, ForeColor = System.Drawing.Color.Gray - }; - - var btnClear = new System.Windows.Forms.Button { Text = "清空AI缓存", Location = new System.Drawing.Point(80, 178), Size = new System.Drawing.Size(100, 28) }; - btnClear.Click += (s2, e2) => - { - try { if (File.Exists(DeepSeekCachePath)) File.Delete(DeepSeekCachePath); _dsCache = null; } - catch { } - MessageBox.Show(form, "AI 缓存已清空。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - }; - - var btnOk = new System.Windows.Forms.Button { Text = "保存", Location = new System.Drawing.Point(240, 178), Size = new System.Drawing.Size(75, 28) }; - var btnCancel = new System.Windows.Forms.Button { Text = "取消", Location = new System.Drawing.Point(325, 178), Size = new System.Drawing.Size(75, 28) }; - - btnOk.Click += (s2, e2) => - { - cfg.ApiKey = txtKey.Text.Trim(); - cfg.Model = cboModel.SelectedItem == null ? "deepseek-v4-flash" : cboModel.SelectedItem.ToString(); - cfg.Enabled = chkEnable.Checked && cfg.ApiKey.Length > 0; - SaveDsConfig(cfg); - form.Close(); - }; - btnCancel.Click += (s2, e2) => form.Close(); - - form.Controls.AddRange(new System.Windows.Forms.Control[] { lblKey, txtKey, chkShow, lblModel, cboModel, chkEnable, lblTip, btnClear, btnOk, btnCancel }); - form.ShowDialog(this); - } - - /// - /// 调 DeepSeek API 批量识别规格对应的元器件名称。 - /// 返回 规格→名称 的哈希表(失败的规格不在结果里)。 - /// - private System.Collections.Hashtable CallDeepSeekMatch(List specs) - { - var result = new System.Collections.Hashtable(); - var cfg = LoadDsConfig(); - if (!cfg.Enabled || string.IsNullOrWhiteSpace(cfg.ApiKey)) return result; - - // 构造提问:证据链推理法(查厂商→确认型号→按厂商定义归类) - var sb = new System.Text.StringBuilder(); - sb.Append("你是低压电器型号识别专家,精通 JB/T 2930《低压电器产品型号编制方法》。为每个规格型号返回【元器件名称】(中文标准品类词)。\n\n"); - sb.Append("【推理方法】(对每个型号按证据链三步走,不要直接猜):\n"); - sb.Append("第1步·识别厂商:从型号前缀判断是哪家厂(如 HUWI→沪工/环宇系、NM→正泰、CDM→德力西、CM→常熟、CW→常熟框架、SZRM→上海人民、XBK→湘湖/新宝凯、QAM→七仪);\n"); - sb.Append("第2步·确认系列:该厂商的此系列号是否存在、属于什么产品线(用你的产品知识回忆厂商型录:如 HUWI=沪工智能型万能式、YLEM=某厂智能框架、BM3=塑壳);\n"); - sb.Append("第3步·按厂商定义归类:厂商型录里该系列挂哪个品类就答什么,不要凭字母表面猜。\n\n"); - sb.Append("【辅助规律】(第2步无记忆时用):\n"); - sb.Append("· 国标类组:前2位字母=品类(DW万能断路器/DZ塑壳/CJ交流接触器/JR热继/LA按钮/HD-HS-HR隔离开关/RT熔断器);\n"); - sb.Append("· 结构特征:电流≥1600A+3P/4P+含W → 框架级(万能式/智能断路器);壳架≤630A+3P → 塑壳;63A以下+1P/2P → 微型;\n"); - sb.Append("· 派生代号:L/E=漏电或电子式,I=智能型,Z=直流/智能,N=可逆;\n"); - sb.Append("· 进口系列:施耐德(NSX/iC65/Vigi/LC1/LR)、ABB(S/SH)、西门子(3RT/5SL)、伊顿(IS)。\n\n"); - sb.Append("【输出格式】(严格遵守):\n"); - sb.Append("只返回纯 JSON 对象 {\"规格原文\":\"元器件名称\",...},不要任何解释、思考过程或其他文字;\n"); - sb.Append("每个规格都必须给出判断:按证据链推理,无法确认厂商和系列时按结构特征推断,实在无据可依才给空字符串;\n"); - sb.Append("名称用标准品类词:万能式断路器/智能断路器/塑壳断路器/小型断路器/漏电断路器/交流接触器/直流接触器/热过载继电器/时间继电器/中间继电器/电流互感器/电压互感器/熔断器/快速熔断器/隔离开关/负荷开关/转换开关/按钮/指示灯/行程开关/双电源/电磁起动器/自耦减压起动器/控制变压器/干式变压器/电涌保护器/电容器/电能表/软启动器/变频器等。\n"); - sb.Append("规格列表:\n"); - for (int i = 0; i < specs.Count; i++) - sb.Append((i + 1) + ". " + specs[i] + "\n"); - - try - { - // ★ 纯AI知识模式:chat/completions(不走联网搜索,快且稳) - // deepseek-v4 系列是思考模型:正式回答在 content,思考过程在 reasoning_content; - // 有时 content 空、答案藏在 reasoning_content 末尾 → 两处都提取 - string body = "{" + - "\"model\":\"" + cfg.Model + "\"," + - "\"messages\":[" + - "{\"role\":\"user\",\"content\":\"" + JsonEscape(sb.ToString()) + "\"}" + - "]," + - "\"temperature\":0.1," + - "\"max_tokens\":3000" + - "}"; - - string url = (cfg.BaseUrl ?? "https://api.deepseek.com").TrimEnd('/') + "/chat/completions"; - var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); - req.Method = "POST"; - req.ContentType = "application/json"; - req.Headers.Add("Authorization", "Bearer " + cfg.ApiKey); - req.Timeout = 60000; // 60秒 - req.ReadWriteTimeout = 60000; - req.Proxy = null; // ★ 不走系统代理(防代理环境卡死) - byte[] data = System.Text.Encoding.UTF8.GetBytes(body); - req.ContentLength = data.Length; - Log("[DeepSeek] 发起请求: " + specs.Count + " 条规格(AI知识模式), url=" + url); - using (var rs = req.GetRequestStream()) rs.Write(data, 0, data.Length); - - string respText; - using (var resp = (System.Net.HttpWebResponse)req.GetResponse()) - using (var sr = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8)) - respText = sr.ReadToEnd(); - Log("[DeepSeek] 响应长度: " + respText.Length + " 字符"); - - // 从响应提取 content(手工解析,取 choices[0].message.content) - string content = ExtractJsonContent(respText); - if (string.IsNullOrEmpty(content)) - { - Log("[DeepSeek] 响应解析失败: " + (respText.Length > 400 ? respText.Substring(0, 400) : respText)); - return result; - } - // ★ 诊断:AI原始输出(排查"返回0条"问题,只打前400字符) - Log("[DeepSeek] AI输出内容: " + (content.Length > 400 ? content.Substring(0, 400) + "..." : content)); - // content 里是 {"规格":"名称",...} - // ★ 思考模型(deepseek-v4)的 content 可能为空,答案在 reasoning_content 末尾: - // 思维链最后一般会写出最终 JSON,从 reasoning_content 里找 {...} 提取 - var map = SimpleJsonParse(content); - if (map.Count == 0) - { - // 从 reasoning_content 提取最后一个完整 JSON 对象 - int rIdx = respText.IndexOf("\"reasoning_content\":\"", System.StringComparison.Ordinal); - if (rIdx >= 0) - { - string reasoning = ExtractEscapedString(respText, rIdx + 21); - int braceStart = reasoning.LastIndexOf('{'); - if (braceStart >= 0) - { - // 从最后一个 { 找到配对的 } - int depth2 = 0; int end = -1; - for (int k = braceStart; k < reasoning.Length; k++) - { - if (reasoning[k] == '{') depth2++; - else if (reasoning[k] == '}') - { - depth2--; - if (depth2 == 0) { end = k; break; } - } - } - if (end > braceStart) - { - string jsonPart = reasoning.Substring(braceStart, end - braceStart + 1); - map = SimpleJsonParse(jsonPart); - Log("[DeepSeek] 从思维链提取到 " + map.Count + " 条结果"); - } - } - } - } - foreach (System.Collections.DictionaryEntry kv in map) - { - string key = kv.Key.ToString(); - string name = (kv.Value ?? "").ToString().Trim(); - if (name.Length == 0) continue; - - // ★ 防线:AI 结果先过本地前缀规则校验,冲突时以规则为准 - // (根治 AI 偶发误判,如把 HGL 隔离开关答成熔断器) - string rule = MatchByPrefixRule(key); - if (rule != null && rule != name) - { - Log("[DeepSeek校验] 「" + key + "」 AI答[" + name + "] 与规则冲突,已改用[" + rule + "]"); - name = rule; - } - result[key] = name; - } - Log("[DeepSeek] 识别 " + specs.Count + " 条,返回 " + result.Count + " 条结果"); - } - catch (Exception ex) - { - Log("[DeepSeek] 请求失败: " + ex.Message); - } - return result; - } - - /// - /// 从 API 响应中提取模型输出文本。 - /// 兼容两种格式: - /// · chat/completions: choices[0].message.content("content":"...") - /// · responses API: output[].content[].text("text":"...")或顶层"output_text" - /// - private static string ExtractJsonContent(string respText) - { - try - { - // 方式1:responses API 的 "output_text":"..." - int idx = respText.IndexOf("\"output_text\":\"", System.StringComparison.Ordinal); - if (idx >= 0) - { - string s = ExtractEscapedString(respText, idx + 15); - if (!string.IsNullOrEmpty(s)) return s; - } - // 方式2:responses API 的输出项文本 "text":"..."(跳过 summary/reasoning, - // 直接找最后一个大 text——输出 message 的正文通常最大) - int best = -1, bestLen = 0; - int pos = 0; - while (true) - { - int t = respText.IndexOf("\"text\":\"", pos, System.StringComparison.Ordinal); - if (t < 0) break; - // 取这个字符串的长度估算 - int len = EstimateEscapedLen(respText, t + 8); - if (len > bestLen) { bestLen = len; best = t; } - pos = t + 8; - } - if (best >= 0) - { - string s = ExtractEscapedString(respText, best + 8); - if (!string.IsNullOrEmpty(s)) return s; - } - // 方式3:chat 的 "content":"..." - idx = respText.IndexOf("\"content\":\"", System.StringComparison.Ordinal); - if (idx >= 0) - { - return ExtractEscapedString(respText, idx + 11); - } - return null; - } - catch { return null; } - } - - /// 从 start 位置读取一个 JSON 转义字符串(处理 \n \" \\ \uXXXX)。 - private static string ExtractEscapedString(string text, int start) - { - var sb = new System.Text.StringBuilder(); - int i = start; - while (i < text.Length) - { - char c = text[i]; - if (c == '\\' && i + 1 < text.Length) - { - char n = text[i + 1]; - if (n == 'n') sb.Append('\n'); - else if (n == 't') sb.Append('\t'); - else if (n == 'r') sb.Append('\r'); - else if (n == '"') sb.Append('"'); - else if (n == '\\') sb.Append('\\'); - else if (n == '/' ) sb.Append('/'); - else if (n == 'u' && i + 5 < text.Length) - { - int code = Convert.ToInt32(text.Substring(i + 2, 4), 16); - sb.Append((char)code); - i += 4; - } - else sb.Append(n); - i += 2; - continue; - } - if (c == '"') break; - sb.Append(c); - i++; - } - return sb.ToString(); - } - - /// 估算 start 位置转义字符串的长度(到未转义引号为止)。 - private static int EstimateEscapedLen(string text, int start) - { - int i = start, len = 0; - while (i < text.Length) - { - char c = text[i]; - if (c == '\\' && i + 1 < text.Length) { i += 2; len += 2; continue; } - if (c == '"') break; - i++; len++; - } - return len; - } - - private static string JsonEscape(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(); - foreach (char c in s) - { - if (c == '"') sb.Append("\\\""); - else if (c == '\\') sb.Append("\\\\"); - else if (c == '\n') sb.Append("\\n"); - else if (c == '\t') sb.Append("\\t"); - else if (c == '\r') sb.Append(""); - else sb.Append(c); - } - return sb.ToString(); - } - - /// - /// 扒元件插入后:对本地匹配失败的规格异步调用 DeepSeek 补名称, - /// 完成后回填数据库 + 刷新表格(UI 线程)。 - /// ★ 单飞+排队:上一个 AI 批次未完成时,后续规格累积到待办队列, - /// 完成后一并提交(防并发互踩/请求堆积)。 - /// - private static readonly object _aiLock = new object(); - private static bool _aiRunning = false; - private static List _aiPendingSpecs = new List(); - private static string _aiPendingTbl = null; - - private void AiFillMissingNames(List failedSpecs, string tblName) - { - if (failedSpecs == null || failedSpecs.Count == 0) return; - var cfg = LoadDsConfig(); - if (!cfg.Enabled || string.IsNullOrWhiteSpace(cfg.ApiKey)) return; - - lock (_aiLock) - { - // 并发防抖:AI 批次进行中 → 累积到待办,由运行中的批次完成后接力 - if (_aiRunning) - { - foreach (string sp in failedSpecs) - if (!_aiPendingSpecs.Contains(sp)) _aiPendingSpecs.Add(sp); - if (_aiPendingTbl == null) _aiPendingTbl = tblName; - Log("[AI队列] 批次进行中," + failedSpecs.Count + " 条已加入待办(累计 " + _aiPendingSpecs.Count + ")"); - return; - } - _aiRunning = true; - _aiPendingTbl = tblName; - } - - RunAiBatch(failedSpecs, tblName); - } - - /// 执行一个 AI 批次(完成后处理待办队列)。 - private void RunAiBatch(List specs, string tblName) - { - var bgw = new System.ComponentModel.BackgroundWorker(); - bgw.DoWork += (s, e) => - { - try - { - // 先查缓存,未缓存的才提交 AI - var cache = LoadDsCache(); - var toAsk = new List(); - var localHits = new System.Collections.Hashtable(); - lock (_aiLock) - { - foreach (string sp in specs) - { - if (cache.ContainsKey(sp)) - { - string cached = (cache[sp] ?? "").ToString(); - // ★ 规则有结果但缓存为空(AI曾未识别) → 用规则(补漏) - string rule = MatchByPrefixRule(sp); - if (rule != null && rule.Length > 0 && rule != cached) - { - Log("[缓存校验] 「" + sp + "」 缓存[" + cached + "]与规则冲突,已纠正为[" + rule + "]"); - cached = rule; - cache[sp] = rule; - } - if (cached.Length > 0) localHits[sp] = cached; - } - else if (!toAsk.Contains(sp)) toAsk.Add(sp); - } - } - - var ai = new System.Collections.Hashtable(); - if (toAsk.Count > 0) - { - ai = CallDeepSeekMatch(toAsk); - // 写缓存(包括未命中的,避免反复问) - lock (_aiLock) - { - foreach (string sp in toAsk) - cache[sp] = ai.Contains(sp) ? ai[sp].ToString() : ""; - SaveDsCache(); - } - } - - // 合并结果 - var final = new System.Collections.Hashtable(); - foreach (System.Collections.DictionaryEntry kv in localHits) final[kv.Key] = kv.Value; - foreach (System.Collections.DictionaryEntry kv in ai) final[kv.Key] = kv.Value; - e.Result = final; - } - catch (Exception ex) - { - Log("[AI回填] 后台异常: " + ex); - e.Result = new System.Collections.Hashtable(); - } - }; - bgw.RunWorkerCompleted += (s, e) => - { - // ★ 无论成败都处理:先取走待办队列并释放单飞标记 - List pending; - string pendingTbl; - lock (_aiLock) - { - pending = new List(_aiPendingSpecs); - pendingTbl = _aiPendingTbl; - _aiPendingSpecs = new List(); - _aiPendingTbl = null; - _aiRunning = false; - } - - try - { - var final = e.Result as System.Collections.Hashtable; - if (final == null || final.Count == 0) { if (pending.Count > 0) StartNextAiBatch(pending, pendingTbl); return; } - int updated = 0; - string dbPath = GetQuoteDbPath(_currentProjectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var tx = conn.BeginTransaction()) - { - foreach (System.Collections.DictionaryEntry kv in final) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "UPDATE \"" + tblName + "\" SET 元件名称=@name WHERE 规格=@spec AND (元件名称 IS NULL OR 元件名称='');", conn)) - { - cmd.Parameters.AddWithValue("@name", kv.Value.ToString()); - cmd.Parameters.AddWithValue("@spec", kv.Key.ToString()); - updated += cmd.ExecuteNonQuery(); - } - } - tx.Commit(); - } - } - if (updated > 0) - { - Log("[AI回填] 已回填 " + updated + " 条元件名称"); - _yuanjianCache.Clear(); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - - // ★ AI 识别成功的结果追加进用户库 CSV(库越用越全, - // 下次同规格本地直接命中,不再消耗 AI) - AppendAiResultsToUserLibCsv(final); - } - catch (Exception ex) { Log("[AI回填] 回填异常: " + ex.Message); } - - // ★ 接力:待办队列有货 → 继续下一个批次 - if (pending.Count > 0) StartNextAiBatch(pending, pendingTbl); - }; - bgw.RunWorkerAsync(); - } - - /// 启动下一个 AI 批次(带单飞保护)。 - private void StartNextAiBatch(List specs, string tblName) - { - lock (_aiLock) - { - if (_aiRunning) - { - foreach (string sp in specs) - if (!_aiPendingSpecs.Contains(sp)) _aiPendingSpecs.Add(sp); - return; - } - _aiRunning = true; - _aiPendingTbl = tblName; - } - Log("[AI队列] 接力下一批 " + specs.Count + " 条"); - RunAiBatch(specs, tblName); - } - - /// - /// 把 AI 识别结果(规格→名称)追加到最新用户库 CSV(GBK 编码), - /// 并同步更新内存库 _specNameLib(当前会话立即生效)。 - /// 已存在的规格跳过;每条占一行:名称,规格,只,1,0,1,1,AI识别,0,元件 - /// - private void AppendAiResultsToUserLibCsv(System.Collections.Hashtable aiResults) - { - try - { - if (aiResults == null || aiResults.Count == 0) return; - - // 找最新 CSV(与 EnsureUserLibCsvLoaded 同规则:上级目录+插件目录取最新) - string best = null; DateTime bestTime = DateTime.MinValue; - var dirs = new List(); - try - { - var parent = Path.GetDirectoryName(_baseDir); - if (!string.IsNullOrEmpty(parent) && Directory.Exists(parent)) dirs.Add(parent); - } - catch { } - dirs.Add(_baseDir); - foreach (string d in dirs) - { - try - { - foreach (string f in Directory.GetFiles(d, "用户库*.csv")) - { - DateTime t = File.GetLastWriteTime(f); - if (best == null || t > bestTime) { best = f; bestTime = t; } - } - } - catch { } - } - if (best == null) { Log("[AI入库] 未找到用户库CSV,跳过"); return; } - - // ★ 共享读写:文件可能被 Excel 打开 - var gbk = System.Text.Encoding.GetEncoding("GBK"); - var existing = new HashSet(StringComparer.OrdinalIgnoreCase); - var fs = System.IO.File.Open(best, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using (var sr = new StreamReader(fs, gbk)) - { - string line; - while ((line = sr.ReadLine()) != null) - { - if (string.IsNullOrWhiteSpace(line)) continue; - int comma = line.IndexOf(','); - if (comma > 0) existing.Add(line.Substring(comma + 1).Trim()); - } - } - - // 组装新增行 - var newLines = new List(); - foreach (System.Collections.DictionaryEntry kv in aiResults) - { - string spec = kv.Key.ToString().Trim(); - string name = kv.Value.ToString().Trim(); - if (spec.Length == 0 || name.Length == 0) continue; - if (existing.Contains(spec)) continue; - newLines.Add(name + "," + spec + ",只,1,0,1,1,AI识别,0,元件"); - existing.Add(spec); // 防同批重复 - } - if (newLines.Count == 0) { Log("[AI入库] 全部已存在,无新增"); return; } - - // 追加写(共享读写防 Excel 锁;失败重试3次——扒图进程可能正读CSV) - bool written = false; - for (int attempt = 0; attempt < 3 && !written; attempt++) - { - try - { - using (var fs2 = new FileStream(best, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) - using (var sw = new StreamWriter(fs2, gbk)) - { - foreach (string nl in newLines) sw.WriteLine(nl); - } - written = true; - } - catch (System.IO.IOException) - { - System.Threading.Thread.Sleep(300); // 等 CSV 读取方释放 - } - } - if (!written) Log("[AI入库] 写入失败(文件被占用),跳过本次(下次扒图会再尝试)"); - - // ★ 同步内存库:当前会话的本地匹配立即可用 - try - { - EnsureUserLibCsvLoaded(); - if (_specNameLib != null) - { - foreach (string nl in newLines) - { - string[] cols = nl.Split(','); - if (cols.Length >= 2) - _specNameLib.Add(new SpecNameEntry - { - Name = cols[0], - NormSpec = NormalizeSpec(cols[1]), - Numbers = ExtractNumbers(cols[1]), - Skeleton = ExtractSkeleton(cols[1]) - }); - } - } - } - catch { } - - Log("[AI入库] 新增 " + newLines.Count + " 条到 " + Path.GetFileName(best)); - } - catch (Exception ex) { Log("[AI入库] 失败: " + ex.Message); } - } - - /// 根据项目ID和图号获取箱号表名(查"表索引"表)。 - private string GetQuoteTableName(string projectId, string tuhao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return ""; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 表名 FROM " + IndexTableName + " WHERE 图号=@t LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@t", tuhao); - object o = cmd.ExecuteScalar(); - return o == null ? "" : o.ToString(); - } - } - } - catch { return ""; } - } - - private void InsertTuhao(string projectId, string tuhao, string frameHandle, string textHandle) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - string sql = "INSERT INTO " + TuhaoTableName + - " (序号, 图号, 台数, 箱柜数量, 单价, 总价, 成本总价, 毛利, 毛利率, 框Handle, 文本Handle) " + - "VALUES (@seq, @th, @taishu, 0, 0, 0, 0, 0, 0, @frameHandle, @textHandle);"; - string seq = GetNextSeqNumber(TuhaoTableName, "图号", projectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.Parameters.AddWithValue("@taishu", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.Parameters.AddWithValue("@textHandle", textHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteTuhao(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var tablesToDrop = new List(); - string selIdx = "SELECT 实际表名 FROM 表索引 WHERE 图号 = @th;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selIdx, conn)) - { - sel.Parameters.AddWithValue("@th", tuhao); - using (var reader = sel.ExecuteReader()) - { - while (reader.Read()) - { - string realTbl = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(realTbl)) tablesToDrop.Add(realTbl); - } - } - } - foreach (string realTbl in tablesToDrop) - { - using (var dropCmd = new System.Data.SQLite.SQLiteCommand( - "DROP TABLE IF EXISTS \"" + realTbl + "\";", conn)) - dropCmd.ExecuteNonQuery(); - } - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM " + TuhaoTableName + " WHERE 图号 = @th;", conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.ExecuteNonQuery(); - } - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM 表索引 WHERE 图号 = @th;", conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.ExecuteNonQuery(); - } - } - } - - private void InsertXianghao(string projectId, string tuhao, string xianghao, string frameHandle, string textHandle) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - string tblName = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(tblName)) - { - tblName = GetNextTableId(projectId, "xh"); - CreateXianghaoTable(projectId, tblName); - AddTableIndex(projectId, "箱号", tuhao, "", tblName); - } - // ★ 确保旧箱号表也有"箱名"/"框Handle"/"文本Handle"列 - using (var connEns = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - connEns.Open(); - EnsureColumns(connEns, "\"" + tblName + "\"", new[] { "箱名", "框Handle", "文本Handle" }); - } - string seq = GetXianghaoCount(projectId, tuhao); - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 箱号, 箱名, 单位, 数量," + - " 单台成本, 成本价, 单台报出, 报出价, 利润, 利润率, 毛利率, 框Handle, 文本Handle) " + - "VALUES (@seq, @xh, @xm, @unit, @shuliang, 0, 0, 0, 0, 0, 0, 0, @frameHandle, @textHandle);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@xh", xianghao); - cmd.Parameters.AddWithValue("@xm", ""); // 箱名默认空,由用户在表格里填写 - cmd.Parameters.AddWithValue("@unit", "台"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.Parameters.AddWithValue("@textHandle", textHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteXianghao(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - if (!string.IsNullOrEmpty(yjTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DROP TABLE IF EXISTS \"" + yjTbl + "\";", conn)) - cmd.ExecuteNonQuery(); - } - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (!string.IsNullOrEmpty(xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + xhTbl + "\" WHERE 箱号 = @xh;", conn)) - { - cmd.Parameters.AddWithValue("@xh", xianghao); - cmd.ExecuteNonQuery(); - } - } - } - RemoveTableIndex(projectId, "元件", tuhao, xianghao); - } - - private void InsertYuanjian(string projectId, string tuhao, string xianghao, string name) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - EnsureYuanjianTableExists(projectId, tuhao, xianghao); - string tblName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tblName)) - { - System.Windows.Forms.MessageBox.Show("元件表创建失败(表索引未注册),图号=" + tuhao + " 箱号=" + xianghao); - return; - } - string seq; - using (var conn0 = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn0.Open(); - using (var c = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\";", conn0)) - { - int n = 0; - object o = c.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - seq = (n + 1).ToString(); - } - } - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型) " + - "VALUES (@seq, @name, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件');"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@name", name); - cmd.Parameters.AddWithValue("@unit", "只"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@caigou", "1"); - cmd.Parameters.AddWithValue("@baochu", "1"); - cmd.ExecuteNonQuery(); - } - } - } - - /// 扒元件专用:把文本写到【规格】列(元件名称留空),同时写入框Handle。 - private void InsertYuanjianSpec(string projectId, string tuhao, string xianghao, string spec, string frameHandle) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - EnsureYuanjianTableExists(projectId, tuhao, xianghao); - string tblName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tblName)) - { - System.Windows.Forms.MessageBox.Show("元件表创建失败(表索引未注册),图号=" + tuhao + " 箱号=" + xianghao); - return; - } - string seq; - using (var conn0 = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn0.Open(); - using (var c = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\";", conn0)) - { - int n = 0; - object o = c.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - seq = (n + 1).ToString(); - } - } - // ★ 写入"规格"列 + 框Handle - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 规格, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型, 框Handle) " + - "VALUES (@seq, '', @spec, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件', @frameHandle);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@spec", spec); - cmd.Parameters.AddWithValue("@unit", "只"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@caigou", "1"); - cmd.Parameters.AddWithValue("@baochu", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteYuanjian(string projectId, string tuhao, string xianghao, string seq) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(xianghao)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(realTbl)) return; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + realTbl + "\" WHERE 序号 = @seq;", conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.ExecuteNonQuery(); - } - } - } - - // ============================================================ - // 数据库回写:把内存 DataTable 的改动写回报价库 - // ============================================================ - - private void SaveTableToDatabase(DataTable table, string projectId, string tableName, - string whereClause, Dictionary whereParams, bool force = false) - { - if (table == null || string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - - DataGridView dgv = null; - if (table == _tuhaoTable) dgv = this.advancedDataGridView9; - else if (table == _xianghaoTable) dgv = this.advancedDataGridView4; - else if (table == _yuanjianTable) dgv = this.advancedDataGridView5; - if (dgv != null) dgv.EndEdit(); - - if (table.Rows.Count == 0) return; - if (!force && table.GetChanges() == null) return; - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var tx = conn.BeginTransaction()) - { - string delSql = "DELETE FROM " + tableName; - if (!string.IsNullOrWhiteSpace(whereClause)) delSql += " WHERE " + whereClause; - delSql += ";"; - using (var delCmd = new System.Data.SQLite.SQLiteCommand(delSql, conn)) - { - if (whereParams != null) - { - foreach (var kv in whereParams) delCmd.Parameters.AddWithValue(kv.Key, kv.Value); - } - delCmd.ExecuteNonQuery(); - } - if (table.Rows.Count > 0) - { - var colNames = new List(table.Columns.Count); - foreach (DataColumn c in table.Columns) colNames.Add(c.ColumnName); - var paramList = new List(colNames.Count); - foreach (string c in colNames) paramList.Add("@" + c); - string insertSql = "INSERT INTO " + tableName + " (" + - string.Join(", ", colNames.ToArray()) + ") VALUES (" + - string.Join(", ", paramList.ToArray()) + ");"; - using (var insCmd = new System.Data.SQLite.SQLiteCommand(insertSql, conn)) - { - foreach (string col in colNames) - insCmd.Parameters.Add("@" + col, System.Data.DbType.String); - try { insCmd.Prepare(); } catch { } - foreach (DataRow row in table.Rows) - { - if (row.RowState == DataRowState.Deleted) continue; - foreach (string col in colNames) - { - object v = row[col]; - insCmd.Parameters["@" + col].Value = - (v == null || v == DBNull.Value) ? "" : v.ToString(); - } - insCmd.ExecuteNonQuery(); - } - } - } - tx.Commit(); - } - table.AcceptChanges(); - } - } - - private void SaveTuhaoTableIfDirty() - { - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null); - } - - private void SaveXianghaoTableIfDirty() - { - if (_xianghaoTable == null || string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) return; - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null); - } - - private void SaveYuanjianTableIfDirty() - { - if (_yuanjianTable == null || string.IsNullOrWhiteSpace(_yuanjianTable.TableName)) return; - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null); - } - - private void SaveAllQuoteTablesIfDirty(bool force = true) - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_yuanjianTable != null && !string.IsNullOrWhiteSpace(_yuanjianTable.TableName)) - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null, force); - if (_xianghaoTable != null && !string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null, force); - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, force); - } - catch { } - } - - private void SaveAllToDatabaseSilent() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - try - { - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - foreach (var kv in _xianghaoCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - foreach (var kv in _yuanjianCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - RecalcAllFromDatabase(_currentProjectId); - ReloadProjectsFromDatabase(); - } - catch { } - } - - // ============================================================ - // 联动刷新:项目 → 图号 → 箱号 → 元件 - // ============================================================ - - private void ReloadProjectsFromDatabase() - { - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return; - - var indexTable = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT 项目编号, 箱柜台数, 成本总价, 报出总价, 利润, 利润率 FROM " + - ProjectsTableName + " ORDER BY rowid;"; - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(sql, conn)) - adapter.Fill(indexTable); - } - - var table = new DataTable(); - table.Columns.Add("项目编号", typeof(string)); - table.Columns.Add("项目名称", typeof(string)); - table.Columns.Add("客户名称", typeof(string)); - table.Columns.Add("客户地址", typeof(string)); - table.Columns.Add("联系人", typeof(string)); - table.Columns.Add("联系电话", typeof(string)); - table.Columns.Add("项目日期", typeof(string)); - table.Columns.Add("箱柜台数", typeof(string)); - table.Columns.Add("成本总价", typeof(string)); - table.Columns.Add("报出总价", typeof(string)); - table.Columns.Add("利润", typeof(string)); - table.Columns.Add("利润率", typeof(string)); - table.Columns.Add("备注", typeof(string)); - - foreach (DataRow idxRow in indexTable.Rows) - { - string projectId = idxRow["项目编号"] == null ? "" : idxRow["项目编号"].ToString().Trim(); - if (string.IsNullOrEmpty(projectId)) continue; - var info = GetProjectInfoFromQuoteDb(projectId); - var row = table.NewRow(); - row["项目编号"] = projectId; - row["项目名称"] = GetInfoOrDefault(info, "项目名称"); - row["客户名称"] = GetInfoOrDefault(info, "客户名称"); - row["客户地址"] = GetInfoOrDefault(info, "客户地址"); - row["联系人"] = GetInfoOrDefault(info, "联系人"); - row["联系电话"] = GetInfoOrDefault(info, "联系电话"); - row["项目日期"] = GetInfoOrDefault(info, "项目日期"); - row["备注"] = GetInfoOrDefault(info, "备注"); - row["箱柜台数"] = idxRow["箱柜台数"] == null ? "" : idxRow["箱柜台数"].ToString(); - row["成本总价"] = idxRow["成本总价"] == null ? "" : idxRow["成本总价"].ToString(); - row["报出总价"] = idxRow["报出总价"] == null ? "" : idxRow["报出总价"].ToString(); - row["利润"] = idxRow["利润"] == null ? "" : idxRow["利润"].ToString(); - row["利润率"] = idxRow["利润率"] == null ? "" : idxRow["利润率"].ToString(); - table.Rows.Add(row); - } - - this.advancedDataGridView6.AutoGenerateColumns = false; - table = ConvertFormulaColumnsToDouble(table); - this.advancedDataGridView6.DataSource = table; - } - - private static string GetInfoOrDefault(Dictionary info, string key) - { - if (info == null) return ""; - string v; - return info.TryGetValue(key, out v) ? (v ?? "") : ""; - } - - private void ReloadTuhaoByProject(string projectId) - { - bool outerGuard = _isReloading; - _isReloading = true; - try - { - if (string.IsNullOrWhiteSpace(projectId) || !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView9.DataSource = null; - _tuhaoTable = null; - _currentTuhao = ""; - ReloadXianghaoByTuhao("", ""); - return; - } - string dbPath = GetQuoteDbPath(projectId); - string sql = "SELECT * FROM " + TuhaoTableName + " ORDER BY CAST(序号 AS INTEGER);"; - var table = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - this.advancedDataGridView9.AutoGenerateColumns = false; - this.advancedDataGridView9.DataSource = table; - _tuhaoTable = table; - ApplyPriceFormat(this.advancedDataGridView9, _单台小数位文本); - - _currentTuhao = ""; - if (this.advancedDataGridView9.Rows.Count > 0) - { - SetCurrentCell(this.advancedDataGridView9, 0); - _currentTuhao = GetCellValueAsString(this.advancedDataGridView9.Rows[0], "图号"); - } - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - finally { _isReloading = outerGuard; } - } - - private void ReloadXianghaoByTuhao(string projectId, string tuhao) - { - bool outerGuard = _isReloading; - _isReloading = true; - try - { - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView4.DataSource = null; - _xianghaoTable = null; - _currentXianghao = ""; - ReloadYuanjianByXianghao("", "", ""); - return; - } - string dbPath = GetQuoteDbPath(projectId); - string realTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(realTbl)) - { - realTbl = GetNextTableId(projectId, "xh"); - CreateXianghaoTable(projectId, realTbl); - AddTableIndex(projectId, "箱号", tuhao, "", realTbl); - } - - DataTable table; - // ★ 禁用缓存命中:每次都从数据库重新读取,确保删除/变更能及时反映到UI - if (_xianghaoCache.ContainsKey(tuhao)) _xianghaoCache.Remove(tuhao); - { - string sql = "SELECT * FROM \"" + realTbl + "\" ORDER BY CAST(序号 AS INTEGER);"; - table = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 老库结构兼容:箱号表可能还没有"箱名"列,读取前幂等补列(表格绑定依赖该列) - EnsureColumns(conn, "\"" + realTbl + "\"", new[] { "箱名" }); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - table.TableName = realTbl; - _xianghaoCache[tuhao] = table; - } - - this.advancedDataGridView4.AutoGenerateColumns = false; - this.advancedDataGridView4.DataSource = table; - _xianghaoTable = table; - ApplyPriceFormat(this.advancedDataGridView4, _单台小数位文本); - - _currentXianghao = ""; - if (this.advancedDataGridView4.Rows.Count > 0) - { - SetCurrentCell(this.advancedDataGridView4, 0); - _currentXianghao = GetCellValueAsString(this.advancedDataGridView4.Rows[0], "箱号"); - } - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - finally { _isReloading = outerGuard; } - } - - private void ReloadYuanjianByXianghao(string projectId, string tuhao, string xianghao) - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - string.IsNullOrWhiteSpace(xianghao) || !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView5.DataSource = null; - _yuanjianTable = null; - return; - } - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - string dbPath = GetQuoteDbPath(projectId); - string cacheKey = tuhao + "\n" + xianghao; - DataTable table; - // ★ 禁用缓存命中:每次都从数据库重新读取,确保删除/变更能及时反映到UI - if (_yuanjianCache.ContainsKey(cacheKey)) _yuanjianCache.Remove(cacheKey); - { - table = new DataTable(); - if (!string.IsNullOrEmpty(realTbl)) - { - string sql = "SELECT * FROM \"" + realTbl + "\" ORDER BY CAST(序号 AS INTEGER);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - } - table.TableName = realTbl; - _yuanjianCache[cacheKey] = table; - } - this.advancedDataGridView5.AutoGenerateColumns = false; - this.advancedDataGridView5.DataSource = table; - _yuanjianTable = table; - ApplyPriceFormat(this.advancedDataGridView5, _单台小数位文本); - } - - // ============================================================ - // 公式重算 - // ============================================================ - - private void RecalcYuanjianRow(DataGridViewRow row) - { - if (row == null) return; - decimal biaoJia = GetCellDecimal(row, "表价"); - decimal caiGouXiShu = GetCellDecimal(row, "采购系数"); - decimal baoChuXiShu = GetCellDecimal(row, "报出系数"); - decimal shuLiang = GetCellDecimal(row, "数量"); - decimal caiGouDanJia = biaoJia * caiGouXiShu; - decimal caiGouJia = caiGouDanJia * shuLiang; - decimal baoChuDanJia = caiGouDanJia * baoChuXiShu; - decimal baoChuJia = baoChuDanJia * shuLiang; - SetCell(row, "采购单价", caiGouDanJia); - SetCell(row, "采购价", caiGouJia); - SetCell(row, "报出单价", baoChuDanJia); - SetCell(row, "报出价", baoChuJia); - } - - private void RecalcXianghaoRowFromYuanjian(DataGridViewRow xianghaoRow) - { - if (xianghaoRow == null) return; - decimal sumCaiGouJia = 0m; - decimal sumBaoChuJia = 0m; - DataGridView dgv5 = this.advancedDataGridView5; - if (dgv5 != null && dgv5.Rows != null) - { - foreach (DataGridViewRow yj in dgv5.Rows) - { - if (yj == null || yj.IsNewRow) continue; - sumCaiGouJia += GetCellDecimal(yj, "采购价"); - sumBaoChuJia += GetCellDecimal(yj, "报出价"); - } - } - decimal shuLiang = GetCellDecimal(xianghaoRow, "数量"); - decimal danTaiChengBen = sumCaiGouJia; - decimal chengBenJia = danTaiChengBen * shuLiang; - decimal danTaiBaoChu = sumBaoChuJia; - decimal baoChuJia = danTaiBaoChu * shuLiang; - decimal liRun = baoChuJia - chengBenJia; - decimal liRunLv = chengBenJia == 0m ? 0m : liRun / chengBenJia; - decimal maoLiLv = baoChuJia == 0m ? 0m : liRun / baoChuJia; - SetCell(xianghaoRow, "单台成本", danTaiChengBen); - SetCell(xianghaoRow, "成本价", chengBenJia); - SetCell(xianghaoRow, "单台报出", danTaiBaoChu); - SetCell(xianghaoRow, "报出价", baoChuJia); - SetCell(xianghaoRow, "利润", liRun); - SetCell(xianghaoRow, "利润率", liRunLv); - SetCell(xianghaoRow, "毛利率", maoLiLv); - } - - private void RecalcTuhaoRowFromXianghao(DataGridViewRow tuhaoRow) - { - if (tuhaoRow == null) return; - decimal sumShuLiang = 0m; - decimal sumBaoChuJia = 0m; - decimal sumChengBenJia = 0m; - DataGridView dgv4 = this.advancedDataGridView4; - if (dgv4 != null && dgv4.Rows != null) - { - foreach (DataGridViewRow xh in dgv4.Rows) - { - if (xh == null || xh.IsNewRow) continue; - sumShuLiang += GetCellDecimal(xh, "数量"); - sumBaoChuJia += GetCellDecimal(xh, "报出价"); - sumChengBenJia += GetCellDecimal(xh, "成本价"); - } - } - decimal taiShu = GetCellDecimal(tuhaoRow, "台数"); - decimal xiangGuiShuLiang = sumShuLiang; - decimal danJia = sumBaoChuJia; - decimal zongJia = danJia * taiShu; - decimal chengBenZongJia = sumChengBenJia * taiShu; - decimal maoLi = zongJia - chengBenZongJia; - decimal maoLiLv = zongJia == 0m ? 0m : maoLi / zongJia; - SetCell(tuhaoRow, "箱柜数量", xiangGuiShuLiang); - SetCell(tuhaoRow, "单价", danJia); - SetCell(tuhaoRow, "总价", zongJia); - SetCell(tuhaoRow, "成本总价", chengBenZongJia); - SetCell(tuhaoRow, "毛利", maoLi); - SetCell(tuhaoRow, "毛利率", maoLiLv); - RecalcProjectRowFromTuhao(); - } - - private void RecalcProjectRowFromTuhao() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - decimal sumXiangGuiShuLiang = 0m; - decimal sumChengBenZongJia = 0m; - decimal sumZongJia = 0m; - DataGridView dgv9 = this.advancedDataGridView9; - if (dgv9 != null && dgv9.Rows != null) - { - foreach (DataGridViewRow th in dgv9.Rows) - { - if (th == null || th.IsNewRow) continue; - sumXiangGuiShuLiang += GetCellDecimal(th, "箱柜数量"); - sumChengBenZongJia += GetCellDecimal(th, "成本总价"); - sumZongJia += GetCellDecimal(th, "总价"); - } - } - decimal xiangGuiTaiShu = sumXiangGuiShuLiang; - decimal baoChuZongJia = sumZongJia; - decimal liRun = baoChuZongJia - sumChengBenZongJia; - decimal liRunLv = sumChengBenZongJia == 0m ? 0m : liRun / sumChengBenZongJia; - DataGridViewRow projRow = FindProjectRowById(_currentProjectId); - if (projRow != null) - { - SetCell(projRow, "箱柜台数", xiangGuiTaiShu); - SetCell(projRow, "成本总价", sumChengBenZongJia); - SetCell(projRow, "报出总价", baoChuZongJia); - SetCell(projRow, "利润", liRun); - SetCell(projRow, "利润率", liRunLv); - } - } - - private void RecalcAllAfterReload() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - _isRecalculating = true; - _isReloading = true; - try - { - DataGridView dgv5 = this.advancedDataGridView5; - if (dgv5 != null && dgv5.Rows != null) - { - foreach (DataGridViewRow yj in dgv5.Rows) - { - if (yj == null || yj.IsNewRow) continue; - RecalcYuanjianRow(yj); - } - } - var xhRow = GetFirstSelectedRow(this.advancedDataGridView4); - if (xhRow != null) RecalcXianghaoRowFromYuanjian(xhRow); - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - - SaveYuanjianTableIfDirty(); - SaveXianghaoTableIfDirty(); - SaveTuhaoTableIfDirty(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - } - finally - { - _isRecalculating = false; - _lastRecalcTime = DateTime.Now; - _isReloading = false; - } - } - - // ---------- 全量数据库重算 ---------- - - private class TuhaoCalcRow { public long RowId; public decimal TaiShu; public string Tuhao; } - private class XianghaoCalcRow { public long RowId; public decimal ShuLiang; public string Xianghao; } - - private void RecalcAllFromDatabase(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) projectId = _currentProjectId; - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var tuhaoRows = new List(); - string selTuhao = "SELECT rowid, 台数, 图号 FROM " + TuhaoTableName + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selTuhao, conn)) - using (var rdr = sel.ExecuteReader()) - { - while (rdr.Read()) - { - var t = new TuhaoCalcRow(); - t.RowId = rdr.GetInt64(0); - t.TaiShu = ParseDecimal(rdr.IsDBNull(1) ? "" : rdr.GetValue(1)); - t.Tuhao = rdr.IsDBNull(2) ? "" : rdr.GetValue(2).ToString().Trim(); - tuhaoRows.Add(t); - } - } - decimal sumProjXiangGui = 0m; - decimal sumProjChengBen = 0m; - decimal sumProjZongJia = 0m; - foreach (var t in tuhaoRows) - { - if (string.IsNullOrWhiteSpace(t.Tuhao)) continue; - try - { - string xhTable = GetXianghaoTableByIndex(t.Tuhao, conn); - if (string.IsNullOrEmpty(xhTable)) - { - UpdateTuhaoCalc(conn, t.RowId, 0m, 0m, 0m, 0m, 0m, 0m); - continue; - } - string xhQuoted = "\"" + xhTable + "\""; - decimal sumThXiangGuiShuLiang = 0m; - decimal sumThBaoChuJia = 0m; - decimal sumThChengBenJia = 0m; - var xhRows = new List(); - string selXh = "SELECT rowid, 数量, 箱号 FROM " + xhQuoted + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selXh, conn)) - using (var rdr = sel.ExecuteReader()) - { - while (rdr.Read()) - { - var x = new XianghaoCalcRow(); - x.RowId = rdr.GetInt64(0); - x.ShuLiang = ParseDecimal(rdr.IsDBNull(1) ? "" : rdr.GetValue(1)); - x.Xianghao = rdr.IsDBNull(2) ? "" : rdr.GetValue(2).ToString(); - xhRows.Add(x); - } - } - foreach (var x in xhRows) - { - try - { - sumThXiangGuiShuLiang += x.ShuLiang; - string yjTable = GetYuanjianTableByIndex(t.Tuhao, x.Xianghao, conn); - decimal sumCaiGou = 0m; - decimal sumBaoChu = 0m; - if (!string.IsNullOrEmpty(yjTable)) - { - string yjQuoted = "\"" + yjTable + "\""; - string selYj = "SELECT rowid, 表价, 采购系数, 报出系数, 数量 FROM " + - yjQuoted + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selYj, conn)) - using (var sr = sel.ExecuteReader()) - { - while (sr.Read()) - { - long yjRid = sr.GetInt64(0); - decimal yjBiaoJia = ParseDecimal(sr.IsDBNull(1) ? "" : sr.GetValue(1)); - decimal yjCgXs = ParseDecimal(sr.IsDBNull(2) ? "" : sr.GetValue(2)); - decimal yjBcXs = ParseDecimal(sr.IsDBNull(3) ? "" : sr.GetValue(3)); - decimal yjSl = ParseDecimal(sr.IsDBNull(4) ? "" : sr.GetValue(4)); - decimal yjCaiGouDanJia = yjBiaoJia * yjCgXs; - decimal yjCaiGouJia = yjCaiGouDanJia * yjSl; - decimal yjBaoChuDanJia = yjCaiGouDanJia * yjBcXs; - decimal yjBaoChuJia = yjBaoChuDanJia * yjSl; - sumCaiGou += yjCaiGouJia; - sumBaoChu += yjBaoChuJia; - UpdateYuanjianCalc(conn, yjQuoted, yjRid, - yjCaiGouDanJia, yjCaiGouJia, yjBaoChuDanJia, yjBaoChuJia); - } - } - } - decimal danTaiChengBen = sumCaiGou; - decimal chengBenJia = danTaiChengBen * x.ShuLiang; - decimal danTaiBaoChu = sumBaoChu; - decimal baoChuJia = danTaiBaoChu * x.ShuLiang; - decimal xhLiRun = baoChuJia - chengBenJia; - decimal xhLiRunLv = chengBenJia == 0m ? 0m : xhLiRun / chengBenJia; - decimal xhMaoLiLv = baoChuJia == 0m ? 0m : xhLiRun / baoChuJia; - sumThBaoChuJia += baoChuJia; - sumThChengBenJia += chengBenJia; - UpdateXianghaoCalc(conn, xhQuoted, x.RowId, - danTaiChengBen, chengBenJia, danTaiBaoChu, baoChuJia, - xhLiRun, xhLiRunLv, xhMaoLiLv); - } - catch { } - } - decimal xiangGuiShuLiang = sumThXiangGuiShuLiang; - decimal danJia = sumThBaoChuJia; - decimal zongJia = danJia * t.TaiShu; - decimal chengBenZongJia = sumThChengBenJia * t.TaiShu; - decimal maoLi = zongJia - chengBenZongJia; - decimal maoLiLv = zongJia == 0m ? 0m : maoLi / zongJia; - sumProjXiangGui += xiangGuiShuLiang; - sumProjChengBen += chengBenZongJia; - sumProjZongJia += zongJia; - UpdateTuhaoCalc(conn, t.RowId, xiangGuiShuLiang, danJia, - zongJia, chengBenZongJia, maoLi, maoLiLv); - } - catch { } - } - decimal projLiRun = sumProjZongJia - sumProjChengBen; - decimal projLiRunLv = sumProjChengBen == 0m ? 0m : projLiRun / sumProjChengBen; - UpdateProjectQuoteTotalsById(projectId, sumProjXiangGui, - sumProjChengBen, sumProjZongJia, projLiRun, projLiRunLv); - } - } - catch { } - } - - private static void UpdateYuanjianCalc(System.Data.SQLite.SQLiteConnection conn, - string yjQuoted, long rowId, - decimal caiGouDanJia, decimal caiGouJia, decimal baoChuDanJia, decimal baoChuJia) - { - string sql = "UPDATE " + yjQuoted + " SET " + - "采购单价=@a, 采购价=@b, 报出单价=@c, 报出价=@d WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", caiGouDanJia == 0m ? (object)DBNull.Value : (object)caiGouDanJia); - cmd.Parameters.AddWithValue("@b", caiGouJia == 0m ? (object)DBNull.Value : (object)caiGouJia); - cmd.Parameters.AddWithValue("@c", baoChuDanJia == 0m ? (object)DBNull.Value : (object)baoChuDanJia); - cmd.Parameters.AddWithValue("@d", baoChuJia == 0m ? (object)DBNull.Value : (object)baoChuJia); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private static void UpdateXianghaoCalc(System.Data.SQLite.SQLiteConnection conn, - string xhQuoted, long rowId, - decimal danTaiChengBen, decimal chengBenJia, decimal danTaiBaoChu, decimal baoChuJia, - decimal liRun, decimal liRunLv, decimal maoLiLv) - { - string sql = "UPDATE " + xhQuoted + " SET " + - "单台成本=@a, 成本价=@b, 单台报出=@c, 报出价=@d, " + - "利润=@e, 利润率=@f, 毛利率=@g WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", danTaiChengBen == 0m ? (object)DBNull.Value : (object)danTaiChengBen); - cmd.Parameters.AddWithValue("@b", chengBenJia == 0m ? (object)DBNull.Value : (object)chengBenJia); - cmd.Parameters.AddWithValue("@c", danTaiBaoChu == 0m ? (object)DBNull.Value : (object)danTaiBaoChu); - cmd.Parameters.AddWithValue("@d", baoChuJia == 0m ? (object)DBNull.Value : (object)baoChuJia); - cmd.Parameters.AddWithValue("@e", liRun == 0m ? (object)DBNull.Value : (object)liRun); - cmd.Parameters.AddWithValue("@f", liRunLv.ToString()); - cmd.Parameters.AddWithValue("@g", maoLiLv.ToString()); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private static void UpdateTuhaoCalc(System.Data.SQLite.SQLiteConnection conn, - long rowId, decimal xiangGuiShuLiang, decimal danJia, - decimal zongJia, decimal chengBenZongJia, decimal maoLi, decimal maoLiLv) - { - string sql = "UPDATE " + TuhaoTableName + " SET " + - "箱柜数量=@a, 单价=@b, 总价=@c, 成本总价=@d, 毛利=@e, 毛利率=@f " + - "WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", xiangGuiShuLiang == 0m ? (object)DBNull.Value : (object)xiangGuiShuLiang); - cmd.Parameters.AddWithValue("@b", danJia == 0m ? (object)DBNull.Value : (object)danJia); - cmd.Parameters.AddWithValue("@c", zongJia == 0m ? (object)DBNull.Value : (object)zongJia); - cmd.Parameters.AddWithValue("@d", chengBenZongJia == 0m ? (object)DBNull.Value : (object)chengBenZongJia); - cmd.Parameters.AddWithValue("@e", maoLi == 0m ? (object)DBNull.Value : (object)maoLi); - cmd.Parameters.AddWithValue("@f", maoLiLv.ToString()); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private void UpdateProjectQuoteTotalsById(string projectId, - decimal xiangGuiTaiShu, decimal chengBenZongJia, - decimal baoChuZongJia, decimal liRun, decimal liRunLv) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "UPDATE " + ProjectsTableName + " SET " + - "箱柜台数=@xgts, 成本总价=@cbzj, 报出总价=@bczj, " + - "利润=@lr, 利润率=@lrl WHERE 项目编号=@id;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@xgts", xiangGuiTaiShu == 0m ? (object)DBNull.Value : (object)xiangGuiTaiShu); - cmd.Parameters.AddWithValue("@cbzj", chengBenZongJia == 0m ? (object)DBNull.Value : (object)chengBenZongJia); - cmd.Parameters.AddWithValue("@bczj", baoChuZongJia == 0m ? (object)DBNull.Value : (object)baoChuZongJia); - cmd.Parameters.AddWithValue("@lr", liRun == 0m ? (object)DBNull.Value : (object)liRun); - cmd.Parameters.AddWithValue("@lrl", liRunLv.ToString()); - cmd.Parameters.AddWithValue("@id", projectId); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - // ============================================================ - // 事件:CellValueChanged / DirtyStateChanged / CellEndEdit - // ============================================================ - - private void Grid_DirtyStateChanged(object sender, EventArgs e) - { - if (_isRecalculating || _isReloading) return; - var msSinceRecalc = (DateTime.Now - _lastRecalcTime).TotalMilliseconds; - if (msSinceRecalc < 2000) return; - var dgv = sender as DataGridView; - if (dgv != null && dgv.IsCurrentCellDirty) - dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); - } - - private void Yuanjian_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView5; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - _isRecalculating = true; - try - { - RecalcYuanjianRow(row); - var xhRow = GetFirstSelectedRow(this.advancedDataGridView4); - if (xhRow != null) - { - RecalcXianghaoRowFromYuanjian(xhRow); - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - } - } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - private void Xianghao_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView4; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - _isRecalculating = true; - try - { - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - private void Tuhao_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView9; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - DataGridViewColumn col = e.ColumnIndex >= 0 ? dgv.Columns[e.ColumnIndex] : null; - string colName = col == null ? "" : - (!string.IsNullOrEmpty(col.DataPropertyName) ? col.DataPropertyName : col.HeaderText); - if (colName != "台数") return; - _isRecalculating = true; - try { RecalcTuhaoRowFromXianghao(row); } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - /// CellEndEdit:把公式列的字符串值转为 double,让 DefaultCellStyle.Format 生效。 - private void Grid_CellEndEdit(object sender, DataGridViewCellEventArgs e) - { - var dgv = sender as DataGridView; - if (dgv == null || e.ColumnIndex < 0 || e.ColumnIndex >= dgv.Columns.Count) return; - string dp = dgv.Columns[e.ColumnIndex].DataPropertyName; - string cn = dgv.Columns[e.ColumnIndex].HeaderText; - string colKey = !string.IsNullOrEmpty(dp) ? dp : cn; - if (!s_公式列集合.Contains(colKey)) return; - if (e.RowIndex < 0 || e.RowIndex >= dgv.Rows.Count) return; - object v = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; - if (v == null || v is double) return; - string str = v.ToString().Trim(); - if (string.IsNullOrEmpty(str)) return; - double d; - if (double.TryParse(str, out d)) - dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = d; - } - - // ============================================================ - // SelectionChanged 联动 - // ============================================================ - - private void advancedDataGridView9_SelectionChanged(object sender, EventArgs e) - { - if (_isReloading) return; - if (this.advancedDataGridView9 != null && this.advancedDataGridView9.SelectedCells.Count > 1) return; - DataGridViewRow row = GetFirstSelectedRow(this.advancedDataGridView9); - if (row == null) return; - string tuhao = GetCellValueAsString(row, "图号"); - if (tuhao == _currentTuhao) return; - _currentTuhao = tuhao; - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - - private void advancedDataGridView4_SelectionChanged(object sender, EventArgs e) - { - if (_isReloading) return; - if (this.advancedDataGridView4 != null && this.advancedDataGridView4.SelectedCells.Count > 1) return; - DataGridViewRow row = GetFirstSelectedRow(this.advancedDataGridView4); - if (row == null) return; - string xh = GetCellValueAsString(row, "箱号"); - if (xh == _currentXianghao) return; - _currentXianghao = xh; - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - - private void advancedDataGridView5_SelectionChanged(object sender, EventArgs e) { } - - // ============================================================ - // ★ 点击表格行 → 定位到对应的扒图框(缩放居中) - // 读取数据行的"框Handle"列,用 Handle 反查 CAD 实体,缩放到实体范围 - // ============================================================ - private void Grid_CellClick_Zoom(object sender, DataGridViewCellEventArgs e) - { - if (_isReloading) return; - if (e.RowIndex < 0) return; - DataGridView dgv = sender as DataGridView; - if (dgv == null) return; - DataGridViewRow row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - // ★ 直接从 DataRow 读取"框Handle"(不依赖 DataGridView 列映射) - string handle = ""; - var drv = row.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) handle = v.ToString().Trim(); - } - if (!string.IsNullOrWhiteSpace(handle)) - { - ZoomToFrameHandle(handle); - } - } - - /// - /// 根据框 Handle 字符串定位网页 CAD 视图:缩放居中到框的位置并高亮。 - /// Handle 是扒图时绘制的彩色矩形框的句柄(十六进制字符串), - /// 与网页端实体 objectId 一致,通过 CadBridge 转发给网页 CAD 执行。 - /// - private static void ZoomToFrameHandle(string handle) - { - if (string.IsNullOrWhiteSpace(handle)) return; - try - { - cadbt.CadBridge.ZoomToFrameHandle(handle); - } - catch { } - } - - /// - /// ★ 网页 CAD 会话内的扒图框由网页端持有,无需像 AutoCAD 版那样 - /// 定期 SaveAs 整个 DWG(原为防止 CAD 关闭时框丢失)。保留空实现 - /// 以兼容调用点。 - /// - private static DateTime _lastDwgSaveTime = DateTime.MinValue; - - // ★ 扒元件后待选中的行(框Handle),finally 延迟执行选中 - private List _pendingSelectYuanjianHandles = new List(); - - private static void SaveCurrentDwg() - { - // 网页版:扒图框保存在网页 CAD 会话中,无需保存 DWG 文件。 - } - - /// - /// ★ 删除指定 Handle 对应的 CAD 框实体(单个,转发到批量方法)。 - /// - private void DeleteFrameByHandle(string handle) - { - DeleteFramesByHandles(new string[] { handle }); - } - - /// - /// ★ 批量删除多个 Handle 对应的框:打包成一条消息发给网页 CAD, - /// 网页端逐个 erase 后只 regen 一次(保持原版"批量一次刷新"的优化)。 - /// - private void DeleteFramesByHandles(System.Collections.Generic.IEnumerable handles) - { - var list = new List(); - if (handles != null) - foreach (string h in handles) - if (!string.IsNullOrWhiteSpace(h)) list.Add(h); - if (list.Count == 0) { Log("[DeleteFramesByHandles] 无有效 handle,跳过"); return; } - try - { - cadbt.CadBridge.DeleteFramesByHandles(list); - Log("[DeleteFramesByHandles] 已发送网页删除请求: 请求=" + list.Count); - } - catch (System.Exception ex) { Log("[DeleteFramesByHandles] 异常: " + ex.Message); } - } - - /// - /// ★ 收集指定图号下所有箱号表和元件表的框Handle(级联删框用)。 - /// 不包含图号表自身的框(图号行框由调用方从内存表收集)。 - /// - private void CollectFrameHandlesForTuhao(string projectId, string tuhao, List handles) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) { Log("[CollectFrameHandlesForTuhao] 数据库不存在: " + dbPath); return; } - int beforeCount = handles.Count; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // 箱号表 - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - Log("[CollectFrameHandlesForTuhao] 图号=" + tuhao + " 箱号表名=" + (xhTbl ?? "(null)")); - if (!string.IsNullOrEmpty(xhTbl) && TableExists(conn, xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle, 箱号 FROM \"" + xhTbl + "\";", conn)) - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - string xh = reader.IsDBNull(1) ? "" : reader.GetString(1); - Log("[CollectFrameHandlesForTuhao] 箱号=" + xh + " 框Handle=" + h); - // 查该箱号的元件表 - if (!string.IsNullOrWhiteSpace(xh)) - { - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xh); - if (!string.IsNullOrEmpty(yjTbl) && TableExists(conn, yjTbl)) - { - using (var yjCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + yjTbl + "\";", conn)) - using (var yjReader = yjCmd.ExecuteReader()) - while (yjReader.Read()) - { - string yh = yjReader.IsDBNull(0) ? "" : yjReader.GetString(0); - if (!string.IsNullOrWhiteSpace(yh)) handles.Add(yh); - Log("[CollectFrameHandlesForTuhao] 元件框Handle=" + yh); - } - } - } - } - } - } - } - Log("[CollectFrameHandlesForTuhao] 新增框Handle数: " + (handles.Count - beforeCount)); - } - catch (Exception ex) { Log("[CollectFrameHandlesForTuhao] 异常: " + ex.Message); } - } - - /// - /// ★ 收集指定箱号下元件表的框Handle(级联删框用)。 - /// 不包含箱号表自身的框(箱号行框由调用方从内存表收集)。 - /// - private void CollectFrameHandlesForXianghao(string projectId, string tuhao, string xianghao, List handles) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - string.IsNullOrWhiteSpace(xianghao)) return; - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) { Log("[CollectFrameHandlesForXianghao] 数据库不存在: " + dbPath); return; } - int beforeCount = handles.Count; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先收集箱号表自身该箱号的框Handle(之前遗漏,导致删箱号时蒙版不删) - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - Log("[CollectFrameHandlesForXianghao] 图号=" + tuhao + " 箱号=" + xianghao + " 箱号表名=" + (xhTbl ?? "(null)")); - if (!string.IsNullOrEmpty(xhTbl) && TableExists(conn, xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + xhTbl + "\" WHERE 箱号=@xh;", conn)) - { - cmd.Parameters.AddWithValue("@xh", xianghao); - using (var reader = cmd.ExecuteReader()) - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - Log("[CollectFrameHandlesForXianghao] 箱号自身框Handle=" + h); - } - } - } - // ★ 再收集该箱号下元件表的框Handle - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - Log("[CollectFrameHandlesForXianghao] 元件表名=" + (yjTbl ?? "(null)")); - if (!string.IsNullOrEmpty(yjTbl) && TableExists(conn, yjTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + yjTbl + "\";", conn)) - using (var reader = cmd.ExecuteReader()) - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - Log("[CollectFrameHandlesForXianghao] 元件框Handle=" + h); - } - } - } - Log("[CollectFrameHandlesForXianghao] 新增框Handle数: " + (handles.Count - beforeCount)); - } - catch (Exception ex) { Log("[CollectFrameHandlesForXianghao] 异常: " + ex.Message); } - } - - /// 检查表是否存在(SQLite)。 - private static bool TableExists(System.Data.SQLite.SQLiteConnection conn, string tableName) - { - if (conn == null || string.IsNullOrWhiteSpace(tableName)) return false; - try - { - string name = tableName.Trim().Trim('"'); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT name FROM sqlite_master WHERE type='table' AND name=@n;", conn)) - { - cmd.Parameters.AddWithValue("@n", name); - object o = cmd.ExecuteScalar(); - return o != null && o != DBNull.Value; - } - } - catch { return false; } - } - - // ============================================================ - // 双击项目行 → 进入项目 - // ============================================================ - - private void advancedDataGridView6_CellDoubleClick(object sender, DataGridViewCellEventArgs e) - { - if (e.RowIndex < 0) return; - DataGridViewRow row = this.advancedDataGridView6.Rows[e.RowIndex]; - string pid = GetCellValueAsString(row, "项目编号"); - if (string.IsNullOrWhiteSpace(pid)) return; - - // 切项目前:先把当前项目的所有改动回写库,然后清空缓存 - if (!string.IsNullOrWhiteSpace(_currentProjectId) && _currentProjectId != pid) - { - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - foreach (var kv in _xianghaoCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - foreach (var kv in _yuanjianCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - } - catch { } - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - _tuhaoTable = null; - } - _currentProjectId = pid; - EnterProjectCore(pid); - } - - private void EnterProjectCore(string pid) - { - // 切换主区域到报价页(tabPage4) - this.tabControl2.SelectedTab = this.tabPage4; - EnsureQuoteDbExists(pid); - LoadPriceFormatConfig(pid); - RecalcAllFromDatabase(pid); - ReloadTuhaoByProject(pid); - ApplyPriceFormat(this.advancedDataGridView9, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView4, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView5, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - } - - // ============================================================ - // ★ 右键点击时保持多行选中 - // WinForms 默认行为:右键点击未选中行 → 清除多选,只选一行 - // 修正:右键点击已选中行 → 保持多选;点击未选中行 → 正常切换 - // ============================================================ - private void Grid_MouseDown_KeepMultiSelect(object sender, MouseEventArgs e) - { - if (e.Button != MouseButtons.Right) return; - var dgv = sender as DataGridView; - if (dgv == null) return; - var hit = dgv.HitTest(e.X, e.Y); - if (hit.Type != DataGridViewHitTestType.Cell && hit.Type != DataGridViewHitTestType.RowHeader) return; - if (hit.RowIndex < 0) return; - // 如果右键点击的行已经在选中行中,不做任何操作(保持多选) - // 如果不在选中行中,让默认行为生效(选中该行) - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r.Index == hit.RowIndex) return; - } - // 选中行中没有包含右键点击的行 → 手动选中该行 - dgv.ClearSelection(); - dgv.Rows[hit.RowIndex].Selected = true; - dgv.CurrentCell = dgv.Rows[hit.RowIndex].Cells[0]; - } - - // ============================================================ - // ★ 键盘 Delete 键批量删除选中行 - // 图号表→MenuTuhao_Delete_Click;箱号表→MenuXianghao_Delete_Click;元件表→MenuYuanjian_Delete_Click - // ============================================================ - // 连续批量模式标记:Shift+F1 触发,或 1 秒内连按 F1 触发 - private DateTime _lastF1Time = DateTime.MinValue; - private bool _f1BatchMode; - - /// F1:元件两两配对合并;F2:元件三个一组配对合并。 - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - if ((keyData & Keys.KeyCode) == Keys.F1 && this.advancedDataGridView5 != null) - { - try { RunF1Merge(); } catch (Exception ex) { Log("[F1] " + ex.Message); } - return true; - } - if ((keyData & Keys.KeyCode) == Keys.F2 && this.advancedDataGridView5 != null) - { - try { MergeYuanjianByGroup(3); } catch (Exception ex) { Log("[F2] " + ex.Message); } - return true; - } - if ((keyData & Keys.KeyCode) == Keys.F3 && this.advancedDataGridView5 != null) - { - try { MergeYuanjianByGroup(4); } catch (Exception ex) { Log("[F3] " + ex.Message); } - return true; - } - return base.ProcessCmdKey(ref msg, keyData); - } - - /// 统一 F1 入口(宿主按键/网页转发共用)。 - private void RunF1Merge() - { - MergeAdjacentYuanjianByF1(); - } - - private void Grid_KeyDown_Delete(object sender, KeyEventArgs e) - { - if (e.KeyCode != Keys.Delete) return; - var dgv = sender as DataGridView; - if (dgv == null) return; - if (dgv.SelectedRows.Count == 0 && dgv.SelectedCells.Count == 0) return; - if (dgv.IsCurrentCellInEditMode) return; // 编辑模式下不拦截 Delete - - e.SuppressKeyPress = true; - e.Handled = true; - - if (dgv == this.advancedDataGridView9) - MenuTuhao_Delete_Click(null, null); - else if (dgv == this.advancedDataGridView4) - MenuXianghao_Delete_Click(null, null); - else if (dgv == this.advancedDataGridView5) - MenuYuanjian_Delete_Click(null, null); - } - - // ============================================================ - // 右键菜单:创建 + 行移动 - // ============================================================ - - private void BuildContextMenus() - { - // 图号菜单(advancedDataGridView9) - _menuTuhao = new ContextMenuStrip(); - _menuTuhao.Items.Add("新建图号", null, MenuTuhao_New_Click); - _menuTuhao.Items.Add("删除图号", null, MenuTuhao_Delete_Click); - _menuTuhao.Items.Add(new ToolStripSeparator()); - _menuTuhao.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Top)); - _menuTuhao.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Up)); - _menuTuhao.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Down)); - _menuTuhao.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Bottom)); - _menuTuhao.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.To)); - this.advancedDataGridView9.ContextMenuStrip = _menuTuhao; - - // 箱号菜单(advancedDataGridView4) - _menuXianghao = new ContextMenuStrip(); - _menuXianghao.Items.Add("新建箱号", null, MenuXianghao_New_Click); - _menuXianghao.Items.Add("删除箱号", null, MenuXianghao_Delete_Click); - _menuXianghao.Items.Add(new ToolStripSeparator()); - _menuXianghao.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Top)); - _menuXianghao.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Up)); - _menuXianghao.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Down)); - _menuXianghao.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Bottom)); - _menuXianghao.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.To)); - this.advancedDataGridView4.ContextMenuStrip = _menuXianghao; - - // 元件菜单(advancedDataGridView5) - _menuYuanjian = new ContextMenuStrip(); - _menuYuanjian.Items.Add("新建元件", null, MenuYuanjian_New_Click); - _menuYuanjian.Items.Add("删除元件", null, MenuYuanjian_Delete_Click); - _menuYuanjian.Items.Add("合并元件", null, MenuYuanjian_Merge_Click); - _menuYuanjian.Items.Add(new ToolStripSeparator()); - _menuYuanjian.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Top)); - _menuYuanjian.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Up)); - _menuYuanjian.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Down)); - _menuYuanjian.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Bottom)); - _menuYuanjian.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.To)); - this.advancedDataGridView5.ContextMenuStrip = _menuYuanjian; - } - - private enum RowMoveAction { Top, Up, Down, Bottom, To } - - private void MoveSelectedRowInGrid(DataGridView dgv, RowMoveAction action) - { - if (dgv == null || string.IsNullOrWhiteSpace(_currentProjectId)) return; - DataTable table = null; - System.Action reloadAction = null; - if (dgv == this.advancedDataGridView5) - { - table = _yuanjianTable; - reloadAction = () => ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - else if (dgv == this.advancedDataGridView4) - { - table = _xianghaoTable; - reloadAction = () => ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - else if (dgv == this.advancedDataGridView9) - { - table = _tuhaoTable; - reloadAction = () => ReloadTuhaoByProject(_currentProjectId); - } - if (table == null || table.Rows.Count == 0) - { - MessageBox.Show(this, "没有数据可移动。", "移动行", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var dgvRow = GetFirstSelectedRow(dgv); - if (dgvRow == null) - { - MessageBox.Show(this, "请先选择要移动的行。", "移动行", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - int dataCount = dgv.Rows.Count; - if (dgv.AllowUserToAddRows) dataCount--; - if (dataCount <= 0) return; - int oldIndex = dgvRow.Index; - if (oldIndex >= dataCount) return; - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - int newIndex = -1; - _isReloading = true; - try - { - dgv.EndEdit(); - newIndex = oldIndex; - switch (action) - { - case RowMoveAction.Top: newIndex = 0; break; - case RowMoveAction.Up: newIndex = Math.Max(0, oldIndex - 1); break; - case RowMoveAction.Down: newIndex = Math.Min(dataCount - 1, oldIndex + 1); break; - case RowMoveAction.Bottom: newIndex = dataCount - 1; break; - case RowMoveAction.To: - string input = ShowInputDialog("移动到", - "请输入目标行号(1-" + dataCount + "):", (oldIndex + 1).ToString()); - if (string.IsNullOrEmpty(input)) { newIndex = -1; return; } - int target; - if (!int.TryParse(input.Trim(), out target)) - { - MessageBox.Show(this, "请输入有效数字。", "移动到", MessageBoxButtons.OK, MessageBoxIcon.Warning); - newIndex = -1; - return; - } - newIndex = Math.Max(0, Math.Min(dataCount - 1, target - 1)); - break; - } - if (newIndex == oldIndex) { newIndex = -1; return; } - - DataRow rowToMove = table.Rows[oldIndex]; - object[] savedValues = rowToMove.ItemArray; - table.Rows.Remove(rowToMove); - DataRow newRow = table.NewRow(); - newRow.ItemArray = savedValues; - table.Rows.InsertAt(newRow, newIndex); - - if (table.Columns.Contains("序号")) - { - for (int i = 0; i < table.Rows.Count; i++) table.Rows[i]["序号"] = (i + 1).ToString(); - } - if (dgv == this.advancedDataGridView9) - SaveTableToDatabase(table, _currentProjectId, TuhaoTableName, null, null, true); - else - SaveTableToDatabase(table, _currentProjectId, "\"" + table.TableName + "\"", null, null, true); - } - catch (Exception ex) - { - MessageBox.Show(this, "移动行失败:\n" + ex.Message, "移动行", MessageBoxButtons.OK, MessageBoxIcon.Error); - newIndex = -1; - } - finally - { - _isReloading = false; - if (newIndex >= 0) - { - if (dgv == this.advancedDataGridView9) - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - else if (dgv == this.advancedDataGridView4) - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - else if (dgv == this.advancedDataGridView5) - SelectRowByValue(this.advancedDataGridView5, "序号", (newIndex + 1).ToString()); - } - } - } - - private void MoveLastRowBelowSelected(DataGridView dgv, DataTable table, - int afterIndex, string dbTableName, string projectId) - { - if (dgv == null || table == null || afterIndex < 0 || table.Rows.Count < 2) return; - int lastIndex = table.Rows.Count - 1; - int targetIndex = afterIndex + 1; - if (targetIndex >= lastIndex) return; - object[] savedValues = table.Rows[lastIndex].ItemArray; - table.Rows.RemoveAt(lastIndex); - DataRow newRow = table.NewRow(); - newRow.ItemArray = savedValues; - table.Rows.InsertAt(newRow, targetIndex); - if (table.Columns.Contains("序号")) - { - for (int i = 0; i < table.Rows.Count; i++) table.Rows[i]["序号"] = (i + 1).ToString(); - } - SaveTableToDatabase(table, projectId, dbTableName, null, null, true); - try { if (targetIndex < dgv.Rows.Count) dgv.FirstDisplayedScrollingRowIndex = targetIndex; } catch { } - } - - // ---------- 图号菜单事件 ---------- - - private void MenuTuhao_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) - { - MessageBox.Show(this, "请先在项目表中双击选择一个项目,再新建图号。", - "新建图号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string newTuhao = "新图号" + GetNextSeqNumber(TuhaoTableName, "图号", _currentProjectId); - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView9); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertTuhao(_currentProjectId, newTuhao, "", ""); - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - ReloadTuhaoByProject(_currentProjectId); - MoveLastRowBelowSelected(this.advancedDataGridView9, _tuhaoTable, selectedIndex, TuhaoTableName, _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建图号失败:\n" + ex.Message, - "新建图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = newTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", newTuhao); - _isReloading = false; - ReloadXianghaoByTuhao(_currentProjectId, newTuhao); - } - } - - private void MenuTuhao_Delete_Click(object sender, EventArgs e) - { - var rows = GetAllSelectedRows(this.advancedDataGridView9); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的图号。", - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var tuhaos = new List(); - foreach (var r in rows) - { - string th = GetCellValueAsString(r, "图号"); - if (!string.IsNullOrWhiteSpace(th) && !tuhaos.Contains(th)) tuhaos.Add(th); - } - if (tuhaos.Count == 0) - { - MessageBox.Show(this, "选中行没有图号,无法删除。", - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // ★ 收集选中图号行自己的框Handle - var frameHandles = new List(); - foreach (var r in rows) - { - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - // ★ 收集每个图号下所有箱号和元件的框Handle(级联删框) - foreach (string tuhao in tuhaos) - { - CollectFrameHandlesForTuhao(_currentProjectId, tuhao, frameHandles); - } - Log("[MenuTuhao_Delete] 删除图号: " + string.Join(",", tuhaos) + " 收集到框Handle数: " + frameHandles.Count); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string tuhao in tuhaos) - { - DeleteTuhao(_currentProjectId, tuhao); - if (!string.IsNullOrEmpty(tuhao)) - { - _xianghaoCache.Remove(tuhao); - var keysToRemove = new List(); - foreach (var key in _yuanjianCache.Keys) - if (key.StartsWith(tuhao + "\n")) keysToRemove.Add(key); - foreach (var key in keysToRemove) _yuanjianCache.Remove(key); - } - } - RenumberTable(_currentProjectId, TuhaoTableName); - ReloadTuhaoByProject(_currentProjectId); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重) - var tuhaoDistinct = new HashSet(frameHandles); - foreach (string h in tuhaoDistinct) - { - Log("[MenuTuhao_Delete] 准备删除框Handle: " + h); - DeleteFrameByHandle(h); - } - Log("[MenuTuhao_Delete] 框实体删除完成,共 " + tuhaoDistinct.Count + " 个"); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除图号失败:\n" + ex.Message, - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally { _isReloading = false; } - } - - // ---------- 箱号菜单事件 ---------- - - private void MenuXianghao_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || string.IsNullOrWhiteSpace(_currentTuhao)) - { - MessageBox.Show(this, "请先选择图号,再新建箱号。", - "新建箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string rememberTuhao = _currentTuhao; - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView4); - string newXh = "新箱号" + GetXianghaoCount(_currentProjectId, _currentTuhao); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertXianghao(_currentProjectId, _currentTuhao, newXh, "", ""); - if (!string.IsNullOrEmpty(rememberTuhao)) _xianghaoCache.Remove(rememberTuhao); - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - if (_xianghaoTable != null) - MoveLastRowBelowSelected(this.advancedDataGridView4, _xianghaoTable, selectedIndex, - "\"" + _xianghaoTable.TableName + "\"", _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建箱号失败:\n" + ex.Message, - "新建箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = newXh; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", newXh); - _isReloading = false; - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, newXh); - } - } - - private void MenuXianghao_Delete_Click(object sender, EventArgs e) - { - var rows = GetAllSelectedRows(this.advancedDataGridView4); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的箱号。", - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var xhs = new List(); - foreach (var r in rows) - { - string xh = GetCellValueAsString(r, "箱号"); - if (!string.IsNullOrWhiteSpace(xh) && !xhs.Contains(xh)) xhs.Add(xh); - } - if (xhs.Count == 0) - { - MessageBox.Show(this, "选中行没有箱号,无法删除。", - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // ★ 收集选中箱号行自己的框Handle - var frameHandles = new List(); - foreach (var r in rows) - { - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - // ★ 收集每个箱号下元件表的框Handle(级联删框) - foreach (string xh in xhs) - { - CollectFrameHandlesForXianghao(_currentProjectId, _currentTuhao, xh, frameHandles); - } - Log("[MenuXianghao_Delete] 删除箱号: " + string.Join(",", xhs) + " 图号=" + _currentTuhao + " 收集到框Handle数: " + frameHandles.Count); - string rememberTuhao = _currentTuhao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string xh in xhs) - { - DeleteXianghao(_currentProjectId, _currentTuhao, xh); - string yjKey = _currentTuhao + "\n" + xh; - _yuanjianCache.Remove(yjKey); - } - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, _currentTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - if (!string.IsNullOrEmpty(_currentTuhao)) _xianghaoCache.Remove(_currentTuhao); - Log("[MenuXianghao_Delete] 开始 ReloadXianghaoByTuhao..."); - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - Log("[MenuXianghao_Delete] ReloadXianghaoByTuhao 完成,开始删除框实体..."); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重,避免重复删除) - var distinctHandles = new HashSet(frameHandles); - foreach (string h in distinctHandles) - { - Log("[MenuXianghao_Delete] 准备删除框Handle: " + h); - DeleteFrameByHandle(h); - } - Log("[MenuXianghao_Delete] 框实体删除完成,共 " + distinctHandles.Count + " 个"); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - Log("[MenuXianghao_Delete] 异常: " + ex.Message + "\n" + ex.StackTrace); - MessageBox.Show(this, "删除箱号失败:\n" + ex.Message, - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - _isReloading = false; - } - } - - // ---------- 元件菜单事件 ---------- - - private void MenuYuanjian_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再新建元件。", - "新建元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView5); - string newName = "新元件" + GetYuanjianCount(_currentProjectId, _currentTuhao, _currentXianghao); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertYuanjian(_currentProjectId, _currentTuhao, _currentXianghao, newName); - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - if (_yuanjianTable != null) - MoveLastRowBelowSelected(this.advancedDataGridView5, _yuanjianTable, selectedIndex, - "\"" + _yuanjianTable.TableName + "\"", _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建元件失败:\n" + ex.Message, - "新建元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - private void MenuYuanjian_Delete_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再删除元件。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var rows = GetAllSelectedRows(this.advancedDataGridView5); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的元件。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var seqs = new List(); - var frameHandles = new List(); - foreach (var r in rows) - { - string seq = GetCellValueAsString(r, "序号"); - if (!string.IsNullOrWhiteSpace(seq) && !seqs.Contains(seq)) seqs.Add(seq); - // ★ 收集元件行的框Handle - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - if (seqs.Count == 0) - { - MessageBox.Show(this, "选中行没有序号,无法删除。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string seq in seqs) - DeleteYuanjian(_currentProjectId, _currentTuhao, _currentXianghao, seq); - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重) - foreach (string h in new HashSet(frameHandles)) DeleteFrameByHandle(h); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除元件失败:\n" + ex.Message, - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - // ============================================================ - // 合并元件:把选中的多行元件合并为一行 - // · 元件名称:所有非空名称直接拼接(去重,不加符号) - // · 规格:所有非空规格直接拼接(去重,不加符号) - // · 数量:保持为 1(合并后是一个元件,数量不变) - // · 其他列(单位/系数/价格):取第一行 - // · 删除被合并的其他行,重新编号,保存刷新 - // ============================================================ - /// 按框Handle集合选中元件表中的行(多选,滚动到第一行)。 - private void SelectYuanjianRowsByFrameHandles(List frameHandles) - { - var dgv = this.advancedDataGridView5; - if (dgv == null || frameHandles == null || frameHandles.Count == 0) return; - try - { - dgv.MultiSelect = true; - if (dgv.SelectionMode != DataGridViewSelectionMode.RowHeaderSelect && - dgv.SelectionMode != DataGridViewSelectionMode.FullRowSelect) - { - dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - } - dgv.ClearSelection(); - DataGridViewRow first = null; - foreach (DataGridViewRow row in dgv.Rows) - { - var drv = row.DataBoundItem as DataRowView; - if (drv == null || drv.Row == null) continue; - if (!drv.Row.Table.Columns.Contains("框Handle")) continue; - object v = drv.Row["框Handle"]; - string h = v != null && v != DBNull.Value ? v.ToString().Trim() : ""; - if (!string.IsNullOrWhiteSpace(h) && frameHandles.Contains(h)) - { - row.Selected = true; - if (first == null) first = row; - } - } - if (first != null && first.DataGridView != null) - first.DataGridView.FirstDisplayedScrollingRowIndex = Math.Max(0, first.Index); - } - catch (Exception ex) { Log("[SelectYuanjianRows] " + ex.Message); } - } - - /// 网页转发的 F1:转到统一入口(焦点在网页时 WinForms 收不到按键)。 - private void OnF1FromBridge() - { - try { RunF1Merge(); } - catch (Exception ex) { Log("[F1桥接] " + ex.Message); } - } - - /// 网页转发的 F2:三个一组配对合并。 - private void OnF2FromBridge() - { - try { MergeYuanjianByGroup(3); } - catch (Exception ex) { Log("[F2桥接] " + ex.Message); } - } - - /// 网页转发的 F3:四个一组配对合并。 - private void OnF3FromBridge() - { - try { MergeYuanjianByGroup(4); } - catch (Exception ex) { Log("[F3桥接] " + ex.Message); } - } - - /// - /// F1:合并元件表中相邻的两个元件(按序号顺序)。 - /// · 选中 ≥2 行 → 合并前两行 - /// · 选中 1 行 → 与它的下一行合并 - /// · 未选中 → 合并第 1、2 行 - /// 合并时网页 CAD 里的蒙版同步合并(保留行蒙版扩大到并集)。 - /// - private void MergeAdjacentYuanjianByF1() - { - MergeYuanjianByGroup(2); - } - - /// 按 groupSize 分组合并选中元件(F1=两两,F2=三个一组)。 - private void MergeYuanjianByGroup(int groupSize) - { - var dgv = this.advancedDataGridView5; - if (dgv == null) return; - var rows = GetAllSelectedRows(dgv); - if (rows == null || rows.Count < groupSize) - { - MessageBox.Show(this, "请先选中至少 " + groupSize + " 行元件(扒元件后会自动全选)。", "合并元件", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - // ★ F1 = 两两配对批量合并(1+2、3+4、5+6...),一次处理完所有选中行; - // 只想合并单独一对时,只选中那一对两行即可。 - // 合并会刷新表格使行对象失效,所以先记下配对的框Handle,再用 Handle 逐对定位。 - var orderedHandles = new List(); - foreach (var r in rows) - { - orderedHandles.Add(GetFrameHandleOfRow(r)); - } - int groups = orderedHandles.Count / groupSize; - int merged = 0; - for (int i = 0; i < groups; i++) - { - var groupRows = new List(); - var groupHandles = new List(); - for (int k = 0; k < groupSize; k++) - { - string h = orderedHandles[i * groupSize + k]; - if (string.IsNullOrWhiteSpace(h)) { groupRows = null; break; } - var rowK = FindRowByFrameHandle(dgv, h); - if (rowK == null) { groupRows = null; break; } - groupRows.Add(rowK); - groupHandles.Add(h); - } - if (groupRows == null) continue; - // 组内若含重复行(同句柄)跳过 - if (new HashSet(groupHandles).Count != groupSize) continue; - MergeYuanjianRows(groupRows); - merged++; - } - Log("[F1批量] " + groupSize + " 个一组配对合并完成: " + merged + "/" + groups + " 组"); - } - - /// 读行的框Handle:优先 DataRow("框Handle"可能不在显示列,Cells 读不到)。 - private static string GetFrameHandleOfRow(DataGridViewRow row) - { - if (row == null) return ""; - var drv = row.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - return v == null || v == DBNull.Value ? "" : v.ToString().Trim(); - } - return GetCellValueAsString(row, "框Handle"); - } - - /// 按框Handle在元件表中找行(找不到返回 null)。 - private DataGridViewRow FindRowByFrameHandle(DataGridView dgv, string frameHandle) - { - if (string.IsNullOrWhiteSpace(frameHandle)) return null; - foreach (DataGridViewRow row in dgv.Rows) - { - if (row == null || row.IsNewRow) continue; - string h = GetFrameHandleOfRow(row); - if (!string.IsNullOrWhiteSpace(h) && h == frameHandle) return row; - } - return null; - } - - /// 合并指定行(按序号排序):第一行为合并目标,其余删除;蒙版同步合并。 - private void MergeYuanjianRows(List rows) - { - // 按序号排序(保证合并顺序与表格顺序一致) - rows.Sort((a, b) => - { - int ia = 0, ib = 0; - int.TryParse(GetCellValueAsString(a, "序号"), out ia); - int.TryParse(GetCellValueAsString(b, "序号"), out ib); - return ia.CompareTo(ib); - }); - - // 收集要合并的内容(直接拼接,不加任何符号) - var names = new List(); - var specs = new List(); - foreach (var r in rows) - { - string nm = GetCellValueAsString(r, "元件名称"); - if (!string.IsNullOrWhiteSpace(nm) && !names.Contains(nm)) names.Add(nm); - string sp = GetCellValueAsString(r, "规格"); - if (!string.IsNullOrWhiteSpace(sp) && !specs.Contains(sp)) specs.Add(sp); - } - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - string keepHandle = GetFrameHandleOfRow(rows[0]); - var absorbedHandles = new List(); - for (int i = 1; i < rows.Count; i++) - { - string h = GetFrameHandleOfRow(rows[i]); - if (!string.IsNullOrWhiteSpace(h)) absorbedHandles.Add(h); - } - - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - - if (_yuanjianTable == null || _yuanjianTable.Rows.Count == 0) - { - MessageBox.Show(this, "元件表为空,无法合并。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 取出选中行对应的 DataRow - var dataRows = new List(); - foreach (var dgvRow in rows) - { - var drv = dgvRow.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null) dataRows.Add(drv.Row); - } - if (dataRows.Count < 2) - { - MessageBox.Show(this, "无法获取选中行的数据,请重试。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 第一行作为合并目标,更新名称/规格(直接拼接,不加任何符号) - // 数量保持为 1(合并后是一个元件) - DataRow target = dataRows[0]; - if (_yuanjianTable.Columns.Contains("元件名称")) - target["元件名称"] = string.Join("", names); - if (_yuanjianTable.Columns.Contains("规格")) - target["规格"] = string.Join("", specs); - if (_yuanjianTable.Columns.Contains("数量")) - target["数量"] = "1"; - - // 删除其他被合并的行 - for (int i = 1; i < dataRows.Count; i++) - { - dataRows[i].Delete(); - } - - // 保存到数据库 - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + realTbl + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - } - - // ★ 网页 CAD 蒙版同步合并:保留行蒙版扩大到并集,被合并行蒙版移除 - if (!string.IsNullOrWhiteSpace(keepHandle) && absorbedHandles.Count > 0) - { - cadbt.CadBridge.MergeMasks(keepHandle, absorbedHandles); - Log("[MergeYuanjianRows] 蒙版合并: 保留=" + keepHandle); - } - - // 刷新缓存与表格 - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "合并元件失败:\n" + ex.Message, - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - _isReloading = false; - // ★ 合并后的行保持选中(连续按 F1 可继续与下一行合并): - // 延迟到刷新事件链走完再选,否则会被清掉 - if (!string.IsNullOrWhiteSpace(keepHandle)) - { - var kh = keepHandle; - BeginInvoke((Action)(() => - { - BeginInvoke((Action)(() => - { - SelectYuanjianRowsByFrameHandles(new List { kh }); - })); - })); - } - } - } - - private void MenuYuanjian_Merge_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再合并元件。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var rows = GetAllSelectedRows(this.advancedDataGridView5); - if (rows == null || rows.Count < 2) - { - MessageBox.Show(this, "请先选择至少两行要合并的元件(按住 Ctrl/Shift 多选)。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - // 按序号排序(保证合并顺序与表格顺序一致) - rows.Sort((a, b) => - { - int ia = 0, ib = 0; - int.TryParse(GetCellValueAsString(a, "序号"), out ia); - int.TryParse(GetCellValueAsString(b, "序号"), out ib); - return ia.CompareTo(ib); - }); - - // 收集要合并的内容(直接拼接,不加任何符号) - var names = new List(); - var specs = new List(); - foreach (var r in rows) - { - string nm = GetCellValueAsString(r, "元件名称"); - if (!string.IsNullOrWhiteSpace(nm) && !names.Contains(nm)) names.Add(nm); - string sp = GetCellValueAsString(r, "规格"); - if (!string.IsNullOrWhiteSpace(sp) && !specs.Contains(sp)) specs.Add(sp); - } - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - - if (_yuanjianTable == null || _yuanjianTable.Rows.Count == 0) - { - MessageBox.Show(this, "元件表为空,无法合并。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 取出选中行对应的 DataRow - var dataRows = new List(); - foreach (var dgvRow in rows) - { - var drv = dgvRow.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null) dataRows.Add(drv.Row); - } - if (dataRows.Count < 2) - { - MessageBox.Show(this, "无法获取选中行的数据,请重试。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 第一行作为合并目标,更新名称/规格(直接拼接,不加符号) - // 数量保持为 1(合并后是一个元件) - DataRow target = dataRows[0]; - if (_yuanjianTable.Columns.Contains("元件名称")) - target["元件名称"] = string.Join("", names); - if (_yuanjianTable.Columns.Contains("规格")) - target["规格"] = string.Join("", specs); - if (_yuanjianTable.Columns.Contains("数量")) - target["数量"] = "1"; - - // ★ 收集被合并行(第2行起)的框Handle,合并后删除这些框 - var mergedFrameHandles = new List(); - if (_yuanjianTable.Columns.Contains("框Handle")) - { - for (int i = 1; i < dataRows.Count; i++) - { - object v = dataRows[i]["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) mergedFrameHandles.Add(h); - } - } - } - - // 删除其他被合并的行 - for (int i = 1; i < dataRows.Count; i++) - { - dataRows[i].Delete(); - } - - // 保存到数据库 - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + realTbl + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - } - - // ★ 删除被合并行的框实体 - foreach (string h in mergedFrameHandles) DeleteFrameByHandle(h); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - - // 刷新缓存与表格 - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "合并元件失败:\n" + ex.Message, - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - // ============================================================ - // 工具栏:新建项目 / 删除项目 / 导出数据 - // ============================================================ - - private void toolStripButton5_Click(object sender, EventArgs e) - { - // 用自定义对话框收集项目信息字段(无主项目的"新建项目"窗体可用) - var fields = ShowNewProjectDialog(); - if (fields == null) return; - try - { - int affected = InsertProjectToDatabase(fields); - if (affected <= 0) - { - MessageBox.Show(this, "未写入任何字段,请检查输入。", - "新建项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - ReloadProjectsFromDatabase(); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - } - catch (Exception ex) - { - MessageBox.Show(this, "保存项目失败:\n" + ex.Message, - "新建项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - /// 弹出新建项目窗口,收集项目信息 + 价格格式化配置。 - private Dictionary ShowNewProjectDialog() - { - string dbPath = GetDbFullPath(ProjectsDbPath); - using (var dlg = new 新建项目(dbPath, ProjectsTableName)) - { - if (dlg.ShowDialog(this) != DialogResult.OK) return null; - return dlg.GetInputValues(); - } - } - - private void toolStripButton6_Click(object sender, EventArgs e) - { - DataGridViewRow row = GetFirstSelectedProjectRow(); - if (row == null) - { - MessageBox.Show(this, "请先在项目表格中选择要删除的项目。", - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string projectId = GetCellValueAsString(row, "项目编号"); - if (string.IsNullOrWhiteSpace(projectId)) - { - MessageBox.Show(this, "选中行没有“项目编号”,无法定位要删除的数据库记录。", - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - DialogResult dr = MessageBox.Show(this, - "确定要删除项目编号为 “" + projectId + "” 的项目吗?\n" + - "该项目下的所有图号/箱号/元件数据也会一并删除!\n此操作不可恢复。", - "删除项目", MessageBoxButtons.YesNo, MessageBoxIcon.Question, - MessageBoxDefaultButton.Button2); - if (dr != DialogResult.Yes) return; - try - { - int affected = DeleteProjectFromDatabase(projectId); - CascadeDeleteByProject(projectId); - _currentProjectId = ""; - _currentTuhao = ""; - _currentXianghao = ""; - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - _tuhaoTable = null; - ReloadProjectsFromDatabase(); - ReloadTuhaoByProject(""); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除项目失败:\n" + ex.Message, - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - // ---------- 项目表查找(button28)---------- - - private void button28_Click(object sender, EventArgs e) - { - string field = this.comboBox2.Text == null ? "" : this.comboBox2.Text.Trim(); - string colName = MapSearchFieldToColumn(field); - if (string.IsNullOrEmpty(colName)) - { - MessageBox.Show(this, - "请先在搜索条件下拉框中选择有效的搜索字段(项目名称 / 项目编号 / 客户名称)。", - "查找", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string keyword = this.textBox1.Text == null ? "" : this.textBox1.Text.Trim(); - DataTable table = this.advancedDataGridView6.DataSource as DataTable; - if (table == null) - { - MessageBox.Show(this, "项目表暂无数据,无法搜索。", "查找", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - if (keyword.Length == 0) - { - if (table.DefaultView.RowFilter.Length > 0) table.DefaultView.RowFilter = ""; - return; - } - string escaped = EscapeLikeValue(keyword); - try { table.DefaultView.RowFilter = "[" + colName + "] LIKE '%" + escaped + "%'"; } - catch (System.Data.SyntaxErrorException ex) - { - MessageBox.Show(this, "搜索条件解析失败,请检查输入的关键词。\n详情:" + ex.Message, - "查找", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - if (table.DefaultView.Count == 0) - { - MessageBox.Show(this, "没有找到 " + field + " 包含 “" + keyword + "” 的项目。", - "查找", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - - private static string MapSearchFieldToColumn(string field) - { - if (string.IsNullOrEmpty(field)) return ""; - string f = field.Replace(" ", "").Trim(); - if (f == "项目名称" || f == "名称") return "项目名称"; - if (f == "项目编号" || f == "编号") return "项目编号"; - if (f == "客户名称" || f == "客户") return "客户名称"; - return ""; - } - - private static string EscapeLikeValue(string value) - { - if (string.IsNullOrEmpty(value)) return ""; - var sb = new System.Text.StringBuilder(value.Length * 2); - foreach (char c in value) - { - if (c == '\'') sb.Append("''"); - else if (c == '%' || c == '_' || c == '[' || c == ']') sb.Append('[').Append(c).Append(']'); - else sb.Append(c); - } - return sb.ToString(); - } - - // ---------- 导出数据(toolStripButton1)---------- - - private void toolStripButton1_Click(object sender, EventArgs e) - { - string pid = ""; - try - { - var projects = ReadAllProjectsFromDatabase(); - if (projects == null || projects.Count == 0) - { - MessageBox.Show(this, "项目列表为空,无项目可导出。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - if (projects.Count == 1) - { - pid = projects[0].ContainsKey("项目编号") ? (projects[0]["项目编号"] ?? "").ToString() : ""; - } - else - { - pid = PickProjectDialog(projects); - if (string.IsNullOrWhiteSpace(pid)) return; - } - if (string.IsNullOrWhiteSpace(pid)) - { - MessageBox.Show(this, "未能确定要导出的项目编号。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 先保存当前项目的所有改动 - SaveAllToDatabaseSilent(); - - string dbPath = GetQuoteDbPath(pid); - if (!File.Exists(dbPath)) - { - MessageBox.Show(this, "项目数据库文件不存在:\n" + dbPath, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - var meta = ReadProjectMetaData(pid); - if (meta == null) - { - MessageBox.Show(this, "项目元数据读取失败,项目编号:" + pid, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - string projName = meta.ContainsKey("项目名称") ? (meta["项目名称"] ?? "").ToString() : ""; - string safeName = MakeSafeFileName(projName + "_" + pid); - string defaultFileName = safeName + "_" + DateTime.Now.ToString("yyyyMMdd") + ".zip"; - - string initialDir = ""; - try - { - string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - if (!string.IsNullOrEmpty(desktop) && Directory.Exists(desktop)) initialDir = desktop; - } - catch { } - if (string.IsNullOrEmpty(initialDir)) - { - try - { - string docs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - if (!string.IsNullOrEmpty(docs) && Directory.Exists(docs)) initialDir = docs; - } - catch { } - } - - // ★ 打包到临时 zip(不弹保存对话框,直接联动主窗口) - string tempZip = Path.Combine(Path.GetTempPath(), "cadcj_导出_" + Guid.NewGuid().ToString("N") + ".zip"); - string tempDir = Path.Combine(Path.GetTempPath(), "cadcj_导出_" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(tempDir); - try - { - // 复制 db(用 SQL ATTACH 绕开文件锁,兜底 File.Copy) - string dstDb = Path.Combine(tempDir, "项目" + MakeSafeFileName(pid) + ".db"); - BackupSQLiteDb(dbPath, dstDb); - - // 写 meta.json - var sb = new System.Text.StringBuilder(); - sb.Append("{\n \"项目编号\": \""); - sb.Append(EscapeJsonString(pid)); - sb.Append("\",\n \"字段\": {"); - bool firstKv = true; - foreach (var kv in meta) - { - if (firstKv) firstKv = false; else sb.Append(","); - sb.Append("\n \""); - sb.Append(EscapeJsonString(kv.Key)); - sb.Append("\": \""); - sb.Append(EscapeJsonString((kv.Value ?? "").ToString())); - sb.Append("\""); - } - sb.Append("\n }\n}"); - File.WriteAllText(Path.Combine(tempDir, "meta.json"), sb.ToString(), new System.Text.UTF8Encoding(false)); - - // 打包 zip - if (File.Exists(tempZip)) File.Delete(tempZip); - System.IO.Compression.ZipFile.CreateFromDirectory(tempDir, tempZip); - - // ★ 查找主窗口 exe(cadcj 目录的上级目录) - string mainExePath = null; - try - { - string pluginDir = Path.GetDirectoryName( - new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath); - string parentDir = Path.GetFullPath(Path.Combine(pluginDir, "..")); - string candidate = Path.Combine(parentDir, "成套报价软件.exe"); - if (File.Exists(candidate)) mainExePath = candidate; - } - catch { } - - if (!string.IsNullOrEmpty(mainExePath)) - { - // ★ 启动主窗口并传递 zip 路径,主窗口自动导入并打开项目 - var psi = new System.Diagnostics.ProcessStartInfo - { - FileName = mainExePath, - Arguments = "\"" + tempZip + "\"", - UseShellExecute = true, - }; - System.Diagnostics.Process.Start(psi); - MessageBox.Show(this, - "已发送到主窗口!\n\n项目:" + projName + " (" + pid + ")\n主程序已打开该项目(若主程序未开会自动启动)。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - else - { - // ★ 找不到主窗口 exe,退回到保存对话框模式 - using (var sfd = new SaveFileDialog - { - Title = "导出项目", - Filter = "项目包 (*.zip)|*.zip", - FileName = defaultFileName, - RestoreDirectory = true, - }) - { - if (!string.IsNullOrEmpty(initialDir)) sfd.InitialDirectory = initialDir; - if (sfd.ShowDialog(this) != DialogResult.OK) return; - string zipPath = sfd.FileName; - File.Copy(tempZip, zipPath, true); - MessageBox.Show(this, - "导出成功!\n\n项目:" + projName + " (" + pid + ")\n文件:" + zipPath + - "\n\n(未找到主窗口程序,已保存为zip文件,可手动导入)", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - } - finally - { - try { Directory.Delete(tempDir, true); } catch { } - // 临时 zip 不立即删除(主窗口可能正在读取) - } - } - catch (Exception ex) - { - MessageBox.Show(this, "导出失败:\n" + ex.Message, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - /// 用 SQL ATTACH 复制 SQLite 库,兜底 File.Copy。 - private void BackupSQLiteDb(string srcDbPath, string dstDbPath) - { - try { if (File.Exists(dstDbPath)) File.Delete(dstDbPath); } catch { } - Exception sqlErr = null; - try - { - using (var srcConn = new System.Data.SQLite.SQLiteConnection( - "Data Source=" + srcDbPath + ";Version=3;Pooling=False;ReadOnly=True;")) - { - srcConn.Open(); - using (var att = new System.Data.SQLite.SQLiteCommand("ATTACH DATABASE @path AS dst;", srcConn)) - { - att.Parameters.AddWithValue("@path", dstDbPath); - att.ExecuteNonQuery(); - } - string selAll = "SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"; - var tables = new List>(); - using (var sel = new System.Data.SQLite.SQLiteCommand(selAll, srcConn)) - using (var rd = sel.ExecuteReader()) - { - while (rd.Read()) - { - string tn = rd.IsDBNull(0) ? "" : rd.GetString(0); - string sql = rd.IsDBNull(1) ? "" : rd.GetString(1); - if (!string.IsNullOrEmpty(tn)) tables.Add(new KeyValuePair(tn, sql)); - } - } - foreach (var kv in tables) - { - string tn = kv.Key; - string sql = kv.Value; - if (!string.IsNullOrEmpty(sql)) - { - string dstSql = sql.Replace("CREATE TABLE " + tn, "CREATE TABLE dst." + tn); - using (var c = new System.Data.SQLite.SQLiteCommand(dstSql, srcConn)) c.ExecuteNonQuery(); - } - using (var c = new System.Data.SQLite.SQLiteCommand( - "INSERT INTO dst.\"" + tn + "\" SELECT * FROM main.\"" + tn + "\";", srcConn)) - c.ExecuteNonQuery(); - } - using (var det = new System.Data.SQLite.SQLiteCommand("DETACH DATABASE dst;", srcConn)) - det.ExecuteNonQuery(); - return; - } - } - catch (Exception ex) { sqlErr = ex; } - // 兜底:File.Copy - try { System.Data.SQLite.SQLiteConnection.ClearAllPools(); } catch { } - try { if (File.Exists(dstDbPath)) File.Delete(dstDbPath); } catch { } - File.Copy(srcDbPath, dstDbPath, true); - } - - /// 弹出一个简单对话框,让用户从项目列表中选一个项目,返回项目编号。 - private string PickProjectDialog(List> projects) - { - try - { - using (var dlg = new Form - { - Text = "选择要导出的项目", - StartPosition = FormStartPosition.CenterParent, - FormBorderStyle = FormBorderStyle.FixedDialog, - MaximizeBox = false, - MinimizeBox = false, - ClientSize = new Size(520, 360), - }) - { - var lbl = new Label - { - Text = "请选择要导出的项目:", - Location = new Point(12, 12), - Size = new Size(496, 23), - TextAlign = ContentAlignment.MiddleLeft, - }; - dlg.Controls.Add(lbl); - var lv = new ListView - { - Location = new Point(12, 40), - Size = new Size(496, 260), - View = View.Details, - FullRowSelect = true, - MultiSelect = false, - HideSelection = false, - }; - lv.Columns.Add("项目编号", 100); - lv.Columns.Add("项目名称", 160); - lv.Columns.Add("客户名称", 130); - lv.Columns.Add("项目日期", 90); - foreach (var p in projects) - { - string bh = p.ContainsKey("项目编号") ? (p["项目编号"] ?? "").ToString() : ""; - string mc = p.ContainsKey("项目名称") ? (p["项目名称"] ?? "").ToString() : ""; - string kh = p.ContainsKey("客户名称") ? (p["客户名称"] ?? "").ToString() : ""; - string rq = p.ContainsKey("项目日期") ? (p["项目日期"] ?? "").ToString() : ""; - var item = new ListViewItem(bh); - item.SubItems.Add(mc); - item.SubItems.Add(kh); - item.SubItems.Add(rq); - lv.Items.Add(item); - } - if (lv.Items.Count > 0) lv.Items[0].Selected = true; - dlg.Controls.Add(lv); - var btnOk = new Button - { - Text = "导出选中项", - DialogResult = DialogResult.OK, - Location = new Point(330, 310), - Size = new Size(85, 28), - }; - dlg.Controls.Add(btnOk); - var btnCancel = new Button - { - Text = "取消", - DialogResult = DialogResult.Cancel, - Location = new Point(425, 310), - Size = new Size(75, 28), - }; - dlg.Controls.Add(btnCancel); - dlg.AcceptButton = btnOk; - dlg.CancelButton = btnCancel; - if (dlg.ShowDialog(this) == DialogResult.OK && lv.SelectedItems.Count > 0) - return lv.SelectedItems[0].Text; - return ""; - } - } - catch { return ""; } - } - - // ============================================================ - // 窗体关闭:回写当前项目的所有改动 - // ============================================================ - - private void Form3_Disposed(object sender, EventArgs e) - { - try { SaveAllToDatabaseSilent(); } - catch { } - - // ★ 取消 CadBridge 事件订阅,避免事件泄漏 - try - { - cadbt.CadBridge.EntityErased -= Database_ObjectErased; - cadbt.CadBridge.PaPicked -= OnPaTextsPicked; - cadbt.CadBridge.F1Requested -= OnF1FromBridge; - cadbt.CadBridge.F2Requested -= OnF2FromBridge; - cadbt.CadBridge.F3Requested -= OnF3FromBridge; - } - catch { } - } - } -} diff --git a/cadbt/cadbt/Plugin/Form3.ui.cs b/cadbt/cadbt/Plugin/Form3.ui.cs deleted file mode 100644 index f2db1ef..0000000 --- a/cadbt/cadbt/Plugin/Form3.ui.cs +++ /dev/null @@ -1,1404 +0,0 @@ -namespace MyApp -{ - public partial class Form3 : System.Windows.Forms.Form - { - /// 必需的设计器变量。 - private System.ComponentModel.IContainer components = null; - - /// 清理正在使用的资源。 - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows 窗体设计器生成的代码 - - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - - this.tabControl2 = new System.Windows.Forms.TabControl(); - this.tabPage3 = new System.Windows.Forms.TabPage(); - this.advancedDataGridView6 = new Zuby.ADGV.AdvancedDataGridView(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView6)).BeginInit(); - this.panel1 = new System.Windows.Forms.Panel(); - this.button28 = new System.Windows.Forms.Button(); - this.textBox1 = new System.Windows.Forms.TextBox(); - this.comboBox2 = new System.Windows.Forms.ComboBox(); - this.tabPage4 = new System.Windows.Forms.TabPage(); - this.splitContainer2 = new System.Windows.Forms.SplitContainer(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); - this.advancedDataGridView9 = new Zuby.ADGV.AdvancedDataGridView(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView9)).BeginInit(); - this.splitContainer3 = new System.Windows.Forms.SplitContainer(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); - this.advancedDataGridView4 = new Zuby.ADGV.AdvancedDataGridView(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView4)).BeginInit(); - this.advancedDataGridView5 = new Zuby.ADGV.AdvancedDataGridView(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView5)).BeginInit(); - this.toolStrip1 = new System.Windows.Forms.ToolStrip(); - this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton5 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton6 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton2 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton3 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton4 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton7 = new System.Windows.Forms.ToolStripButton(); - this.SuspendLayout(); - // - // tabControl2 - // - this.tabControl2.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl2.Alignment = System.Windows.Forms.TabAlignment.Top; - this.tabControl2.Appearance = System.Windows.Forms.TabAppearance.Normal; - this.tabControl2.DrawMode = System.Windows.Forms.TabDrawMode.Normal; - this.tabControl2.HotTrack = false; - this.tabControl2.ItemSize = new System.Drawing.Size(60, 21); - this.tabControl2.Multiline = false; - this.tabControl2.Padding = new System.Drawing.Point(6, 3); - this.tabControl2.RightToLeftLayout = false; - this.tabControl2.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; - this.tabControl2.ShowToolTips = false; - this.tabControl2.Enabled = true; - this.tabControl2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.tabControl2.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.tabControl2.MaximumSize = new System.Drawing.Size(0, 0); - this.tabControl2.MinimumSize = new System.Drawing.Size(0, 0); - this.tabControl2.TabIndex = 0; - this.tabControl2.TabStop = true; - this.tabControl2.Name = "tabControl2"; - - // - // tabPage3 - // - this.tabPage3.BackColor = System.Drawing.SystemColors.Control; - this.tabPage3.UseVisualStyleBackColor = true; - this.tabPage3.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.tabPage3.AutoScroll = false; - this.tabPage3.AutoScrollMargin = new System.Drawing.Size(0, 0); - this.tabPage3.AutoScrollMinSize = new System.Drawing.Size(0, 0); - this.tabPage3.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.tabPage3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.tabPage3.ForeColor = System.Drawing.SystemColors.ControlText; - this.tabPage3.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.tabPage3.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.tabPage3.Size = new System.Drawing.Size(479, 717); - this.tabPage3.Text = "项目"; - this.tabPage3.Name = "tabPage3"; - - // - // advancedDataGridView6 - // - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView6.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Window; - this.advancedDataGridView6.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText; - this.advancedDataGridView6.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView6.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView6.DefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView6.DefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView6.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView6.RowHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView6.RowHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView6.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView6.EnableExcelStyleSelection = true; - this.advancedDataGridView6.EnableCellPaste = false; - this.advancedDataGridView6.AllowUserToAddRows = false; - this.advancedDataGridView6.AllowUserToDeleteRows = true; - this.advancedDataGridView6.AllowUserToOrderColumns = false; - this.advancedDataGridView6.AllowUserToResizeColumns = true; - this.advancedDataGridView6.AllowUserToResizeRows = false; - this.advancedDataGridView6.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.None; - this.advancedDataGridView6.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.None; - this.advancedDataGridView6.BackgroundColor = System.Drawing.Color.White; - this.advancedDataGridView6.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.advancedDataGridView6.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.Single; - this.advancedDataGridView6.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithAutoHeaderText; - this.advancedDataGridView6.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView6.ColumnHeadersHeight = 25; - this.advancedDataGridView6.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.EnableResizing; - this.advancedDataGridView6.ColumnHeadersVisible = true; - this.advancedDataGridView6.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystrokeOrF2; - this.advancedDataGridView6.EnableHeadersVisualStyles = false; - this.advancedDataGridView6.GridColor = System.Drawing.SystemColors.ControlDark; - this.advancedDataGridView6.MultiSelect = true; - this.advancedDataGridView6.ReadOnly = true; - this.advancedDataGridView6.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView6.RowHeadersVisible = true; - this.advancedDataGridView6.RowHeadersWidth = 41; - this.advancedDataGridView6.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.EnableResizing; - this.advancedDataGridView6.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.advancedDataGridView6.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect; - this.advancedDataGridView6.ShowCellErrors = true; - this.advancedDataGridView6.ShowCellToolTips = true; - this.advancedDataGridView6.ShowEditingIcon = true; - this.advancedDataGridView6.ShowRowErrors = true; - this.advancedDataGridView6.StandardTab = false; - this.advancedDataGridView6.VirtualMode = false; - this.advancedDataGridView6.Enabled = true; - this.advancedDataGridView6.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.advancedDataGridView6.MaximumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView6.MinimumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView6.TabIndex = 1; - this.advancedDataGridView6.TabStop = true; - this.advancedDataGridView6.Name = "advancedDataGridView6"; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[0].Name = "Column2"; - this.advancedDataGridView6.Columns[0].HeaderText = "项目编号"; - this.advancedDataGridView6.Columns[0].Width = 100; - this.advancedDataGridView6.Columns[0].Visible = true; - this.advancedDataGridView6.Columns[0].ReadOnly = true; - this.advancedDataGridView6.Columns[0].Frozen = false; - this.advancedDataGridView6.Columns[0].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[0].DataPropertyName = "项目编号"; - this.advancedDataGridView6.Columns[0].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[1].Name = "Column3"; - this.advancedDataGridView6.Columns[1].HeaderText = "项目名称"; - this.advancedDataGridView6.Columns[1].Width = 100; - this.advancedDataGridView6.Columns[1].Visible = true; - this.advancedDataGridView6.Columns[1].ReadOnly = true; - this.advancedDataGridView6.Columns[1].Frozen = false; - this.advancedDataGridView6.Columns[1].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[1].DataPropertyName = "项目名称"; - this.advancedDataGridView6.Columns[1].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[2].Name = ""; - this.advancedDataGridView6.Columns[2].HeaderText = "客户名称"; - this.advancedDataGridView6.Columns[2].Width = 100; - this.advancedDataGridView6.Columns[2].Visible = true; - this.advancedDataGridView6.Columns[2].ReadOnly = true; - this.advancedDataGridView6.Columns[2].Frozen = false; - this.advancedDataGridView6.Columns[2].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[2].DataPropertyName = "客户名称"; - this.advancedDataGridView6.Columns[2].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[3].Name = ""; - this.advancedDataGridView6.Columns[3].HeaderText = "客户地址"; - this.advancedDataGridView6.Columns[3].Width = 100; - this.advancedDataGridView6.Columns[3].Visible = true; - this.advancedDataGridView6.Columns[3].ReadOnly = true; - this.advancedDataGridView6.Columns[3].Frozen = false; - this.advancedDataGridView6.Columns[3].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[3].DataPropertyName = "客户地址"; - this.advancedDataGridView6.Columns[3].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[4].Name = ""; - this.advancedDataGridView6.Columns[4].HeaderText = "联系人"; - this.advancedDataGridView6.Columns[4].Width = 100; - this.advancedDataGridView6.Columns[4].Visible = true; - this.advancedDataGridView6.Columns[4].ReadOnly = true; - this.advancedDataGridView6.Columns[4].Frozen = false; - this.advancedDataGridView6.Columns[4].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[4].DataPropertyName = "联系人"; - this.advancedDataGridView6.Columns[4].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[5].Name = ""; - this.advancedDataGridView6.Columns[5].HeaderText = "联系电话"; - this.advancedDataGridView6.Columns[5].Width = 100; - this.advancedDataGridView6.Columns[5].Visible = true; - this.advancedDataGridView6.Columns[5].ReadOnly = true; - this.advancedDataGridView6.Columns[5].Frozen = false; - this.advancedDataGridView6.Columns[5].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[5].DataPropertyName = "联系电话"; - this.advancedDataGridView6.Columns[5].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[6].Name = ""; - this.advancedDataGridView6.Columns[6].HeaderText = "项目日期"; - this.advancedDataGridView6.Columns[6].Width = 100; - this.advancedDataGridView6.Columns[6].Visible = true; - this.advancedDataGridView6.Columns[6].ReadOnly = true; - this.advancedDataGridView6.Columns[6].Frozen = false; - this.advancedDataGridView6.Columns[6].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[6].DataPropertyName = "项目日期"; - this.advancedDataGridView6.Columns[6].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[7].Name = ""; - this.advancedDataGridView6.Columns[7].HeaderText = "箱柜台数"; - this.advancedDataGridView6.Columns[7].Width = 100; - this.advancedDataGridView6.Columns[7].Visible = true; - this.advancedDataGridView6.Columns[7].ReadOnly = true; - this.advancedDataGridView6.Columns[7].Frozen = false; - this.advancedDataGridView6.Columns[7].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[7].DataPropertyName = "箱柜台数"; - this.advancedDataGridView6.Columns[7].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[8].Name = ""; - this.advancedDataGridView6.Columns[8].HeaderText = "成本总价"; - this.advancedDataGridView6.Columns[8].Width = 100; - this.advancedDataGridView6.Columns[8].Visible = true; - this.advancedDataGridView6.Columns[8].ReadOnly = true; - this.advancedDataGridView6.Columns[8].Frozen = false; - this.advancedDataGridView6.Columns[8].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[8].DataPropertyName = "成本总价"; - this.advancedDataGridView6.Columns[8].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[9].Name = ""; - this.advancedDataGridView6.Columns[9].HeaderText = "报出总价"; - this.advancedDataGridView6.Columns[9].Width = 100; - this.advancedDataGridView6.Columns[9].Visible = true; - this.advancedDataGridView6.Columns[9].ReadOnly = true; - this.advancedDataGridView6.Columns[9].Frozen = false; - this.advancedDataGridView6.Columns[9].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[9].DataPropertyName = "报出总价"; - this.advancedDataGridView6.Columns[9].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[10].Name = ""; - this.advancedDataGridView6.Columns[10].HeaderText = "利润"; - this.advancedDataGridView6.Columns[10].Width = 100; - this.advancedDataGridView6.Columns[10].Visible = true; - this.advancedDataGridView6.Columns[10].ReadOnly = true; - this.advancedDataGridView6.Columns[10].Frozen = false; - this.advancedDataGridView6.Columns[10].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[10].DataPropertyName = "利润"; - this.advancedDataGridView6.Columns[10].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[11].Name = ""; - this.advancedDataGridView6.Columns[11].HeaderText = "利润率"; - this.advancedDataGridView6.Columns[11].Width = 100; - this.advancedDataGridView6.Columns[11].Visible = true; - this.advancedDataGridView6.Columns[11].ReadOnly = true; - this.advancedDataGridView6.Columns[11].Frozen = false; - this.advancedDataGridView6.Columns[11].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[11].DataPropertyName = "利润率"; - this.advancedDataGridView6.Columns[11].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView6.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView6.Columns[12].Name = ""; - this.advancedDataGridView6.Columns[12].HeaderText = "备注"; - this.advancedDataGridView6.Columns[12].Width = 100; - this.advancedDataGridView6.Columns[12].Visible = true; - this.advancedDataGridView6.Columns[12].ReadOnly = true; - this.advancedDataGridView6.Columns[12].Frozen = false; - this.advancedDataGridView6.Columns[12].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView6.Columns[12].DataPropertyName = "备注"; - this.advancedDataGridView6.Columns[12].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - - // - // panel1 - // - this.panel1.Dock = System.Windows.Forms.DockStyle.Top; - this.panel1.AutoSize = false; - this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.panel1.TabStop = false; - this.panel1.AutoScroll = false; - this.panel1.AutoScrollMargin = new System.Drawing.Size(0, 0); - this.panel1.AutoScrollMinSize = new System.Drawing.Size(0, 0); - this.panel1.BackColor = System.Drawing.SystemColors.Control; - this.panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.panel1.Enabled = true; - this.panel1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.panel1.ForeColor = System.Drawing.SystemColors.ControlText; - this.panel1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.panel1.MaximumSize = new System.Drawing.Size(0, 0); - this.panel1.MinimumSize = new System.Drawing.Size(0, 0); - this.panel1.TabIndex = 0; - this.panel1.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.panel1.Size = new System.Drawing.Size(473, 28); - this.panel1.Location = new System.Drawing.Point(3, 3); - this.panel1.Name = "panel1"; - - // - // button28 - // - this.button28.Dock = System.Windows.Forms.DockStyle.None; - this.button28.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.button28.DialogResult = System.Windows.Forms.DialogResult.None; - this.button28.AutoEllipsis = false; - this.button28.AutoSize = false; - this.button28.BackColor = System.Drawing.SystemColors.Control; - this.button28.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.button28.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.button28.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.button28.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; - this.button28.UseMnemonic = true; - this.button28.UseCompatibleTextRendering = false; - this.button28.UseVisualStyleBackColor = true; - this.button28.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.button28.Enabled = true; - this.button28.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.button28.ForeColor = System.Drawing.SystemColors.ControlText; - this.button28.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.button28.MaximumSize = new System.Drawing.Size(0, 0); - this.button28.MinimumSize = new System.Drawing.Size(0, 0); - this.button28.TabIndex = 2; - this.button28.TabStop = true; - this.button28.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.button28.Size = new System.Drawing.Size(75, 23); - this.button28.Location = new System.Drawing.Point(335, 2); - this.button28.Text = "查找"; - this.button28.Name = "button28"; - - // - // textBox1 - // - this.textBox1.Dock = System.Windows.Forms.DockStyle.None; - this.textBox1.AcceptsReturn = false; - this.textBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.textBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.textBox1.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.textBox1.Multiline = false; - this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.textBox1.UseSystemPasswordChar = false; - this.textBox1.AcceptsTab = false; - this.textBox1.ShortcutsEnabled = true; - this.textBox1.BackColor = System.Drawing.SystemColors.Window; - this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.textBox1.ForeColor = System.Drawing.SystemColors.WindowText; - this.textBox1.HideSelection = true; - this.textBox1.MaxLength = 32767; - this.textBox1.ReadOnly = false; - this.textBox1.WordWrap = true; - this.textBox1.Enabled = true; - this.textBox1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.textBox1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.textBox1.MaximumSize = new System.Drawing.Size(0, 0); - this.textBox1.MinimumSize = new System.Drawing.Size(0, 0); - this.textBox1.TabIndex = 1; - this.textBox1.TabStop = true; - this.textBox1.Size = new System.Drawing.Size(210, 21); - this.textBox1.Location = new System.Drawing.Point(119, 4); - this.textBox1.Name = "textBox1"; - - // - // comboBox2 - // - this.comboBox2.Dock = System.Windows.Forms.DockStyle.None; - this.comboBox2.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.comboBox2.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.comboBox2.BackColor = System.Drawing.SystemColors.Window; - this.comboBox2.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.comboBox2.DropDownWidth = 108; - this.comboBox2.DropDownHeight = 106; - this.comboBox2.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.comboBox2.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox2.IntegralHeight = true; - this.comboBox2.ItemHeight = 12; - this.comboBox2.MaxDropDownItems = 8; - this.comboBox2.MaximumSize = new System.Drawing.Size(0, 0); - this.comboBox2.MinimumSize = new System.Drawing.Size(0, 0); - this.comboBox2.MaxLength = 0; - this.comboBox2.Sorted = false; - this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.comboBox2.FormattingEnabled = false; - this.comboBox2.Enabled = true; - this.comboBox2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.comboBox2.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.comboBox2.TabIndex = 0; - this.comboBox2.TabStop = true; - this.comboBox2.Size = new System.Drawing.Size(108, 20); - this.comboBox2.Location = new System.Drawing.Point(5, 4); - this.comboBox2.Text = "项目名称"; - this.comboBox2.Name = "comboBox2"; - this.comboBox2.Items.Add("项目名称"); - this.comboBox2.Items.Add("项目编号"); - this.comboBox2.Items.Add("客户名称"); - - // - // tabPage4 - // - this.tabPage4.BackColor = System.Drawing.SystemColors.Control; - this.tabPage4.UseVisualStyleBackColor = true; - this.tabPage4.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.tabPage4.AutoScroll = false; - this.tabPage4.AutoScrollMargin = new System.Drawing.Size(0, 0); - this.tabPage4.AutoScrollMinSize = new System.Drawing.Size(0, 0); - this.tabPage4.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.tabPage4.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.tabPage4.ForeColor = System.Drawing.SystemColors.ControlText; - this.tabPage4.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.tabPage4.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.tabPage4.Size = new System.Drawing.Size(479, 692); - this.tabPage4.Text = "报价"; - this.tabPage4.Name = "tabPage4"; - - // - // splitContainer2 - // - this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.None; - this.splitContainer2.IsSplitterFixed = false; - this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; - this.splitContainer2.Panel1Collapsed = false; - this.splitContainer2.Panel2Collapsed = false; - this.splitContainer2.Panel1MinSize = 25; - this.splitContainer2.Panel2MinSize = 25; - this.splitContainer2.SplitterIncrement = 1; - this.splitContainer2.SplitterWidth = 6; - this.splitContainer2.TabStop = true; - this.splitContainer2.BackColor = System.Drawing.SystemColors.Control; - this.splitContainer2.Enabled = true; - this.splitContainer2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.splitContainer2.ForeColor = System.Drawing.SystemColors.ControlText; - this.splitContainer2.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.splitContainer2.MaximumSize = new System.Drawing.Size(0, 0); - this.splitContainer2.MinimumSize = new System.Drawing.Size(0, 0); - this.splitContainer2.TabIndex = 0; - this.splitContainer2.Name = "splitContainer2"; - - // - // advancedDataGridView9 - // - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView9.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Window; - this.advancedDataGridView9.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText; - this.advancedDataGridView9.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView9.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView9.DefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView9.DefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView9.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView9.RowHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView9.RowHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView9.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView9.EnableExcelStyleSelection = true; - this.advancedDataGridView9.EnableCellPaste = true; - this.advancedDataGridView9.AllowUserToAddRows = false; - this.advancedDataGridView9.AllowUserToDeleteRows = true; - this.advancedDataGridView9.AllowUserToOrderColumns = false; - this.advancedDataGridView9.AllowUserToResizeColumns = true; - this.advancedDataGridView9.AllowUserToResizeRows = false; - this.advancedDataGridView9.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.None; - this.advancedDataGridView9.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.None; - this.advancedDataGridView9.BackgroundColor = System.Drawing.Color.White; - this.advancedDataGridView9.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.advancedDataGridView9.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.Single; - this.advancedDataGridView9.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithAutoHeaderText; - this.advancedDataGridView9.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView9.ColumnHeadersHeight = 35; - this.advancedDataGridView9.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.EnableResizing; - this.advancedDataGridView9.ColumnHeadersVisible = true; - this.advancedDataGridView9.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView9.EnableHeadersVisualStyles = false; - this.advancedDataGridView9.GridColor = System.Drawing.SystemColors.ControlDark; - this.advancedDataGridView9.MultiSelect = true; - this.advancedDataGridView9.ReadOnly = false; - this.advancedDataGridView9.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView9.RowHeadersVisible = true; - this.advancedDataGridView9.RowHeadersWidth = 41; - this.advancedDataGridView9.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.EnableResizing; - this.advancedDataGridView9.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.advancedDataGridView9.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect; - this.advancedDataGridView9.ShowCellErrors = true; - this.advancedDataGridView9.ShowCellToolTips = true; - this.advancedDataGridView9.ShowEditingIcon = true; - this.advancedDataGridView9.ShowRowErrors = true; - this.advancedDataGridView9.StandardTab = false; - this.advancedDataGridView9.VirtualMode = false; - this.advancedDataGridView9.Enabled = true; - this.advancedDataGridView9.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.advancedDataGridView9.MaximumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView9.MinimumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView9.TabIndex = 0; - this.advancedDataGridView9.TabStop = true; - this.advancedDataGridView9.Name = "advancedDataGridView9"; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[0].Name = ""; - this.advancedDataGridView9.Columns[0].HeaderText = "序号"; - this.advancedDataGridView9.Columns[0].Width = 35; - this.advancedDataGridView9.Columns[0].Visible = true; - this.advancedDataGridView9.Columns[0].ReadOnly = false; - this.advancedDataGridView9.Columns[0].Frozen = true; - this.advancedDataGridView9.Columns[0].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; - this.advancedDataGridView9.Columns[0].DataPropertyName = "序号"; - this.advancedDataGridView9.Columns[0].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns[0].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[1].Name = ""; - this.advancedDataGridView9.Columns[1].HeaderText = "图号"; - this.advancedDataGridView9.Columns[1].Width = 100; - this.advancedDataGridView9.Columns[1].Visible = true; - this.advancedDataGridView9.Columns[1].ReadOnly = false; - this.advancedDataGridView9.Columns[1].Frozen = false; - this.advancedDataGridView9.Columns[1].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[1].DataPropertyName = "图号"; - this.advancedDataGridView9.Columns[1].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[2].Name = ""; - this.advancedDataGridView9.Columns[2].HeaderText = "图名"; - this.advancedDataGridView9.Columns[2].Width = 100; - this.advancedDataGridView9.Columns[2].Visible = true; - this.advancedDataGridView9.Columns[2].ReadOnly = false; - this.advancedDataGridView9.Columns[2].Frozen = false; - this.advancedDataGridView9.Columns[2].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[2].DataPropertyName = "图名"; - this.advancedDataGridView9.Columns[2].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[3].Name = ""; - this.advancedDataGridView9.Columns[3].HeaderText = "台数"; - this.advancedDataGridView9.Columns[3].Width = 35; - this.advancedDataGridView9.Columns[3].Visible = true; - this.advancedDataGridView9.Columns[3].ReadOnly = false; - this.advancedDataGridView9.Columns[3].Frozen = false; - this.advancedDataGridView9.Columns[3].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[3].DataPropertyName = "台数"; - this.advancedDataGridView9.Columns[3].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns[3].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[4].Name = ""; - this.advancedDataGridView9.Columns[4].HeaderText = "箱柜数量"; - this.advancedDataGridView9.Columns[4].Width = 35; - this.advancedDataGridView9.Columns[4].Visible = true; - this.advancedDataGridView9.Columns[4].ReadOnly = false; - this.advancedDataGridView9.Columns[4].Frozen = false; - this.advancedDataGridView9.Columns[4].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[4].DataPropertyName = "箱柜数量"; - this.advancedDataGridView9.Columns[4].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns[4].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[5].Name = ""; - this.advancedDataGridView9.Columns[5].HeaderText = "单价"; - this.advancedDataGridView9.Columns[5].Width = 100; - this.advancedDataGridView9.Columns[5].Visible = true; - this.advancedDataGridView9.Columns[5].ReadOnly = false; - this.advancedDataGridView9.Columns[5].Frozen = false; - this.advancedDataGridView9.Columns[5].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[5].DataPropertyName = "单价"; - this.advancedDataGridView9.Columns[5].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[6].Name = ""; - this.advancedDataGridView9.Columns[6].HeaderText = "总价"; - this.advancedDataGridView9.Columns[6].Width = 100; - this.advancedDataGridView9.Columns[6].Visible = true; - this.advancedDataGridView9.Columns[6].ReadOnly = false; - this.advancedDataGridView9.Columns[6].Frozen = false; - this.advancedDataGridView9.Columns[6].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[6].DataPropertyName = "总价"; - this.advancedDataGridView9.Columns[6].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[7].Name = ""; - this.advancedDataGridView9.Columns[7].HeaderText = "成本总价"; - this.advancedDataGridView9.Columns[7].Width = 100; - this.advancedDataGridView9.Columns[7].Visible = true; - this.advancedDataGridView9.Columns[7].ReadOnly = false; - this.advancedDataGridView9.Columns[7].Frozen = false; - this.advancedDataGridView9.Columns[7].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[7].DataPropertyName = "成本总价"; - this.advancedDataGridView9.Columns[7].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[8].Name = ""; - this.advancedDataGridView9.Columns[8].HeaderText = "毛利"; - this.advancedDataGridView9.Columns[8].Width = 100; - this.advancedDataGridView9.Columns[8].Visible = true; - this.advancedDataGridView9.Columns[8].ReadOnly = false; - this.advancedDataGridView9.Columns[8].Frozen = false; - this.advancedDataGridView9.Columns[8].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[8].DataPropertyName = "毛利"; - this.advancedDataGridView9.Columns[8].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView9.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView9.Columns[9].Name = ""; - this.advancedDataGridView9.Columns[9].HeaderText = "毛利率"; - this.advancedDataGridView9.Columns[9].Width = 100; - this.advancedDataGridView9.Columns[9].Visible = true; - this.advancedDataGridView9.Columns[9].ReadOnly = false; - this.advancedDataGridView9.Columns[9].Frozen = false; - this.advancedDataGridView9.Columns[9].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView9.Columns[9].DataPropertyName = "毛利率"; - this.advancedDataGridView9.Columns[9].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - - // - // splitContainer3 - // - this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.None; - this.splitContainer3.IsSplitterFixed = false; - this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; - this.splitContainer3.Panel1Collapsed = false; - this.splitContainer3.Panel2Collapsed = false; - this.splitContainer3.Panel1MinSize = 25; - this.splitContainer3.Panel2MinSize = 25; - this.splitContainer3.SplitterIncrement = 1; - this.splitContainer3.SplitterWidth = 6; - this.splitContainer3.TabStop = true; - this.splitContainer3.BackColor = System.Drawing.SystemColors.Control; - this.splitContainer3.Enabled = true; - this.splitContainer3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.splitContainer3.ForeColor = System.Drawing.SystemColors.ControlText; - this.splitContainer3.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.splitContainer3.MaximumSize = new System.Drawing.Size(0, 0); - this.splitContainer3.MinimumSize = new System.Drawing.Size(0, 0); - this.splitContainer3.TabIndex = 0; - this.splitContainer3.Name = "splitContainer3"; - - // - // advancedDataGridView4 - // - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView4.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Window; - this.advancedDataGridView4.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText; - this.advancedDataGridView4.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView4.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView4.DefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView4.DefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView4.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView4.RowHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView4.RowHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView4.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView4.EnableExcelStyleSelection = true; - this.advancedDataGridView4.EnableCellPaste = true; - this.advancedDataGridView4.AllowUserToAddRows = false; - this.advancedDataGridView4.AllowUserToDeleteRows = true; - this.advancedDataGridView4.AllowUserToOrderColumns = false; - this.advancedDataGridView4.AllowUserToResizeColumns = true; - this.advancedDataGridView4.AllowUserToResizeRows = false; - this.advancedDataGridView4.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.None; - this.advancedDataGridView4.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.None; - this.advancedDataGridView4.BackgroundColor = System.Drawing.Color.White; - this.advancedDataGridView4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.advancedDataGridView4.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.Single; - this.advancedDataGridView4.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithAutoHeaderText; - this.advancedDataGridView4.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView4.ColumnHeadersHeight = 35; - this.advancedDataGridView4.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.EnableResizing; - this.advancedDataGridView4.ColumnHeadersVisible = true; - this.advancedDataGridView4.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView4.EnableHeadersVisualStyles = false; - this.advancedDataGridView4.GridColor = System.Drawing.SystemColors.ControlDark; - this.advancedDataGridView4.MultiSelect = true; - this.advancedDataGridView4.ReadOnly = false; - this.advancedDataGridView4.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView4.RowHeadersVisible = true; - this.advancedDataGridView4.RowHeadersWidth = 41; - this.advancedDataGridView4.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.EnableResizing; - this.advancedDataGridView4.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.advancedDataGridView4.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect; - this.advancedDataGridView4.ShowCellErrors = true; - this.advancedDataGridView4.ShowCellToolTips = true; - this.advancedDataGridView4.ShowEditingIcon = true; - this.advancedDataGridView4.ShowRowErrors = true; - this.advancedDataGridView4.StandardTab = false; - this.advancedDataGridView4.VirtualMode = false; - this.advancedDataGridView4.Enabled = true; - this.advancedDataGridView4.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.advancedDataGridView4.MaximumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView4.MinimumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView4.TabIndex = 0; - this.advancedDataGridView4.TabStop = true; - this.advancedDataGridView4.Name = "advancedDataGridView4"; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[0].Name = ""; - this.advancedDataGridView4.Columns[0].HeaderText = "序号"; - this.advancedDataGridView4.Columns[0].Width = 35; - this.advancedDataGridView4.Columns[0].Visible = true; - this.advancedDataGridView4.Columns[0].ReadOnly = false; - this.advancedDataGridView4.Columns[0].Frozen = false; - this.advancedDataGridView4.Columns[0].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[0].DataPropertyName = "序号"; - this.advancedDataGridView4.Columns[0].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns[0].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[1].Name = ""; - this.advancedDataGridView4.Columns[1].HeaderText = "箱号"; - this.advancedDataGridView4.Columns[1].Width = 150; - this.advancedDataGridView4.Columns[1].Visible = true; - this.advancedDataGridView4.Columns[1].ReadOnly = false; - this.advancedDataGridView4.Columns[1].Frozen = false; - this.advancedDataGridView4.Columns[1].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[1].DataPropertyName = "箱号"; - this.advancedDataGridView4.Columns[1].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[2].Name = ""; - this.advancedDataGridView4.Columns[2].HeaderText = "箱名"; - this.advancedDataGridView4.Columns[2].Width = 150; - this.advancedDataGridView4.Columns[2].Visible = true; - this.advancedDataGridView4.Columns[2].ReadOnly = false; - this.advancedDataGridView4.Columns[2].Frozen = false; - this.advancedDataGridView4.Columns[2].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[2].DataPropertyName = "箱名"; - this.advancedDataGridView4.Columns[2].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns[2].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[3].Name = ""; - this.advancedDataGridView4.Columns[3].HeaderText = "型号"; - this.advancedDataGridView4.Columns[3].Width = 150; - this.advancedDataGridView4.Columns[3].Visible = true; - this.advancedDataGridView4.Columns[3].ReadOnly = false; - this.advancedDataGridView4.Columns[3].Frozen = false; - this.advancedDataGridView4.Columns[3].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[3].DataPropertyName = "型号"; - this.advancedDataGridView4.Columns[3].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[4].Name = ""; - this.advancedDataGridView4.Columns[4].HeaderText = "规格"; - this.advancedDataGridView4.Columns[4].Width = 150; - this.advancedDataGridView4.Columns[4].Visible = true; - this.advancedDataGridView4.Columns[4].ReadOnly = false; - this.advancedDataGridView4.Columns[4].Frozen = false; - this.advancedDataGridView4.Columns[4].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[4].DataPropertyName = "规格"; - this.advancedDataGridView4.Columns[4].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[5].Name = ""; - this.advancedDataGridView4.Columns[5].HeaderText = "单位"; - this.advancedDataGridView4.Columns[5].Width = 35; - this.advancedDataGridView4.Columns[5].Visible = true; - this.advancedDataGridView4.Columns[5].ReadOnly = false; - this.advancedDataGridView4.Columns[5].Frozen = false; - this.advancedDataGridView4.Columns[5].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[5].DataPropertyName = "单位"; - this.advancedDataGridView4.Columns[5].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns[5].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[6].Name = ""; - this.advancedDataGridView4.Columns[6].HeaderText = "数量"; - this.advancedDataGridView4.Columns[6].Width = 45; - this.advancedDataGridView4.Columns[6].Visible = true; - this.advancedDataGridView4.Columns[6].ReadOnly = false; - this.advancedDataGridView4.Columns[6].Frozen = false; - this.advancedDataGridView4.Columns[6].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[6].DataPropertyName = "数量"; - this.advancedDataGridView4.Columns[6].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns[6].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[7].Name = ""; - this.advancedDataGridView4.Columns[7].HeaderText = "单台成本"; - this.advancedDataGridView4.Columns[7].Width = 100; - this.advancedDataGridView4.Columns[7].Visible = true; - this.advancedDataGridView4.Columns[7].ReadOnly = false; - this.advancedDataGridView4.Columns[7].Frozen = false; - this.advancedDataGridView4.Columns[7].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[7].DataPropertyName = "单台成本"; - this.advancedDataGridView4.Columns[7].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[8].Name = ""; - this.advancedDataGridView4.Columns[8].HeaderText = "成本价"; - this.advancedDataGridView4.Columns[8].Width = 100; - this.advancedDataGridView4.Columns[8].Visible = true; - this.advancedDataGridView4.Columns[8].ReadOnly = false; - this.advancedDataGridView4.Columns[8].Frozen = false; - this.advancedDataGridView4.Columns[8].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[8].DataPropertyName = "成本价"; - this.advancedDataGridView4.Columns[8].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[9].Name = ""; - this.advancedDataGridView4.Columns[9].HeaderText = "单台报出"; - this.advancedDataGridView4.Columns[9].Width = 100; - this.advancedDataGridView4.Columns[9].Visible = true; - this.advancedDataGridView4.Columns[9].ReadOnly = false; - this.advancedDataGridView4.Columns[9].Frozen = false; - this.advancedDataGridView4.Columns[9].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[9].DataPropertyName = "单台报出"; - this.advancedDataGridView4.Columns[9].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[10].Name = ""; - this.advancedDataGridView4.Columns[10].HeaderText = "报出价"; - this.advancedDataGridView4.Columns[10].Width = 100; - this.advancedDataGridView4.Columns[10].Visible = true; - this.advancedDataGridView4.Columns[10].ReadOnly = false; - this.advancedDataGridView4.Columns[10].Frozen = false; - this.advancedDataGridView4.Columns[10].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[10].DataPropertyName = "报出价"; - this.advancedDataGridView4.Columns[10].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[11].Name = ""; - this.advancedDataGridView4.Columns[11].HeaderText = "利润"; - this.advancedDataGridView4.Columns[11].Width = 100; - this.advancedDataGridView4.Columns[11].Visible = true; - this.advancedDataGridView4.Columns[11].ReadOnly = false; - this.advancedDataGridView4.Columns[11].Frozen = false; - this.advancedDataGridView4.Columns[11].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[11].DataPropertyName = "利润"; - this.advancedDataGridView4.Columns[11].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[12].Name = ""; - this.advancedDataGridView4.Columns[12].HeaderText = "利润率"; - this.advancedDataGridView4.Columns[12].Width = 100; - this.advancedDataGridView4.Columns[12].Visible = true; - this.advancedDataGridView4.Columns[12].ReadOnly = false; - this.advancedDataGridView4.Columns[12].Frozen = false; - this.advancedDataGridView4.Columns[12].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[12].DataPropertyName = "利润率"; - this.advancedDataGridView4.Columns[12].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[13].Name = ""; - this.advancedDataGridView4.Columns[13].HeaderText = "毛利率"; - this.advancedDataGridView4.Columns[13].Width = 100; - this.advancedDataGridView4.Columns[13].Visible = true; - this.advancedDataGridView4.Columns[13].ReadOnly = false; - this.advancedDataGridView4.Columns[13].Frozen = false; - this.advancedDataGridView4.Columns[13].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[13].DataPropertyName = "毛利率"; - this.advancedDataGridView4.Columns[13].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[14].Name = ""; - this.advancedDataGridView4.Columns[14].HeaderText = "箱柜类型"; - this.advancedDataGridView4.Columns[14].Width = 100; - this.advancedDataGridView4.Columns[14].Visible = true; - this.advancedDataGridView4.Columns[14].ReadOnly = false; - this.advancedDataGridView4.Columns[14].Frozen = false; - this.advancedDataGridView4.Columns[14].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[14].DataPropertyName = "箱柜类型"; - this.advancedDataGridView4.Columns[14].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[15].Name = ""; - this.advancedDataGridView4.Columns[15].HeaderText = "备注"; - this.advancedDataGridView4.Columns[15].Width = 100; - this.advancedDataGridView4.Columns[15].Visible = true; - this.advancedDataGridView4.Columns[15].ReadOnly = false; - this.advancedDataGridView4.Columns[15].Frozen = false; - this.advancedDataGridView4.Columns[15].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[15].DataPropertyName = "备注"; - this.advancedDataGridView4.Columns[15].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView4.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView4.Columns[16].Name = ""; - this.advancedDataGridView4.Columns[16].HeaderText = "图纸"; - this.advancedDataGridView4.Columns[16].Width = 100; - this.advancedDataGridView4.Columns[16].Visible = true; - this.advancedDataGridView4.Columns[16].ReadOnly = false; - this.advancedDataGridView4.Columns[16].Frozen = false; - this.advancedDataGridView4.Columns[16].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView4.Columns[16].DataPropertyName = "图纸"; - this.advancedDataGridView4.Columns[16].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - - // - // advancedDataGridView5 - // - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView5.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Window; - this.advancedDataGridView5.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText; - this.advancedDataGridView5.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView5.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView5.DefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView5.DefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView5.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 1); - this.advancedDataGridView5.RowHeadersDefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView5.RowHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - this.advancedDataGridView5.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView5.EnableExcelStyleSelection = true; - this.advancedDataGridView5.EnableCellPaste = true; - this.advancedDataGridView5.AllowUserToAddRows = false; - this.advancedDataGridView5.AllowUserToDeleteRows = true; - this.advancedDataGridView5.AllowUserToOrderColumns = false; - this.advancedDataGridView5.AllowUserToResizeColumns = true; - this.advancedDataGridView5.AllowUserToResizeRows = false; - this.advancedDataGridView5.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.None; - this.advancedDataGridView5.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.None; - this.advancedDataGridView5.BackgroundColor = System.Drawing.Color.White; - this.advancedDataGridView5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.advancedDataGridView5.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.Single; - this.advancedDataGridView5.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithAutoHeaderText; - this.advancedDataGridView5.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView5.ColumnHeadersHeight = 35; - this.advancedDataGridView5.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.EnableResizing; - this.advancedDataGridView5.ColumnHeadersVisible = true; - this.advancedDataGridView5.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView5.EnableHeadersVisualStyles = false; - this.advancedDataGridView5.GridColor = System.Drawing.SystemColors.ControlDark; - this.advancedDataGridView5.MultiSelect = true; - this.advancedDataGridView5.ReadOnly = false; - this.advancedDataGridView5.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Raised; - this.advancedDataGridView5.RowHeadersVisible = true; - this.advancedDataGridView5.RowHeadersWidth = 41; - this.advancedDataGridView5.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.EnableResizing; - this.advancedDataGridView5.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.advancedDataGridView5.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect; - this.advancedDataGridView5.ShowCellErrors = true; - this.advancedDataGridView5.ShowCellToolTips = true; - this.advancedDataGridView5.ShowEditingIcon = true; - this.advancedDataGridView5.ShowRowErrors = true; - this.advancedDataGridView5.StandardTab = false; - this.advancedDataGridView5.VirtualMode = false; - this.advancedDataGridView5.Enabled = true; - this.advancedDataGridView5.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.advancedDataGridView5.MaximumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView5.MinimumSize = new System.Drawing.Size(0, 0); - this.advancedDataGridView5.TabIndex = 0; - this.advancedDataGridView5.TabStop = true; - this.advancedDataGridView5.Name = "advancedDataGridView5"; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[0].Name = ""; - this.advancedDataGridView5.Columns[0].HeaderText = "序号"; - this.advancedDataGridView5.Columns[0].Width = 35; - this.advancedDataGridView5.Columns[0].Visible = true; - this.advancedDataGridView5.Columns[0].ReadOnly = false; - this.advancedDataGridView5.Columns[0].Frozen = false; - this.advancedDataGridView5.Columns[0].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[0].DataPropertyName = "序号"; - this.advancedDataGridView5.Columns[0].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns[0].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[1].Name = ""; - this.advancedDataGridView5.Columns[1].HeaderText = "元件名称"; - this.advancedDataGridView5.Columns[1].Width = 150; - this.advancedDataGridView5.Columns[1].Visible = true; - this.advancedDataGridView5.Columns[1].ReadOnly = false; - this.advancedDataGridView5.Columns[1].Frozen = false; - this.advancedDataGridView5.Columns[1].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[1].DataPropertyName = "元件名称"; - this.advancedDataGridView5.Columns[1].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[2].Name = ""; - this.advancedDataGridView5.Columns[2].HeaderText = "规格"; - this.advancedDataGridView5.Columns[2].Width = 150; - this.advancedDataGridView5.Columns[2].Visible = true; - this.advancedDataGridView5.Columns[2].ReadOnly = false; - this.advancedDataGridView5.Columns[2].Frozen = false; - this.advancedDataGridView5.Columns[2].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[2].DataPropertyName = "规格"; - this.advancedDataGridView5.Columns[2].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[3].Name = ""; - this.advancedDataGridView5.Columns[3].HeaderText = "单位"; - this.advancedDataGridView5.Columns[3].Width = 35; - this.advancedDataGridView5.Columns[3].Visible = true; - this.advancedDataGridView5.Columns[3].ReadOnly = false; - this.advancedDataGridView5.Columns[3].Frozen = false; - this.advancedDataGridView5.Columns[3].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[3].DataPropertyName = "单位"; - this.advancedDataGridView5.Columns[3].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns[3].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[4].Name = ""; - this.advancedDataGridView5.Columns[4].HeaderText = "数量"; - this.advancedDataGridView5.Columns[4].Width = 40; - this.advancedDataGridView5.Columns[4].Visible = true; - this.advancedDataGridView5.Columns[4].ReadOnly = false; - this.advancedDataGridView5.Columns[4].Frozen = false; - this.advancedDataGridView5.Columns[4].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[4].DataPropertyName = "数量"; - this.advancedDataGridView5.Columns[4].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns[4].DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[5].Name = ""; - this.advancedDataGridView5.Columns[5].HeaderText = "表价"; - this.advancedDataGridView5.Columns[5].Width = 100; - this.advancedDataGridView5.Columns[5].Visible = true; - this.advancedDataGridView5.Columns[5].ReadOnly = false; - this.advancedDataGridView5.Columns[5].Frozen = false; - this.advancedDataGridView5.Columns[5].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[5].DataPropertyName = "表价"; - this.advancedDataGridView5.Columns[5].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[6].Name = ""; - this.advancedDataGridView5.Columns[6].HeaderText = "采购单价"; - this.advancedDataGridView5.Columns[6].Width = 100; - this.advancedDataGridView5.Columns[6].Visible = true; - this.advancedDataGridView5.Columns[6].ReadOnly = false; - this.advancedDataGridView5.Columns[6].Frozen = false; - this.advancedDataGridView5.Columns[6].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[6].DataPropertyName = "采购单价"; - this.advancedDataGridView5.Columns[6].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[7].Name = ""; - this.advancedDataGridView5.Columns[7].HeaderText = "采购系数"; - this.advancedDataGridView5.Columns[7].Width = 100; - this.advancedDataGridView5.Columns[7].Visible = true; - this.advancedDataGridView5.Columns[7].ReadOnly = false; - this.advancedDataGridView5.Columns[7].Frozen = false; - this.advancedDataGridView5.Columns[7].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[7].DataPropertyName = "采购系数"; - this.advancedDataGridView5.Columns[7].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[8].Name = ""; - this.advancedDataGridView5.Columns[8].HeaderText = "采购价"; - this.advancedDataGridView5.Columns[8].Width = 100; - this.advancedDataGridView5.Columns[8].Visible = true; - this.advancedDataGridView5.Columns[8].ReadOnly = false; - this.advancedDataGridView5.Columns[8].Frozen = false; - this.advancedDataGridView5.Columns[8].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[8].DataPropertyName = "采购价"; - this.advancedDataGridView5.Columns[8].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[9].Name = ""; - this.advancedDataGridView5.Columns[9].HeaderText = "报出单价"; - this.advancedDataGridView5.Columns[9].Width = 100; - this.advancedDataGridView5.Columns[9].Visible = true; - this.advancedDataGridView5.Columns[9].ReadOnly = false; - this.advancedDataGridView5.Columns[9].Frozen = false; - this.advancedDataGridView5.Columns[9].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[9].DataPropertyName = "报出单价"; - this.advancedDataGridView5.Columns[9].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[10].Name = ""; - this.advancedDataGridView5.Columns[10].HeaderText = "报出系数"; - this.advancedDataGridView5.Columns[10].Width = 100; - this.advancedDataGridView5.Columns[10].Visible = true; - this.advancedDataGridView5.Columns[10].ReadOnly = false; - this.advancedDataGridView5.Columns[10].Frozen = false; - this.advancedDataGridView5.Columns[10].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[10].DataPropertyName = "报出系数"; - this.advancedDataGridView5.Columns[10].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[11].Name = ""; - this.advancedDataGridView5.Columns[11].HeaderText = "报出价"; - this.advancedDataGridView5.Columns[11].Width = 100; - this.advancedDataGridView5.Columns[11].Visible = true; - this.advancedDataGridView5.Columns[11].ReadOnly = false; - this.advancedDataGridView5.Columns[11].Frozen = false; - this.advancedDataGridView5.Columns[11].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[11].DataPropertyName = "报出价"; - this.advancedDataGridView5.Columns[11].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[12].Name = ""; - this.advancedDataGridView5.Columns[12].HeaderText = "图纸规格"; - this.advancedDataGridView5.Columns[12].Width = 100; - this.advancedDataGridView5.Columns[12].Visible = true; - this.advancedDataGridView5.Columns[12].ReadOnly = false; - this.advancedDataGridView5.Columns[12].Frozen = false; - this.advancedDataGridView5.Columns[12].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[12].DataPropertyName = "图纸规格"; - this.advancedDataGridView5.Columns[12].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[13].Name = ""; - this.advancedDataGridView5.Columns[13].HeaderText = "品牌"; - this.advancedDataGridView5.Columns[13].Width = 100; - this.advancedDataGridView5.Columns[13].Visible = true; - this.advancedDataGridView5.Columns[13].ReadOnly = false; - this.advancedDataGridView5.Columns[13].Frozen = false; - this.advancedDataGridView5.Columns[13].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[13].DataPropertyName = "品牌"; - this.advancedDataGridView5.Columns[13].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[14].Name = ""; - this.advancedDataGridView5.Columns[14].HeaderText = "系列"; - this.advancedDataGridView5.Columns[14].Width = 100; - this.advancedDataGridView5.Columns[14].Visible = true; - this.advancedDataGridView5.Columns[14].ReadOnly = false; - this.advancedDataGridView5.Columns[14].Frozen = false; - this.advancedDataGridView5.Columns[14].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[14].DataPropertyName = "系列"; - this.advancedDataGridView5.Columns[14].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[15].Name = ""; - this.advancedDataGridView5.Columns[15].HeaderText = "类型"; - this.advancedDataGridView5.Columns[15].Width = 100; - this.advancedDataGridView5.Columns[15].Visible = true; - this.advancedDataGridView5.Columns[15].ReadOnly = false; - this.advancedDataGridView5.Columns[15].Frozen = false; - this.advancedDataGridView5.Columns[15].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[15].DataPropertyName = "类型"; - this.advancedDataGridView5.Columns[15].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.advancedDataGridView5.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn()); - this.advancedDataGridView5.Columns[16].Name = ""; - this.advancedDataGridView5.Columns[16].HeaderText = "备注"; - this.advancedDataGridView5.Columns[16].Width = 100; - this.advancedDataGridView5.Columns[16].Visible = true; - this.advancedDataGridView5.Columns[16].ReadOnly = false; - this.advancedDataGridView5.Columns[16].Frozen = false; - this.advancedDataGridView5.Columns[16].AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.NotSet; - this.advancedDataGridView5.Columns[16].DataPropertyName = "备注"; - this.advancedDataGridView5.Columns[16].SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - - // - // toolStrip1 - // - this.toolStrip1.Dock = System.Windows.Forms.DockStyle.Top; - this.toolStrip1.AutoSize = true; - this.toolStrip1.AllowItemReorder = false; - this.toolStrip1.AllowMerge = true; - this.toolStrip1.BackColor = System.Drawing.SystemColors.Control; - this.toolStrip1.CanOverflow = true; - this.toolStrip1.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Visible; - this.toolStrip1.GripMargin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.toolStrip1.ImageScalingSize = new System.Drawing.Size(16, 16); - this.toolStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; - this.toolStrip1.Stretch = false; - this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.ManagerRenderMode; - this.toolStrip1.ShowItemToolTips = true; - this.toolStrip1.TabStop = false; - this.toolStrip1.TextDirection = System.Windows.Forms.ToolStripTextDirection.Horizontal; - this.toolStrip1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.toolStrip1.Enabled = true; - this.toolStrip1.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.toolStrip1.MaximumSize = new System.Drawing.Size(0, 0); - this.toolStrip1.MinimumSize = new System.Drawing.Size(0, 0); - this.toolStrip1.TabIndex = 1; - this.toolStrip1.Padding = new System.Windows.Forms.Padding(0, 0, 1, 0); - this.toolStrip1.Size = new System.Drawing.Size(487, 25); - this.toolStrip1.Location = new System.Drawing.Point(0, 0); - this.toolStrip1.Name = "toolStrip1"; - - // - // toolStripButton1 - // - this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton1.ToolTipText = "导出数据"; - this.toolStripButton1.Size = new System.Drawing.Size(60, 22); - this.toolStripButton1.Text = "导出数据"; - this.toolStripButton1.Name = "toolStripButton1"; - - // - // toolStripButton5 - // - this.toolStripButton5.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton5.ToolTipText = "新建项目"; - this.toolStripButton5.Size = new System.Drawing.Size(60, 22); - this.toolStripButton5.Text = "新建项目"; - this.toolStripButton5.Name = "toolStripButton5"; - - // - // toolStripButton6 - // - this.toolStripButton6.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton6.ToolTipText = "删除项目"; - this.toolStripButton6.Size = new System.Drawing.Size(60, 22); - this.toolStripButton6.Text = "删除项目"; - this.toolStripButton6.Name = "toolStripButton6"; - - // - // toolStripButton2 - // - this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton2.ToolTipText = "扒图号"; - this.toolStripButton2.Size = new System.Drawing.Size(48, 22); - this.toolStripButton2.Text = "扒图号"; - this.toolStripButton2.Name = "toolStripButton2"; - - // - // toolStripButton3 - // - this.toolStripButton3.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton3.ToolTipText = "扒箱号"; - this.toolStripButton3.Size = new System.Drawing.Size(48, 22); - this.toolStripButton3.Text = "扒箱号"; - this.toolStripButton3.Name = "toolStripButton3"; - - // - // toolStripButton4 - // - this.toolStripButton4.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton4.ToolTipText = "扒元件"; - this.toolStripButton4.Size = new System.Drawing.Size(48, 22); - this.toolStripButton4.Text = "扒元件"; - this.toolStripButton4.Name = "toolStripButton4"; - - // - // toolStripButton7 - // - this.toolStripButton7.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton7.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolStripButton7.Size = new System.Drawing.Size(36, 22); - this.toolStripButton7.Text = "设置"; - this.toolStripButton7.Name = "toolStripButton7"; - - // Form3 - this.Controls.AddRange(new System.Windows.Forms.Control[] { - this.tabControl2, - this.toolStrip1, - }); - // tabControl2 - this.tabControl2.Controls.AddRange(new System.Windows.Forms.Control[] { - this.tabPage3, - this.tabPage4, - }); - // tabPage3 - this.tabPage3.Controls.AddRange(new System.Windows.Forms.Control[] { - this.advancedDataGridView6, - this.panel1, - }); - // panel1 - this.panel1.Controls.AddRange(new System.Windows.Forms.Control[] { - this.button28, - this.textBox1, - this.comboBox2, - }); - // tabPage4 - this.tabPage4.Controls.AddRange(new System.Windows.Forms.Control[] { - this.splitContainer2, - }); - // Panel1 - this.splitContainer2.Panel1.Controls.AddRange(new System.Windows.Forms.Control[] { - this.advancedDataGridView9, - }); - // Panel2 - this.splitContainer2.Panel2.Controls.AddRange(new System.Windows.Forms.Control[] { - this.splitContainer3, - }); - // Panel1 - this.splitContainer3.Panel1.Controls.AddRange(new System.Windows.Forms.Control[] { - this.advancedDataGridView4, - }); - // Panel2 - this.splitContainer3.Panel2.Controls.AddRange(new System.Windows.Forms.Control[] { - this.advancedDataGridView5, - }); - // toolStrip1 - this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripButton1, - this.toolStripButton5, - this.toolStripButton6, - this.toolStripButton2, - this.toolStripButton3, - this.toolStripButton4, - this.toolStripButton7, - }); - // - // Form3 - // - this.Dock = System.Windows.Forms.DockStyle.None; - this.AutoScroll = false; - this.AutoSize = false; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocusChange; - this.BackColor = System.Drawing.SystemColors.Control; - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; - this.ControlBox = true; - this.HelpButton = false; - this.IsMdiContainer = false; - this.KeyPreview = false; - this.MaximumSize = new System.Drawing.Size(0, 0); - this.MinimumSize = new System.Drawing.Size(0, 0); - this.MaximizeBox = true; - this.MinimizeBox = true; - this.Opacity = 1; - this.RightToLeftLayout = false; - this.ShowInTaskbar = true; - this.ShowIcon = true; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Auto; - this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultLocation; - this.TopMost = false; - this.WindowState = System.Windows.Forms.FormWindowState.Normal; - this.AutoScrollMargin = new System.Drawing.Size(0, 0); - this.AutoScrollMinSize = new System.Drawing.Size(0, 0); - this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.Enabled = true; - this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.ForeColor = System.Drawing.SystemColors.ControlText; - this.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.Size = new System.Drawing.Size(503, 785); - this.Text = "Form3"; - this.Name = "Form3"; - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView6)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView9)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView4)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView5)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - this.splitContainer2.SplitterDistance = 173; - this.splitContainer3.SplitterDistance = 239; - - // === DataGridView Excel 风格选中效果 === - - // === SQLite 设计时数据绑定(由设计器注入) === - // 在 Form.Load 事件中加载所有绑定数据 - this.Load += (sender, e) => LoadAllSqliteData(); - } - - #endregion - - private System.Windows.Forms.TabControl tabControl2; - private System.Windows.Forms.TabPage tabPage3; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView6; - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Button button28; - private System.Windows.Forms.TextBox textBox1; - private System.Windows.Forms.ComboBox comboBox2; - private System.Windows.Forms.TabPage tabPage4; - private System.Windows.Forms.SplitContainer splitContainer2; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView9; - private System.Windows.Forms.SplitContainer splitContainer3; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView4; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView5; - private System.Windows.Forms.ToolStrip toolStrip1; - private System.Windows.Forms.ToolStripButton toolStripButton1; - private System.Windows.Forms.ToolStripButton toolStripButton5; - private System.Windows.Forms.ToolStripButton toolStripButton6; - private System.Windows.Forms.ToolStripButton toolStripButton2; - private System.Windows.Forms.ToolStripButton toolStripButton3; - private System.Windows.Forms.ToolStripButton toolStripButton4; - private System.Windows.Forms.ToolStripButton toolStripButton7; - - /// 加载所有 SQLite 设计数据绑定。 - private void LoadAllSqliteData() - { - // cadbt 宿主为 x86 进程,引用的是 x86 版 System.Data.SQLite.dll, - // 无需 AutoCAD 插件版的 64 位检查,直接加载。 - try { LoadSqliteData_advancedDataGridView6(); } catch (System.Exception ex_advancedDataGridView6) { System.Windows.Forms.MessageBox.Show("加载数据失败 (advancedDataGridView6): " + ex_advancedDataGridView6.Message); } - } - - /// 为 advancedDataGridView6 加载 SQLite 数据(由设计器生成)。 - private void LoadSqliteData_advancedDataGridView6() - { - // ★ 数据库路径:优先用插件真实目录(_baseDir 在 Form3.cs,注册表/CodeBase 解析), - // 在 CAD 中加载时 BaseDirectory 指向 CAD 安装目录会找不到库 - string dbPath = System.IO.Path.Combine( - GetPluginBaseDirForUi(), @"sjk\advancedDataGridView6Table.db"); - if (!System.IO.File.Exists(dbPath)) - { - // ★ 静默跳过(不弹窗):构造函数里的 Load 事件已用正确路径重新加载 - System.Diagnostics.Debug.WriteLine("找不到数据库文件: " + dbPath); - return; - } - - string connStr = "Data Source=" + dbPath + ";Version=3;busy_timeout=3000;"; - var table = new System.Data.DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(connStr)) - { - conn.Open(); - string sql = @"SELECT * FROM advancedDataGridView6Table"; - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(sql, conn)) - { - adapter.Fill(table); - } - } - - this.advancedDataGridView6.AutoGenerateColumns = false; - // KeepCustomColumns=true:设计器中自定义的列不会被覆盖, - // 数据库列通过 DataPropertyName 与控件列关联。 - // 若列名与数据库列名相同,运行时会自动绑定数据。 - this.advancedDataGridView6.DataSource = table; - } - - /// - /// ui.cs 侧获取插件目录:复用 Form3.cs 的 _baseDir - /// (partial 类同字段;_baseDir 在 Form3.cs 中由注册表/CodeBase 解析) - /// - private string GetPluginBaseDirForUi() - { - return _baseDir; - } - } -} diff --git a/cadbt/cadbt/Plugin/PaTypes.cs b/cadbt/cadbt/Plugin/PaTypes.cs deleted file mode 100644 index 3c4e287..0000000 --- a/cadbt/cadbt/Plugin/PaTypes.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ============================================================ -// 扒图数据类型(与原 cadcj 插件 / 网页端 cadbridge.ts 保持一致) -// ============================================================ -using System.Collections.Generic; - -namespace MyApp -{ - /// - /// 扒数据模式:图号/箱号/元件 - /// - public enum PaMode - { - Tuhao, // 扒图号 - Xianghao, // 扒箱号 - Yuanjian // 扒元件 - } - - /// - /// 扒图结果:一条文本 + 它对应的彩色框的 Handle(句柄字符串) - /// 用于关联表格数据行与网页 CAD 框实体,实现点击行定位、删除行删框。 - /// ★ TextHandle:源文本实体自身的 Handle,用于判断"是否同一个文本"。 - /// - public class PaTextResult - { - public string Text; - public string FrameHandle; - public string TextHandle = ""; - } -} diff --git a/cadbt/cadbt/Plugin/新建项目.cs b/cadbt/cadbt/Plugin/新建项目.cs deleted file mode 100644 index 494c388..0000000 --- a/cadbt/cadbt/Plugin/新建项目.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Forms; - -namespace MyApp -{ - /// - /// 新建项目 窗口(简化版,不依赖企业信息)。 - /// UI 布局见 新建项目.ui.cs,本文件只含交互逻辑。 - /// - public partial class 新建项目 : Form - { - // 价格格式化选项(与主项目 价格格式化.cs 保持一致) - private static readonly string[] 小数位选项 = - { - "保留整数", "保留1位小数", "保留2位小数", "保留3位小数", - "保留4位小数", "保留5位小数", "保留6位小数" - }; - private static readonly string[] 取整方式选项 = - { - "不取整", "四舍五入", "四舍五入到角", "四舍五入到元", - "四舍五入到十元", "向上取整到元", "最近5元", "最近10元" - }; - - private readonly string _dbPath; - private readonly string _tableName; - - public 新建项目() : this(null, null) { } - - /// 带数据库路径的构造函数(用于自动生成项目编号)。 - public 新建项目(string dbPath, string tableName) - { - InitializeComponent(); - _dbPath = dbPath; - _tableName = tableName; - InitPriceFormatCombos(); - this.Load += 新建项目_Load; - } - - private void InitPriceFormatCombos() - { - cmb单台价格.Items.Clear(); - cmb单台价格.Items.AddRange(小数位选项); - cmb项目总价.Items.Clear(); - cmb项目总价.Items.AddRange(小数位选项); - comboBox1.Items.Clear(); - comboBox1.Items.AddRange(取整方式选项); - comboBox2.Items.Clear(); - comboBox2.Items.AddRange(取整方式选项); - } - - private void 新建项目_Load(object sender, EventArgs e) - { - FillAutoFields(); - } - - /// 自动填充项目日期(当天)和项目编号(yyyyMMdd+3位序号)。 - private void FillAutoFields() - { - DateTime today = DateTime.Today; - txt项目日期.Text = today.ToString("yyyy-MM-dd"); - - string datePart = today.ToString("yyyyMMdd"); - int seq = GetNextSeqForDate(datePart); - txt项目编号.Text = datePart + seq.ToString("000"); - txt项目编号.ReadOnly = true; - txt项目编号.TabStop = false; - txt项目编号.BackColor = System.Drawing.SystemColors.Control; - } - - /// 查数据库当天最大序号+1,失败返回1。 - private int GetNextSeqForDate(string datePart) - { - if (string.IsNullOrEmpty(datePart) || - string.IsNullOrEmpty(_dbPath) || - string.IsNullOrEmpty(_tableName) || - !System.IO.File.Exists(_dbPath)) - { - return 1; - } - try - { - string connStr = "Data Source=" + _dbPath + ";Version=3;"; - using (var conn = new System.Data.SQLite.SQLiteConnection(connStr)) - { - conn.Open(); - string sql = - "SELECT MAX(CAST(SUBSTR(项目编号, 9) AS INTEGER)) " + - "FROM " + _tableName + " " + - "WHERE SUBSTR(项目编号, 1, 8) = '" + datePart + "';"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - object result = cmd.ExecuteScalar(); - if (result == null || result == DBNull.Value) return 1; - int maxSeq; - if (int.TryParse(result.ToString(), out maxSeq)) return maxSeq + 1; - return 1; - } - } - } - catch { return 1; } - } - - /// 收集对话框字段,以列名为键返回(供 Form3 写入数据库)。 - public Dictionary GetInputValues() - { - var values = new Dictionary(); - AddIfNotEmpty(values, "项目编号", txt项目编号.Text); - AddIfNotEmpty(values, "项目日期", txt项目日期.Text); - AddIfNotEmpty(values, "项目名称", txt项目名称.Text); - AddIfNotEmpty(values, "客户名称", txt客户名称.Text); - AddIfNotEmpty(values, "客户地址", txt客户地址.Text); - AddIfNotEmpty(values, "联系人", txt联系人.Text); - AddIfNotEmpty(values, "联系电话", txt联系电话.Text); - AddIfNotEmpty(values, "备注", txt备注.Text); - AddIfNotEmpty(values, "成套厂名称", txt成套厂名称.Text); - AddIfNotEmpty(values, "成套厂地址", txt成套厂地址.Text); - AddIfNotEmpty(values, "成套厂联系人", txt成套厂联系人.Text); - AddIfNotEmpty(values, "成套厂联系电话", txt成套厂联系电话.Text); - values["单台小数位"] = (cmb单台价格.SelectedItem ?? cmb单台价格.Text ?? "").ToString(); - values["项目小数位"] = (cmb项目总价.SelectedItem ?? cmb项目总价.Text ?? "").ToString(); - values["单台取整方式"] = (comboBox1.SelectedItem ?? comboBox1.Text ?? "").ToString(); - values["项目取整方式"] = (comboBox2.SelectedItem ?? comboBox2.Text ?? "").ToString(); - return values; - } - - private static void AddIfNotEmpty(Dictionary dict, string key, string value) - { - if (!string.IsNullOrWhiteSpace(value)) dict[key] = value.Trim(); - } - } -} diff --git a/cadbt/cadbt/Plugin/新建项目.ui.cs b/cadbt/cadbt/Plugin/新建项目.ui.cs deleted file mode 100644 index 37aeee3..0000000 --- a/cadbt/cadbt/Plugin/新建项目.ui.cs +++ /dev/null @@ -1,1337 +0,0 @@ -namespace MyApp -{ - public partial class 新建项目 : System.Windows.Forms.Form - { - /// 必需的设计器变量。 - private System.ComponentModel.IContainer components = null; - - /// 清理正在使用的资源。 - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows 窗体设计器生成的代码 - - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - - this.lbl项目编号 = new System.Windows.Forms.Label(); - this.txt项目编号 = new System.Windows.Forms.TextBox(); - this.lbl项目日期 = new System.Windows.Forms.Label(); - this.txt项目日期 = new System.Windows.Forms.TextBox(); - this.lbl项目名称 = new System.Windows.Forms.Label(); - this.txt项目名称 = new System.Windows.Forms.TextBox(); - this.lbl客户名称 = new System.Windows.Forms.Label(); - this.txt客户名称 = new System.Windows.Forms.TextBox(); - this.btn选择客户 = new System.Windows.Forms.Button(); - this.lbl客户地址 = new System.Windows.Forms.Label(); - this.txt客户地址 = new System.Windows.Forms.TextBox(); - this.lbl联系人 = new System.Windows.Forms.Label(); - this.txt联系人 = new System.Windows.Forms.TextBox(); - this.lbl联系电话 = new System.Windows.Forms.Label(); - this.txt联系电话 = new System.Windows.Forms.TextBox(); - this.lbl成套厂名称 = new System.Windows.Forms.Label(); - this.txt成套厂名称 = new System.Windows.Forms.TextBox(); - this.lbl成套厂地址 = new System.Windows.Forms.Label(); - this.txt成套厂地址 = new System.Windows.Forms.TextBox(); - this.lbl成套厂联系人 = new System.Windows.Forms.Label(); - this.txt成套厂联系人 = new System.Windows.Forms.TextBox(); - this.lbl成套厂联系电话 = new System.Windows.Forms.Label(); - this.txt成套厂联系电话 = new System.Windows.Forms.TextBox(); - this.lbl报出方式 = new System.Windows.Forms.Label(); - this.cmb报出方式 = new System.Windows.Forms.ComboBox(); - this.lbl箱柜模板 = new System.Windows.Forms.Label(); - this.cmb箱柜模板 = new System.Windows.Forms.ComboBox(); - this.lbl单台价格 = new System.Windows.Forms.Label(); - this.cmb单台价格 = new System.Windows.Forms.ComboBox(); - this.lbl项目总价 = new System.Windows.Forms.Label(); - this.lbl备注 = new System.Windows.Forms.Label(); - this.txt备注 = new System.Windows.Forms.TextBox(); - this.btn确定 = new System.Windows.Forms.Button(); - this.btn取消 = new System.Windows.Forms.Button(); - this.comboBox1 = new System.Windows.Forms.ComboBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.comboBox2 = new System.Windows.Forms.ComboBox(); - this.cmb项目总价 = new System.Windows.Forms.ComboBox(); - this.SuspendLayout(); - // - // lbl项目编号 - // - this.lbl项目编号.Dock = System.Windows.Forms.DockStyle.None; - this.lbl项目编号.AutoSize = false; - this.lbl项目编号.AutoEllipsis = false; - this.lbl项目编号.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl项目编号.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl项目编号.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl项目编号.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl项目编号.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl项目编号.UseCompatibleTextRendering = false; - this.lbl项目编号.UseMnemonic = true; - this.lbl项目编号.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目编号.Enabled = true; - this.lbl项目编号.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl项目编号.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目编号.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl项目编号.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl项目编号.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl项目编号.TabIndex = 0; - this.lbl项目编号.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl项目编号.Size = new System.Drawing.Size(70, 23); - this.lbl项目编号.Location = new System.Drawing.Point(20, 25); - this.lbl项目编号.Text = "项目编号:"; - this.lbl项目编号.Name = "lbl项目编号"; - - // - // txt项目编号 - // - this.txt项目编号.Dock = System.Windows.Forms.DockStyle.None; - this.txt项目编号.AcceptsReturn = false; - this.txt项目编号.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt项目编号.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt项目编号.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt项目编号.Multiline = false; - this.txt项目编号.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt项目编号.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt项目编号.UseSystemPasswordChar = false; - this.txt项目编号.AcceptsTab = false; - this.txt项目编号.ShortcutsEnabled = true; - this.txt项目编号.BackColor = System.Drawing.SystemColors.Window; - this.txt项目编号.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt项目编号.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目编号.HideSelection = true; - this.txt项目编号.MaxLength = 32767; - this.txt项目编号.ReadOnly = false; - this.txt项目编号.WordWrap = true; - this.txt项目编号.Enabled = true; - this.txt项目编号.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt项目编号.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt项目编号.MaximumSize = new System.Drawing.Size(0, 0); - this.txt项目编号.MinimumSize = new System.Drawing.Size(0, 0); - this.txt项目编号.TabIndex = 0; - this.txt项目编号.TabStop = true; - this.txt项目编号.Size = new System.Drawing.Size(220, 21); - this.txt项目编号.Location = new System.Drawing.Point(95, 25); - this.txt项目编号.Name = "txt项目编号"; - - // - // lbl项目日期 - // - this.lbl项目日期.Dock = System.Windows.Forms.DockStyle.None; - this.lbl项目日期.AutoSize = false; - this.lbl项目日期.AutoEllipsis = false; - this.lbl项目日期.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl项目日期.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl项目日期.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl项目日期.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl项目日期.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.lbl项目日期.UseCompatibleTextRendering = false; - this.lbl项目日期.UseMnemonic = true; - this.lbl项目日期.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目日期.Enabled = true; - this.lbl项目日期.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl项目日期.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目日期.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl项目日期.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl项目日期.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl项目日期.TabIndex = 1; - this.lbl项目日期.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl项目日期.Size = new System.Drawing.Size(70, 18); - this.lbl项目日期.Location = new System.Drawing.Point(380, 28); - this.lbl项目日期.Text = "项目日期:"; - this.lbl项目日期.Name = "lbl项目日期"; - - // - // txt项目日期 - // - this.txt项目日期.Dock = System.Windows.Forms.DockStyle.None; - this.txt项目日期.AcceptsReturn = false; - this.txt项目日期.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt项目日期.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt项目日期.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt项目日期.Multiline = false; - this.txt项目日期.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt项目日期.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt项目日期.UseSystemPasswordChar = false; - this.txt项目日期.AcceptsTab = false; - this.txt项目日期.ShortcutsEnabled = true; - this.txt项目日期.BackColor = System.Drawing.SystemColors.Window; - this.txt项目日期.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt项目日期.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目日期.HideSelection = true; - this.txt项目日期.MaxLength = 32767; - this.txt项目日期.ReadOnly = false; - this.txt项目日期.WordWrap = true; - this.txt项目日期.Enabled = true; - this.txt项目日期.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt项目日期.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt项目日期.MaximumSize = new System.Drawing.Size(0, 0); - this.txt项目日期.MinimumSize = new System.Drawing.Size(0, 0); - this.txt项目日期.TabIndex = 1; - this.txt项目日期.TabStop = true; - this.txt项目日期.Size = new System.Drawing.Size(210, 21); - this.txt项目日期.Location = new System.Drawing.Point(455, 25); - this.txt项目日期.Name = "txt项目日期"; - - // - // lbl项目名称 - // - this.lbl项目名称.Dock = System.Windows.Forms.DockStyle.None; - this.lbl项目名称.AutoSize = false; - this.lbl项目名称.AutoEllipsis = false; - this.lbl项目名称.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl项目名称.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl项目名称.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl项目名称.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl项目名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl项目名称.UseCompatibleTextRendering = false; - this.lbl项目名称.UseMnemonic = true; - this.lbl项目名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目名称.Enabled = true; - this.lbl项目名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl项目名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目名称.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl项目名称.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl项目名称.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl项目名称.TabIndex = 2; - this.lbl项目名称.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl项目名称.Size = new System.Drawing.Size(70, 23); - this.lbl项目名称.Location = new System.Drawing.Point(20, 55); - this.lbl项目名称.Text = "项目名称:"; - this.lbl项目名称.Name = "lbl项目名称"; - - // - // txt项目名称 - // - this.txt项目名称.Dock = System.Windows.Forms.DockStyle.None; - this.txt项目名称.AcceptsReturn = false; - this.txt项目名称.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt项目名称.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt项目名称.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt项目名称.Multiline = false; - this.txt项目名称.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt项目名称.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt项目名称.UseSystemPasswordChar = false; - this.txt项目名称.AcceptsTab = false; - this.txt项目名称.ShortcutsEnabled = true; - this.txt项目名称.BackColor = System.Drawing.SystemColors.Window; - this.txt项目名称.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt项目名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目名称.HideSelection = true; - this.txt项目名称.MaxLength = 32767; - this.txt项目名称.ReadOnly = false; - this.txt项目名称.WordWrap = true; - this.txt项目名称.Enabled = true; - this.txt项目名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt项目名称.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt项目名称.MaximumSize = new System.Drawing.Size(0, 0); - this.txt项目名称.MinimumSize = new System.Drawing.Size(0, 0); - this.txt项目名称.TabIndex = 2; - this.txt项目名称.TabStop = true; - this.txt项目名称.Size = new System.Drawing.Size(570, 21); - this.txt项目名称.Location = new System.Drawing.Point(95, 55); - this.txt项目名称.Name = "txt项目名称"; - - // - // lbl客户名称 - // - this.lbl客户名称.Dock = System.Windows.Forms.DockStyle.None; - this.lbl客户名称.AutoSize = false; - this.lbl客户名称.AutoEllipsis = false; - this.lbl客户名称.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl客户名称.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl客户名称.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl客户名称.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl客户名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl客户名称.UseCompatibleTextRendering = false; - this.lbl客户名称.UseMnemonic = true; - this.lbl客户名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl客户名称.Enabled = true; - this.lbl客户名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl客户名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl客户名称.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl客户名称.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl客户名称.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl客户名称.TabIndex = 3; - this.lbl客户名称.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl客户名称.Size = new System.Drawing.Size(70, 23); - this.lbl客户名称.Location = new System.Drawing.Point(20, 85); - this.lbl客户名称.Text = "客户名称:"; - this.lbl客户名称.Name = "lbl客户名称"; - - // - // txt客户名称 - // - this.txt客户名称.Dock = System.Windows.Forms.DockStyle.None; - this.txt客户名称.AcceptsReturn = false; - this.txt客户名称.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt客户名称.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt客户名称.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt客户名称.Multiline = false; - this.txt客户名称.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt客户名称.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt客户名称.UseSystemPasswordChar = false; - this.txt客户名称.AcceptsTab = false; - this.txt客户名称.ShortcutsEnabled = true; - this.txt客户名称.BackColor = System.Drawing.SystemColors.Window; - this.txt客户名称.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt客户名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt客户名称.HideSelection = true; - this.txt客户名称.MaxLength = 32767; - this.txt客户名称.ReadOnly = false; - this.txt客户名称.WordWrap = true; - this.txt客户名称.Enabled = true; - this.txt客户名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt客户名称.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt客户名称.MaximumSize = new System.Drawing.Size(0, 0); - this.txt客户名称.MinimumSize = new System.Drawing.Size(0, 0); - this.txt客户名称.TabIndex = 3; - this.txt客户名称.TabStop = true; - this.txt客户名称.Size = new System.Drawing.Size(479, 21); - this.txt客户名称.Location = new System.Drawing.Point(95, 85); - this.txt客户名称.Name = "txt客户名称"; - - // - // btn选择客户 - // - this.btn选择客户.Dock = System.Windows.Forms.DockStyle.None; - this.btn选择客户.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.btn选择客户.DialogResult = System.Windows.Forms.DialogResult.None; - this.btn选择客户.AutoEllipsis = false; - this.btn选择客户.AutoSize = false; - this.btn选择客户.BackColor = System.Drawing.SystemColors.Control; - this.btn选择客户.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.btn选择客户.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn选择客户.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn选择客户.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; - this.btn选择客户.UseMnemonic = true; - this.btn选择客户.UseCompatibleTextRendering = false; - this.btn选择客户.UseVisualStyleBackColor = true; - this.btn选择客户.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.btn选择客户.Enabled = true; - this.btn选择客户.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.btn选择客户.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn选择客户.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.btn选择客户.MaximumSize = new System.Drawing.Size(0, 0); - this.btn选择客户.MinimumSize = new System.Drawing.Size(0, 0); - this.btn选择客户.TabIndex = 4; - this.btn选择客户.TabStop = true; - this.btn选择客户.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.btn选择客户.Size = new System.Drawing.Size(85, 23); - this.btn选择客户.Location = new System.Drawing.Point(580, 85); - this.btn选择客户.Text = "选择客户"; - this.btn选择客户.Name = "btn选择客户"; - - // - // lbl客户地址 - // - this.lbl客户地址.Dock = System.Windows.Forms.DockStyle.None; - this.lbl客户地址.AutoSize = false; - this.lbl客户地址.AutoEllipsis = false; - this.lbl客户地址.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl客户地址.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl客户地址.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl客户地址.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl客户地址.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl客户地址.UseCompatibleTextRendering = false; - this.lbl客户地址.UseMnemonic = true; - this.lbl客户地址.BackColor = System.Drawing.SystemColors.Control; - this.lbl客户地址.Enabled = true; - this.lbl客户地址.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl客户地址.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl客户地址.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl客户地址.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl客户地址.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl客户地址.TabIndex = 5; - this.lbl客户地址.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl客户地址.Size = new System.Drawing.Size(70, 23); - this.lbl客户地址.Location = new System.Drawing.Point(20, 115); - this.lbl客户地址.Text = "客户地址:"; - this.lbl客户地址.Name = "lbl客户地址"; - - // - // txt客户地址 - // - this.txt客户地址.Dock = System.Windows.Forms.DockStyle.None; - this.txt客户地址.AcceptsReturn = false; - this.txt客户地址.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt客户地址.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt客户地址.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt客户地址.Multiline = false; - this.txt客户地址.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt客户地址.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt客户地址.UseSystemPasswordChar = false; - this.txt客户地址.AcceptsTab = false; - this.txt客户地址.ShortcutsEnabled = true; - this.txt客户地址.BackColor = System.Drawing.SystemColors.Window; - this.txt客户地址.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt客户地址.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt客户地址.HideSelection = true; - this.txt客户地址.MaxLength = 32767; - this.txt客户地址.ReadOnly = false; - this.txt客户地址.WordWrap = true; - this.txt客户地址.Enabled = true; - this.txt客户地址.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt客户地址.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt客户地址.MaximumSize = new System.Drawing.Size(0, 0); - this.txt客户地址.MinimumSize = new System.Drawing.Size(0, 0); - this.txt客户地址.TabIndex = 5; - this.txt客户地址.TabStop = true; - this.txt客户地址.Size = new System.Drawing.Size(570, 21); - this.txt客户地址.Location = new System.Drawing.Point(95, 115); - this.txt客户地址.Name = "txt客户地址"; - - // - // lbl联系人 - // - this.lbl联系人.Dock = System.Windows.Forms.DockStyle.None; - this.lbl联系人.AutoSize = false; - this.lbl联系人.AutoEllipsis = false; - this.lbl联系人.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl联系人.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl联系人.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl联系人.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl联系人.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl联系人.UseCompatibleTextRendering = false; - this.lbl联系人.UseMnemonic = true; - this.lbl联系人.BackColor = System.Drawing.SystemColors.Control; - this.lbl联系人.Enabled = true; - this.lbl联系人.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl联系人.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl联系人.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl联系人.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl联系人.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl联系人.TabIndex = 6; - this.lbl联系人.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl联系人.Size = new System.Drawing.Size(60, 23); - this.lbl联系人.Location = new System.Drawing.Point(30, 145); - this.lbl联系人.Text = "联系人:"; - this.lbl联系人.Name = "lbl联系人"; - - // - // txt联系人 - // - this.txt联系人.Dock = System.Windows.Forms.DockStyle.None; - this.txt联系人.AcceptsReturn = false; - this.txt联系人.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt联系人.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt联系人.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt联系人.Multiline = false; - this.txt联系人.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt联系人.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt联系人.UseSystemPasswordChar = false; - this.txt联系人.AcceptsTab = false; - this.txt联系人.ShortcutsEnabled = true; - this.txt联系人.BackColor = System.Drawing.SystemColors.Window; - this.txt联系人.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt联系人.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt联系人.HideSelection = true; - this.txt联系人.MaxLength = 32767; - this.txt联系人.ReadOnly = false; - this.txt联系人.WordWrap = true; - this.txt联系人.Enabled = true; - this.txt联系人.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt联系人.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt联系人.MaximumSize = new System.Drawing.Size(0, 0); - this.txt联系人.MinimumSize = new System.Drawing.Size(0, 0); - this.txt联系人.TabIndex = 6; - this.txt联系人.TabStop = true; - this.txt联系人.Size = new System.Drawing.Size(220, 21); - this.txt联系人.Location = new System.Drawing.Point(95, 145); - this.txt联系人.Name = "txt联系人"; - - // - // lbl联系电话 - // - this.lbl联系电话.Dock = System.Windows.Forms.DockStyle.None; - this.lbl联系电话.AutoSize = false; - this.lbl联系电话.AutoEllipsis = false; - this.lbl联系电话.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl联系电话.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl联系电话.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl联系电话.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl联系电话.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.lbl联系电话.UseCompatibleTextRendering = false; - this.lbl联系电话.UseMnemonic = true; - this.lbl联系电话.BackColor = System.Drawing.SystemColors.Control; - this.lbl联系电话.Enabled = true; - this.lbl联系电话.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl联系电话.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl联系电话.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl联系电话.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl联系电话.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl联系电话.TabIndex = 7; - this.lbl联系电话.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl联系电话.Size = new System.Drawing.Size(70, 21); - this.lbl联系电话.Location = new System.Drawing.Point(380, 145); - this.lbl联系电话.Text = "联系电话:"; - this.lbl联系电话.Name = "lbl联系电话"; - - // - // txt联系电话 - // - this.txt联系电话.Dock = System.Windows.Forms.DockStyle.None; - this.txt联系电话.AcceptsReturn = false; - this.txt联系电话.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt联系电话.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt联系电话.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt联系电话.Multiline = false; - this.txt联系电话.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt联系电话.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt联系电话.UseSystemPasswordChar = false; - this.txt联系电话.AcceptsTab = false; - this.txt联系电话.ShortcutsEnabled = true; - this.txt联系电话.BackColor = System.Drawing.SystemColors.Window; - this.txt联系电话.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt联系电话.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt联系电话.HideSelection = true; - this.txt联系电话.MaxLength = 32767; - this.txt联系电话.ReadOnly = false; - this.txt联系电话.WordWrap = true; - this.txt联系电话.Enabled = true; - this.txt联系电话.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt联系电话.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt联系电话.MaximumSize = new System.Drawing.Size(0, 0); - this.txt联系电话.MinimumSize = new System.Drawing.Size(0, 0); - this.txt联系电话.TabIndex = 7; - this.txt联系电话.TabStop = true; - this.txt联系电话.Size = new System.Drawing.Size(210, 21); - this.txt联系电话.Location = new System.Drawing.Point(455, 145); - this.txt联系电话.Name = "txt联系电话"; - - // - // lbl成套厂名称 - // - this.lbl成套厂名称.Dock = System.Windows.Forms.DockStyle.None; - this.lbl成套厂名称.AutoSize = false; - this.lbl成套厂名称.AutoEllipsis = false; - this.lbl成套厂名称.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl成套厂名称.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl成套厂名称.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl成套厂名称.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl成套厂名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl成套厂名称.UseCompatibleTextRendering = false; - this.lbl成套厂名称.UseMnemonic = true; - this.lbl成套厂名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂名称.Enabled = true; - this.lbl成套厂名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl成套厂名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂名称.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl成套厂名称.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂名称.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂名称.TabIndex = 8; - this.lbl成套厂名称.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl成套厂名称.Size = new System.Drawing.Size(80, 23); - this.lbl成套厂名称.Location = new System.Drawing.Point(10, 175); - this.lbl成套厂名称.Text = "成套厂名称:"; - this.lbl成套厂名称.Name = "lbl成套厂名称"; - - // - // txt成套厂名称 - // - this.txt成套厂名称.Dock = System.Windows.Forms.DockStyle.None; - this.txt成套厂名称.AcceptsReturn = false; - this.txt成套厂名称.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt成套厂名称.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt成套厂名称.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt成套厂名称.Multiline = false; - this.txt成套厂名称.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt成套厂名称.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt成套厂名称.UseSystemPasswordChar = false; - this.txt成套厂名称.AcceptsTab = false; - this.txt成套厂名称.ShortcutsEnabled = true; - this.txt成套厂名称.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂名称.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt成套厂名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂名称.HideSelection = true; - this.txt成套厂名称.MaxLength = 32767; - this.txt成套厂名称.ReadOnly = false; - this.txt成套厂名称.WordWrap = true; - this.txt成套厂名称.Enabled = true; - this.txt成套厂名称.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt成套厂名称.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt成套厂名称.MaximumSize = new System.Drawing.Size(0, 0); - this.txt成套厂名称.MinimumSize = new System.Drawing.Size(0, 0); - this.txt成套厂名称.TabIndex = 8; - this.txt成套厂名称.TabStop = true; - this.txt成套厂名称.Size = new System.Drawing.Size(570, 21); - this.txt成套厂名称.Location = new System.Drawing.Point(95, 175); - this.txt成套厂名称.Name = "txt成套厂名称"; - - // - // lbl成套厂地址 - // - this.lbl成套厂地址.Dock = System.Windows.Forms.DockStyle.None; - this.lbl成套厂地址.AutoSize = false; - this.lbl成套厂地址.AutoEllipsis = false; - this.lbl成套厂地址.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl成套厂地址.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl成套厂地址.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl成套厂地址.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl成套厂地址.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl成套厂地址.UseCompatibleTextRendering = false; - this.lbl成套厂地址.UseMnemonic = true; - this.lbl成套厂地址.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂地址.Enabled = true; - this.lbl成套厂地址.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl成套厂地址.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂地址.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl成套厂地址.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂地址.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂地址.TabIndex = 9; - this.lbl成套厂地址.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl成套厂地址.Size = new System.Drawing.Size(80, 23); - this.lbl成套厂地址.Location = new System.Drawing.Point(10, 205); - this.lbl成套厂地址.Text = "成套厂地址:"; - this.lbl成套厂地址.Name = "lbl成套厂地址"; - - // - // txt成套厂地址 - // - this.txt成套厂地址.Dock = System.Windows.Forms.DockStyle.None; - this.txt成套厂地址.AcceptsReturn = false; - this.txt成套厂地址.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt成套厂地址.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt成套厂地址.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt成套厂地址.Multiline = false; - this.txt成套厂地址.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt成套厂地址.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt成套厂地址.UseSystemPasswordChar = false; - this.txt成套厂地址.AcceptsTab = false; - this.txt成套厂地址.ShortcutsEnabled = true; - this.txt成套厂地址.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂地址.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt成套厂地址.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂地址.HideSelection = true; - this.txt成套厂地址.MaxLength = 32767; - this.txt成套厂地址.ReadOnly = false; - this.txt成套厂地址.WordWrap = true; - this.txt成套厂地址.Enabled = true; - this.txt成套厂地址.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt成套厂地址.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt成套厂地址.MaximumSize = new System.Drawing.Size(0, 0); - this.txt成套厂地址.MinimumSize = new System.Drawing.Size(0, 0); - this.txt成套厂地址.TabIndex = 9; - this.txt成套厂地址.TabStop = true; - this.txt成套厂地址.Size = new System.Drawing.Size(570, 21); - this.txt成套厂地址.Location = new System.Drawing.Point(95, 205); - this.txt成套厂地址.Name = "txt成套厂地址"; - - // - // lbl成套厂联系人 - // - this.lbl成套厂联系人.Dock = System.Windows.Forms.DockStyle.None; - this.lbl成套厂联系人.AutoSize = false; - this.lbl成套厂联系人.AutoEllipsis = false; - this.lbl成套厂联系人.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl成套厂联系人.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl成套厂联系人.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl成套厂联系人.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl成套厂联系人.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl成套厂联系人.UseCompatibleTextRendering = false; - this.lbl成套厂联系人.UseMnemonic = true; - this.lbl成套厂联系人.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂联系人.Enabled = true; - this.lbl成套厂联系人.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl成套厂联系人.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂联系人.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl成套厂联系人.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂联系人.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂联系人.TabIndex = 10; - this.lbl成套厂联系人.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl成套厂联系人.Size = new System.Drawing.Size(60, 23); - this.lbl成套厂联系人.Location = new System.Drawing.Point(30, 235); - this.lbl成套厂联系人.Text = "联系人:"; - this.lbl成套厂联系人.Name = "lbl成套厂联系人"; - - // - // txt成套厂联系人 - // - this.txt成套厂联系人.Dock = System.Windows.Forms.DockStyle.None; - this.txt成套厂联系人.AcceptsReturn = false; - this.txt成套厂联系人.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt成套厂联系人.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt成套厂联系人.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt成套厂联系人.Multiline = false; - this.txt成套厂联系人.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt成套厂联系人.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt成套厂联系人.UseSystemPasswordChar = false; - this.txt成套厂联系人.AcceptsTab = false; - this.txt成套厂联系人.ShortcutsEnabled = true; - this.txt成套厂联系人.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂联系人.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt成套厂联系人.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂联系人.HideSelection = true; - this.txt成套厂联系人.MaxLength = 32767; - this.txt成套厂联系人.ReadOnly = false; - this.txt成套厂联系人.WordWrap = true; - this.txt成套厂联系人.Enabled = true; - this.txt成套厂联系人.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt成套厂联系人.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt成套厂联系人.MaximumSize = new System.Drawing.Size(0, 0); - this.txt成套厂联系人.MinimumSize = new System.Drawing.Size(0, 0); - this.txt成套厂联系人.TabIndex = 10; - this.txt成套厂联系人.TabStop = true; - this.txt成套厂联系人.Size = new System.Drawing.Size(220, 21); - this.txt成套厂联系人.Location = new System.Drawing.Point(95, 235); - this.txt成套厂联系人.Name = "txt成套厂联系人"; - - // - // lbl成套厂联系电话 - // - this.lbl成套厂联系电话.Dock = System.Windows.Forms.DockStyle.None; - this.lbl成套厂联系电话.AutoSize = false; - this.lbl成套厂联系电话.AutoEllipsis = false; - this.lbl成套厂联系电话.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl成套厂联系电话.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl成套厂联系电话.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl成套厂联系电话.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl成套厂联系电话.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.lbl成套厂联系电话.UseCompatibleTextRendering = false; - this.lbl成套厂联系电话.UseMnemonic = true; - this.lbl成套厂联系电话.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂联系电话.Enabled = true; - this.lbl成套厂联系电话.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl成套厂联系电话.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂联系电话.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl成套厂联系电话.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂联系电话.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl成套厂联系电话.TabIndex = 11; - this.lbl成套厂联系电话.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl成套厂联系电话.Size = new System.Drawing.Size(70, 21); - this.lbl成套厂联系电话.Location = new System.Drawing.Point(380, 235); - this.lbl成套厂联系电话.Text = "联系电话:"; - this.lbl成套厂联系电话.Name = "lbl成套厂联系电话"; - - // - // txt成套厂联系电话 - // - this.txt成套厂联系电话.Dock = System.Windows.Forms.DockStyle.None; - this.txt成套厂联系电话.AcceptsReturn = false; - this.txt成套厂联系电话.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt成套厂联系电话.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt成套厂联系电话.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt成套厂联系电话.Multiline = false; - this.txt成套厂联系电话.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt成套厂联系电话.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt成套厂联系电话.UseSystemPasswordChar = false; - this.txt成套厂联系电话.AcceptsTab = false; - this.txt成套厂联系电话.ShortcutsEnabled = true; - this.txt成套厂联系电话.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂联系电话.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt成套厂联系电话.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂联系电话.HideSelection = true; - this.txt成套厂联系电话.MaxLength = 32767; - this.txt成套厂联系电话.ReadOnly = false; - this.txt成套厂联系电话.WordWrap = true; - this.txt成套厂联系电话.Enabled = true; - this.txt成套厂联系电话.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt成套厂联系电话.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt成套厂联系电话.MaximumSize = new System.Drawing.Size(0, 0); - this.txt成套厂联系电话.MinimumSize = new System.Drawing.Size(0, 0); - this.txt成套厂联系电话.TabIndex = 11; - this.txt成套厂联系电话.TabStop = true; - this.txt成套厂联系电话.Size = new System.Drawing.Size(210, 21); - this.txt成套厂联系电话.Location = new System.Drawing.Point(455, 232); - this.txt成套厂联系电话.Name = "txt成套厂联系电话"; - - // - // lbl报出方式 - // - this.lbl报出方式.Dock = System.Windows.Forms.DockStyle.None; - this.lbl报出方式.AutoSize = false; - this.lbl报出方式.AutoEllipsis = false; - this.lbl报出方式.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl报出方式.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl报出方式.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl报出方式.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl报出方式.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl报出方式.UseCompatibleTextRendering = false; - this.lbl报出方式.UseMnemonic = true; - this.lbl报出方式.BackColor = System.Drawing.SystemColors.Control; - this.lbl报出方式.Enabled = true; - this.lbl报出方式.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl报出方式.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl报出方式.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl报出方式.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl报出方式.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl报出方式.TabIndex = 12; - this.lbl报出方式.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl报出方式.Size = new System.Drawing.Size(70, 23); - this.lbl报出方式.Location = new System.Drawing.Point(20, 265); - this.lbl报出方式.Text = "报出方式:"; - this.lbl报出方式.Name = "lbl报出方式"; - - // - // cmb报出方式 - // - this.cmb报出方式.Dock = System.Windows.Forms.DockStyle.None; - this.cmb报出方式.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.cmb报出方式.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.cmb报出方式.BackColor = System.Drawing.SystemColors.Window; - this.cmb报出方式.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.cmb报出方式.DropDownWidth = 200; - this.cmb报出方式.DropDownHeight = 106; - this.cmb报出方式.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.cmb报出方式.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb报出方式.IntegralHeight = true; - this.cmb报出方式.ItemHeight = 12; - this.cmb报出方式.MaxDropDownItems = 8; - this.cmb报出方式.MaximumSize = new System.Drawing.Size(0, 0); - this.cmb报出方式.MinimumSize = new System.Drawing.Size(0, 0); - this.cmb报出方式.MaxLength = 0; - this.cmb报出方式.Sorted = false; - this.cmb报出方式.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.cmb报出方式.FormattingEnabled = false; - this.cmb报出方式.Enabled = true; - this.cmb报出方式.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.cmb报出方式.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.cmb报出方式.TabIndex = 12; - this.cmb报出方式.TabStop = true; - this.cmb报出方式.Size = new System.Drawing.Size(220, 20); - this.cmb报出方式.Location = new System.Drawing.Point(95, 265); - this.cmb报出方式.Text = "报出价=表价*采购系数*报出系数"; - this.cmb报出方式.Name = "cmb报出方式"; - - // - // lbl箱柜模板 - // - this.lbl箱柜模板.Dock = System.Windows.Forms.DockStyle.None; - this.lbl箱柜模板.AutoSize = false; - this.lbl箱柜模板.AutoEllipsis = false; - this.lbl箱柜模板.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl箱柜模板.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl箱柜模板.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl箱柜模板.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl箱柜模板.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.lbl箱柜模板.UseCompatibleTextRendering = false; - this.lbl箱柜模板.UseMnemonic = true; - this.lbl箱柜模板.BackColor = System.Drawing.SystemColors.Control; - this.lbl箱柜模板.Enabled = true; - this.lbl箱柜模板.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl箱柜模板.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl箱柜模板.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl箱柜模板.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl箱柜模板.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl箱柜模板.TabIndex = 13; - this.lbl箱柜模板.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl箱柜模板.Size = new System.Drawing.Size(70, 20); - this.lbl箱柜模板.Location = new System.Drawing.Point(380, 265); - this.lbl箱柜模板.Text = "箱柜模板:"; - this.lbl箱柜模板.Name = "lbl箱柜模板"; - - // - // cmb箱柜模板 - // - this.cmb箱柜模板.Dock = System.Windows.Forms.DockStyle.None; - this.cmb箱柜模板.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.cmb箱柜模板.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.cmb箱柜模板.BackColor = System.Drawing.SystemColors.Window; - this.cmb箱柜模板.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.cmb箱柜模板.DropDownWidth = 200; - this.cmb箱柜模板.DropDownHeight = 106; - this.cmb箱柜模板.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.cmb箱柜模板.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb箱柜模板.IntegralHeight = true; - this.cmb箱柜模板.ItemHeight = 12; - this.cmb箱柜模板.MaxDropDownItems = 8; - this.cmb箱柜模板.MaximumSize = new System.Drawing.Size(0, 0); - this.cmb箱柜模板.MinimumSize = new System.Drawing.Size(0, 0); - this.cmb箱柜模板.MaxLength = 0; - this.cmb箱柜模板.Sorted = false; - this.cmb箱柜模板.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.cmb箱柜模板.FormattingEnabled = false; - this.cmb箱柜模板.Enabled = true; - this.cmb箱柜模板.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.cmb箱柜模板.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.cmb箱柜模板.TabIndex = 13; - this.cmb箱柜模板.TabStop = true; - this.cmb箱柜模板.Size = new System.Drawing.Size(210, 20); - this.cmb箱柜模板.Location = new System.Drawing.Point(455, 262); - this.cmb箱柜模板.Name = "cmb箱柜模板"; - - // - // lbl单台价格 - // - this.lbl单台价格.Dock = System.Windows.Forms.DockStyle.None; - this.lbl单台价格.AutoSize = false; - this.lbl单台价格.AutoEllipsis = false; - this.lbl单台价格.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl单台价格.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl单台价格.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl单台价格.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl单台价格.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl单台价格.UseCompatibleTextRendering = false; - this.lbl单台价格.UseMnemonic = true; - this.lbl单台价格.BackColor = System.Drawing.SystemColors.Control; - this.lbl单台价格.Enabled = true; - this.lbl单台价格.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl单台价格.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl单台价格.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl单台价格.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl单台价格.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl单台价格.TabIndex = 14; - this.lbl单台价格.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl单台价格.Size = new System.Drawing.Size(70, 23); - this.lbl单台价格.Location = new System.Drawing.Point(20, 293); - this.lbl单台价格.Text = "单台价格:"; - this.lbl单台价格.Name = "lbl单台价格"; - - // - // cmb单台价格 - // - this.cmb单台价格.Dock = System.Windows.Forms.DockStyle.None; - this.cmb单台价格.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.cmb单台价格.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.cmb单台价格.BackColor = System.Drawing.SystemColors.Window; - this.cmb单台价格.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.cmb单台价格.DropDownWidth = 200; - this.cmb单台价格.DropDownHeight = 106; - this.cmb单台价格.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.cmb单台价格.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb单台价格.IntegralHeight = true; - this.cmb单台价格.ItemHeight = 12; - this.cmb单台价格.MaxDropDownItems = 8; - this.cmb单台价格.MaximumSize = new System.Drawing.Size(0, 0); - this.cmb单台价格.MinimumSize = new System.Drawing.Size(0, 0); - this.cmb单台价格.MaxLength = 0; - this.cmb单台价格.Sorted = false; - this.cmb单台价格.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.cmb单台价格.FormattingEnabled = false; - this.cmb单台价格.Enabled = true; - this.cmb单台价格.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.cmb单台价格.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.cmb单台价格.TabIndex = 14; - this.cmb单台价格.TabStop = true; - this.cmb单台价格.Size = new System.Drawing.Size(220, 20); - this.cmb单台价格.Location = new System.Drawing.Point(95, 293); - this.cmb单台价格.Text = "保留整数"; - this.cmb单台价格.Name = "cmb单台价格"; - - // - // lbl项目总价 - // - this.lbl项目总价.Dock = System.Windows.Forms.DockStyle.None; - this.lbl项目总价.AutoSize = false; - this.lbl项目总价.AutoEllipsis = false; - this.lbl项目总价.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl项目总价.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl项目总价.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl项目总价.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl项目总价.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.lbl项目总价.UseCompatibleTextRendering = false; - this.lbl项目总价.UseMnemonic = true; - this.lbl项目总价.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目总价.Enabled = true; - this.lbl项目总价.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl项目总价.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目总价.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl项目总价.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl项目总价.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl项目总价.TabIndex = 15; - this.lbl项目总价.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl项目总价.Size = new System.Drawing.Size(70, 20); - this.lbl项目总价.Location = new System.Drawing.Point(379, 293); - this.lbl项目总价.Text = "项目总价:"; - this.lbl项目总价.Name = "lbl项目总价"; - - // - // lbl备注 - // - this.lbl备注.Dock = System.Windows.Forms.DockStyle.None; - this.lbl备注.AutoSize = false; - this.lbl备注.AutoEllipsis = false; - this.lbl备注.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.lbl备注.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.lbl备注.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.lbl备注.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.lbl备注.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.lbl备注.UseCompatibleTextRendering = false; - this.lbl备注.UseMnemonic = true; - this.lbl备注.BackColor = System.Drawing.SystemColors.Control; - this.lbl备注.Enabled = true; - this.lbl备注.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.lbl备注.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl备注.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.lbl备注.MaximumSize = new System.Drawing.Size(0, 0); - this.lbl备注.MinimumSize = new System.Drawing.Size(0, 0); - this.lbl备注.TabIndex = 16; - this.lbl备注.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.lbl备注.Size = new System.Drawing.Size(46, 23); - this.lbl备注.Location = new System.Drawing.Point(44, 352); - this.lbl备注.Text = "备注:"; - this.lbl备注.Name = "lbl备注"; - - // - // txt备注 - // - this.txt备注.Dock = System.Windows.Forms.DockStyle.None; - this.txt备注.AcceptsReturn = false; - this.txt备注.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.txt备注.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.txt备注.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; - this.txt备注.Multiline = true; - this.txt备注.ScrollBars = System.Windows.Forms.ScrollBars.None; - this.txt备注.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; - this.txt备注.UseSystemPasswordChar = false; - this.txt备注.AcceptsTab = false; - this.txt备注.ShortcutsEnabled = true; - this.txt备注.BackColor = System.Drawing.SystemColors.Window; - this.txt备注.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.txt备注.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt备注.HideSelection = true; - this.txt备注.MaxLength = 32767; - this.txt备注.ReadOnly = false; - this.txt备注.WordWrap = true; - this.txt备注.Enabled = true; - this.txt备注.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.txt备注.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.txt备注.MaximumSize = new System.Drawing.Size(0, 0); - this.txt备注.MinimumSize = new System.Drawing.Size(0, 0); - this.txt备注.TabIndex = 16; - this.txt备注.TabStop = true; - this.txt备注.Size = new System.Drawing.Size(570, 80); - this.txt备注.Location = new System.Drawing.Point(95, 352); - this.txt备注.Name = "txt备注"; - - // - // btn确定 - // - this.btn确定.Dock = System.Windows.Forms.DockStyle.None; - this.btn确定.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.btn确定.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btn确定.AutoEllipsis = false; - this.btn确定.AutoSize = false; - this.btn确定.BackColor = System.Drawing.SystemColors.Control; - this.btn确定.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.btn确定.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn确定.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn确定.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; - this.btn确定.UseMnemonic = true; - this.btn确定.UseCompatibleTextRendering = false; - this.btn确定.UseVisualStyleBackColor = true; - this.btn确定.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.btn确定.Enabled = true; - this.btn确定.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.btn确定.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn确定.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.btn确定.MaximumSize = new System.Drawing.Size(0, 0); - this.btn确定.MinimumSize = new System.Drawing.Size(0, 0); - this.btn确定.TabIndex = 17; - this.btn确定.TabStop = true; - this.btn确定.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.btn确定.Size = new System.Drawing.Size(100, 28); - this.btn确定.Location = new System.Drawing.Point(455, 449); - this.btn确定.Text = "确定"; - this.btn确定.Name = "btn确定"; - - // - // btn取消 - // - this.btn取消.Dock = System.Windows.Forms.DockStyle.None; - this.btn取消.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.btn取消.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btn取消.AutoEllipsis = false; - this.btn取消.AutoSize = false; - this.btn取消.BackColor = System.Drawing.SystemColors.Control; - this.btn取消.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.btn取消.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn取消.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.btn取消.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; - this.btn取消.UseMnemonic = true; - this.btn取消.UseCompatibleTextRendering = false; - this.btn取消.UseVisualStyleBackColor = true; - this.btn取消.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.btn取消.Enabled = true; - this.btn取消.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.btn取消.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn取消.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.btn取消.MaximumSize = new System.Drawing.Size(0, 0); - this.btn取消.MinimumSize = new System.Drawing.Size(0, 0); - this.btn取消.TabIndex = 18; - this.btn取消.TabStop = true; - this.btn取消.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.btn取消.Size = new System.Drawing.Size(100, 28); - this.btn取消.Location = new System.Drawing.Point(565, 449); - this.btn取消.Text = "取消"; - this.btn取消.Name = "btn取消"; - - // - // comboBox1 - // - this.comboBox1.Dock = System.Windows.Forms.DockStyle.None; - this.comboBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.comboBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.comboBox1.BackColor = System.Drawing.SystemColors.Window; - this.comboBox1.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.comboBox1.DropDownWidth = 210; - this.comboBox1.DropDownHeight = 106; - this.comboBox1.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.comboBox1.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox1.IntegralHeight = true; - this.comboBox1.ItemHeight = 12; - this.comboBox1.MaxDropDownItems = 8; - this.comboBox1.MaximumSize = new System.Drawing.Size(0, 0); - this.comboBox1.MinimumSize = new System.Drawing.Size(0, 0); - this.comboBox1.MaxLength = 0; - this.comboBox1.Sorted = false; - this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.comboBox1.FormattingEnabled = false; - this.comboBox1.Enabled = true; - this.comboBox1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.comboBox1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.comboBox1.TabIndex = 14; - this.comboBox1.TabStop = true; - this.comboBox1.Size = new System.Drawing.Size(210, 20); - this.comboBox1.Location = new System.Drawing.Point(455, 322); - this.comboBox1.Text = "四舍五入"; - this.comboBox1.Name = "comboBox1"; - - // - // label1 - // - this.label1.Dock = System.Windows.Forms.DockStyle.None; - this.label1.AutoSize = false; - this.label1.AutoEllipsis = false; - this.label1.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.label1.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.label1.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label1.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.label1.UseCompatibleTextRendering = false; - this.label1.UseMnemonic = true; - this.label1.BackColor = System.Drawing.SystemColors.Control; - this.label1.Enabled = true; - this.label1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.label1.ForeColor = System.Drawing.SystemColors.ControlText; - this.label1.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.label1.MaximumSize = new System.Drawing.Size(0, 0); - this.label1.MinimumSize = new System.Drawing.Size(0, 0); - this.label1.TabIndex = 14; - this.label1.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.label1.Size = new System.Drawing.Size(70, 23); - this.label1.Location = new System.Drawing.Point(19, 320); - this.label1.Text = "单台取整:"; - this.label1.Name = "label1"; - - // - // label2 - // - this.label2.Dock = System.Windows.Forms.DockStyle.None; - this.label2.AutoSize = false; - this.label2.AutoEllipsis = false; - this.label2.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.label2.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.label2.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label2.LiveSetting = System.Windows.Forms.Automation.AutomationLiveSetting.Off; - this.label2.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.label2.UseCompatibleTextRendering = false; - this.label2.UseMnemonic = true; - this.label2.BackColor = System.Drawing.SystemColors.Control; - this.label2.Enabled = true; - this.label2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.label2.ForeColor = System.Drawing.SystemColors.ControlText; - this.label2.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.label2.MaximumSize = new System.Drawing.Size(0, 0); - this.label2.MinimumSize = new System.Drawing.Size(0, 0); - this.label2.TabIndex = 15; - this.label2.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.label2.Size = new System.Drawing.Size(70, 20); - this.label2.Location = new System.Drawing.Point(379, 324); - this.label2.Text = "项目取整:"; - this.label2.Name = "label2"; - - // - // comboBox2 - // - this.comboBox2.Dock = System.Windows.Forms.DockStyle.None; - this.comboBox2.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.comboBox2.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.comboBox2.BackColor = System.Drawing.SystemColors.Window; - this.comboBox2.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.comboBox2.DropDownWidth = 220; - this.comboBox2.DropDownHeight = 106; - this.comboBox2.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.comboBox2.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox2.IntegralHeight = true; - this.comboBox2.ItemHeight = 12; - this.comboBox2.MaxDropDownItems = 8; - this.comboBox2.MaximumSize = new System.Drawing.Size(0, 0); - this.comboBox2.MinimumSize = new System.Drawing.Size(0, 0); - this.comboBox2.MaxLength = 0; - this.comboBox2.Sorted = false; - this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.comboBox2.FormattingEnabled = false; - this.comboBox2.Enabled = true; - this.comboBox2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.comboBox2.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.comboBox2.TabIndex = 14; - this.comboBox2.TabStop = true; - this.comboBox2.Size = new System.Drawing.Size(220, 20); - this.comboBox2.Location = new System.Drawing.Point(95, 324); - this.comboBox2.Text = "四舍五入"; - this.comboBox2.Name = "comboBox2"; - - // - // cmb项目总价 - // - this.cmb项目总价.Dock = System.Windows.Forms.DockStyle.None; - this.cmb项目总价.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None; - this.cmb项目总价.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None; - this.cmb项目总价.BackColor = System.Drawing.SystemColors.Window; - this.cmb项目总价.DrawMode = System.Windows.Forms.DrawMode.Normal; - this.cmb项目总价.DropDownWidth = 200; - this.cmb项目总价.DropDownHeight = 106; - this.cmb项目总价.FlatStyle = System.Windows.Forms.FlatStyle.Standard; - this.cmb项目总价.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb项目总价.IntegralHeight = true; - this.cmb项目总价.ItemHeight = 12; - this.cmb项目总价.MaxDropDownItems = 8; - this.cmb项目总价.MaximumSize = new System.Drawing.Size(0, 0); - this.cmb项目总价.MinimumSize = new System.Drawing.Size(0, 0); - this.cmb项目总价.MaxLength = 0; - this.cmb项目总价.Sorted = false; - this.cmb项目总价.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; - this.cmb项目总价.FormattingEnabled = false; - this.cmb项目总价.Enabled = true; - this.cmb项目总价.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.cmb项目总价.Margin = new System.Windows.Forms.Padding(3, 3, 3, 3); - this.cmb项目总价.TabIndex = 14; - this.cmb项目总价.TabStop = true; - this.cmb项目总价.Size = new System.Drawing.Size(210, 20); - this.cmb项目总价.Location = new System.Drawing.Point(455, 290); - this.cmb项目总价.Text = "保留整数"; - this.cmb项目总价.Name = "cmb项目总价"; - - // 新建项目 - this.Controls.AddRange(new System.Windows.Forms.Control[] { - this.lbl项目编号, - this.txt项目编号, - this.lbl项目日期, - this.txt项目日期, - this.lbl项目名称, - this.txt项目名称, - this.lbl客户名称, - this.txt客户名称, - this.btn选择客户, - this.lbl客户地址, - this.txt客户地址, - this.lbl联系人, - this.txt联系人, - this.lbl联系电话, - this.txt联系电话, - this.lbl成套厂名称, - this.txt成套厂名称, - this.lbl成套厂地址, - this.txt成套厂地址, - this.lbl成套厂联系人, - this.txt成套厂联系人, - this.lbl成套厂联系电话, - this.txt成套厂联系电话, - this.lbl报出方式, - this.cmb报出方式, - this.lbl箱柜模板, - this.cmb箱柜模板, - this.lbl单台价格, - this.cmb单台价格, - this.lbl项目总价, - this.lbl备注, - this.txt备注, - this.btn确定, - this.btn取消, - this.comboBox1, - this.label1, - this.label2, - this.comboBox2, - this.cmb项目总价, - }); - // - // 新建项目 - // - this.Dock = System.Windows.Forms.DockStyle.None; - this.AutoScroll = false; - this.AutoSize = false; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; - this.AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocusChange; - this.BackColor = System.Drawing.SystemColors.Control; - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.ControlBox = true; - this.HelpButton = false; - this.IsMdiContainer = false; - this.KeyPreview = false; - this.MaximumSize = new System.Drawing.Size(0, 0); - this.MinimumSize = new System.Drawing.Size(0, 0); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Opacity = 1; - this.RightToLeftLayout = false; - this.ShowInTaskbar = true; - this.ShowIcon = true; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Auto; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.TopMost = false; - this.WindowState = System.Windows.Forms.FormWindowState.Normal; - this.AutoScrollMargin = new System.Drawing.Size(0, 0); - this.AutoScrollMinSize = new System.Drawing.Size(0, 0); - this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Tile; - this.Enabled = true; - this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.ForeColor = System.Drawing.SystemColors.ControlText; - this.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.Size = new System.Drawing.Size(700, 538); - this.Text = "新建项目"; - this.Name = "新建项目"; - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.Label lbl项目编号; - private System.Windows.Forms.TextBox txt项目编号; - private System.Windows.Forms.Label lbl项目日期; - private System.Windows.Forms.TextBox txt项目日期; - private System.Windows.Forms.Label lbl项目名称; - private System.Windows.Forms.TextBox txt项目名称; - private System.Windows.Forms.Label lbl客户名称; - private System.Windows.Forms.TextBox txt客户名称; - private System.Windows.Forms.Button btn选择客户; - private System.Windows.Forms.Label lbl客户地址; - private System.Windows.Forms.TextBox txt客户地址; - private System.Windows.Forms.Label lbl联系人; - private System.Windows.Forms.TextBox txt联系人; - private System.Windows.Forms.Label lbl联系电话; - private System.Windows.Forms.TextBox txt联系电话; - private System.Windows.Forms.Label lbl成套厂名称; - private System.Windows.Forms.TextBox txt成套厂名称; - private System.Windows.Forms.Label lbl成套厂地址; - private System.Windows.Forms.TextBox txt成套厂地址; - private System.Windows.Forms.Label lbl成套厂联系人; - private System.Windows.Forms.TextBox txt成套厂联系人; - private System.Windows.Forms.Label lbl成套厂联系电话; - private System.Windows.Forms.TextBox txt成套厂联系电话; - private System.Windows.Forms.Label lbl报出方式; - private System.Windows.Forms.ComboBox cmb报出方式; - private System.Windows.Forms.Label lbl箱柜模板; - private System.Windows.Forms.ComboBox cmb箱柜模板; - private System.Windows.Forms.Label lbl单台价格; - private System.Windows.Forms.ComboBox cmb单台价格; - private System.Windows.Forms.Label lbl项目总价; - private System.Windows.Forms.Label lbl备注; - private System.Windows.Forms.TextBox txt备注; - private System.Windows.Forms.Button btn确定; - private System.Windows.Forms.Button btn取消; - private System.Windows.Forms.ComboBox comboBox1; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.ComboBox comboBox2; - private System.Windows.Forms.ComboBox cmb项目总价; - } -} diff --git a/cadbt/cadbt/Program.cs b/cadbt/cadbt/Program.cs deleted file mode 100644 index f041c15..0000000 --- a/cadbt/cadbt/Program.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 由SharpDevelop创建。 - * 用户: 099978 - * 日期: 2026-09-04 - * 时间: 12:24 - * - * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 - */ -using System; -using System.Windows.Forms; - -namespace cadbt -{ - /// - /// Class with program entry point. - /// - internal sealed class Program - { - /// - /// Program entry point. - /// - [STAThread] - private static void Main(string[] args) - { - // 单实例保护:重复启动时激活已有实例并退出,避免残留多个进程 - bool createdNew; - using (var mutex = new System.Threading.Mutex(true, "cadbt_SingleInstance", out createdNew)) - { - if (!createdNew) - { - MessageBox.Show("cadbt 已在运行中。", "cadbt", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); - GC.KeepAlive(mutex); - } - } - - } -} diff --git a/cadbt/cadbt/Properties/AssemblyInfo.cs b/cadbt/cadbt/Properties/AssemblyInfo.cs deleted file mode 100644 index a0a3c60..0000000 --- a/cadbt/cadbt/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -#region Using directives - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -#endregion - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("cadbt")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("cadbt")] -[assembly: AssemblyCopyright("Copyright 2026")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.*")] diff --git a/cadbt/cadbt/app.config b/cadbt/cadbt/app.config deleted file mode 100644 index f6ecaf5..0000000 --- a/cadbt/cadbt/app.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/cadbt/cadbt/app.manifest b/cadbt/cadbt/app.manifest deleted file mode 100644 index 6d88151..0000000 --- a/cadbt/cadbt/app.manifest +++ /dev/null @@ -1,8 +0,0 @@ - - - - - true - - - diff --git a/cadbt/cadbt/cadbt.csproj b/cadbt/cadbt/cadbt.csproj deleted file mode 100644 index d9fcca4..0000000 --- a/cadbt/cadbt/cadbt.csproj +++ /dev/null @@ -1,147 +0,0 @@ - - - - {0A91D57B-B279-4672-9440-78088D022EB1} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Debug - AnyCPU - WinExe - cadbt - cadbt - v4.8 - Properties - x86 - app.manifest - - - bin\Debug\ - True - Full - False - True - DEBUG;TRACE - - - bin\Release\ - False - None - True - False - TRACE - - - True - - - - 4.0 - - - - 3.5 - - - - 3.5 - - - - - - 3.5 - - - 3.5 - - - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\Smart.CustomComponents.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Data.SQLite.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\log4net.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Resources.Extensions.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Memory.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Runtime.CompilerServices.Unsafe.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Numerics.Vectors.dll - True - - - libs\AdvancedDataGridView.dll - True - - - libs\webview2\Microsoft.Web.WebView2.Core.dll - True - - - libs\webview2\Microsoft.Web.WebView2.WinForms.dll - True - - - - - - MainForm.cs - - - MainForm.cs - - - - - - - Form3.cs - - - - - 新建项目.cs - - - - CadViewerWindow.cs - - - - QuoteWindow.cs - - - - - - - - - WebView2Loader.dll - PreserveNewest - - - - \ No newline at end of file diff --git a/cadbt/cadbt/lib/Smart.CustomComponents.dll b/cadbt/cadbt/lib/Smart.CustomComponents.dll deleted file mode 100644 index 717c96b..0000000 Binary files a/cadbt/cadbt/lib/Smart.CustomComponents.dll and /dev/null differ diff --git a/cadbt/cadbt/libs/AdvancedDataGridView.dll b/cadbt/cadbt/libs/AdvancedDataGridView.dll deleted file mode 100644 index f520283..0000000 Binary files a/cadbt/cadbt/libs/AdvancedDataGridView.dll and /dev/null differ diff --git a/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.Core.dll b/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.Core.dll deleted file mode 100644 index 4a27877..0000000 Binary files a/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.Core.dll and /dev/null differ diff --git a/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.WinForms.dll b/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.WinForms.dll deleted file mode 100644 index 21caf04..0000000 Binary files a/cadbt/cadbt/libs/webview2/Microsoft.Web.WebView2.WinForms.dll and /dev/null differ diff --git a/cadbt/cadbt/libs/webview2/WebView2Loader.dll b/cadbt/cadbt/libs/webview2/WebView2Loader.dll deleted file mode 100644 index a8565ba..0000000 Binary files a/cadbt/cadbt/libs/webview2/WebView2Loader.dll and /dev/null differ diff --git a/ghj/MainForm.Designer.cs b/ghj/MainForm.Designer.cs deleted file mode 100644 index dcf54ff..0000000 --- a/ghj/MainForm.Designer.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 由SharpDevelop创建。 - * 用户: 099978 - * 日期: 2026-09-28 - * 时间: 13:00 - * - * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 - */ -namespace ghj -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - // - // MainForm - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Text = "ghj"; - this.Name = "MainForm"; - } - } -} diff --git a/ghj/MainForm.cs b/ghj/MainForm.cs deleted file mode 100644 index 087ae95..0000000 --- a/ghj/MainForm.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 由SharpDevelop创建。 - * 用户: 099978 - * 日期: 2026-09-28 - * 时间: 13:00 - * - * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 - */ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; - -namespace ghj -{ - /// - /// Description of MainForm. - /// - public partial class MainForm : Form - { - public MainForm() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - - // - // TODO: Add constructor code after the InitializeComponent() call. - // - } - } -} diff --git a/ghj/Program.cs b/ghj/Program.cs deleted file mode 100644 index 80d5687..0000000 --- a/ghj/Program.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 由SharpDevelop创建。 - * 用户: 099978 - * 日期: 2026-09-28 - * 时间: 13:00 - * - * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 - */ -using System; -using System.Windows.Forms; - -namespace ghj -{ - /// - /// Class with program entry point. - /// - internal sealed class Program - { - /// - /// Program entry point. - /// - [STAThread] - private static void Main(string[] args) - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); - } - - } -} diff --git a/ghj/Properties/AssemblyInfo.cs b/ghj/Properties/AssemblyInfo.cs deleted file mode 100644 index 3fb9ecc..0000000 --- a/ghj/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -#region Using directives - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -#endregion - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ghj")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ghj")] -[assembly: AssemblyCopyright("Copyright 2026")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.*")] diff --git a/ghj/app.config b/ghj/app.config deleted file mode 100644 index f6ecaf5..0000000 --- a/ghj/app.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ghj/app.manifest b/ghj/app.manifest deleted file mode 100644 index 6d88151..0000000 --- a/ghj/app.manifest +++ /dev/null @@ -1,8 +0,0 @@ - - - - - true - - - diff --git a/ghj/ghj.csproj b/ghj/ghj.csproj deleted file mode 100644 index c64f235..0000000 --- a/ghj/ghj.csproj +++ /dev/null @@ -1,67 +0,0 @@ - - - - {C9E28D5E-B911-4F7C-9C9D-75EBD3250694} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Debug - AnyCPU - WinExe - ghj - ghj - v4.8 - Properties - x86 - app.manifest - - - bin\Debug\ - True - Full - False - True - DEBUG;TRACE - - - bin\Release\ - False - None - True - False - TRACE - - - True - - - - 4.0 - - - - 3.5 - - - - 3.5 - - - - - - 3.5 - - - - - - MainForm.cs - - - - - - - - - - \ No newline at end of file diff --git a/pdfbt/.zcode/plans/plan-sess_102a5996-c0fe-48a9-b058-69b91506b2b8.md b/pdfbt/.zcode/plans/plan-sess_102a5996-c0fe-48a9-b058-69b91506b2b8.md deleted file mode 100644 index a7cefa0..0000000 --- a/pdfbt/.zcode/plans/plan-sess_102a5996-c0fe-48a9-b058-69b91506b2b8.md +++ /dev/null @@ -1,29 +0,0 @@ -# 新增 UApiPro(uapis.cn) 通用文字识别引擎(第五个 OCR 引擎) - -## 已确认的接口细节(官方文档 + 官网已核实) -- 端点:`POST https://uapis.cn/api/v1/image/ocr`,multipart/form-data -- 鉴权:`X-API-Key: `(uapis.cn/console 邮箱注册即生成,免费积分 4积分/次,限速 4QPS) -- 请求字段:`image_base64`(纯 base64 或 DataURI)+ `need_location="true"`(返回坐标)+ `enable_cls="true"`(方向校正) -- 响应:`words_result[]{words, location{left,top,width,height}, score}` ——**每行带位置和置信度**,结构与百度OCR几乎一致 -- 布尔参数是字符串形式;图片 ≤10MB - -## 修改文件 - -### 1. 新增 UapisOcrClient.cs -- multipart/form-data 手工拼装(net48 无 MultipartFormDataContent) -- words_result 解析 → OcrItem(location 像素坐标直接用,score 保留供图形符号过滤用) -- 错误处理:HTTP 错误体 {code,message} 与业务 code 非 200 双查 -- Key 存 baidu_ocr.json 的 uapis_api_key - -### 2. OcrClient.cs 路由加 "uapis" -- 新增 _uapis 成员 + StatusChanged 转发 + LoadConfig 注入 Key + RecognizeAsync 路由 - -### 3. OcrSettingsForm 第四个引擎选项 -- 下拉加"UApiPro 通用OCR(免费积分/带位置)";选中显示 UApiPro Key 输入行;保存 uapis_api_key - -### 4. csproj 注册 → 编译 → 关闭重启 → 交付说明 - -## 说明 -- 该引擎带 score 置信度,图形符号过滤(<0.8 短串拦截、<0.55 长文本兜底)对它自动生效 -- 4QPS 限速对人工框选节奏完全够用;免费积分计费 -- 五引擎格局:百度(内置Key即用)/ 智谱GLM / 千帆PaddleOCR-VL / UApiPro,外加本地GPU rapidocr 已退役 \ No newline at end of file diff --git a/pdfbt/DockWindows/QuoteWindow.Designer.cs b/pdfbt/DockWindows/QuoteWindow.Designer.cs deleted file mode 100644 index 4774ff4..0000000 --- a/pdfbt/DockWindows/QuoteWindow.Designer.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace pdfbt.DockWindows -{ - partial class QuoteWindow - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) components.Dispose(); - base.Dispose(disposing); - } - - #region Designer generated code - - private void InitializeComponent() - { - this.SuspendLayout(); - // - // QuoteWindow - // - this.Name = "QuoteWindow"; - this.ResumeLayout(false); - } - - #endregion - } -} diff --git a/pdfbt/DockWindows/QuoteWindow.cs b/pdfbt/DockWindows/QuoteWindow.cs deleted file mode 100644 index 7d7fc03..0000000 --- a/pdfbt/DockWindows/QuoteWindow.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ============================================================ -// 停靠窗口:报价插件工具栏(左侧) -// 把 cadcj 的 Form3 报价界面作为子控件嵌入(TopLevel=false)。 -// ============================================================ -using System.Windows.Forms; - -namespace pdfbt.DockWindows -{ - /// 停靠窗口:报价插件工具栏(DockState.DockLeft)。 - public partial class QuoteWindow : WeifenLuo.WinFormsUI.Docking.DockContent - { - public QuoteWindow() - { - InitializeComponent(); - Text = "报价工具"; - TabText = "报价工具"; - - var form = new MyApp.Form3(); - form.TopLevel = false; - form.FormBorderStyle = FormBorderStyle.None; - form.Dock = DockStyle.Fill; - Controls.Add(form); - form.Show(); - } - } -} diff --git a/pdfbt/MainForm.Designer.cs b/pdfbt/MainForm.Designer.cs deleted file mode 100644 index 79cc738..0000000 --- a/pdfbt/MainForm.Designer.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace pdfbt -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. - /// - private void InitializeComponent() - { - Smart.CustomComponents.DockWindows.DockWindowItem dockWindowItem1 = new Smart.CustomComponents.DockWindows.DockWindowItem(); - Smart.CustomComponents.DockWindows.DockWindowItem dockWindowItem2 = new Smart.CustomComponents.DockWindows.DockWindowItem(); - this.dockSurface1 = new Smart.CustomComponents.DockSurface(); - this.SuspendLayout(); - // - // dockSurface1 - // - this.dockSurface1.Dock = System.Windows.Forms.DockStyle.Fill; - this.dockSurface1.DockBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(238)))), ((int)(((byte)(238)))), ((int)(((byte)(242))))); - dockWindowItem1.ClassName = "QuoteWindow"; - dockWindowItem1.DefaultWidth = 440; - dockWindowItem1.ShowCloseButton = false; - dockWindowItem1.Title = "报价工具"; - dockWindowItem2.ClassName = "PdfViewerWindow"; - dockWindowItem2.DockState = WeifenLuo.WinFormsUI.Docking.DockState.Document; - dockWindowItem2.ShowCloseButton = false; - dockWindowItem2.Title = "PDF 查看器"; - this.dockSurface1.DockWindows.Add(dockWindowItem1); - this.dockSurface1.DockWindows.Add(dockWindowItem2); - this.dockSurface1.Location = new System.Drawing.Point(0, 0); - this.dockSurface1.Name = "dockSurface1"; - this.dockSurface1.Padding = new System.Windows.Forms.Padding(6); - this.dockSurface1.ShowAutoHideContentOnHover = false; - this.dockSurface1.Size = new System.Drawing.Size(1184, 661); - this.dockSurface1.TabIndex = 0; - // - // MainForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1184, 661); - this.Controls.Add(this.dockSurface1); - this.Name = "MainForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "PDF 扒图"; - this.ResumeLayout(false); - - } - - private Smart.CustomComponents.DockSurface dockSurface1; - } -} diff --git a/pdfbt/MainForm.DockWindows.cs b/pdfbt/MainForm.DockWindows.cs deleted file mode 100644 index 76ed75b..0000000 --- a/pdfbt/MainForm.DockWindows.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 本文件由『生成停靠窗口代码』自动生成格式参考手写,集合变更后请同步刷新。 -using System; -using WeifenLuo.WinFormsUI.Docking; - -namespace pdfbt -{ - public partial class MainForm - { - void CreateDockWindows_dockSurface1() - { - var dockSurface1 = this.dockSurface1 as Smart.CustomComponents.DockSurface; - if (dockSurface1 == null) return; - dockSurface1.EnsureDefaultTheme(); // 必须:Show 前保证有效主题 - - var quote = new pdfbt.DockWindows.QuoteWindow(); - quote.CloseButtonVisible = false; - quote.TabText = "报价工具"; - quote.Text = "报价工具"; - quote.Show(dockSurface1, DockState.DockLeft); - - var viewer = new pdfbt.PdfViewerWindow(); - viewer.CloseButtonVisible = false; - viewer.TabText = "PDF 查看器"; - viewer.Text = "PDF 查看器"; - viewer.Show(dockSurface1, DockState.Document); - } - } -} diff --git a/pdfbt/MainForm.cs b/pdfbt/MainForm.cs deleted file mode 100644 index 762c334..0000000 --- a/pdfbt/MainForm.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * MainForm:主窗体(报价工具 + PDF 查看器) - * 由 cadbt 改造:WebView2 网页 CAD → pdfium 原生 PDF 查看 + 框选 OCR - */ -using System; -using System.IO; -using System.Windows.Forms; -using 成套报价软件; // ★ A1:OCR/PDF 基础设施已链接共享主项目源码(类型在 成套报价软件 命名空间) -namespace pdfbt -{ - public partial class MainForm : Form - { - public MainForm() - { - InitializeComponent(); - CreateDockWindows_dockSurface1(); - - // ★ 全局 F1/F2/F3 过滤器:焦点在任何 WinForms 控件上都触发元件合并 - // (与 cadbt 一致,两路都汇聚到 PdfBridge.F*Requested) - Application.AddMessageFilter(new F1MessageFilter()); - FormClosed += (s, e) => Application.RemoveMessageFilter(f1Filter); - - // ★ Umi-OCR 预热:已装本体且当前引擎为 umi 时,主程序一启动就静默拉起 - // (--hide 托盘),不等首次框选;后台线程跑,不拖慢窗口出现 - System.Threading.ThreadPool.QueueUserWorkItem(_ => - { - try - { - if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "baidu_ocr.json"))) - { - var jsv = new System.Web.Script.Serialization.JavaScriptSerializer() - .Deserialize>( - File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "baidu_ocr.json"))); - string eng = jsv != null && jsv.ContainsKey("engine") ? jsv["engine"] : "baidu"; - if (eng == "umi" && UmiOcrHost.IsInstalled) UmiOcrLauncher.EnsureRunning(); // ★ A1:启停已拆到 UmiOcrLauncher(主项目共享版) - } - } - catch { } - }); - } - - private readonly F1MessageFilter f1Filter = new F1MessageFilter(); - - /// - /// 把 F1/F2/F3 按键(0x70/0x71/0x72)转成 PdfBridge 事件。 - /// ★ 焦点在报价插件(Form3)树内时不触发——那条路径由 Form3.ProcessCmdKey - /// 处理,此处再触发会双跑一次(F1 合并两遍:第一遍成功、第二遍弹 - /// "请先选中至少2行"的误提示)。 - /// - private class F1MessageFilter : IMessageFilter - { - public bool PreFilterMessage(ref Message m) - { - const int WM_KEYDOWN = 0x0100; - bool isFKey = m.Msg == WM_KEYDOWN && - ((int)m.WParam == 0x70 || (int)m.WParam == 0x71 || (int)m.WParam == 0x72); - if (!isFKey) return false; - - // 焦点控件在 Form3 树内 → 交给 Form3.ProcessCmdKey,跳过 - try - { - var focused = Control.FromHandle(m.HWnd); - for (var c = focused; c != null; c = c.Parent) - { - if (c is MyApp.Form3) return false; - } - } - catch { } - - int key = (int)m.WParam; - try - { - if (key == 0x70) PdfBridge.RaiseF1(); - else if (key == 0x71) PdfBridge.RaiseF2(); - else if (key == 0x72) PdfBridge.RaiseF3(); - } - catch { } - return false; - } - } - } -} diff --git a/pdfbt/MainForm.resx b/pdfbt/MainForm.resx deleted file mode 100644 index 1af7de1..0000000 --- a/pdfbt/MainForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/pdfbt/PdfBridge.cs b/pdfbt/PdfBridge.cs deleted file mode 100644 index 9ecef9c..0000000 --- a/pdfbt/PdfBridge.cs +++ /dev/null @@ -1,148 +0,0 @@ -// ============================================================ -// PdfBridge:报价插件(Form3)与 PDF 查看器之间的桥 -// 与 cadbt 的 CadBridge 保持相同的 API 形状: -// · 下行(Form3→查看器):SendPaCommand / ZoomToFrameHandle / -// DeleteFramesByHandles / MergeMasks / ClearHighlight -// · 上行(查看器→Form3):PaPicked / EntityErased / PaExited / -// F1/F2/F3Requested -// 扒图逻辑:用户在 PDF 上框选 → 裁剪 → OCR 工作进程识别 → -// 按 CAD 版语义组装 results(正向逐条/反向合并) → PaPicked -// → Form3 入表格;查看器在框选位置画彩色蒙版框。 -// ============================================================ -using System; -using System.Collections.Generic; - -namespace pdfbt -{ - public static class PdfBridge - { - private static PdfViewerWindow _viewer; - - /// PDF 查看器是否已挂载且打开了文档。 - public static bool IsViewerReady - { - get { return _viewer != null && _viewer.IsDocumentOpen; } - } - - /// 扒图连续模式当前是否激活(供 ESC 全局过滤判断)。 - public static bool PickModeActive - { - get { return _viewer != null && _viewer.PickModeActive; } - } - - /// 兼容 CadBridge:查看器中蒙版被外部删除(当前无触发源,保留事件形状)。 - public static event Action EntityErased; - - /// 框选识别完成一批(图号/箱号/元件)。 - public static event Action> PaPicked; - - /// 用户按 ESC 退出连续扒图模式。 - public static event Action PaExited; - - /// 用户按 F1 —— 元件两两合并。 - public static event Action F1Requested; - - /// 用户按 F2 —— 元件三个一组合并。 - public static event Action F2Requested; - - /// 用户按 F3 —— 元件四个一组合并。 - public static event Action F3Requested; - - /// 把 PDF 查看器挂到桥上(查看器构造时调用一次)。 - public static void Attach(PdfViewerWindow viewer) - { - _viewer = viewer; - } - - // ------------------------------------------------------------ - // 查看器 → Form3 的上行事件触发(仅查看器调用) - // ------------------------------------------------------------ - - public static void RaisePaPicked(MyApp.PaMode mode, List results) - { - if (PaPicked != null) PaPicked(mode, results); - } - - public static void RaisePaExited() - { - if (PaExited != null) PaExited(); - } - - public static void RaiseEntityErased(string handle) - { - if (!string.IsNullOrWhiteSpace(handle) && EntityErased != null) - EntityErased(handle); - } - - public static void RaiseF1() { if (F1Requested != null) F1Requested(); } - public static void RaiseF2() { if (F2Requested != null) F2Requested(); } - public static void RaiseF3() { if (F3Requested != null) F3Requested(); } - - // ------------------------------------------------------------ - // Form3 → 查看器的下行命令 - // ------------------------------------------------------------ - - /// - /// 发送扒图命令。接受原 CAD 命令名(CADPATU/CADPAXH/CADPAYJ/CADPACL) - /// 或网页命令名(patu/paxh/payj/pacl)。 - /// - public static void SendPaCommand(string cmd) - { - if (string.IsNullOrWhiteSpace(cmd)) return; - string c = cmd.Trim().ToUpperInvariant(); - int mode = 0; - if (c == "CADPATU" || c == "PATU") mode = 0; - else if (c == "CADPAXH" || c == "PAXH") mode = 1; - else if (c == "CADPAYJ" || c == "PAYJ") mode = 2; - else if (c == "CADPACL" || c == "PACL") - { - ClearHighlight(); - return; - } - else return; - - if (_viewer == null) return; - _viewer.StartPick(mode); - } - - /// 定位到指定 Handle 的蒙版框(点击表格行定位)。 - public static void ZoomToFrameHandle(string handle) - { - if (string.IsNullOrWhiteSpace(handle) || _viewer == null) return; - _viewer.ZoomToFrame(handle); - } - - /// 批量删除指定 Handle 的蒙版(删表格行联动删框)。 - public static void DeleteFramesByHandles(IEnumerable handles) - { - if (handles == null || _viewer == null) return; - var list = new List(); - foreach (string h in handles) - if (!string.IsNullOrWhiteSpace(h)) list.Add(h); - if (list.Count == 0) return; - _viewer.DeleteFrames(list); - } - - /// - /// 合并蒙版:保留 keep 的蒙版并扩大到所有 removes 蒙版的并集, - /// 被合并行的蒙版移除(元件合并时蒙版同步合并)。 - /// - public static void MergeMasks(string keep, IEnumerable removes) - { - if (string.IsNullOrWhiteSpace(keep) || _viewer == null) return; - var list = new List(); - if (removes != null) - foreach (string h in removes) - if (!string.IsNullOrWhiteSpace(h) && h != keep) list.Add(h); - if (list.Count == 0) return; - _viewer.MergeMasks(keep, list); - } - - /// 清除所有高亮。 - public static void ClearHighlight() - { - if (_viewer == null) return; - _viewer.ClearHighlight(); - } - } -} diff --git a/pdfbt/PdfViewerWindow.cs b/pdfbt/PdfViewerWindow.cs deleted file mode 100644 index 4c36065..0000000 --- a/pdfbt/PdfViewerWindow.cs +++ /dev/null @@ -1,1400 +0,0 @@ -// ============================================================ -// PdfViewerWindow:停靠窗口(中央文档区)—— PDF 查看 + 框选 OCR 扒图 -// · pdfium 渲染;单画布自管理滚动偏移 + 双缓冲 → 拖动/滚动无闪烁 -// · 框选(仿 CAD 窗选语义): -// 正向(左→右) = 逐条:每个识别文本一个彩色蒙版框、各自 Handle -// 反向(右→左) = 合并:整块一个蒙版框、共享 Handle(Form3 拼接为一条规格) -// · ★ 框选区域按 300DPI 高清重渲染后交 Windows 内置 OCR(PowerShell 桥) -// —— 与屏幕缩放无关,任意缩放下识别质量一致,单次 ~0.1-0.3s -// · 结果按"列分组、列内从上到下"排序(与 CAD 版 PaTextSelector 一致) -// · 蒙版持久化:.pdfmask.json,重开 PDF 自动恢复 -// · ZoomToFrame/DeleteFrames/MergeMasks 供 PdfBridge 联动表格 -// ============================================================ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Web.Script.Serialization; -using 成套报价软件; // ★ A1:OCR/PDF 基础设施已链接共享主项目源码(类型在 成套报价软件 命名空间) -using System.Windows.Forms; -using WeifenLuo.WinFormsUI.Docking; - -namespace pdfbt -{ - /// 一个已绘制的蒙版框。 - public class PdfMaskItem - { - public string Handle; // 唯一编号 "M1"... - public string TextHandle; // 稳定文本标识(页+粗化位置),用于判重 - public int Page; // 0 基页码 - public RectangleF RectPt; // 页面坐标(PDF 点) - public int Mode; // 0=图号 1=箱号 2=元件 - - public Color Color - { - get { return MaskColor(Mode); } - } - - public static Color MaskColor(int mode) - { - switch (mode) - { - case 0: return Color.FromArgb(220, 40, 40); // 图号 红 - case 1: return Color.FromArgb(30, 110, 220); // 箱号 蓝 - default: return Color.FromArgb(20, 150, 90); // 元件 绿 - } - } - } - - /// PDF 查看器停靠窗口(DockState.Document)。 - public class PdfViewerWindow : DockContent - { - // ---------- 子控件 ---------- - private ToolStrip _toolbar; - private ToolStripButton _btnOpen; - private ToolStripButton _btnPrev, _btnNext; - private ToolStripLabel _lblPage; - private ToolStripButton _btnZoomOut, _btnZoomIn, _btnFitWidth, _btnFitPage; - private ToolStripLabel _lblZoom; - private ToolStripLabel _lblMode; - private StatusStrip _status; - private ToolStripStatusLabel _statusLeft, _statusOcr; - private ViewerCanvas _canvas; - private HScrollBar _hsb; - private VScrollBar _vsb; - - // ---------- 文档状态 ---------- - private PdfDocument _doc; - private float _zoom = 1.0f; // 1.0 = 96dpi 视觉尺寸 - private float _dpiFactor = 96f / 72f; // 像素/点 基准,构造时按实际 DPI 校准 - private int _pageIndex; - private float _pxPerPt; // 当前页实际渲染比例(等比上限修正后) - - // ---------- 滚动/平移 ---------- - private int _scrollX, _scrollY; // 页面位图相对视口原点偏移(≥0) - private bool _panning; - private Point _panStart; - private int _panScrollX, _panScrollY; - - // ---------- 扒图状态 ---------- - private int _pickMode = -1; // -1=未激活 0/1/2 - private bool _picking; - private Point _pickStart; // 画布客户区坐标 - private Rectangle _rubber; - private int _ocrBusyCount; - private bool _ocrErrorShown; - - // ---------- 蒙版 ---------- - private List _masks = new List(); - private HashSet _highlight = new HashSet(); - private int _handleCounter = 1; - private List _sessionPicked = new List(); - private string _maskSavePath; - - // ★ 缩放卡顿修复(2026-10-01):光栅化转后台线程的两根支柱 - private static readonly object PdfRenderGate = new object(); // pdfium 非线程安全,所有渲染/文档操作全局互斥 - private volatile int _renderGen; // 渲染代数:每次发起渲染+1,过期结果直接丢弃 - - private OcrClient _ocr; - private readonly JavaScriptSerializer _json = new JavaScriptSerializer(); - - private EventHandler _btnOcrcfg_Click; - - /// OCR 设置:打开设计器窗体 OcrSettingsForm。 - private void ShowOcrSettings() - { - using (var f = new OcrSettingsForm(_ocr)) - { - f.ShowDialog(this); - } - } - private Timer _highlightTimer; - - private const int MAX_RENDER_DIM = 8192; // 单边渲染像素上限(等比) - private const int OCR_MAX_DIM = 4000; // OCR 区域单边像素上限 - private const float OCR_DPI = 300f; // OCR 渲染分辨率 - - public bool IsDocumentOpen - { - get { return _doc != null && _doc.IsOpen; } - } - - public bool PickModeActive - { - get { return _pickMode >= 0; } - } - - public PdfViewerWindow() - { - BuildUi(); - Text = "PDF 查看器"; - TabText = "PDF 查看器"; - PdfBridge.Attach(this); - AllowDrop = true; - DragEnter += (s, e) => - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - e.Effect = DragDropEffects.Copy; - }; - DragDrop += (s, e) => - { - var files = e.Data.GetData(DataFormats.FileDrop) as string[]; - if (files != null && files.Length > 0) - OpenPdf(files[0]); - }; - - _ocr = new OcrClient(); - _ocr.StatusChanged += msg => - { - if (InvokeRequired) BeginInvoke((Action)(() => _statusOcr.Text = msg)); - else _statusOcr.Text = msg; - }; - - try - { - using (var g = CreateGraphics()) - _dpiFactor = g.DpiX / 72f; - } - catch { } - } - - // ============================================================ - // UI 构建 - // ============================================================ - private void BuildUi() - { - _toolbar = new ToolStrip(); - _toolbar.GripStyle = ToolStripGripStyle.Hidden; - _toolbar.RenderMode = ToolStripRenderMode.System; - - _btnOpen = new ToolStripButton("打开PDF"); - _btnOpen.Click += (s, e) => ShowOpenDialog(); - _btnPrev = new ToolStripButton("◀"); - _btnPrev.Click += (s, e) => SetPage(_pageIndex - 1); - _lblPage = new ToolStripLabel("0 / 0"); - _btnNext = new ToolStripButton("▶"); - _btnNext.Click += (s, e) => SetPage(_pageIndex + 1); - _btnZoomOut = new ToolStripButton("-"); - _btnZoomOut.Click += (s, e) => SetZoom(_zoom / 1.25f); - _lblZoom = new ToolStripLabel("100%"); - _btnZoomIn = new ToolStripButton("+"); - _btnZoomIn.Click += (s, e) => SetZoom(_zoom * 1.25f); - _btnFitWidth = new ToolStripButton("适合宽度"); - _btnFitWidth.Click += (s, e) => FitWidth(); - _btnFitPage = new ToolStripButton("适合整页"); - _btnFitPage.Click += (s, e) => FitPage(); - _lblMode = new ToolStripLabel(""); - _lblMode.ForeColor = Color.Firebrick; - _lblMode.Font = new Font(_lblMode.Font, FontStyle.Bold); - - _toolbar.Items.Add(_btnOpen); - var _btnOcrCfg = new ToolStripButton("OCR设置"); - _btnOcrcfg_Click = delegate { ShowOcrSettings(); }; - _btnOcrCfg.Click += _btnOcrcfg_Click; - _toolbar.Items.Add(_btnOcrCfg); - _toolbar.Items.Add(new ToolStripSeparator()); - _toolbar.Items.Add(_btnPrev); - _toolbar.Items.Add(_lblPage); - _toolbar.Items.Add(_btnNext); - _toolbar.Items.Add(new ToolStripSeparator()); - _toolbar.Items.Add(_btnZoomOut); - _toolbar.Items.Add(_lblZoom); - _toolbar.Items.Add(_btnZoomIn); - _toolbar.Items.Add(_btnFitWidth); - _toolbar.Items.Add(_btnFitPage); - _toolbar.Items.Add(new ToolStripSeparator()); - _toolbar.Items.Add(_lblMode); - - _status = new StatusStrip(); - _statusLeft = new ToolStripStatusLabel("请打开 PDF 图纸(或直接拖入窗口)"); - _statusLeft.Spring = true; - _statusLeft.TextAlign = ContentAlignment.MiddleLeft; - _statusOcr = new ToolStripStatusLabel("OCR 未启动"); - _status.Items.Add(_statusLeft); - _status.Items.Add(_statusOcr); - - _canvas = new ViewerCanvas(); - _canvas.Dock = DockStyle.Fill; - _canvas.BackColor = Color.FromArgb(70, 70, 74); - - _hsb = new HScrollBar(); - _hsb.Dock = DockStyle.Bottom; - _hsb.SmallChange = 30; - _hsb.LargeChange = 120; - _vsb = new VScrollBar(); - _vsb.Dock = DockStyle.Right; - _vsb.SmallChange = 30; - _vsb.LargeChange = 120; - _hsb.ValueChanged += (s, e) => { _scrollX = _hsb.Value; _canvas.Invalidate(); }; - _vsb.ValueChanged += (s, e) => { _scrollY = _vsb.Value; _canvas.Invalidate(); }; - - // 布局顺序(Dock 逆序处理):toolbar(Top) → status(Bottom) → hsb(Bottom) → vsb(Right) → canvas(Fill) - Controls.Add(_canvas); - Controls.Add(_vsb); - Controls.Add(_hsb); - Controls.Add(_status); - Controls.Add(_toolbar); - - _canvas.MouseDown += CanvasMouseDown; - _canvas.MouseMove += CanvasMouseMove; - _canvas.MouseUp += CanvasMouseUp; - _canvas.MouseWheel += CanvasMouseWheel; - _canvas.OriginProvider = () => PageOrigin; - _canvas.Resize += (s, e) => { UpdateScrollbars(); _canvas.Invalidate(); }; - - _highlightTimer = new Timer(); - _highlightTimer.Interval = 3000; - _highlightTimer.Tick += (s, e) => - { - _highlightTimer.Stop(); - _highlight.Clear(); - RefreshMasks(); - }; - } - - private void ShowOpenDialog() - { - using (var dlg = new OpenFileDialog()) - { - dlg.Filter = "PDF 文件 (*.pdf)|*.pdf|所有文件 (*.*)|*.*"; - dlg.Title = "打开 PDF 图纸"; - if (dlg.ShowDialog(this) == DialogResult.OK) - OpenPdf(dlg.FileName); - } - } - - // ============================================================ - // 打开 / 渲染 / 导航 - // ============================================================ - - public void OpenPdf(string path) - { - if (string.IsNullOrEmpty(path) || !File.Exists(path)) - { - MessageBox.Show(this, "文件不存在: " + path, "打开 PDF"); - return; - } - try - { - // ★ 先把当前 PDF 关掉再开新的(用户要求的机制)—— - // 旧文档(含后备缓冲/页句柄/掩码状态)先释放,也避免两份大 PDF 同时占内存 - if (_doc != null) - { - _renderGen++; // 作废所有在途后台渲染 - lock (PdfRenderGate) { _doc.Dispose(); } // 与后台渲染互斥,等它出锁再释放 - _doc = null; - } - - var doc = new PdfDocument(); - doc.Open(path, null); - _doc = doc; - _pageIndex = 0; - _scrollX = 0; _scrollY = 0; - _canvas.SetPage(null, 1f); // 清掉上一份 PDF 的位图,白底等新页(渲染已异步) - - _maskSavePath = path + ".pdfmask.json"; - LoadMasks(); - - Text = Path.GetFileName(path); - TabText = Path.GetFileName(path); - _statusLeft.Text = path + " · " + _doc.PageCount + " 页"; - - // ★ 强制重绘:SetZoom 在新旧 PDF 页宽相同(工程图同为 A4/A3 很常见)时 - // 算出相同缩放会直接 return,不触发 RenderCurrentPage——画布停留在 - // 第一份 PDF 的位图上("换 PDF 显示不变"的元凶)。先把缩放置为无效值, - // FitWidth→SetZoom 必然视为变化,强制渲染新文档。 - _zoom = -1f; - FitWidth(); - UpdateNavUi(); - } - catch (Exception ex) - { - MessageBox.Show(this, ex.Message, "打开 PDF 失败", - MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private float MaxZoom - { - get - { - if (!IsDocumentOpen) return 8f; - float maxSide = Math.Max(_doc.PageWidthPt[_pageIndex], _doc.PageHeightPt[_pageIndex]); - if (maxSide <= 0) return 8f; - return Math.Min(8f, MAX_RENDER_DIM / maxSide / _dpiFactor); - } - } - - private void SetPage(int index) - { - if (!IsDocumentOpen) return; - if (index < 0) index = 0; - if (index > _doc.PageCount - 1) index = _doc.PageCount - 1; - if (index == _pageIndex && _canvas.Page != null) return; - _pageIndex = index; - _scrollX = 0; _scrollY = 0; - RenderCurrentPage(clearPage: true); // 翻页:清旧页位图,白底等新页 - UpdateNavUi(); - } - - private void UpdateNavUi() - { - _lblPage.Text = IsDocumentOpen - ? (_pageIndex + 1) + " / " + _doc.PageCount - : "0 / 0"; - } - - private void SetZoom(float zoom) - { - zoom = Math.Max(0.05f, Math.Min(MaxZoom, zoom)); - if (Math.Abs(zoom - _zoom) < 0.001f) return; - _zoom = zoom; - _lblZoom.Text = (int)Math.Round(_zoom * 100) + "%"; - RenderCurrentPage(); - } - - private void FitWidth() - { - if (!IsDocumentOpen) return; - float pageWpt = _doc.PageWidthPt[_pageIndex]; - int avail = _canvas.ClientSize.Width - (int)_dpiFactor * 16; - if (pageWpt <= 0 || avail <= 0) return; - SetZoom(avail / (pageWpt * _dpiFactor)); - } - - private void FitPage() - { - if (!IsDocumentOpen) return; - float pageWpt = _doc.PageWidthPt[_pageIndex]; - float pageHpt = _doc.PageHeightPt[_pageIndex]; - int availW = _canvas.ClientSize.Width - (int)_dpiFactor * 16; - int availH = _canvas.ClientSize.Height - (int)_dpiFactor * 16; - if (pageWpt <= 0 || pageHpt <= 0) return; - float z = Math.Min(availW / (pageWpt * _dpiFactor), availH / (pageHpt * _dpiFactor)); - SetZoom(Math.Max(0.05f, z)); - } - - /// 异步重渲染当前页(等比限制在 MAX_RENDER_DIM 内)。 - /// ★ 缩放卡顿修复(2026-10-01):原来 UI 线程同步光栅化整页,大幅面工程图每档滚轮 - /// 冻结数百毫秒~秒级。现在:视图比例立即生效+旧位图拉伸过渡帧(滚轮即时反馈), - /// 光栅化转后台线程;连续触发用代数令牌只落最后一档,过期任务连渲染都不做。 - private void RenderCurrentPage(bool clearPage = false) - { - if (!IsDocumentOpen) - { - _canvas.SetPage(null, 1f); - UpdateScrollbars(); - _canvas.Invalidate(); - return; - } - - float scale = _zoom * _dpiFactor; - float maxSide = Math.Max(_doc.PageWidthPt[_pageIndex], _doc.PageHeightPt[_pageIndex]); - if (maxSide > 0 && scale * maxSide > MAX_RENDER_DIM) - scale = MAX_RENDER_DIM / maxSide; // ★ 等比降档,保持长宽比 - _pxPerPt = scale; - - if (clearPage) - { - // 翻页/换文档:旧页位图直接清掉(画布白底),避免"上一页拉伸"的错觉 - _canvas.SetPage(null, scale); - } - else - { - // 缩放:保留旧位图按新比例拉伸显示(过渡帧),高清渲染完成后自动替换 - _canvas.SetViewScale(scale); - } - UpdateScrollbars(); - _canvas.Invalidate(); - - int gen = ++_renderGen; - int page = _pageIndex; - var doc = _doc; - System.Threading.Tasks.Task.Factory.StartNew(() => - { - lock (PdfRenderGate) // pdfium 非线程安全:与 OCR 渲染/文档开关全局互斥 - { - if (gen != _renderGen || doc != _doc) return null; // 过期:不再光栅化 - return doc.RenderPage(page, scale); - } - }).ContinueWith(t => - { - var bmp = t.Result; - // 回 UI 线程后复核:期间又缩放/翻页/换文档/窗口销毁 → 丢弃结果 - if (gen != _renderGen || doc != _doc || page != _pageIndex || IsDisposed) - { - if (bmp != null) bmp.Dispose(); - return; - } - if (bmp == null) - { - _statusLeft.Text = "页面渲染失败"; - return; - } - _canvas.SetPage(bmp, scale); - _canvas.Masks = CurrentPageMasks(); - UpdateScrollbars(); - _canvas.Invalidate(); - }, TaskScheduler.FromCurrentSynchronizationContext()); - } - - private List CurrentPageMasks() - { - var list = new List(); - foreach (var m in _masks) - if (m.Page == _pageIndex) list.Add(m); - return list; - } - - private void RefreshMasks() - { - _canvas.Masks = CurrentPageMasks(); - _canvas.Highlight = _highlight; - _canvas.Invalidate(); - } - - // ============================================================ - // 滚动条 / 偏移 - // ============================================================ - - /// 页面位图按当前视图比例(ViewScale)的显示尺寸。 - /// 过渡帧拉伸期间与位图实际尺寸不同,滚动范围/原点/居中都必须用它。 - private Size PageViewSize - { - get - { - var p = _canvas.Page; - if (p == null) return Size.Empty; - float st = _canvas.ViewScale; - return new Size((int)Math.Round(p.Width * st), (int)Math.Round(p.Height * st)); - } - } - - private void UpdateScrollbars() - { - var view = PageViewSize; - int clientW = _canvas.ClientSize.Width; - int clientH = _canvas.ClientSize.Height; - int pageW = view.Width; - int pageH = view.Height; - - int maxX = Math.Max(0, pageW - clientW); - int maxY = Math.Max(0, pageH - clientH); - _scrollX = Clamp(_scrollX, 0, maxX); - _scrollY = Clamp(_scrollY, 0, maxY); - - _hsb.Enabled = maxX > 0; - _vsb.Enabled = maxY > 0; - // Maximum 需含 LargeChange 补偿,否则最大值滚不到底 - _hsb.LargeChange = Math.Max(10, Math.Min(clientW, maxX + 10)); - _hsb.Maximum = maxX + _hsb.LargeChange - 1; - _hsb.Value = Clamp(_hsb.Value, 0, Math.Max(0, _hsb.Maximum - _hsb.LargeChange + 1)); - if (_hsb.Value != _scrollX) _hsb.Value = _scrollX; - _vsb.LargeChange = Math.Max(10, Math.Min(clientH, maxY + 10)); - _vsb.Maximum = maxY + _vsb.LargeChange - 1; - _vsb.Value = Clamp(_vsb.Value, 0, Math.Max(0, _vsb.Maximum - _vsb.LargeChange + 1)); - if (_vsb.Value != _scrollY) _vsb.Value = _scrollY; - } - - private static int Clamp(int v, int lo, int hi) - { - if (hi < lo) hi = lo; - return v < lo ? lo : (v > hi ? hi : v); - } - - /// 页面位图在画布上的绘制原点(小于视口时居中)。按视图尺寸(含过渡帧拉伸)计算。 - private Point PageOrigin - { - get - { - var view = PageViewSize; - if (view.IsEmpty) return Point.Empty; - int dx = view.Width <= _canvas.ClientSize.Width - ? (_canvas.ClientSize.Width - view.Width) / 2 : -_scrollX; - int dy = view.Height <= _canvas.ClientSize.Height - ? (_canvas.ClientSize.Height - view.Height) / 2 : -_scrollY; - return new Point(dx, dy); - } - } - - // ============================================================ - // 鼠标交互 - // ============================================================ - - private void CanvasMouseDown(object sender, MouseEventArgs e) - { - _canvas.Focus(); - if (e.Button == MouseButtons.Middle) - { - _panStart = e.Location; - _panScrollX = _scrollX; - _panScrollY = _scrollY; - _panning = true; - return; - } - if (e.Button == MouseButtons.Right) - { - // ★ 扒图会话中右键循环切换模式(与网页 CAD 版一致): - // 图号→箱号→元件→退出;无会话时忽略 - if (_pickMode >= 0) - { - _picking = false; - _canvas.Rubber = Rectangle.Empty; - if (_pickMode == 0) StartPick(1); - else if (_pickMode == 1) StartPick(2); - else - { - ExitPickMode(); - PdfBridge.RaisePaExited(); - } - } - return; - } - if (e.Button == MouseButtons.Left && _pickMode >= 0 && IsDocumentOpen) - { - _picking = true; - _pickStart = e.Location; - _rubber = new Rectangle(e.Location, Size.Empty); - } - } - - private void CanvasMouseMove(object sender, MouseEventArgs e) - { - if (_panning) - { - var view = PageViewSize; // 视图尺寸(与滚动条范围一致) - int maxX = Math.Max(0, view.Width - _canvas.ClientSize.Width); - int maxY = Math.Max(0, view.Height - _canvas.ClientSize.Height); - _scrollX = Clamp(_panScrollX - (e.X - _panStart.X), 0, maxX); - _scrollY = Clamp(_panScrollY - (e.Y - _panStart.Y), 0, maxY); - SyncScrollbars(); - _canvas.Invalidate(); - return; - } - if (_picking) - { - _rubber = Rectangle.FromLTRB( - Math.Min(_pickStart.X, e.X), Math.Min(_pickStart.Y, e.Y), - Math.Max(_pickStart.X, e.X), Math.Max(_pickStart.Y, e.Y)); - _canvas.Rubber = _rubber; - _canvas.RubberMerge = _pickStart.X > e.X; // 反向拖拽 = 合并 - _canvas.Invalidate(); - } - } - - private void CanvasMouseUp(object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Middle) { _panning = false; return; } - - if (e.Button == MouseButtons.Left && _picking) - { - _picking = false; - _canvas.Rubber = Rectangle.Empty; - var rect = _rubber; - _rubber = Rectangle.Empty; - _canvas.Invalidate(); - - if (rect.Width < 5 || rect.Height < 5) return; // 误点忽略 - bool merge = _pickStart.X > e.X; // 反向 = 合并 - RunPickOcr(rect, merge); - } - } - - private void CanvasMouseWheel(object sender, MouseEventArgs e) - { - var hme = e as HandledMouseEventArgs; - if ((Control.ModifierKeys & Keys.Control) != 0) - { - if (hme != null) hme.Handled = true; - if (!IsDocumentOpen) return; - // 以鼠标为中心缩放:记住鼠标处页面点,缩放后滚回 - var origin = PageOrigin; - float ptX = (e.X - origin.X) / _pxPerPt; - float ptY = (e.Y - origin.Y) / _pxPerPt; - SetZoom(e.Delta > 0 ? _zoom * 1.2f : _zoom / 1.2f); - _scrollX = Clamp((int)(ptX * _pxPerPt) - e.X, 0, int.MaxValue); - _scrollY = Clamp((int)(ptY * _pxPerPt) - e.Y, 0, int.MaxValue); - UpdateScrollbars(); - SyncScrollbars(); - _canvas.Invalidate(); - } - else - { - if (hme != null) hme.Handled = true; - int pageH = PageViewSize.Height; // 视图尺寸(过渡帧拉伸期间跟随缩放) - int maxY = Math.Max(0, pageH - _canvas.ClientSize.Height); - _scrollY = Clamp(_scrollY - e.Delta, 0, maxY); - SyncScrollbars(); - _canvas.Invalidate(); - } - } - - private void SyncScrollbars() - { - if (_hsb.Value != _scrollX && _scrollX <= _hsb.Maximum) _hsb.Value = _scrollX; - if (_vsb.Value != _scrollY && _scrollY <= _vsb.Maximum) _vsb.Value = _scrollY; - } - - // ============================================================ - // 扒图:框选 → 高清重渲染 → OCR → 组装结果 + 蒙版 - // ============================================================ - - public void StartPick(int mode) - { - if (!IsDocumentOpen) - { - _statusLeft.Text = "请先打开 PDF 图纸,再点扒图按钮"; - return; - } - _pickMode = mode; - _highlight.Clear(); - RefreshMasks(); - string[] names = { "扒图号", "扒箱号", "扒元件" }; - _lblMode.Text = names[mode] + ":框选中(左→右逐条 / 右→左合并),ESC 退出"; - _canvas.Cursor = Cursors.Cross; - _statusLeft.Text = "框选识别:正向拖拽=逐条,反向拖拽=合并,ESC 退出"; - } - - public void ExitPickMode() - { - _pickMode = -1; - _picking = false; - _lblMode.Text = ""; - _canvas.Cursor = Cursors.Default; - _canvas.Rubber = Rectangle.Empty; - _canvas.Invalidate(); - _statusLeft.Text = "已退出扒图模式"; - } - - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - if (keyData == Keys.Escape && _pickMode >= 0) - { - ExitPickMode(); - PdfBridge.RaisePaExited(); - return true; - } - return base.ProcessCmdKey(ref msg, keyData); - } - - /// - /// 框选完成:客户区矩形 → 页面pt矩形 → 300DPI 高清重渲染 → OCR。 - /// ★ 与屏幕缩放无关:任意缩放下识别质量一致。 - /// - private void RunPickOcr(Rectangle rectClient, bool merge) - { - if (!IsDocumentOpen) return; - var origin = PageOrigin; - // 客户区 → 页面pt - float x0 = (rectClient.Left - origin.X) / _pxPerPt; - float y0 = (rectClient.Top - origin.Y) / _pxPerPt; - float x1 = (rectClient.Right - origin.X) / _pxPerPt; - float y1 = (rectClient.Bottom - origin.Y) / _pxPerPt; - var rectPt = RectangleF.FromLTRB( - Math.Min(x0, x1), Math.Min(y0, y1), Math.Max(x0, x1), Math.Max(y0, y1)); - - // OCR 渲染分辨率:300DPI,单边超限降档;不低于当前屏幕渲染比例 - float ocrScale = OCR_DPI / 72f; - float maxSidePt = Math.Max(rectPt.Width, rectPt.Height); - if (maxSidePt > 0 && maxSidePt * ocrScale > OCR_MAX_DIM) - ocrScale = OCR_MAX_DIM / maxSidePt; - if (ocrScale < _pxPerPt) ocrScale = _pxPerPt; - - Bitmap crop; - try - { - lock (PdfRenderGate) // pdfium 非线程安全:与后台缩放渲染互斥 - { - crop = _doc.RenderRegion(_pageIndex, rectPt, ocrScale); - } - } - catch (Exception ex) - { - _statusLeft.Text = "框选区域渲染失败: " + ex.Message; - return; - } - if (crop == null || crop.Width < 4 || crop.Height < 4) return; - - // Umi-OCR 本地引擎:识别前确保本体已安装且服务在线(懒启动,首次约几秒) - if (_ocr.Engine == "umi") - { - try - { - _statusLeft.Text = "正在启动 Umi-OCR 本地引擎…"; - if (!UmiOcrLauncher.EnsureRunning()) // ★ A1:启停已拆到 UmiOcrLauncher(主项目共享版) - { - _statusLeft.Text = "Umi-OCR 服务启动超时(本体已安装),请稍后重试或检查 Umi-OCR 窗口"; - crop.Dispose(); - return; - } - } - catch (Exception exUmi) - { - _statusLeft.Text = exUmi.Message; - MessageBox.Show(this, exUmi.Message, "Umi-OCR", MessageBoxButtons.OK, MessageBoxIcon.Information); - crop.Dispose(); - return; - } - } - - int mode = _pickMode; - _ocrBusyCount++; - UpdateOcrStatus(); - var sw = System.Diagnostics.Stopwatch.StartNew(); - - _ocr.RecognizeAsync(crop, 30000).ContinueWith(t => - { - _ocrBusyCount--; - UpdateOcrStatus(); - try - { - var items = t.Result; - // crop 传入过滤层(图形符号墨水/笔画判定用) - HandleOcrResult(mode, items, rectPt, merge, ocrScale, sw.ElapsedMilliseconds, crop); - } - catch (Exception ex) - { - // t.Result 抛的 AggregateException 消息恒为"发生一个或多个错误",解包取根因 - Exception root = ex is AggregateException ? ((AggregateException)ex).GetBaseException() : ex; - string msg = "OCR 识别失败: " + root.Message; - _statusLeft.Text = msg; - if (!_ocrErrorShown) - { - _ocrErrorShown = true; - MessageBox.Show(this, msg + "\r\n\r\n下次框选时将自动重启 OCR。", - "OCR", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } - finally - { - crop.Dispose(); - } - }, TaskScheduler.FromCurrentSynchronizationContext()); - } - - private void UpdateOcrStatus() - { - if (_ocrBusyCount > 0) - _statusOcr.Text = "OCR 识别中…(" + _ocrBusyCount + " 个框)"; - else - _statusOcr.Text = "OCR 空闲"; - } - - /// - /// 高风险短串:2-4 字符、含 ASCII 字母、非纯数字、不含汉字。 - /// (X1/M4/KI 这类图形误读高发形态;纯数字数量、汉字、长规格不受此门约束) - /// - private static bool IsShortLetterText(string s) - { - if (string.IsNullOrEmpty(s) || s.Length < 2 || s.Length > 4) return false; - bool hasLetter = false; - foreach (char c in s) - { - if (c >= 0x4E00 && c <= 0x9FFF) return false; // 含汉字不适用 - if (!char.IsDigit(c)) - { - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) hasLetter = true; - // 其他字符(如 -)允许出现 - } - } - return hasLetter; - } - - /// - /// 图形误读判定(基于裁剪图 bbox 区域的笔画特征): - /// · 百度置信度 <0.8(真短标注通常 >0.9;GLM Score=1 跳过,由下面两条兜底) - /// · 墨水密度 ≥22%(前景=亮度<140;粗线符号 15-60%,文字 5-15%) - /// · 水平行程中位数 ≥8px(粗笔画;文字笔画 2-5px@300DPI) - /// 三条任一命中即判图形。 - /// - private static bool IsGraphicMisread(OcrItem it, Bitmap crop) - { - if (it.Score > 0f && it.Score < 0.8f) return true; - if (crop == null) return false; - return StrokeMetrics(crop, it.Bounds); - } - - /// 计算 bbox 区域墨水密度与水平行程中位数,超限返回 true。 - private static bool StrokeMetrics(Bitmap crop, RectangleF boundsF) - { - var r = Rectangle.Round(boundsF); - r.Intersect(new Rectangle(0, 0, crop.Width, crop.Height)); - if (r.Width < 4 || r.Height < 4) return false; - - var data = crop.LockBits(r, - System.Drawing.Imaging.ImageLockMode.ReadOnly, - System.Drawing.Imaging.PixelFormat.Format32bppArgb); - int fg = 0, total = 0; - var runs = new List(); - try - { - var buf = new byte[r.Width * 4]; - for (int y = 0; y < r.Height; y++) - { - System.Runtime.InteropServices.Marshal.Copy( - new IntPtr(data.Scan0.ToInt64() + y * data.Stride), buf, 0, buf.Length); - int run = 0; - for (int x = 0; x < r.Width; x++) - { - byte b = buf[x * 4], g = buf[x * 4 + 1], rr = buf[x * 4 + 2]; - int lum = (rr * 299 + g * 587 + b * 114) / 1000; - if (lum < 140) { fg++; run++; } - else { if (run >= 2) runs.Add(run); run = 0; } - } - if (run >= 2) runs.Add(run); - total += r.Width; - } - } - finally - { - crop.UnlockBits(data); - } - if (total == 0) return false; - float density = (float)fg / total; - if (density >= 0.22f) return true; - if (runs.Count == 0) return false; - runs.Sort(); - float strokeMedian = runs[runs.Count / 2]; - return strokeMedian >= 8; - } - - /// 过滤丢弃记录(exe 旁 filter.log,便于调阈值);失败静默。 - private static void FilterLog(string msg) - { - try - { - File.AppendAllText( - Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "filter.log"), - DateTime.Now.ToString("HH:mm:ss.fff") + " " + msg + "\r\n"); - } - catch { } - } - - /// - /// 剥离图形符号字符:电气图纸上的小三角(▲▼◀▶△)、箭头、制表线、 - /// 杂项符号等被 OCR 误当文字的内容。剥完只剩空白 → 整条丢弃(调用处判断)。 - /// ★ 只删明确的符号区段,不碰正常文字/标点/工程符号(-/.×x#等)。 - /// - private static string RemoveSymbolJunk(string s) - { - if (string.IsNullOrEmpty(s)) return s; - bool changed = false; - var sb = new System.Text.StringBuilder(s.Length); - foreach (char c in s) - { - if (IsJunkSymbolChar(c)) { changed = true; continue; } - sb.Append(c); - } - if (!changed) return s; - string r = sb.ToString().Trim(); - while (r.Contains(" ")) r = r.Replace(" ", " "); - return r; - } - - /// 图形符号字符判定(几何图形/箭头/制表线/杂项符号/零宽字符)。 - private static bool IsJunkSymbolChar(char c) - { - int u = c; - if (u >= 0x25A0 && u <= 0x25FF) return true; // ▲△■□●○◤◥ 等 - if (u >= 0x2190 && u <= 0x21FF) return true; // ←↑→↓↖↗↘↙ 等箭头 - if (u >= 0x2500 && u <= 0x257F) return true; // ─│┌┐└┘├┤┬┴┼ 制表线 - if (u >= 0x2600 && u <= 0x27BF) return true; // ★☆※§ 等杂项 - if (u == 0xFE0F || u == 0x200B || u == 0x200D) return true; // 变体/零宽 - return false; - } - - /// Windows OCR 符号归一化:间隔号/全角/Unicode 连字符 → 半角工程符号。 - private static string NormalizeOcrText(string s) { - if (string.IsNullOrEmpty(s)) return s; - s = s.Replace(" · ", "-").Replace(" - ", "-").Replace(" / ", "/"); - s = s.Replace('\u00B7', '-'); // 间隔号· - s = s.Replace('\uFF0D', '-'); // 全角- - s = s.Replace('\uFF0F', '/'); // 全角/ - s = s.Replace('\u2010', '-').Replace('\u2011', '-') - .Replace('\u2012', '-').Replace('\u2013', '-') - .Replace('\u2014', '-').Replace('\u2212', '-'); - return s.Trim(); - } - - /// OCR 完成:按 CAD 语义组装 results + 画蒙版 + 通知 Form3。 - private void HandleOcrResult(int mode, List items, - RectangleF rectPt, bool merge, float ocrScale, long elapsedMs, Bitmap crop) - { - var valid = new List(); - foreach (var it in items) - { - string norm = NormalizeOcrText(it.Text); - norm = RemoveSymbolJunk(norm); // ★ 剥离图形符号字符(▲等) - if (string.IsNullOrWhiteSpace(norm)) continue; - // ★ 电气图形符号被 OCR 误读成文字的特征过滤: - // 1) 剥完只剩 1 个非数字非汉字的字符(如图形认成 "A"/"M") → 丢 - // 2) 低置信度(<0.55,百度引擎给出;GLM 恒为 1 不受影响) → 丢 - // 3) 短文本(2-3字符,非纯数字)+ 近方形框 → 圆圈/三角等图形符号误读 - // (真实横排文字宽高比 >1.4,图形外接框宽≈高;纯数字与汉字单字保护) - if (norm.Length == 1 && !char.IsDigit(norm[0]) && - !(norm[0] >= 0x4E00 && norm[0] <= 0x9FFF)) continue; - if (it.Score > 0f && it.Score < 0.55f) continue; - if (norm.Length >= 2 && norm.Length <= 3) - { - bool allDigits = true; - foreach (char c in norm) if (!char.IsDigit(c)) { allDigits = false; break; } - if (!allDigits) - { - var b = it.Bounds; - if (b.Height > 4) - { - float ratio = b.Width / b.Height; - if (ratio >= 0.7f && ratio <= 1.4f) continue; - } - } - } - // 4) ★ 短串(2-4字符,含字母)+ 图形笔画特征 → 线圈/方框等粗线符号误读 - // (如 X|X 绕组符号认成 "X1":横宽与真文字一样,靠墨水密度/笔画宽度区分) - if (IsShortLetterText(norm) && IsGraphicMisread(it, crop)) - { - FilterLog("丢弃疑似图形符号 '" + norm + "' score=" + - it.Score.ToString("0.00") + " 密度/笔画超限"); - continue; - } - it.Text = norm; - valid.Add(it); - } - if (valid.Count == 0) - { - _statusLeft.Text = "未识别到文字 —— 可放大视图或调整框选范围后重试 (" + elapsedMs + "ms)"; - return; - } - - // 列分组、列内从上到下(与 CAD 版 PaTextSelector 顺序语义一致) - valid = SortByColumns(valid); - - var results = new List(); - string mergeHandle = null; - - foreach (var it in valid) - { - // 裁剪图像素 → 页面点 - RectangleF b = it.Bounds; - RectangleF boxPt = new RectangleF( - rectPt.X + b.X / ocrScale, - rectPt.Y + b.Y / ocrScale, - b.Width / ocrScale, b.Height / ocrScale); - string textHandle = FindOrBuildTextHandle(_pageIndex, boxPt); - - string frameHandle; - if (merge) - { - if (mergeHandle == null) - { - mergeHandle = NewHandle(); - _masks.Add(new PdfMaskItem - { - Handle = mergeHandle, - TextHandle = BuildTextHandle(_pageIndex, rectPt), - Page = _pageIndex, - RectPt = rectPt, - Mode = mode - }); - } - frameHandle = mergeHandle; - } - else - { - frameHandle = NewHandle(); - _masks.Add(new PdfMaskItem - { - Handle = frameHandle, - TextHandle = textHandle, - Page = _pageIndex, - RectPt = boxPt, - Mode = mode - }); - } - - results.Add(new MyApp.PaTextResult - { - Text = it.Text.Trim(), - FrameHandle = frameHandle, - TextHandle = textHandle - }); - } - - SaveMasks(); - RefreshMasks(); - _statusLeft.Text = "识别到 " + valid.Count + " 条文本(" + elapsedMs + "ms)" + - (merge ? ",合并模式,已拼为一条规格" : "") + ",已入表格并画框"; - _ocrErrorShown = false; - - PdfBridge.RaisePaPicked((MyApp.PaMode)mode, results); - } - - /// 按"列分组、列内从上到下"排序(阅读顺序)。 - private static List SortByColumns(List items) - { - var byX = items.OrderBy(i => i.Bounds.X).ToList(); - var columns = new List>(); - foreach (var it in byX) - { - bool placed = false; - foreach (var col in columns) - { - float colLeft = col.Min(c => c.Bounds.Left); - float colRight = col.Max(c => c.Bounds.Right); - float itMid = it.Bounds.Left + it.Bounds.Width / 2f; - if (itMid >= colLeft - 2 && itMid <= colRight + 2) - { - col.Add(it); - placed = true; - break; - } - } - if (!placed) columns.Add(new List { it }); - } - var result = new List(); - foreach (var col in columns) - result.AddRange(col.OrderBy(c => c.Bounds.Y).ThenBy(c => c.Bounds.X)); - return result; - } - - private string NewHandle() - { - return "M" + (_handleCounter++); - } - - /// 稳定文本标识:页码 + 中心点(10pt 网格) + 尺寸(5pt 网格)。 - private static string BuildTextHandle(int page, RectangleF rectPt) - { - float cx = rectPt.X + rectPt.Width / 2f; - float cy = rectPt.Y + rectPt.Height / 2f; - return "P" + page - + "@" + (int)Math.Round(cx / 10.0) + "," + (int)Math.Round(cy / 10.0) - + "|" + (int)Math.Round(rectPt.Width / 5.0) + "x" + (int)Math.Round(rectPt.Height / 5.0); - } - - /// 会话内复用:同页 IoU>0.5 的旧框 → 沿用其 TextHandle。 - private string FindOrBuildTextHandle(int page, RectangleF rectPt) - { - foreach (var m in _sessionPicked) - { - if (m.Page != page) continue; - RectangleF a = m.RectPt; - RectangleF inter = RectangleF.Intersect(a, rectPt); - if (inter.Width <= 0 || inter.Height <= 0) continue; - float interArea = inter.Width * inter.Height; - float union = a.Width * a.Height + rectPt.Width * rectPt.Height - interArea; - if (union > 0 && interArea / union > 0.5f) - { - m.RectPt = rectPt; - return m.TextHandle; - } - } - string th = BuildTextHandle(page, rectPt); - _sessionPicked.Add(new PdfMaskItem - { - Handle = "", - TextHandle = th, - Page = page, - RectPt = rectPt - }); - return th; - } - - // ============================================================ - // 桥联动:定位 / 删框 / 合并 / 高亮 - // ============================================================ - - public void ZoomToFrame(string handle) - { - PdfMaskItem m = null; - foreach (var k in _masks) - if (k.Handle == handle) { m = k; break; } - if (m == null) return; - - if (m.Page != _pageIndex) - { - _pageIndex = m.Page; - RenderCurrentPage(clearPage: true); // 跨页定位:清旧页位图 - UpdateNavUi(); - } - // 框太小看不清时放大到框宽约 300px - float pxw = m.RectPt.Width * _pxPerPt; - if (pxw < 300) - { - float want = (300f / m.RectPt.Width) / _dpiFactor; - SetZoom(Math.Min(MaxZoom, want)); - } - - float cx = (m.RectPt.X + m.RectPt.Width / 2f) * _pxPerPt; - float cy = (m.RectPt.Y + m.RectPt.Height / 2f) * _pxPerPt; - var view = PageViewSize; // 视图尺寸(过渡帧拉伸期间按当前视图比例算滚动范围) - _scrollX = Clamp((int)cx - _canvas.ClientSize.Width / 2, 0, Math.Max(0, view.Width - _canvas.ClientSize.Width)); - _scrollY = Clamp((int)cy - _canvas.ClientSize.Height / 2, 0, Math.Max(0, view.Height - _canvas.ClientSize.Height)); - UpdateScrollbars(); - SyncScrollbars(); - - _highlight.Clear(); - _highlight.Add(handle); - RefreshMasks(); - _highlightTimer.Stop(); - _highlightTimer.Start(); - } - - public void DeleteFrames(List handles) - { - if (handles == null || handles.Count == 0) return; - bool changed = false; - foreach (string h in handles) - { - int n = _masks.RemoveAll(m => m.Handle == h); - if (n > 0) changed = true; - _highlight.Remove(h); - } - if (changed) - { - SaveMasks(); - RefreshMasks(); - } - } - - public void MergeMasks(string keep, List removes) - { - PdfMaskItem k = null; - foreach (var m in _masks) - if (m.Handle == keep) { k = m; break; } - if (k == null) return; - bool changed = false; - foreach (string h in removes) - { - PdfMaskItem r = _masks.FirstOrDefault(m => m.Handle == h); - if (r == null) continue; - float l = Math.Min(k.RectPt.Left, r.RectPt.Left); - float t = Math.Min(k.RectPt.Top, r.RectPt.Top); - float rr = Math.Max(k.RectPt.Right, r.RectPt.Right); - float b = Math.Max(k.RectPt.Bottom, r.RectPt.Bottom); - k.RectPt = RectangleF.FromLTRB(l, t, rr, b); - _masks.Remove(r); - changed = true; - } - if (changed) - { - SaveMasks(); - RefreshMasks(); - } - } - - public void ClearHighlight() - { - _highlight.Clear(); - RefreshMasks(); - } - - // ============================================================ - // 蒙版持久化 - // ============================================================ - - private void SaveMasks() - { - if (string.IsNullOrEmpty(_maskSavePath)) return; - try - { - var data = new - { - counter = _handleCounter, - masks = _masks.Select(m => new - { - handle = m.Handle, - textHandle = m.TextHandle, - page = m.Page, - mode = m.Mode, - rect = new[] { m.RectPt.X, m.RectPt.Y, m.RectPt.Width, m.RectPt.Height } - }).ToArray() - }; - File.WriteAllText(_maskSavePath, _json.Serialize(data)); - } - catch { } - } - - private void LoadMasks() - { - _masks = new List(); - _sessionPicked = new List(); - _highlight.Clear(); - _handleCounter = 1; - if (string.IsNullOrEmpty(_maskSavePath) || !File.Exists(_maskSavePath)) return; - try - { - var data = _json.Deserialize>(File.ReadAllText(_maskSavePath)); - if (data == null) return; - if (data.ContainsKey("counter")) - _handleCounter = Convert.ToInt32(data["counter"]); - var arr = data.ContainsKey("masks") ? data["masks"] as System.Collections.ArrayList : null; - if (arr != null) - { - foreach (Dictionary m in arr) - { - var rect = m["rect"] as System.Collections.ArrayList; - var item = new PdfMaskItem - { - Handle = Convert.ToString(m["handle"]), - TextHandle = Convert.ToString(m["textHandle"]), - Page = Convert.ToInt32(m["page"]), - Mode = Convert.ToInt32(m["mode"]), - RectPt = new RectangleF( - Convert.ToSingle(rect[0]), Convert.ToSingle(rect[1]), - Convert.ToSingle(rect[2]), Convert.ToSingle(rect[3])) - }; - _masks.Add(item); - _sessionPicked.Add(item); - } - } - } - catch { } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - try { if (_ocr != null) _ocr.Dispose(); } catch { } - try - { - if (_doc != null) - { - _renderGen++; // 作废在途后台渲染 - lock (PdfRenderGate) { _doc.Dispose(); } // 与后台渲染互斥后释放 - } - } - catch { } - // Umi-OCR:只停由本程序启动的实例(用户自己开的 Umi-OCR 不动) - try { UmiOcrLauncher.StopIfStartedByUs(); } catch { } // ★ A1:启停已拆到 UmiOcrLauncher(主项目共享版) - } - base.Dispose(disposing); - } - - // ============================================================ - // 内部画布:位图 + 蒙版 + 橡皮筋(同一双缓冲绘制,无闪烁) - // ============================================================ - private class ViewerCanvas : Control - { - private Bitmap _page; - public float PxPerPt = 1f; - /// 视图比例/位图实际比例(缩放过渡帧>1 或 <1:位图待拉伸;高清渲染落图后回 1)。 - public float ViewScale = 1f; - public List Masks = new List(); - public HashSet Highlight = new HashSet(); - public Rectangle Rubber = Rectangle.Empty; - public bool RubberMerge; - - public ViewerCanvas() - { - SetStyle(ControlStyles.AllPaintingInWmPaint - | ControlStyles.OptimizedDoubleBuffer - | ControlStyles.UserPaint - | ControlStyles.ResizeRedraw, true); - Cursor = Cursors.Default; - TabStop = true; - } - - public Bitmap Page - { - get { return _page; } - } - - public void SetPage(Bitmap bmp, float pxPerPt) - { - if (_page != null && _page != bmp) _page.Dispose(); - _page = bmp; - PxPerPt = pxPerPt; - ViewScale = 1f; // 新位图即视图比例 - Invalidate(); - } - - /// 缩放过渡帧:不换位图,只把视图比例改为 viewPxPerPt(旧位图按 ViewScale 拉伸显示), - /// 后台高清渲染完成 SetPage 后自动复位。位图未就绪时忽略。 - public void SetViewScale(float viewPxPerPt) - { - if (_page == null || PxPerPt <= 0) return; - float st = viewPxPerPt / PxPerPt; - if (Math.Abs(st - ViewScale) < 0.001f) return; - ViewScale = st; - Invalidate(); - } - - protected override void OnPaint(PaintEventArgs e) - { - var g = e.Graphics; - g.Clear(BackColor); - if (_page == null) return; - - var origin = GetOrigin(); - // ★ 过渡帧:位图按 ViewScale 拉伸绘制(1:1 时与原 DrawImage 完全等价); - // 大图拉伸用 Bilinear(默认 HighQualityBicubic 更慢,过渡帧求即时反馈) - bool stretching = Math.Abs(ViewScale - 1f) > 0.001f; - if (stretching) g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; - g.DrawImage(_page, origin.X, origin.Y, - _page.Width * ViewScale, _page.Height * ViewScale); - - float vpp = PxPerPt * ViewScale; // 当前视图比例(蒙版换算用) - - // 蒙版框(页面pt → 屏幕) - foreach (var m in Masks) - { - var rect = new RectangleF( - origin.X + m.RectPt.X * vpp, - origin.Y + m.RectPt.Y * vpp, - m.RectPt.Width * vpp, m.RectPt.Height * vpp); - if (rect.Width < 1 || rect.Height < 1) continue; - bool hl = Highlight.Contains(m.Handle); - using (var fill = new SolidBrush(Color.FromArgb(70, m.Color))) - g.FillRectangle(fill, rect); - using (var pen = new Pen(m.Color, hl ? 4f : 2f)) - g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); - if (hl) - { - using (var pen2 = new Pen(Color.FromArgb(120, Color.Gold), 7f)) - g.DrawRectangle(pen2, rect.X - 3, rect.Y - 3, - rect.Width + 6, rect.Height + 6); - } - } - - // 橡皮筋 - if (Rubber.Width > 0 && Rubber.Height > 0) - { - Color rc = RubberMerge ? Color.OrangeRed : Color.RoyalBlue; - using (var fill = new SolidBrush(Color.FromArgb(40, rc))) - g.FillRectangle(fill, Rubber); - using (var pen = new Pen(rc, 1.5f) { DashStyle = DashStyle.Dash }) - g.DrawRectangle(pen, Rubber.X, Rubber.Y, Rubber.Width, Rubber.Height); - } - base.OnPaint(e); - } - - /// 宿主注入的原点计算(避免画布反查滚动状态)。 - public Func OriginProvider; - - private Point GetOrigin() - { - return OriginProvider != null ? OriginProvider() : Point.Empty; - } - - protected override bool IsInputKey(Keys keyData) - { - // 方向键给画布(避免被父容器抢去切焦点) - if ((keyData & Keys.KeyCode) == Keys.Left || - (keyData & Keys.KeyCode) == Keys.Right || - (keyData & Keys.KeyCode) == Keys.Up || - (keyData & Keys.KeyCode) == Keys.Down) - return true; - return base.IsInputKey(keyData); - } - - protected override void OnPaintBackground(PaintEventArgs e) - { - // 全部在 OnPaint 绘制(双缓冲) - } - } - } -} diff --git a/pdfbt/Plugin/Form3.Designer.cs b/pdfbt/Plugin/Form3.Designer.cs deleted file mode 100644 index f2db03c..0000000 --- a/pdfbt/Plugin/Form3.Designer.cs +++ /dev/null @@ -1,1321 +0,0 @@ -namespace MyApp -{ - public partial class Form3 : System.Windows.Forms.Form - { - /// 必需的设计器变量。 - private System.ComponentModel.IContainer components = null; - - /// 清理正在使用的资源。 - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows 窗体设计器生成的代码 - - private void InitializeComponent() - { - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle(); - this.tabControl2 = new System.Windows.Forms.TabControl(); - this.tabPage3 = new System.Windows.Forms.TabPage(); - this.advancedDataGridView6 = new Zuby.ADGV.AdvancedDataGridView(); - this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn8 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn12 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn13 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.panel1 = new System.Windows.Forms.Panel(); - this.button28 = new System.Windows.Forms.Button(); - this.textBox1 = new System.Windows.Forms.TextBox(); - this.comboBox2 = new System.Windows.Forms.ComboBox(); - this.tabPage4 = new System.Windows.Forms.TabPage(); - this.splitContainer2 = new System.Windows.Forms.SplitContainer(); - this.advancedDataGridView9 = new Zuby.ADGV.AdvancedDataGridView(); - this.dataGridViewTextBoxColumn14 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn15 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn16 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn17 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn18 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn19 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn20 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn21 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn22 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn23 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.splitContainer3 = new System.Windows.Forms.SplitContainer(); - this.advancedDataGridView4 = new Zuby.ADGV.AdvancedDataGridView(); - this.dataGridViewTextBoxColumn24 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn25 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn26 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn27 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn28 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn29 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn30 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn31 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn32 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn33 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn34 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn35 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn36 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn37 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn38 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn39 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn40 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.advancedDataGridView5 = new Zuby.ADGV.AdvancedDataGridView(); - this.dataGridViewTextBoxColumn41 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn42 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn43 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn44 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn45 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn46 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn47 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn48 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn49 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn50 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn51 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn52 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn53 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn54 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn55 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn56 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn57 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.toolStrip1 = new System.Windows.Forms.ToolStrip(); - this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton5 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton6 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton2 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton3 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton4 = new System.Windows.Forms.ToolStripButton(); - this.toolStripButton7 = new System.Windows.Forms.ToolStripButton(); - this.tabControl2.SuspendLayout(); - this.tabPage3.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView6)).BeginInit(); - this.panel1.SuspendLayout(); - this.tabPage4.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); - this.splitContainer2.Panel1.SuspendLayout(); - this.splitContainer2.Panel2.SuspendLayout(); - this.splitContainer2.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView9)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); - this.splitContainer3.Panel1.SuspendLayout(); - this.splitContainer3.Panel2.SuspendLayout(); - this.splitContainer3.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView4)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView5)).BeginInit(); - this.toolStrip1.SuspendLayout(); - this.SuspendLayout(); - // - // tabControl2 - // - this.tabControl2.Controls.Add(this.tabPage3); - this.tabControl2.Controls.Add(this.tabPage4); - this.tabControl2.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl2.Font = new System.Drawing.Font("宋体", 9F); - this.tabControl2.ItemSize = new System.Drawing.Size(60, 21); - this.tabControl2.Location = new System.Drawing.Point(0, 31); - this.tabControl2.Name = "tabControl2"; - this.tabControl2.SelectedIndex = 0; - this.tabControl2.Size = new System.Drawing.Size(540, 838); - this.tabControl2.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; - this.tabControl2.TabIndex = 0; - // - // tabPage3 - // - this.tabPage3.BackColor = System.Drawing.Color.Transparent; - this.tabPage3.Controls.Add(this.advancedDataGridView6); - this.tabPage3.Controls.Add(this.panel1); - this.tabPage3.Font = new System.Drawing.Font("宋体", 9F); - this.tabPage3.ForeColor = System.Drawing.SystemColors.ControlText; - this.tabPage3.Location = new System.Drawing.Point(4, 25); - this.tabPage3.Name = "tabPage3"; - this.tabPage3.Padding = new System.Windows.Forms.Padding(3); - this.tabPage3.Size = new System.Drawing.Size(473, 669); - this.tabPage3.TabIndex = 0; - this.tabPage3.Text = "项目"; - this.tabPage3.UseVisualStyleBackColor = true; - // - // advancedDataGridView6 - // - this.advancedDataGridView6.AllowUserToAddRows = false; - this.advancedDataGridView6.AllowUserToResizeRows = false; - this.advancedDataGridView6.BackgroundColor = System.Drawing.Color.White; - dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle1.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView6.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; - this.advancedDataGridView6.ColumnHeadersHeight = 25; - this.advancedDataGridView6.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.dataGridViewTextBoxColumn1, - this.dataGridViewTextBoxColumn2, - this.dataGridViewTextBoxColumn3, - this.dataGridViewTextBoxColumn4, - this.dataGridViewTextBoxColumn5, - this.dataGridViewTextBoxColumn6, - this.dataGridViewTextBoxColumn7, - this.dataGridViewTextBoxColumn8, - this.dataGridViewTextBoxColumn9, - this.dataGridViewTextBoxColumn10, - this.dataGridViewTextBoxColumn11, - this.dataGridViewTextBoxColumn12, - this.dataGridViewTextBoxColumn13}); - // - // dataGridViewTextBoxColumn1 - // - this.dataGridViewTextBoxColumn1.DataPropertyName = "项目编号"; - this.dataGridViewTextBoxColumn1.HeaderText = "项目编号"; - this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1"; - this.dataGridViewTextBoxColumn1.ReadOnly = true; - this.dataGridViewTextBoxColumn1.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn1.Width = 100; - // - // dataGridViewTextBoxColumn2 - // - this.dataGridViewTextBoxColumn2.DataPropertyName = "项目名称"; - this.dataGridViewTextBoxColumn2.HeaderText = "项目名称"; - this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2"; - this.dataGridViewTextBoxColumn2.ReadOnly = true; - this.dataGridViewTextBoxColumn2.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn2.Width = 100; - // - // dataGridViewTextBoxColumn3 - // - this.dataGridViewTextBoxColumn3.DataPropertyName = "客户名称"; - this.dataGridViewTextBoxColumn3.HeaderText = "客户名称"; - this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3"; - this.dataGridViewTextBoxColumn3.ReadOnly = true; - this.dataGridViewTextBoxColumn3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn3.Width = 100; - // - // dataGridViewTextBoxColumn4 - // - this.dataGridViewTextBoxColumn4.DataPropertyName = "客户地址"; - this.dataGridViewTextBoxColumn4.HeaderText = "客户地址"; - this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4"; - this.dataGridViewTextBoxColumn4.ReadOnly = true; - this.dataGridViewTextBoxColumn4.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn4.Width = 100; - // - // dataGridViewTextBoxColumn5 - // - this.dataGridViewTextBoxColumn5.DataPropertyName = "联系人"; - this.dataGridViewTextBoxColumn5.HeaderText = "联系人"; - this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5"; - this.dataGridViewTextBoxColumn5.ReadOnly = true; - this.dataGridViewTextBoxColumn5.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn5.Width = 100; - // - // dataGridViewTextBoxColumn6 - // - this.dataGridViewTextBoxColumn6.DataPropertyName = "联系电话"; - this.dataGridViewTextBoxColumn6.HeaderText = "联系电话"; - this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6"; - this.dataGridViewTextBoxColumn6.ReadOnly = true; - this.dataGridViewTextBoxColumn6.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn6.Width = 100; - // - // dataGridViewTextBoxColumn7 - // - this.dataGridViewTextBoxColumn7.DataPropertyName = "项目日期"; - this.dataGridViewTextBoxColumn7.HeaderText = "项目日期"; - this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7"; - this.dataGridViewTextBoxColumn7.ReadOnly = true; - this.dataGridViewTextBoxColumn7.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn7.Width = 100; - // - // dataGridViewTextBoxColumn8 - // - this.dataGridViewTextBoxColumn8.DataPropertyName = "箱柜台数"; - this.dataGridViewTextBoxColumn8.HeaderText = "箱柜台数"; - this.dataGridViewTextBoxColumn8.Name = "dataGridViewTextBoxColumn8"; - this.dataGridViewTextBoxColumn8.ReadOnly = true; - this.dataGridViewTextBoxColumn8.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn8.Width = 100; - // - // dataGridViewTextBoxColumn9 - // - this.dataGridViewTextBoxColumn9.DataPropertyName = "成本总价"; - this.dataGridViewTextBoxColumn9.HeaderText = "成本总价"; - this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9"; - this.dataGridViewTextBoxColumn9.ReadOnly = true; - this.dataGridViewTextBoxColumn9.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn9.Width = 100; - // - // dataGridViewTextBoxColumn10 - // - this.dataGridViewTextBoxColumn10.DataPropertyName = "报出总价"; - this.dataGridViewTextBoxColumn10.HeaderText = "报出总价"; - this.dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10"; - this.dataGridViewTextBoxColumn10.ReadOnly = true; - this.dataGridViewTextBoxColumn10.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn10.Width = 100; - // - // dataGridViewTextBoxColumn11 - // - this.dataGridViewTextBoxColumn11.DataPropertyName = "利润"; - this.dataGridViewTextBoxColumn11.HeaderText = "利润"; - this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11"; - this.dataGridViewTextBoxColumn11.ReadOnly = true; - this.dataGridViewTextBoxColumn11.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn11.Width = 100; - // - // dataGridViewTextBoxColumn12 - // - this.dataGridViewTextBoxColumn12.DataPropertyName = "利润率"; - this.dataGridViewTextBoxColumn12.HeaderText = "利润率"; - this.dataGridViewTextBoxColumn12.Name = "dataGridViewTextBoxColumn12"; - this.dataGridViewTextBoxColumn12.ReadOnly = true; - this.dataGridViewTextBoxColumn12.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn12.Width = 100; - // - // dataGridViewTextBoxColumn13 - // - this.dataGridViewTextBoxColumn13.DataPropertyName = "备注"; - this.dataGridViewTextBoxColumn13.HeaderText = "备注"; - this.dataGridViewTextBoxColumn13.Name = "dataGridViewTextBoxColumn13"; - this.dataGridViewTextBoxColumn13.ReadOnly = true; - this.dataGridViewTextBoxColumn13.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn13.Width = 100; - dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle2.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView6.DefaultCellStyle = dataGridViewCellStyle2; - this.advancedDataGridView6.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView6.EnableHeadersVisualStyles = false; - this.advancedDataGridView6.Location = new System.Drawing.Point(3, 31); - this.advancedDataGridView6.Name = "advancedDataGridView6"; - this.advancedDataGridView6.ReadOnly = true; - this.advancedDataGridView6.RightToLeft = System.Windows.Forms.RightToLeft.No; - dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle3.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView6.RowHeadersDefaultCellStyle = dataGridViewCellStyle3; - this.advancedDataGridView6.Size = new System.Drawing.Size(467, 635); - this.advancedDataGridView6.TabIndex = 1; - // - // panel1 - // - this.panel1.BackColor = System.Drawing.SystemColors.Control; - this.panel1.Controls.Add(this.button28); - this.panel1.Controls.Add(this.textBox1); - this.panel1.Controls.Add(this.comboBox2); - this.panel1.Dock = System.Windows.Forms.DockStyle.Top; - this.panel1.Font = new System.Drawing.Font("宋体", 9F); - this.panel1.ForeColor = System.Drawing.SystemColors.ControlText; - this.panel1.Location = new System.Drawing.Point(3, 3); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(467, 28); - this.panel1.TabIndex = 0; - // - // button28 - // - this.button28.BackColor = System.Drawing.SystemColors.Control; - this.button28.Font = new System.Drawing.Font("宋体", 9F); - this.button28.ForeColor = System.Drawing.SystemColors.ControlText; - this.button28.Location = new System.Drawing.Point(335, 2); - this.button28.Name = "button28"; - this.button28.Size = new System.Drawing.Size(75, 23); - this.button28.TabIndex = 2; - this.button28.Text = "查找"; - this.button28.UseVisualStyleBackColor = true; - // - // textBox1 - // - this.textBox1.BackColor = System.Drawing.SystemColors.Window; - this.textBox1.Font = new System.Drawing.Font("宋体", 9F); - this.textBox1.ForeColor = System.Drawing.SystemColors.WindowText; - this.textBox1.Location = new System.Drawing.Point(119, 4); - this.textBox1.Name = "textBox1"; - this.textBox1.Size = new System.Drawing.Size(210, 28); - this.textBox1.TabIndex = 1; - // - // comboBox2 - // - this.comboBox2.BackColor = System.Drawing.SystemColors.Window; - this.comboBox2.DropDownWidth = 108; - this.comboBox2.Font = new System.Drawing.Font("宋体", 9F); - this.comboBox2.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox2.ItemHeight = 18; - this.comboBox2.Items.AddRange(new object[] { - "项目名称", - "项目编号", - "客户名称"}); - this.comboBox2.Location = new System.Drawing.Point(5, 4); - this.comboBox2.Name = "comboBox2"; - this.comboBox2.Size = new System.Drawing.Size(108, 26); - this.comboBox2.TabIndex = 0; - this.comboBox2.Text = "项目名称"; - // - // tabPage4 - // - this.tabPage4.BackColor = System.Drawing.Color.Transparent; - this.tabPage4.Controls.Add(this.splitContainer2); - this.tabPage4.Font = new System.Drawing.Font("宋体", 9F); - this.tabPage4.ForeColor = System.Drawing.SystemColors.ControlText; - this.tabPage4.Location = new System.Drawing.Point(4, 25); - this.tabPage4.Name = "tabPage4"; - this.tabPage4.Padding = new System.Windows.Forms.Padding(3); - this.tabPage4.Size = new System.Drawing.Size(532, 809); - this.tabPage4.TabIndex = 1; - this.tabPage4.Text = "报价"; - this.tabPage4.UseVisualStyleBackColor = true; - // - // splitContainer2 - // - this.splitContainer2.BackColor = System.Drawing.SystemColors.Control; - this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer2.Font = new System.Drawing.Font("宋体", 9F); - this.splitContainer2.ForeColor = System.Drawing.SystemColors.ControlText; - this.splitContainer2.Location = new System.Drawing.Point(3, 3); - this.splitContainer2.Name = "splitContainer2"; - this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer2.Panel1 - // - this.splitContainer2.Panel1.Controls.Add(this.advancedDataGridView9); - // - // splitContainer2.Panel2 - // - this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(526, 803); - this.splitContainer2.SplitterDistance = 254; - this.splitContainer2.SplitterWidth = 6; - this.splitContainer2.TabIndex = 0; - // - // advancedDataGridView9 - // - this.advancedDataGridView9.AllowUserToAddRows = false; - this.advancedDataGridView9.AllowUserToResizeRows = false; - this.advancedDataGridView9.BackgroundColor = System.Drawing.Color.White; - dataGridViewCellStyle4.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - dataGridViewCellStyle4.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle4.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle4.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle4.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle4.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle4.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView9.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle4; - this.advancedDataGridView9.ColumnHeadersHeight = 35; - this.advancedDataGridView9.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.dataGridViewTextBoxColumn14, - this.dataGridViewTextBoxColumn15, - this.dataGridViewTextBoxColumn16, - this.dataGridViewTextBoxColumn17, - this.dataGridViewTextBoxColumn18, - this.dataGridViewTextBoxColumn19, - this.dataGridViewTextBoxColumn20, - this.dataGridViewTextBoxColumn21, - this.dataGridViewTextBoxColumn22, - this.dataGridViewTextBoxColumn23}); - // - // dataGridViewTextBoxColumn14 - // - this.dataGridViewTextBoxColumn14.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; - this.dataGridViewTextBoxColumn14.DataPropertyName = "序号"; - dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn14.DefaultCellStyle = dataGridViewCellStyle13; - this.dataGridViewTextBoxColumn14.Frozen = true; - this.dataGridViewTextBoxColumn14.HeaderText = "序号"; - this.dataGridViewTextBoxColumn14.Name = "dataGridViewTextBoxColumn14"; - this.dataGridViewTextBoxColumn14.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn14.Width = 35; - // - // dataGridViewTextBoxColumn15 - // - this.dataGridViewTextBoxColumn15.DataPropertyName = "图号"; - this.dataGridViewTextBoxColumn15.HeaderText = "图号"; - this.dataGridViewTextBoxColumn15.Name = "dataGridViewTextBoxColumn15"; - this.dataGridViewTextBoxColumn15.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn15.Width = 100; - // - // dataGridViewTextBoxColumn16 - // - this.dataGridViewTextBoxColumn16.DataPropertyName = "图名"; - this.dataGridViewTextBoxColumn16.HeaderText = "图名"; - this.dataGridViewTextBoxColumn16.Name = "dataGridViewTextBoxColumn16"; - this.dataGridViewTextBoxColumn16.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn16.Width = 100; - // - // dataGridViewTextBoxColumn17 - // - this.dataGridViewTextBoxColumn17.DataPropertyName = "台数"; - dataGridViewCellStyle14.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn17.DefaultCellStyle = dataGridViewCellStyle14; - this.dataGridViewTextBoxColumn17.HeaderText = "台数"; - this.dataGridViewTextBoxColumn17.Name = "dataGridViewTextBoxColumn17"; - this.dataGridViewTextBoxColumn17.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn17.Width = 35; - // - // dataGridViewTextBoxColumn18 - // - this.dataGridViewTextBoxColumn18.DataPropertyName = "箱柜数量"; - dataGridViewCellStyle15.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn18.DefaultCellStyle = dataGridViewCellStyle15; - this.dataGridViewTextBoxColumn18.HeaderText = "箱柜数量"; - this.dataGridViewTextBoxColumn18.Name = "dataGridViewTextBoxColumn18"; - this.dataGridViewTextBoxColumn18.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn18.Width = 35; - // - // dataGridViewTextBoxColumn19 - // - this.dataGridViewTextBoxColumn19.DataPropertyName = "单价"; - this.dataGridViewTextBoxColumn19.HeaderText = "单价"; - this.dataGridViewTextBoxColumn19.Name = "dataGridViewTextBoxColumn19"; - this.dataGridViewTextBoxColumn19.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn19.Width = 100; - // - // dataGridViewTextBoxColumn20 - // - this.dataGridViewTextBoxColumn20.DataPropertyName = "总价"; - this.dataGridViewTextBoxColumn20.HeaderText = "总价"; - this.dataGridViewTextBoxColumn20.Name = "dataGridViewTextBoxColumn20"; - this.dataGridViewTextBoxColumn20.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn20.Width = 100; - // - // dataGridViewTextBoxColumn21 - // - this.dataGridViewTextBoxColumn21.DataPropertyName = "成本总价"; - this.dataGridViewTextBoxColumn21.HeaderText = "成本总价"; - this.dataGridViewTextBoxColumn21.Name = "dataGridViewTextBoxColumn21"; - this.dataGridViewTextBoxColumn21.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn21.Width = 100; - // - // dataGridViewTextBoxColumn22 - // - this.dataGridViewTextBoxColumn22.DataPropertyName = "毛利"; - this.dataGridViewTextBoxColumn22.HeaderText = "毛利"; - this.dataGridViewTextBoxColumn22.Name = "dataGridViewTextBoxColumn22"; - this.dataGridViewTextBoxColumn22.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn22.Width = 100; - // - // dataGridViewTextBoxColumn23 - // - this.dataGridViewTextBoxColumn23.DataPropertyName = "毛利率"; - this.dataGridViewTextBoxColumn23.HeaderText = "毛利率"; - this.dataGridViewTextBoxColumn23.Name = "dataGridViewTextBoxColumn23"; - this.dataGridViewTextBoxColumn23.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn23.Width = 100; - dataGridViewCellStyle5.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle5.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle5.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle5.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle5.SelectionBackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle5.SelectionForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle5.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView9.DefaultCellStyle = dataGridViewCellStyle5; - this.advancedDataGridView9.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView9.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView9.EnableCellPaste = true; - this.advancedDataGridView9.EnableHeadersVisualStyles = false; - this.advancedDataGridView9.Location = new System.Drawing.Point(0, 0); - this.advancedDataGridView9.Name = "advancedDataGridView9"; - this.advancedDataGridView9.RightToLeft = System.Windows.Forms.RightToLeft.No; - dataGridViewCellStyle6.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle6.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle6.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle6.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle6.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle6.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle6.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView9.RowHeadersDefaultCellStyle = dataGridViewCellStyle6; - this.advancedDataGridView9.Size = new System.Drawing.Size(526, 254); - this.advancedDataGridView9.TabIndex = 0; - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // splitContainer3 - // - this.splitContainer3.BackColor = System.Drawing.SystemColors.Control; - this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer3.Font = new System.Drawing.Font("宋体", 9F); - this.splitContainer3.ForeColor = System.Drawing.SystemColors.ControlText; - this.splitContainer3.Location = new System.Drawing.Point(0, 0); - this.splitContainer3.Name = "splitContainer3"; - this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer3.Panel1 - // - this.splitContainer3.Panel1.Controls.Add(this.advancedDataGridView4); - // - // splitContainer3.Panel2 - // - this.splitContainer3.Panel2.Controls.Add(this.advancedDataGridView5); - this.splitContainer3.Size = new System.Drawing.Size(526, 543); - this.splitContainer3.SplitterDistance = 265; - this.splitContainer3.SplitterWidth = 6; - this.splitContainer3.TabIndex = 0; - // - // advancedDataGridView4 - // - this.advancedDataGridView4.AllowUserToAddRows = false; - this.advancedDataGridView4.AllowUserToResizeRows = false; - this.advancedDataGridView4.BackgroundColor = System.Drawing.Color.White; - dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - dataGridViewCellStyle7.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle7.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle7.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle7.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle7.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView4.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle7; - this.advancedDataGridView4.ColumnHeadersHeight = 35; - this.advancedDataGridView4.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.dataGridViewTextBoxColumn24, - this.dataGridViewTextBoxColumn25, - this.dataGridViewTextBoxColumn26, - this.dataGridViewTextBoxColumn27, - this.dataGridViewTextBoxColumn28, - this.dataGridViewTextBoxColumn29, - this.dataGridViewTextBoxColumn30, - this.dataGridViewTextBoxColumn31, - this.dataGridViewTextBoxColumn32, - this.dataGridViewTextBoxColumn33, - this.dataGridViewTextBoxColumn34, - this.dataGridViewTextBoxColumn35, - this.dataGridViewTextBoxColumn36, - this.dataGridViewTextBoxColumn37, - this.dataGridViewTextBoxColumn38, - this.dataGridViewTextBoxColumn39, - this.dataGridViewTextBoxColumn40}); - // - // dataGridViewTextBoxColumn24 - // - this.dataGridViewTextBoxColumn24.DataPropertyName = "序号"; - dataGridViewCellStyle16.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn24.DefaultCellStyle = dataGridViewCellStyle16; - this.dataGridViewTextBoxColumn24.HeaderText = "序号"; - this.dataGridViewTextBoxColumn24.Name = "dataGridViewTextBoxColumn24"; - this.dataGridViewTextBoxColumn24.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn24.Width = 35; - // - // dataGridViewTextBoxColumn25 - // - this.dataGridViewTextBoxColumn25.DataPropertyName = "箱号"; - this.dataGridViewTextBoxColumn25.HeaderText = "箱号"; - this.dataGridViewTextBoxColumn25.Name = "dataGridViewTextBoxColumn25"; - this.dataGridViewTextBoxColumn25.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn25.Width = 150; - // - // dataGridViewTextBoxColumn26 - // - this.dataGridViewTextBoxColumn26.DataPropertyName = "箱名"; - dataGridViewCellStyle17.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn26.DefaultCellStyle = dataGridViewCellStyle17; - this.dataGridViewTextBoxColumn26.HeaderText = "箱名"; - this.dataGridViewTextBoxColumn26.Name = "dataGridViewTextBoxColumn26"; - this.dataGridViewTextBoxColumn26.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn26.Width = 150; - // - // dataGridViewTextBoxColumn27 - // - this.dataGridViewTextBoxColumn27.DataPropertyName = "型号"; - this.dataGridViewTextBoxColumn27.HeaderText = "型号"; - this.dataGridViewTextBoxColumn27.Name = "dataGridViewTextBoxColumn27"; - this.dataGridViewTextBoxColumn27.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn27.Width = 150; - // - // dataGridViewTextBoxColumn28 - // - this.dataGridViewTextBoxColumn28.DataPropertyName = "规格"; - this.dataGridViewTextBoxColumn28.HeaderText = "规格"; - this.dataGridViewTextBoxColumn28.Name = "dataGridViewTextBoxColumn28"; - this.dataGridViewTextBoxColumn28.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn28.Width = 150; - // - // dataGridViewTextBoxColumn29 - // - this.dataGridViewTextBoxColumn29.DataPropertyName = "单位"; - dataGridViewCellStyle18.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn29.DefaultCellStyle = dataGridViewCellStyle18; - this.dataGridViewTextBoxColumn29.HeaderText = "单位"; - this.dataGridViewTextBoxColumn29.Name = "dataGridViewTextBoxColumn29"; - this.dataGridViewTextBoxColumn29.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn29.Width = 35; - // - // dataGridViewTextBoxColumn30 - // - this.dataGridViewTextBoxColumn30.DataPropertyName = "数量"; - dataGridViewCellStyle19.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn30.DefaultCellStyle = dataGridViewCellStyle19; - this.dataGridViewTextBoxColumn30.HeaderText = "数量"; - this.dataGridViewTextBoxColumn30.Name = "dataGridViewTextBoxColumn30"; - this.dataGridViewTextBoxColumn30.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn30.Width = 45; - // - // dataGridViewTextBoxColumn31 - // - this.dataGridViewTextBoxColumn31.DataPropertyName = "单台成本"; - this.dataGridViewTextBoxColumn31.HeaderText = "单台成本"; - this.dataGridViewTextBoxColumn31.Name = "dataGridViewTextBoxColumn31"; - this.dataGridViewTextBoxColumn31.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn31.Width = 100; - // - // dataGridViewTextBoxColumn32 - // - this.dataGridViewTextBoxColumn32.DataPropertyName = "成本价"; - this.dataGridViewTextBoxColumn32.HeaderText = "成本价"; - this.dataGridViewTextBoxColumn32.Name = "dataGridViewTextBoxColumn32"; - this.dataGridViewTextBoxColumn32.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn32.Width = 100; - // - // dataGridViewTextBoxColumn33 - // - this.dataGridViewTextBoxColumn33.DataPropertyName = "单台报出"; - this.dataGridViewTextBoxColumn33.HeaderText = "单台报出"; - this.dataGridViewTextBoxColumn33.Name = "dataGridViewTextBoxColumn33"; - this.dataGridViewTextBoxColumn33.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn33.Width = 100; - // - // dataGridViewTextBoxColumn34 - // - this.dataGridViewTextBoxColumn34.DataPropertyName = "报出价"; - this.dataGridViewTextBoxColumn34.HeaderText = "报出价"; - this.dataGridViewTextBoxColumn34.Name = "dataGridViewTextBoxColumn34"; - this.dataGridViewTextBoxColumn34.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn34.Width = 100; - // - // dataGridViewTextBoxColumn35 - // - this.dataGridViewTextBoxColumn35.DataPropertyName = "利润"; - this.dataGridViewTextBoxColumn35.HeaderText = "利润"; - this.dataGridViewTextBoxColumn35.Name = "dataGridViewTextBoxColumn35"; - this.dataGridViewTextBoxColumn35.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn35.Width = 100; - // - // dataGridViewTextBoxColumn36 - // - this.dataGridViewTextBoxColumn36.DataPropertyName = "利润率"; - this.dataGridViewTextBoxColumn36.HeaderText = "利润率"; - this.dataGridViewTextBoxColumn36.Name = "dataGridViewTextBoxColumn36"; - this.dataGridViewTextBoxColumn36.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn36.Width = 100; - // - // dataGridViewTextBoxColumn37 - // - this.dataGridViewTextBoxColumn37.DataPropertyName = "毛利率"; - this.dataGridViewTextBoxColumn37.HeaderText = "毛利率"; - this.dataGridViewTextBoxColumn37.Name = "dataGridViewTextBoxColumn37"; - this.dataGridViewTextBoxColumn37.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn37.Width = 100; - // - // dataGridViewTextBoxColumn38 - // - this.dataGridViewTextBoxColumn38.DataPropertyName = "箱柜类型"; - this.dataGridViewTextBoxColumn38.HeaderText = "箱柜类型"; - this.dataGridViewTextBoxColumn38.Name = "dataGridViewTextBoxColumn38"; - this.dataGridViewTextBoxColumn38.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn38.Width = 100; - // - // dataGridViewTextBoxColumn39 - // - this.dataGridViewTextBoxColumn39.DataPropertyName = "备注"; - this.dataGridViewTextBoxColumn39.HeaderText = "备注"; - this.dataGridViewTextBoxColumn39.Name = "dataGridViewTextBoxColumn39"; - this.dataGridViewTextBoxColumn39.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn39.Width = 100; - // - // dataGridViewTextBoxColumn40 - // - this.dataGridViewTextBoxColumn40.DataPropertyName = "图纸"; - this.dataGridViewTextBoxColumn40.HeaderText = "图纸"; - this.dataGridViewTextBoxColumn40.Name = "dataGridViewTextBoxColumn40"; - this.dataGridViewTextBoxColumn40.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn40.Width = 100; - dataGridViewCellStyle8.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle8.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle8.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle8.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle8.SelectionBackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle8.SelectionForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle8.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView4.DefaultCellStyle = dataGridViewCellStyle8; - this.advancedDataGridView4.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView4.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView4.EnableCellPaste = true; - this.advancedDataGridView4.EnableHeadersVisualStyles = false; - this.advancedDataGridView4.Location = new System.Drawing.Point(0, 0); - this.advancedDataGridView4.Name = "advancedDataGridView4"; - this.advancedDataGridView4.RightToLeft = System.Windows.Forms.RightToLeft.No; - dataGridViewCellStyle9.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle9.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle9.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle9.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle9.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle9.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle9.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView4.RowHeadersDefaultCellStyle = dataGridViewCellStyle9; - this.advancedDataGridView4.Size = new System.Drawing.Size(526, 265); - this.advancedDataGridView4.TabIndex = 0; - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // advancedDataGridView5 - // - this.advancedDataGridView5.AllowUserToAddRows = false; - this.advancedDataGridView5.AllowUserToResizeRows = false; - this.advancedDataGridView5.BackgroundColor = System.Drawing.Color.White; - dataGridViewCellStyle10.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - dataGridViewCellStyle10.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle10.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle10.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle10.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle10.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle10.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView5.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle10; - this.advancedDataGridView5.ColumnHeadersHeight = 35; - this.advancedDataGridView5.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.dataGridViewTextBoxColumn41, - this.dataGridViewTextBoxColumn42, - this.dataGridViewTextBoxColumn43, - this.dataGridViewTextBoxColumn44, - this.dataGridViewTextBoxColumn45, - this.dataGridViewTextBoxColumn46, - this.dataGridViewTextBoxColumn47, - this.dataGridViewTextBoxColumn48, - this.dataGridViewTextBoxColumn49, - this.dataGridViewTextBoxColumn50, - this.dataGridViewTextBoxColumn51, - this.dataGridViewTextBoxColumn52, - this.dataGridViewTextBoxColumn53, - this.dataGridViewTextBoxColumn54, - this.dataGridViewTextBoxColumn55, - this.dataGridViewTextBoxColumn56, - this.dataGridViewTextBoxColumn57}); - // - // dataGridViewTextBoxColumn41 - // - this.dataGridViewTextBoxColumn41.DataPropertyName = "序号"; - dataGridViewCellStyle20.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn41.DefaultCellStyle = dataGridViewCellStyle20; - this.dataGridViewTextBoxColumn41.HeaderText = "序号"; - this.dataGridViewTextBoxColumn41.Name = "dataGridViewTextBoxColumn41"; - this.dataGridViewTextBoxColumn41.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn41.Width = 35; - // - // dataGridViewTextBoxColumn42 - // - this.dataGridViewTextBoxColumn42.DataPropertyName = "元件名称"; - this.dataGridViewTextBoxColumn42.HeaderText = "元件名称"; - this.dataGridViewTextBoxColumn42.Name = "dataGridViewTextBoxColumn42"; - this.dataGridViewTextBoxColumn42.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn42.Width = 150; - // - // dataGridViewTextBoxColumn43 - // - this.dataGridViewTextBoxColumn43.DataPropertyName = "规格"; - this.dataGridViewTextBoxColumn43.HeaderText = "规格"; - this.dataGridViewTextBoxColumn43.Name = "dataGridViewTextBoxColumn43"; - this.dataGridViewTextBoxColumn43.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn43.Width = 150; - // - // dataGridViewTextBoxColumn44 - // - this.dataGridViewTextBoxColumn44.DataPropertyName = "单位"; - dataGridViewCellStyle21.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn44.DefaultCellStyle = dataGridViewCellStyle21; - this.dataGridViewTextBoxColumn44.HeaderText = "单位"; - this.dataGridViewTextBoxColumn44.Name = "dataGridViewTextBoxColumn44"; - this.dataGridViewTextBoxColumn44.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn44.Width = 35; - // - // dataGridViewTextBoxColumn45 - // - this.dataGridViewTextBoxColumn45.DataPropertyName = "数量"; - dataGridViewCellStyle22.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - this.dataGridViewTextBoxColumn45.DefaultCellStyle = dataGridViewCellStyle22; - this.dataGridViewTextBoxColumn45.HeaderText = "数量"; - this.dataGridViewTextBoxColumn45.Name = "dataGridViewTextBoxColumn45"; - this.dataGridViewTextBoxColumn45.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn45.Width = 40; - // - // dataGridViewTextBoxColumn46 - // - this.dataGridViewTextBoxColumn46.DataPropertyName = "表价"; - this.dataGridViewTextBoxColumn46.HeaderText = "表价"; - this.dataGridViewTextBoxColumn46.Name = "dataGridViewTextBoxColumn46"; - this.dataGridViewTextBoxColumn46.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn46.Width = 100; - // - // dataGridViewTextBoxColumn47 - // - this.dataGridViewTextBoxColumn47.DataPropertyName = "采购单价"; - this.dataGridViewTextBoxColumn47.HeaderText = "采购单价"; - this.dataGridViewTextBoxColumn47.Name = "dataGridViewTextBoxColumn47"; - this.dataGridViewTextBoxColumn47.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn47.Width = 100; - // - // dataGridViewTextBoxColumn48 - // - this.dataGridViewTextBoxColumn48.DataPropertyName = "采购系数"; - this.dataGridViewTextBoxColumn48.HeaderText = "采购系数"; - this.dataGridViewTextBoxColumn48.Name = "dataGridViewTextBoxColumn48"; - this.dataGridViewTextBoxColumn48.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn48.Width = 100; - // - // dataGridViewTextBoxColumn49 - // - this.dataGridViewTextBoxColumn49.DataPropertyName = "采购价"; - this.dataGridViewTextBoxColumn49.HeaderText = "采购价"; - this.dataGridViewTextBoxColumn49.Name = "dataGridViewTextBoxColumn49"; - this.dataGridViewTextBoxColumn49.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn49.Width = 100; - // - // dataGridViewTextBoxColumn50 - // - this.dataGridViewTextBoxColumn50.DataPropertyName = "报出单价"; - this.dataGridViewTextBoxColumn50.HeaderText = "报出单价"; - this.dataGridViewTextBoxColumn50.Name = "dataGridViewTextBoxColumn50"; - this.dataGridViewTextBoxColumn50.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn50.Width = 100; - // - // dataGridViewTextBoxColumn51 - // - this.dataGridViewTextBoxColumn51.DataPropertyName = "报出系数"; - this.dataGridViewTextBoxColumn51.HeaderText = "报出系数"; - this.dataGridViewTextBoxColumn51.Name = "dataGridViewTextBoxColumn51"; - this.dataGridViewTextBoxColumn51.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn51.Width = 100; - // - // dataGridViewTextBoxColumn52 - // - this.dataGridViewTextBoxColumn52.DataPropertyName = "报出价"; - this.dataGridViewTextBoxColumn52.HeaderText = "报出价"; - this.dataGridViewTextBoxColumn52.Name = "dataGridViewTextBoxColumn52"; - this.dataGridViewTextBoxColumn52.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn52.Width = 100; - // - // dataGridViewTextBoxColumn53 - // - this.dataGridViewTextBoxColumn53.DataPropertyName = "图纸规格"; - this.dataGridViewTextBoxColumn53.HeaderText = "图纸规格"; - this.dataGridViewTextBoxColumn53.Name = "dataGridViewTextBoxColumn53"; - this.dataGridViewTextBoxColumn53.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn53.Width = 100; - // - // dataGridViewTextBoxColumn54 - // - this.dataGridViewTextBoxColumn54.DataPropertyName = "品牌"; - this.dataGridViewTextBoxColumn54.HeaderText = "品牌"; - this.dataGridViewTextBoxColumn54.Name = "dataGridViewTextBoxColumn54"; - this.dataGridViewTextBoxColumn54.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn54.Width = 100; - // - // dataGridViewTextBoxColumn55 - // - this.dataGridViewTextBoxColumn55.DataPropertyName = "系列"; - this.dataGridViewTextBoxColumn55.HeaderText = "系列"; - this.dataGridViewTextBoxColumn55.Name = "dataGridViewTextBoxColumn55"; - this.dataGridViewTextBoxColumn55.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn55.Width = 100; - // - // dataGridViewTextBoxColumn56 - // - this.dataGridViewTextBoxColumn56.DataPropertyName = "类型"; - this.dataGridViewTextBoxColumn56.HeaderText = "类型"; - this.dataGridViewTextBoxColumn56.Name = "dataGridViewTextBoxColumn56"; - this.dataGridViewTextBoxColumn56.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn56.Width = 100; - // - // dataGridViewTextBoxColumn57 - // - this.dataGridViewTextBoxColumn57.DataPropertyName = "备注"; - this.dataGridViewTextBoxColumn57.HeaderText = "备注"; - this.dataGridViewTextBoxColumn57.Name = "dataGridViewTextBoxColumn57"; - this.dataGridViewTextBoxColumn57.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.dataGridViewTextBoxColumn57.Width = 100; - dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle11.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle11.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle11.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle11.SelectionBackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle11.SelectionForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.advancedDataGridView5.DefaultCellStyle = dataGridViewCellStyle11; - this.advancedDataGridView5.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedDataGridView5.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.advancedDataGridView5.EnableCellPaste = true; - this.advancedDataGridView5.EnableHeadersVisualStyles = false; - this.advancedDataGridView5.Location = new System.Drawing.Point(0, 0); - this.advancedDataGridView5.Name = "advancedDataGridView5"; - this.advancedDataGridView5.RightToLeft = System.Windows.Forms.RightToLeft.No; - dataGridViewCellStyle12.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle12.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle12.Font = new System.Drawing.Font("宋体", 9F); - dataGridViewCellStyle12.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle12.SelectionBackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle12.SelectionForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle12.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.advancedDataGridView5.RowHeadersDefaultCellStyle = dataGridViewCellStyle12; - this.advancedDataGridView5.Size = new System.Drawing.Size(526, 272); - this.advancedDataGridView5.TabIndex = 0; - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // toolStrip1 - // - this.toolStrip1.BackColor = System.Drawing.SystemColors.Control; - this.toolStrip1.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F); - this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripButton1, - this.toolStripButton5, - this.toolStripButton6, - this.toolStripButton2, - this.toolStripButton3, - this.toolStripButton4, - this.toolStripButton7}); - this.toolStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; - this.toolStrip1.Location = new System.Drawing.Point(0, 0); - this.toolStrip1.Name = "toolStrip1"; - this.toolStrip1.Size = new System.Drawing.Size(540, 31); - this.toolStrip1.TabIndex = 1; - // - // toolStripButton1 - // - this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton1.Name = "toolStripButton1"; - this.toolStripButton1.Size = new System.Drawing.Size(86, 28); - this.toolStripButton1.Text = "导出数据"; - this.toolStripButton1.ToolTipText = "导出数据"; - // - // toolStripButton5 - // - this.toolStripButton5.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton5.Name = "toolStripButton5"; - this.toolStripButton5.Size = new System.Drawing.Size(86, 28); - this.toolStripButton5.Text = "新建项目"; - this.toolStripButton5.ToolTipText = "新建项目"; - // - // toolStripButton6 - // - this.toolStripButton6.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton6.Name = "toolStripButton6"; - this.toolStripButton6.Size = new System.Drawing.Size(86, 28); - this.toolStripButton6.Text = "删除项目"; - this.toolStripButton6.ToolTipText = "删除项目"; - // - // toolStripButton2 - // - this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton2.Name = "toolStripButton2"; - this.toolStripButton2.Size = new System.Drawing.Size(68, 28); - this.toolStripButton2.Text = "扒图号"; - this.toolStripButton2.ToolTipText = "扒图号"; - // - // toolStripButton3 - // - this.toolStripButton3.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton3.Name = "toolStripButton3"; - this.toolStripButton3.Size = new System.Drawing.Size(68, 28); - this.toolStripButton3.Text = "扒箱号"; - this.toolStripButton3.ToolTipText = "扒箱号"; - // - // toolStripButton4 - // - this.toolStripButton4.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton4.Name = "toolStripButton4"; - this.toolStripButton4.Size = new System.Drawing.Size(68, 28); - this.toolStripButton4.Text = "扒元件"; - this.toolStripButton4.ToolTipText = "扒元件"; - // - // toolStripButton7 - // - this.toolStripButton7.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.toolStripButton7.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolStripButton7.Name = "toolStripButton7"; - this.toolStripButton7.Size = new System.Drawing.Size(50, 28); - this.toolStripButton7.Text = "设置"; - // - // Form3 - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocusChange; - this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(540, 869); - this.Controls.Add(this.tabControl2); - this.Controls.Add(this.toolStrip1); - this.Font = new System.Drawing.Font("宋体", 9F); - this.ForeColor = System.Drawing.SystemColors.ControlText; - this.Name = "Form3"; - this.Text = "Form3"; - this.tabControl2.ResumeLayout(false); - this.tabPage3.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView6)).EndInit(); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); - this.tabPage4.ResumeLayout(false); - this.splitContainer2.Panel1.ResumeLayout(false); - this.splitContainer2.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); - this.splitContainer2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView9)).EndInit(); - this.splitContainer3.Panel1.ResumeLayout(false); - this.splitContainer3.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); - this.splitContainer3.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView4)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.advancedDataGridView5)).EndInit(); - this.toolStrip1.ResumeLayout(false); - this.toolStrip1.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.TabControl tabControl2; - private System.Windows.Forms.TabPage tabPage3; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView6; - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Button button28; - private System.Windows.Forms.TextBox textBox1; - private System.Windows.Forms.ComboBox comboBox2; - private System.Windows.Forms.TabPage tabPage4; - private System.Windows.Forms.SplitContainer splitContainer2; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView9; - private System.Windows.Forms.SplitContainer splitContainer3; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView4; - private Zuby.ADGV.AdvancedDataGridView advancedDataGridView5; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn6; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn7; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn8; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn12; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn13; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn14; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn15; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn16; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn17; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn18; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn19; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn20; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn21; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn22; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn23; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn24; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn25; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn26; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn27; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn28; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn29; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn30; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn31; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn32; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn33; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn34; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn35; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn36; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn37; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn38; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn39; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn40; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn41; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn42; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn43; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn44; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn45; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn46; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn47; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn48; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn49; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn50; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn51; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn52; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn53; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn54; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn55; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn56; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn57; - private System.Windows.Forms.ToolStrip toolStrip1; - private System.Windows.Forms.ToolStripButton toolStripButton1; - private System.Windows.Forms.ToolStripButton toolStripButton5; - private System.Windows.Forms.ToolStripButton toolStripButton6; - private System.Windows.Forms.ToolStripButton toolStripButton2; - private System.Windows.Forms.ToolStripButton toolStripButton3; - private System.Windows.Forms.ToolStripButton toolStripButton4; - private System.Windows.Forms.ToolStripButton toolStripButton7; - - /// 加载所有 SQLite 设计数据绑定。 - private void LoadAllSqliteData() - { - // cadbt 宿主为 x86 进程,引用的是 x86 版 System.Data.SQLite.dll, - // 无需 AutoCAD 插件版的 64 位检查,直接加载。 - try { LoadSqliteData_advancedDataGridView6(); } catch (System.Exception ex_advancedDataGridView6) { System.Windows.Forms.MessageBox.Show("加载数据失败 (advancedDataGridView6): " + ex_advancedDataGridView6.Message); } - } - - /// 为 advancedDataGridView6 加载 SQLite 数据(由设计器生成)。 - private void LoadSqliteData_advancedDataGridView6() - { - // ★ 数据库路径:优先用插件真实目录(_baseDir 在 Form3.cs,注册表/CodeBase 解析), - // 在 CAD 中加载时 BaseDirectory 指向 CAD 安装目录会找不到库 - string dbPath = System.IO.Path.Combine( - GetPluginBaseDirForUi(), @"sjk\advancedDataGridView6Table.db"); - if (!System.IO.File.Exists(dbPath)) - { - // ★ 静默跳过(不弹窗):构造函数里的 Load 事件已用正确路径重新加载 - System.Diagnostics.Debug.WriteLine("找不到数据库文件: " + dbPath); - return; - } - - string connStr = "Data Source=" + dbPath + ";Version=3;busy_timeout=3000;"; - var table = new System.Data.DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(connStr)) - { - conn.Open(); - string sql = @"SELECT * FROM advancedDataGridView6Table"; - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(sql, conn)) - { - adapter.Fill(table); - } - } - - this.advancedDataGridView6.AutoGenerateColumns = false; - // KeepCustomColumns=true:设计器中自定义的列不会被覆盖, - // 数据库列通过 DataPropertyName 与控件列关联。 - // 若列名与数据库列名相同,运行时会自动绑定数据。 - this.advancedDataGridView6.DataSource = table; - } - - /// - /// ui.cs 侧获取插件目录:复用 Form3.cs 的 _baseDir - /// (partial 类同字段;_baseDir 在 Form3.cs 中由注册表/CodeBase 解析) - /// - private string GetPluginBaseDirForUi() - { - return _baseDir; - } - } -} diff --git a/pdfbt/Plugin/Form3.cs b/pdfbt/Plugin/Form3.cs deleted file mode 100644 index 69a2287..0000000 --- a/pdfbt/Plugin/Form3.cs +++ /dev/null @@ -1,6882 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Drawing; -using System.IO; -using System.Windows.Forms; -using Microsoft.Win32; -using Zuby.ADGV; - -namespace MyApp -{ - /// - /// Form3 的交互逻辑(CAD 2018 插件报价窗口)。 - /// 功能与主项目报价页面一致:项目表 + 图号/箱号/元件三级联动 + 公式重算 + 右键菜单 + 项目导出。 - /// UI 布局定义见 Form3.ui.cs。数据库独立存放在 cadcj\sjk\ 目录。 - /// - public partial class Form3 - { - // ============================================================ - // 数据库路径与表名常量(独立于主项目,存放在 cadcj\sjk\ 下) - // ============================================================ - - private const string ProjectsDbPath = @"sjk\advancedDataGridView6Table.db"; - private const string ProjectsTableName = "advancedDataGridView6Table"; - private const string QuoteDbDir = @"sjk\bjb"; - private const string TuhaoTableName = "advancedDataGridView9Table"; - private const string ProjectInfoTableName = "项目信息"; - private const string IndexTableName = "表索引"; - - private const string CadRegPath = @"SOFTWARE\Autodesk\AutoCAD\R22.0\ACAD-1001:804\Apps\CADCJ"; - - /// - /// 插件所在目录(cadcj)。优先从注册表读取 CAD 自动加载的 DLL 路径(最可靠), - /// 然后尝试 CodeBase / Location,最后兜底 BaseDirectory(可能是 CAD 目录,会报错)。 - /// - private static readonly string _baseDir = GetPluginBaseDir(); - - private static string GetPluginBaseDir() - { - // ★ 方案0(standalone 版):exe 所在目录即数据根 - // (不再读 AutoCAD 注册表——旧 cadcj 注册表残留在客户机上会把数据指向已删除的目录) - try - { - var baseDir0 = AppDomain.CurrentDomain.BaseDirectory; - if (!string.IsNullOrEmpty(baseDir0) && Directory.Exists(baseDir0)) - { - WriteDebugLog("[GetPluginBaseDir] BaseDirectory 成功: " + baseDir0); - return baseDir0; - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] BaseDirectory 异常: " + ex.Message); } - - // ★ 方案1(历史保留):从注册表读取 CAD 自动加载配置的 MODULE 路径 - try - { - using (var key = Registry.LocalMachine.OpenSubKey(CadRegPath)) - { - if (key != null) - { - var module = key.GetValue("MODULE") as string; - if (!string.IsNullOrEmpty(module)) - { - var dir = Path.GetDirectoryName(module); - if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) - { - WriteDebugLog("[GetPluginBaseDir] 注册表方案成功: " + dir); - return dir; - } - } - } - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] 注册表方案异常: " + ex.Message); } - - // ★ 方案2:CodeBase(不受 shadow copy 影响) - try - { - var codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase; - WriteDebugLog("[GetPluginBaseDir] CodeBase=" + codeBase); - if (!string.IsNullOrEmpty(codeBase)) - { - var localPath = new Uri(codeBase).LocalPath; - var dir = Path.GetDirectoryName(localPath); - if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) - { - WriteDebugLog("[GetPluginBaseDir] CodeBase方案成功: " + dir); - return dir; - } - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] CodeBase方案异常: " + ex.Message); } - - // ★ 方案3:Location - try - { - var loc = System.Reflection.Assembly.GetExecutingAssembly().Location; - WriteDebugLog("[GetPluginBaseDir] Location=" + loc); - if (!string.IsNullOrEmpty(loc)) - { - var dir = Path.GetDirectoryName(loc); - if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) - { - WriteDebugLog("[GetPluginBaseDir] Location方案成功: " + dir); - return dir; - } - } - } - catch (Exception ex) { WriteDebugLog("[GetPluginBaseDir] Location方案异常: " + ex.Message); } - - // ★ 方案4(最后兜底):BaseDirectory(CAD 目录,数据库会找不到) - var fallback = AppDomain.CurrentDomain.BaseDirectory; - WriteDebugLog("[GetPluginBaseDir] ⚠ 兜底BaseDirectory=" + fallback + " (数据库会找不到!)"); - return fallback; - } - - private static void WriteDebugLog(string msg) - { - try - { - var logDir = Path.Combine( - Path.GetDirectoryName( - new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath), - "sjk"); - if (!Directory.Exists(logDir)) logDir = Path.GetTempPath(); - var logPath = Path.Combine(logDir, "form3_path_debug.log"); - File.AppendAllText(logPath, - "[" + DateTime.Now.ToString("HH:mm:ss") + "] " + msg + Environment.NewLine); - } - catch { } - } - - // ============================================================ - // 当前层级选中状态(联动核心) - // ============================================================ - - private string _currentProjectId = ""; - private string _currentTuhao = ""; - private string _currentXianghao = ""; - private bool _isReloading = false; - private bool _isRecalculating = false; - private DateTime _lastRecalcTime = DateTime.MinValue; - - // 价格显示格式化配置(每个项目独立,随项目信息表加载) - private string _单台小数位文本 = "保留2位小数"; - private string _单台取整方式 = "不取整"; - private string _项目小数位文本 = "保留2位小数"; - private string _项目取整方式 = "不取整"; - - // 当前各表的内存数据(用于关闭/切换时回写数据库) - private DataTable _tuhaoTable; - private DataTable _xianghaoTable; - private DataTable _yuanjianTable; - - // 内存缓存:切换图号/箱号时不丢编辑,点保存才写库 - private Dictionary _xianghaoCache = new Dictionary(); - private Dictionary _yuanjianCache = new Dictionary(); - - // 右键菜单组件(运行时创建,不在设计器 XML 里) - private ContextMenuStrip _menuTuhao; - private ContextMenuStrip _menuXianghao; - private ContextMenuStrip _menuYuanjian; - - private static readonly string[] ProjectInfoColumns = - { - "项目编号", "项目名称", "客户名称", "客户地址", - "联系人", "联系电话", "项目日期", "备注", - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话", - "单台小数位", "单台取整方式", "项目小数位", "项目取整方式" - }; - - /// 公式计算列集合(只包含程序算出来的价格列)。 - private static readonly HashSet s_公式列集合 = - new HashSet(StringComparer.OrdinalIgnoreCase) - { - "表价", "采购单价", "采购价", "报出单价", "报出价", - "单台成本", "成本价", "单台报出", "利润", - "单价", "总价", "成本总价", "毛利", - "成本总价", "报出总价", "利润" - }; - - /// 构造函数:初始化 UI 并绑定事件。 - public Form3() - { - InitializeComponent(); - - // ★ ADGV 右键多选保持(消息钩子版):右键点已选中的行不清空多选集合。 - // 原做法是项目内子类 AdgvKeepMulti 覆写 WndProc——但"设计器+项目内自定义类型" - // 在 SharpDevelop 设计时解析是死结,故改回 DLL 类型+NativeWindow 钩子(语义一致)。 - _keepMultiHooks = new System.Collections.Generic.List(); - HookKeepMulti(advancedDataGridView6); - HookKeepMulti(advancedDataGridView9); - HookKeepMulti(advancedDataGridView4); - HookKeepMulti(advancedDataGridView5); - - // ★ 立即创建数据库(不依赖 Load 事件,UserControl 嵌入 PaletteSet 时 Load 可能延迟) - try - { - Log("[Form3] _baseDir = " + _baseDir); - Log("[Form3] ProjectsDbPath = " + GetDbFullPath(ProjectsDbPath)); - EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); - Log("[Form3] 数据库创建/验证成功"); - } - catch (System.Exception ex) - { - Log("[Form3] 数据库创建失败: " + ex.Message); - } - - // ★ 诊断:后续初始化步骤逐步打点(定位面板空白问题) - try - { - Log("[Form3.init] 开始双缓冲设置"); - EnableDoubleBuffered(this.advancedDataGridView6); - EnableDoubleBuffered(this.advancedDataGridView9); - EnableDoubleBuffered(this.advancedDataGridView4); - EnableDoubleBuffered(this.advancedDataGridView5); - Log("[Form3.init] 双缓冲完成"); - - ApplyReadOnlyColumns(this.advancedDataGridView6, new string[] { - "项目编号", "项目名称", "客户名称", "客户地址", "联系人", "联系电话", - "项目日期", "箱柜台数", "成本总价", "报出总价", "利润", "利润率", "备注" - }); - ApplyReadOnlyColumns(this.advancedDataGridView9, new string[] { - "序号", "箱柜数量", "单价", "总价", "成本总价", "毛利", "毛利率" - }); - ApplyReadOnlyColumns(this.advancedDataGridView4, new string[] { - "序号", "单台成本", "成本价", "单台报出", "报出价", "利润", "利润率", "毛利率" - }); - ApplyReadOnlyColumns(this.advancedDataGridView5, new string[] { - "序号", "采购单价", "采购价", "报出单价", "报出价" - }); - Log("[Form3.init] 只读列完成"); - - // 工具栏按钮事件 - this.toolStripButton1.Click += toolStripButton1_Click; - this.toolStripButton5.Click += toolStripButton5_Click; - this.toolStripButton6.Click += toolStripButton6_Click; - this.toolStripButton2.Click += (s, e) => SendCadPaCommand("CADPATU"); - this.toolStripButton3.Click += (s, e) => SendCadPaCommand("CADPAXH"); - this.toolStripButton4.Click += (s, e) => SendCadPaCommand("CADPAYJ"); - this.toolStripButton7.Click += (s, e) => ShowDeepSeekSettings(); - Log("[Form3.init] 工具栏事件完成"); - - this.button28.Click += button28_Click; - this.advancedDataGridView6.CellDoubleClick += advancedDataGridView6_CellDoubleClick; - - this.advancedDataGridView9.SelectionChanged += advancedDataGridView9_SelectionChanged; - this.advancedDataGridView4.SelectionChanged += advancedDataGridView4_SelectionChanged; - this.advancedDataGridView5.SelectionChanged += advancedDataGridView5_SelectionChanged; - - this.advancedDataGridView9.CellClick += Grid_CellClick_Zoom; - this.advancedDataGridView4.CellClick += Grid_CellClick_Zoom; - this.advancedDataGridView5.CellClick += Grid_CellClick_Zoom; - - this.advancedDataGridView5.CellValueChanged += Yuanjian_CellValueChanged; - this.advancedDataGridView4.CurrentCellDirtyStateChanged += Grid_DirtyStateChanged; - this.advancedDataGridView4.CellValueChanged += Xianghao_CellValueChanged; - this.advancedDataGridView9.CurrentCellDirtyStateChanged += Grid_DirtyStateChanged; - this.advancedDataGridView9.CellValueChanged += Tuhao_CellValueChanged; - - this.advancedDataGridView5.CellEndEdit += Grid_CellEndEdit; - this.advancedDataGridView4.CellEndEdit += Grid_CellEndEdit; - this.advancedDataGridView9.CellEndEdit += Grid_CellEndEdit; - - this.advancedDataGridView5.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView4.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView9.DataError += (s, e) => { e.Cancel = true; }; - this.advancedDataGridView6.DataError += (s, e) => { e.Cancel = true; }; - - this.advancedDataGridView9.MouseDown += Grid_MouseDown_KeepMultiSelect; - this.advancedDataGridView4.MouseDown += Grid_MouseDown_KeepMultiSelect; - this.advancedDataGridView5.MouseDown += Grid_MouseDown_KeepMultiSelect; - - this.advancedDataGridView9.KeyDown += Grid_KeyDown_Delete; - this.advancedDataGridView4.KeyDown += Grid_KeyDown_Delete; - this.advancedDataGridView5.KeyDown += Grid_KeyDown_Delete; - Log("[Form3.init] 表格事件完成"); - - BuildContextMenus(); - Log("[Form3.init] 右键菜单完成"); - - this.Disposed += Form3_Disposed; - - this.Load += (s, e) => - { - try - { - EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); - ReloadProjectsFromDatabase(); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - this.advancedDataGridView9.DataSource = null; - this.advancedDataGridView4.DataSource = null; - this.advancedDataGridView5.DataSource = null; - Log("[Form3.Load] 初始化完成"); - } - catch (System.Exception ex) - { - Log("[Form3.Load] 初始化异常: " + ex.Message); - } - - try - { - // 网页 CAD 桥:订阅实体删除事件(用户在网页里删框时联动删行) - pdfbt.PdfBridge.EntityErased -= Database_ObjectErased; - pdfbt.PdfBridge.EntityErased += Database_ObjectErased; - // 网页 CAD 桥:订阅扒图结果事件(框选完成立即插入表格) - pdfbt.PdfBridge.PaPicked -= OnPaTextsPicked; - pdfbt.PdfBridge.PaPicked += OnPaTextsPicked; - // 网页 CAD 桥:F1/F2 元件合并(焦点在网页时按键由网页转发) - pdfbt.PdfBridge.F1Requested -= OnF1FromBridge; - pdfbt.PdfBridge.F1Requested += OnF1FromBridge; - pdfbt.PdfBridge.F2Requested -= OnF2FromBridge; - pdfbt.PdfBridge.F2Requested += OnF2FromBridge; - pdfbt.PdfBridge.F3Requested -= OnF3FromBridge; - pdfbt.PdfBridge.F3Requested += OnF3FromBridge; - } - catch (System.Exception ex) - { - Log("[Form3.Load] 订阅CadBridge事件失败: " + ex.Message); - } - }; - Log("[Form3.init] 构造函数全部完成 ✓"); - } - catch (System.Exception ex) - { - Log("[Form3.init] ⚠ 初始化异常: " + ex.ToString()); - } - } - - /// - /// ★ 网页 CAD 中实体被删除时触发。如果删除的是 __CADCJ_PA_FRAME 图层上的扒图框, - /// 通过 Handle 查找当前项目下的图号表/箱号表/元件表对应行,同步删除。 - /// - private void Database_ObjectErased(string handle) - { - try - { - if (string.IsNullOrWhiteSpace(handle)) return; - // ★ 如果正在通过表格删除(_isReloading=true),跳过网页 CAD 事件触发的删除 - // 避免表格删除和 CAD 事件删除互相干扰导致蒙版/数据不一致 - if (_isReloading) return; - - Log("[ObjectErased] 触发! Handle=" + handle); - - this.BeginInvoke((Action)(() => - { - try - { - // 再次检查(异步执行时状态可能已变化) - if (_isReloading) { Log("[ObjectErased] _isReloading=true,跳过"); return; } - DeleteRowsByFrameHandle(handle); - } - catch (System.Exception ex) - { - Log("[ObjectErased.BeginInvoke] 异常: " + ex.Message); - } - })); - } - catch (System.Exception ex) - { - Log("[ObjectErased] 异常: " + ex.Message); - } - } - - /// - /// 根据框Handle在当前项目的图号表/箱号表/元件表中删除对应数据行。 - /// - private void DeleteRowsByFrameHandle(string frameHandle) - { - if (string.IsNullOrWhiteSpace(frameHandle)) return; - if (string.IsNullOrWhiteSpace(_currentProjectId)) { Log("[DeleteRowsByFrameHandle] _currentProjectId 为空,放弃"); return; } - _isReloading = true; - try - { - string dbPath = GetQuoteDbPath(_currentProjectId); - if (!File.Exists(dbPath)) { Log("[DeleteRowsByFrameHandle] 数据库不存在: " + dbPath); return; } - - bool deleted = false; - string deletedTuhao = null; - string deletedXianghao = null; - // ★ 收集级联删除的框Handle(图号→箱号→元件,删除数据时同步删蒙版) - var cascadeFrames = new List(); - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - - // 1) 图号表 - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT 图号 FROM " + TuhaoTableName + " WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - using (var reader = sel.ExecuteReader()) - { - if (reader.Read()) - { - deletedTuhao = reader.IsDBNull(0) ? "" : reader.GetString(0); - Log("[DeleteRowsByFrameHandle] 命中图号表: " + deletedTuhao); - } - } - } - if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - // ★ 删除图号前,先收集该图号下所有箱号和元件的框Handle(级联删蒙版) - CollectFrameHandlesForTuhao(_currentProjectId, deletedTuhao, cascadeFrames); - DeleteTuhao(_currentProjectId, deletedTuhao); - deleted = true; - } - - if (!deleted) - { - // 2) 箱号表:通过表索引找到所有箱号表,逐个查 - List allXhTables = new List(); - using (var selIdx = new System.Data.SQLite.SQLiteCommand( - "SELECT 实际表名, 图号 FROM 表索引 WHERE 类型='箱号';", conn)) - using (var rIdx = selIdx.ExecuteReader()) - { - while (rIdx.Read()) - { - string realTbl = rIdx.IsDBNull(0) ? "" : rIdx.GetString(0); - string th = rIdx.IsDBNull(1) ? "" : rIdx.GetString(1); - if (!string.IsNullOrWhiteSpace(realTbl)) - allXhTables.Add(realTbl + "|" + th); - } - } - Log("[DeleteRowsByFrameHandle] 箱号表数量: " + allXhTables.Count); - foreach (string info in allXhTables) - { - string[] parts = info.Split('|'); - string realTbl = parts[0]; - string th = parts.Length > 1 ? parts[1] : ""; - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT 箱号 FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - using (var reader = sel.ExecuteReader()) - { - if (reader.Read()) - { - deletedTuhao = th; - deletedXianghao = reader.IsDBNull(0) ? "" : reader.GetString(0); - Log("[DeleteRowsByFrameHandle] 命中箱号表: 图号=" + th + " 箱号=" + deletedXianghao); - break; - } - } - } - if (!string.IsNullOrWhiteSpace(deletedXianghao)) break; - } - if (!string.IsNullOrWhiteSpace(deletedXianghao)) - { - // ★ 删除箱号前,先收集该箱号下元件表的框Handle(级联删蒙版) - CollectFrameHandlesForXianghao(_currentProjectId, deletedTuhao, deletedXianghao, cascadeFrames); - DeleteXianghao(_currentProjectId, deletedTuhao, deletedXianghao); - deleted = true; - } - } - - if (!deleted) - { - // 3) 元件表:通过表索引找到所有元件表,逐个查 - List allYjTables = new List(); - using (var selIdx = new System.Data.SQLite.SQLiteCommand( - "SELECT 实际表名, 图号, 箱号 FROM 表索引 WHERE 类型='元件';", conn)) - using (var rIdx = selIdx.ExecuteReader()) - { - while (rIdx.Read()) - { - string realTbl = rIdx.IsDBNull(0) ? "" : rIdx.GetString(0); - string th = rIdx.IsDBNull(1) ? "" : rIdx.GetString(1); - string xh = rIdx.IsDBNull(2) ? "" : rIdx.GetString(2); - if (!string.IsNullOrWhiteSpace(realTbl)) - allYjTables.Add(realTbl + "|" + th + "|" + xh); - } - } - Log("[DeleteRowsByFrameHandle] 元件表数量: " + allYjTables.Count + " 查找Handle=" + frameHandle); - foreach (string info in allYjTables) - { - string[] parts = info.Split('|'); - string realTbl = parts[0]; - string th = parts.Length > 1 ? parts[1] : ""; - string xh = parts.Length > 2 ? parts[2] : ""; - // ★ 先列出该表所有的框Handle,排查是否真的写进去了 - using (var selAll = new System.Data.SQLite.SQLiteCommand( - "SELECT 序号, 框Handle FROM \"" + realTbl + "\";", conn)) - using (var rAll = selAll.ExecuteReader()) - { - while (rAll.Read()) - { - string s = rAll.IsDBNull(0) ? "" : rAll.GetString(0); - string h = rAll.IsDBNull(1) ? "" : rAll.GetString(1); - Log(" [元件表 " + realTbl + "] 序号=" + s + " 框Handle=[" + h + "]"); - } - } - using (var sel = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - sel.Parameters.AddWithValue("@fh", frameHandle); - object cnt = sel.ExecuteScalar(); - int matchCount = (cnt != null && cnt != DBNull.Value) ? Convert.ToInt32(cnt) : 0; - if (matchCount > 0) - { - deletedTuhao = th; - deletedXianghao = xh; - Log("[DeleteRowsByFrameHandle] 命中元件表: 图号=" + th + " 箱号=" + xh + " 匹配行数=" + matchCount); - - // ★ 直接用框Handle 删除所有匹配行(解决重复行问题) - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + realTbl + "\" WHERE 框Handle=@fh;", conn)) - { - delCmd.Parameters.AddWithValue("@fh", frameHandle); - int affected = delCmd.ExecuteNonQuery(); - Log("[DeleteRowsByFrameHandle] DELETE 完成,影响行数=" + affected); - } - deleted = true; - break; - } - } - } - } - } - - if (deleted) - { - Log("[DeleteRowsByFrameHandle] 删除成功: Handle=" + frameHandle + " cascadeFrames=" + cascadeFrames.Count); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - // 重新编号(直接操作数据库) - if (!string.IsNullOrWhiteSpace(deletedTuhao) && !string.IsNullOrWhiteSpace(deletedXianghao)) - { - string yjTbl = GetYuanjianTableByIndex(_currentProjectId, deletedTuhao, deletedXianghao); - if (!string.IsNullOrEmpty(yjTbl)) - RenumberTable(_currentProjectId, "\"" + yjTbl + "\""); - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, deletedTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - } - else if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, deletedTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - } - - // ★ 直接在数据库层面重算(不经过内存表,不触发回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - - // ★ 从数据库重新加载到 UI(覆盖内存表,确保 UI 与数据库一致) - if (!string.IsNullOrWhiteSpace(deletedTuhao) && !string.IsNullOrWhiteSpace(deletedXianghao)) - { - if (_currentTuhao == deletedTuhao) - { - ReloadXianghaoByTuhao(_currentProjectId, deletedTuhao); - if (_currentXianghao == deletedXianghao) - ReloadYuanjianByXianghao(_currentProjectId, deletedTuhao, deletedXianghao); - } - } - else if (!string.IsNullOrWhiteSpace(deletedTuhao)) - { - ReloadTuhaoByProject(_currentProjectId); - if (_currentTuhao == deletedTuhao) - ReloadXianghaoByTuhao(_currentProjectId, deletedTuhao); - } - - // ★ 删除级联的框实体(图号删除时,其下箱号和元件的蒙版也要删除) - Log("[DeleteRowsByFrameHandle] cascadeFrames 数量: " + cascadeFrames.Count + " 当前Handle=" + frameHandle); - if (cascadeFrames.Count > 0) - { - // ★ 收集后一次性批量删除(排除当前正在删除的 frameHandle,已由 CAD 端删除) - var toDel = new List(); - foreach (string h in cascadeFrames) - { - if (h != frameHandle) toDel.Add(h); - } - if (toDel.Count > 0) - { - Log("[DeleteRowsByFrameHandle] 级联删除框Handle数: " + toDel.Count); - DeleteFramesByHandles(toDel); - } - SaveCurrentDwg(); - Log("[DeleteRowsByFrameHandle] 级联删除完成"); - } - } - } - finally - { - _isReloading = false; - } - } - - /// 重写 OnLoad:在所有 Load 事件订阅者之前确保项目库文件存在。 - protected override void OnLoad(EventArgs e) - { - try { EnsureProjectDbExists(GetDbFullPath(ProjectsDbPath)); } - catch { } - base.OnLoad(e); - } - - // ============================================================ - // 通用辅助方法 - // ============================================================ - - private void Log(string msg) - { - try - { - string logPath = Path.Combine(_baseDir, "diag.log"); - File.AppendAllText(logPath, - DateTime.Now.ToString("HH:mm:ss.fff") + " " + msg + "\r\n"); - } - catch { } - } - - private string GetDbFullPath(string relativePath) - { - return Path.Combine(_baseDir, relativePath); - } - - private string GetConnString(string dbPath) - { - // ★ busy_timeout=3000:数据库被 CAD 或其他进程短暂占用时等待重试而非卡死; - // Pooling 关闭,避免连接池长期持有文件句柄 - return "Data Source=" + dbPath + ";Version=3;busy_timeout=3000;"; - } - - private string GetQuoteDbPath(string projectId) - { - string safeName = projectId; - char[] invalidChars = Path.GetInvalidFileNameChars(); - foreach (char c in invalidChars) safeName = safeName.Replace(c, '_'); - return GetDbFullPath(QuoteDbDir + @"\项目" + safeName + ".db"); - } - - private static decimal ParseDecimal(object v) - { - if (v == null || v == DBNull.Value) return 0m; - decimal d; - if (decimal.TryParse(v.ToString().Trim(), out d)) return d; - return 0m; - } - - private static DataGridViewColumn FindColumn(DataGridView dgv, string name) - { - if (dgv == null || dgv.Columns == null) return null; - foreach (DataGridViewColumn c in dgv.Columns) - { - if (c == null) continue; - if (c.DataPropertyName == name || c.HeaderText == name || c.Name == name) return c; - } - return null; - } - - private static string GetCellString(DataGridViewRow row, string name) - { - if (row == null || row.DataGridView == null) return ""; - DataGridViewColumn col = FindColumn(row.DataGridView, name); - if (col == null) return ""; - object v = row.Cells[col.Index].Value; - return v == null ? "" : v.ToString().Trim(); - } - - private static decimal GetCellDecimal(DataGridViewRow row, string name) - { - return ParseDecimal(GetCellString(row, name)); - } - - private static string GetCellValueAsString(DataGridViewRow row, string colName) - { - if (row == null || row.Cells == null || string.IsNullOrEmpty(colName)) return ""; - DataGridView grid = row.DataGridView; - if (grid != null) - { - foreach (DataGridViewColumn col in grid.Columns) - { - if (col == null) continue; - string key = !string.IsNullOrEmpty(col.DataPropertyName) - ? col.DataPropertyName - : (!string.IsNullOrEmpty(col.HeaderText) ? col.HeaderText : col.Name); - if (key == colName) - { - object v = row.Cells[col.Index].Value; - return v == null ? "" : v.ToString().Trim(); - } - } - } - return ""; - } - - private static void SetCell(DataGridViewRow row, string colName, decimal value) - { - if (row == null || row.DataGridView == null) return; - DataGridViewColumn col = FindColumn(row.DataGridView, colName); - if (col == null) return; - row.Cells[col.Index].Value = value == 0m ? 0d : (double)value; - } - - private static DataGridViewRow GetFirstSelectedRow(DataGridView dgv) - { - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return null; - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - return r; - } - if (dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) return dgv.CurrentRow; - return null; - } - - private static List GetAllSelectedRows(DataGridView dgv) - { - var result = new List(); - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return result; - var seenRows = new HashSet(); - if (dgv.SelectedRows != null) - { - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - if (seenRows.Add(r.Index)) result.Add(r); - } - } - // ★ 总是通过 SelectedCells 补充收集(不再限制 result.Count == 0) - // ADGV 多选时 SelectedRows 可能不完整,SelectedCells 能覆盖所有选中行 - if (dgv.SelectedCells != null) - { - foreach (DataGridViewCell c in dgv.SelectedCells) - { - if (c == null || c.RowIndex < 0) continue; - DataGridViewRow r = dgv.Rows[c.RowIndex]; - if (r == null || r.IsNewRow) continue; - if (seenRows.Add(r.Index)) result.Add(r); - } - } - // 兜底:如果以上都没收集到,取当前行 - if (result.Count == 0 && dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) - { - result.Add(dgv.CurrentRow); - } - return result; - } - - private DataGridViewRow GetFirstSelectedProjectRow() - { - DataGridView dgv = this.advancedDataGridView6; - if (dgv == null || dgv.Rows == null || dgv.Rows.Count == 0) return null; - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r == null || r.IsNewRow) continue; - return r; - } - if (dgv.CurrentRow != null && !dgv.CurrentRow.IsNewRow) return dgv.CurrentRow; - return null; - } - - private DataGridViewRow FindProjectRowById(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return null; - DataGridView dgv = this.advancedDataGridView6; - if (dgv == null || dgv.Rows == null) return null; - foreach (DataGridViewRow r in dgv.Rows) - { - if (r == null || r.IsNewRow) continue; - if (GetCellValueAsString(r, "项目编号") == projectId) return r; - } - return null; - } - - private static void SetCurrentCell(DataGridView dgv, int rowIndex, int colIndex = 0) - { - if (dgv == null || dgv.Rows == null || rowIndex < 0 || rowIndex >= dgv.Rows.Count) return; - try - { - if (dgv.Rows[rowIndex].IsNewRow) return; - if (colIndex < 0 || colIndex >= dgv.Columns.Count) colIndex = 0; - dgv.ClearSelection(); - dgv.Rows[rowIndex].Selected = true; - dgv.CurrentCell = dgv.Rows[rowIndex].Cells[colIndex]; - } - catch { } - } - - private void SelectRowByValue(DataGridView dgv, string colName, string value) - { - if (dgv == null || dgv.Rows == null || string.IsNullOrEmpty(value)) return; - try - { - _isReloading = true; - foreach (DataGridViewRow r in dgv.Rows) - { - if (r == null || r.IsNewRow) continue; - if (GetCellValueAsString(r, colName) == value) - { - dgv.ClearSelection(); - r.Selected = true; - dgv.CurrentCell = r.Cells[0]; - return; - } - } - } - catch { } - finally { _isReloading = false; } - } - - private static int GetSelectedRowIndex(DataGridView dgv) - { - if (dgv == null) return -1; - if (dgv.CurrentRow == null || dgv.CurrentRow.IsNewRow) return -1; - return dgv.CurrentRow.Index; - } - - private static string MakeSafeFileName(string s) - { - if (string.IsNullOrEmpty(s)) return "未命名"; - string r = s; - char[] invalid = Path.GetInvalidFileNameChars(); - foreach (char c in invalid) r = r.Replace(c, '_'); - return r; - } - - private static string EscapeJsonString(string s) - { - if (s == null) return ""; - return s.Replace("\\", "\\\\").Replace("\"", "\\\"") - .Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t"); - } - - private string ShowInputDialog(string title, string prompt, string defaultValue) - { - using (var dlg = new Form()) - { - dlg.Text = title; - dlg.StartPosition = FormStartPosition.CenterParent; - dlg.FormBorderStyle = FormBorderStyle.FixedDialog; - dlg.MinimizeBox = false; - dlg.MaximizeBox = false; - dlg.Width = 340; - dlg.Height = 170; - - var lbl = new Label(); - lbl.Text = prompt; - lbl.Left = 12; lbl.Top = 15; - lbl.Width = 300; lbl.Height = 30; - dlg.Controls.Add(lbl); - - var txt = new TextBox(); - txt.Text = defaultValue; - txt.Left = 12; txt.Top = 55; - txt.Width = 300; - dlg.Controls.Add(txt); - - var btnOk = new Button(); - btnOk.Text = "确定"; - btnOk.Left = 210; btnOk.Top = 92; - btnOk.Width = 90; - btnOk.DialogResult = DialogResult.OK; - dlg.Controls.Add(btnOk); - - var btnCancel = new Button(); - btnCancel.Text = "取消"; - btnCancel.Left = 108; btnCancel.Top = 92; - btnCancel.Width = 90; - btnCancel.DialogResult = DialogResult.Cancel; - dlg.Controls.Add(btnCancel); - - dlg.AcceptButton = btnOk; - dlg.CancelButton = btnCancel; - - if (dlg.ShowDialog(this) == DialogResult.OK) return txt.Text; - return ""; - } - } - - /// 开启 DataGridView 的双缓冲(消除闪烁)。 - private static void EnableDoubleBuffered(DataGridView dgv) - { - if (dgv == null) return; - try - { - typeof(DataGridView).InvokeMember("DoubleBuffered", - System.Reflection.BindingFlags.SetProperty | - System.Reflection.BindingFlags.Instance | - System.Reflection.BindingFlags.NonPublic, - null, dgv, new object[] { true }); - } - catch { } - } - - /// 按列名设置只读(运行时按 DataPropertyName/HeaderText 查找)。 - private static void ApplyReadOnlyColumns(DataGridView dgv, string[] colNames) - { - if (dgv == null || colNames == null) return; - foreach (string name in colNames) - { - DataGridViewColumn col = FindColumn(dgv, name); - if (col != null) col.ReadOnly = true; - } - } - - // ============================================================ - // 价格显示格式化 - // ============================================================ - - /// 把"保留2位小数"/"保留整数"等转成 .NET 格式字符串(F0/F2)。 - private static string ToFormatString(string 小数位文本) - { - int n = 解析小数位(小数位文本); - if (n < 0) n = 2; - return "F" + n.ToString(); - } - - private static int 解析小数位(string text) - { - if (string.IsNullOrWhiteSpace(text)) return 2; - string t = text.Trim(); - if (t.Contains("整数")) return 0; - if (t.Contains("1位")) return 1; - if (t.Contains("2位")) return 2; - if (t.Contains("3位")) return 3; - if (t.Contains("4位")) return 4; - return 2; - } - - private void ApplyPriceFormat(DataGridView dgv, string 小数位文本) - { - if (dgv == null || dgv.Columns == null) return; - string fmt = ToFormatString(小数位文本); - foreach (DataGridViewColumn col in dgv.Columns) - { - if (col == null) continue; - string name = !string.IsNullOrEmpty(col.DataPropertyName) - ? col.DataPropertyName : col.HeaderText; - if (string.IsNullOrEmpty(name)) continue; - if (s_公式列集合.Contains(name)) - { - col.DefaultCellStyle.Format = fmt; - } - } - } - - /// 老库兼容:把 DataTable 中公式列的类型从 string 转为 double。 - private static DataTable ConvertFormulaColumnsToDouble(DataTable table) - { - if (table == null || table.Columns.Count == 0) return table; - bool needsConvert = false; - foreach (DataColumn dc in table.Columns) - { - if (s_公式列集合.Contains(dc.ColumnName) && dc.DataType == typeof(string)) - { - needsConvert = true; - break; - } - } - if (!needsConvert) return table; - - var newTable = new DataTable(); - foreach (DataColumn dc in table.Columns) - { - Type t = s_公式列集合.Contains(dc.ColumnName) ? typeof(double) : dc.DataType; - newTable.Columns.Add(dc.ColumnName, t); - } - foreach (DataRow row in table.Rows) - { - var newRow = newTable.NewRow(); - foreach (DataColumn dc in table.Columns) - { - if (s_公式列集合.Contains(dc.ColumnName)) - { - object v = row[dc]; - if (v == null || v == DBNull.Value) newRow[dc.ColumnName] = 0d; - else if (v is double) newRow[dc.ColumnName] = v; - else - { - double d; - newRow[dc.ColumnName] = double.TryParse(v.ToString().Trim(), out d) ? d : 0d; - } - } - else newRow[dc.ColumnName] = row[dc]; - } - newTable.Rows.Add(newRow); - } - newTable.TableName = table.TableName; - return newTable; - } - - // ============================================================ - // 数据库结构维护 - // ============================================================ - - private void EnsureProjectDbExists(string dbPath) - { - string dir = Path.GetDirectoryName(dbPath); - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE IF NOT EXISTS " + ProjectsTableName + " (" + - " 项目编号 TEXT, 项目名称 TEXT, 客户名称 TEXT, 客户地址 TEXT," + - " 联系人 TEXT, 联系电话 TEXT, 项目日期 TEXT, 箱柜台数 REAL," + - " 成本总价 REAL, 报出总价 REAL, 利润 REAL, 利润率 REAL, 备注 TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - EnsureColumns(conn, ProjectsTableName, new[] { - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话" - }); - } - } - - private static void EnsureColumns(System.Data.SQLite.SQLiteConnection conn, string tableName, string[] columns) - { - if (columns == null || columns.Length == 0) return; - var existing = new HashSet(StringComparer.OrdinalIgnoreCase); - using (var infoCmd = new System.Data.SQLite.SQLiteCommand("PRAGMA table_info(" + tableName + ");", conn)) - using (var reader = infoCmd.ExecuteReader()) - { - while (reader.Read()) - { - object nameObj = reader["name"]; - if (nameObj != null && nameObj != DBNull.Value) existing.Add(nameObj.ToString()); - } - } - foreach (string col in columns) - { - if (!existing.Contains(col)) - { - string sql = "ALTER TABLE " + tableName + " ADD COLUMN " + col + " TEXT;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - } - } - - private static List GetProjectTableColumns(System.Data.SQLite.SQLiteConnection conn) - { - var cols = new List(); - try - { - using (var infoCmd = new System.Data.SQLite.SQLiteCommand("PRAGMA table_info(" + ProjectsTableName + ");", conn)) - using (var reader = infoCmd.ExecuteReader()) - { - while (reader.Read()) - { - object nameObj = reader["name"]; - if (nameObj != null && nameObj != DBNull.Value) cols.Add(nameObj.ToString()); - } - } - } - catch { } - return cols; - } - - private void EnsureQuoteDbExists(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - string dir = Path.GetDirectoryName(dbPath); - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sqlTuhao = - "CREATE TABLE IF NOT EXISTS " + TuhaoTableName + " (" + - " 序号 TEXT, 图号 TEXT, 图名 TEXT, 台数 TEXT, 箱柜数量 REAL," + - " 单价 REAL, 总价 REAL, 成本总价 REAL, 毛利 REAL, 毛利率 REAL," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - string sqlIndex = - "CREATE TABLE IF NOT EXISTS 表索引 (" + - " 类型 TEXT, 图号 TEXT, 箱号 TEXT, 实际表名 TEXT" + - ");"; - string sqlProjectInfo = - "CREATE TABLE IF NOT EXISTS " + ProjectInfoTableName + " (" + - " 项目编号 TEXT, 项目名称 TEXT, 客户名称 TEXT, 客户地址 TEXT," + - " 联系人 TEXT, 联系电话 TEXT, 项目日期 TEXT, 备注 TEXT," + - " 成套厂名称 TEXT, 成套厂地址 TEXT, 成套厂联系人 TEXT, 成套厂联系电话 TEXT," + - " 单台小数位 TEXT, 单台取整方式 TEXT, 项目小数位 TEXT, 项目取整方式 TEXT" + - ");"; - foreach (string sql in new[] { sqlTuhao, sqlIndex, sqlProjectInfo }) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - EnsureColumns(conn, ProjectInfoTableName, new[] { - "成套厂名称", "成套厂地址", "成套厂联系人", "成套厂联系电话", - "单台小数位", "单台取整方式", "项目小数位", "项目取整方式" - }); - // ★ 确保旧库的图号表也有"框Handle"/"文本Handle"列 - EnsureColumns(conn, TuhaoTableName, new[] { "框Handle", "文本Handle" }); - } - } - - // ---------- 箱号表(每个图号一张独立表,表名=图号原名,双引号括起)---------- - - private static string GetXianghaoTableName(string tuhao) - { - if (string.IsNullOrWhiteSpace(tuhao)) return "\"图号箱号表\""; - return "\"" + tuhao.Replace("\"", "\"\"") + "\""; - } - - private void EnsureXianghaoTableExists(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - // 先查表索引,已有则跳过 - string existing = GetXianghaoTableByIndex(projectId, tuhao); - if (!string.IsNullOrEmpty(existing)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - // 用唯一ID做表名,避免图号名含特殊字符 - string realTbl = GetNextTableId(projectId, "箱号"); - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTbl + "\" (" + - " 序号 TEXT, 箱号 TEXT, 型号 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 单台成本 REAL, 成本价 REAL, 单台报出 REAL, 报出价 REAL," + - " 利润 REAL, 利润率 REAL, 毛利率 REAL, 箱柜类型 TEXT, 备注 TEXT, 图纸 TEXT," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - // ★ 注册到表索引,后续 GetXianghaoTableByIndex 才能查到 - AddTableIndex(projectId, "箱号", tuhao, "", realTbl); - } - catch { } - } - - private string GetXianghaoCount(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return "1"; - string realTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(realTbl)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT COUNT(*) FROM \"" + realTbl + "\";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - catch { return "1"; } - } - - // ---------- 元件计数(用于新建元件命名"新元件N")---------- - - private string GetYuanjianCount(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || - string.IsNullOrWhiteSpace(xianghao)) return "1"; - // 查索引表拿该箱号元件表的真实表名 - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(realTbl)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT COUNT(*) FROM \"" + realTbl + "\";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - catch { return "1"; } - } - - // ---------- 元件表(每个箱号一张独立表)---------- - - private static string GetYuanjianTableName(string xianghao) - { - if (string.IsNullOrWhiteSpace(xianghao)) return "\"元件表\""; - return "\"" + xianghao.Replace("\"", "\"\"") + "\""; - } - - private void EnsureYuanjianTableExists(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - // 先查表索引,已有则跳过 - string existing = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (!string.IsNullOrEmpty(existing)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - // 用唯一ID做表名 - string realTbl = GetNextTableId(projectId, "元件"); - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTbl + "\" (" + - " 序号 TEXT, 元件名称 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 表价 REAL, 采购单价 REAL, 采购系数 TEXT, 采购价 REAL," + - " 报出单价 REAL, 报出系数 TEXT, 报出价 REAL," + - " 图纸规格 TEXT, 品牌 TEXT, 系列 TEXT, 类型 TEXT, 备注 TEXT," + - " 框Handle TEXT, 文本Handle TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - // ★ 注册到表索引(类型=元件,图号,箱号) — 后续 GetYuanjianTableByIndex 才能查到 - AddTableIndex(projectId, "元件", tuhao, xianghao, realTbl); - } - catch { } - } - - // ---------- 表索引(用唯一ID做表名,索引表记录 图号/箱号 → 真实表名)---------- - - private string GetNextTableId(string projectId, string prefix) - { - if (string.IsNullOrWhiteSpace(projectId)) return prefix + "_1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return prefix + "_1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT 实际表名 FROM 表索引 WHERE 实际表名 LIKE @p;"; - int maxN = 0; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@p", prefix + "_%"); - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string t = reader.IsDBNull(0) ? "" : reader.GetString(0); - string numPart = t.StartsWith(prefix + "_") ? t.Substring(prefix.Length + 1) : ""; - int n; - if (int.TryParse(numPart, out n) && n > maxN) maxN = n; - } - } - } - return prefix + "_" + (maxN + 1).ToString(); - } - } - catch { return prefix + "_1"; } - } - - private void AddTableIndex(string projectId, string type, string tuhao, string xianghao, string realTableName) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(realTableName)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "INSERT INTO 表索引 (类型, 图号, 箱号, 实际表名) VALUES (@t, @th, @xh, @real);"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao ?? ""); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - cmd.Parameters.AddWithValue("@real", realTableName); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - private void RemoveTableIndex(string projectId, string type, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "DELETE FROM 表索引 WHERE 类型=@t AND 图号=@th AND 箱号=@xh;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao ?? ""); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - private string GetXianghaoTableByIndex(string projectId, string tuhao) - { - return LookupTableByIndex(projectId, "箱号", tuhao, ""); - } - - private string GetYuanjianTableByIndex(string projectId, string tuhao, string xianghao) - { - return LookupTableByIndex(projectId, "元件", tuhao, xianghao); - } - - private string LookupTableByIndex(string projectId, string type, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return ""; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return ""; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - return LookupTableByIndex(type, tuhao, xianghao, conn); - } - } - catch { return ""; } - } - - private string LookupTableByIndex(string type, string tuhao, string xianghao, System.Data.SQLite.SQLiteConnection conn) - { - if (conn == null || string.IsNullOrWhiteSpace(tuhao)) return ""; - try - { - string sql = "SELECT 实际表名 FROM 表索引 WHERE 类型=@t AND 图号=@th AND 箱号=@xh LIMIT 1;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@t", type); - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.Parameters.AddWithValue("@xh", xianghao ?? ""); - object o = cmd.ExecuteScalar(); - return (o == null || o == DBNull.Value) ? "" : o.ToString(); - } - } - catch { return ""; } - } - - private string GetXianghaoTableByIndex(string tuhao, System.Data.SQLite.SQLiteConnection conn) - { - return LookupTableByIndex("箱号", tuhao, "", conn); - } - - private string GetYuanjianTableByIndex(string tuhao, string xianghao, System.Data.SQLite.SQLiteConnection conn) - { - return LookupTableByIndex("元件", tuhao, xianghao, conn); - } - - private void CreateXianghaoTable(string projectId, string realTableName) - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = - "CREATE TABLE \"" + realTableName + "\" (" + - " 序号 TEXT, 箱号 TEXT, 箱名 TEXT, 型号 TEXT, 规格 TEXT, 单位 TEXT, 数量 TEXT," + - " 单台成本 REAL, 成本价 REAL, 单台报出 REAL, 报出价 REAL," + - " 利润 REAL, 利润率 REAL, 毛利率 REAL, 箱柜类型 TEXT, 备注 TEXT, 图纸 TEXT" + - ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) cmd.ExecuteNonQuery(); - } - } - catch { } - } - - private void RenumberTable(string projectId, string quotedTableName) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(quotedTableName)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string selSql = "SELECT rowid FROM " + quotedTableName + " ORDER BY rowid;"; - var rowids = new List(); - using (var sel = new System.Data.SQLite.SQLiteCommand(selSql, conn)) - using (var reader = sel.ExecuteReader()) - { - while (reader.Read()) rowids.Add(reader.GetInt64(0)); - } - int newSeq = 1; - foreach (long rowid in rowids) - { - string updSql = "UPDATE " + quotedTableName + " SET 序号 = @seq WHERE rowid = @rid;"; - using (var upd = new System.Data.SQLite.SQLiteCommand(updSql, conn)) - { - upd.Parameters.AddWithValue("@seq", newSeq.ToString()); - upd.Parameters.AddWithValue("@rid", rowid); - upd.ExecuteNonQuery(); - } - newSeq++; - } - } - } - catch { } - } - - // ============================================================ - // 报价库「项目信息」表读写 - // ============================================================ - - private void InsertProjectInfoToQuoteDb(string projectId, Dictionary values) - { - if (string.IsNullOrWhiteSpace(projectId) || values == null) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string delSql = "DELETE FROM " + ProjectInfoTableName + " WHERE 项目编号 = @id;"; - using (var del = new System.Data.SQLite.SQLiteCommand(delSql, conn)) - { - del.Parameters.AddWithValue("@id", projectId); - del.ExecuteNonQuery(); - } - var cols = new List(); - var paras = new List(); - foreach (string c in ProjectInfoColumns) - { - if (values.ContainsKey(c)) { cols.Add(c); paras.Add("@" + c); } - } - if (cols.Count == 0) return; - string sql = "INSERT INTO " + ProjectInfoTableName + " (" + - string.Join(", ", cols.ToArray()) + ") VALUES (" + - string.Join(", ", paras.ToArray()) + ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - foreach (string c in cols) cmd.Parameters.AddWithValue("@" + c, values[c] ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private Dictionary GetProjectInfoFromQuoteDb(string projectId) - { - var info = new Dictionary(); - if (string.IsNullOrWhiteSpace(projectId)) return info; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return info; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string chkSql = "SELECT name FROM sqlite_master WHERE type='table' AND name=@n;"; - using (var chk = new System.Data.SQLite.SQLiteCommand(chkSql, conn)) - { - chk.Parameters.AddWithValue("@n", ProjectInfoTableName); - if (chk.ExecuteScalar() == null) return info; - } - string sql = "SELECT * FROM " + ProjectInfoTableName + " WHERE 项目编号 = @id LIMIT 1;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@id", projectId); - using (var reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - var existCols = new HashSet(StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < reader.FieldCount; i++) existCols.Add(reader.GetName(i)); - foreach (string c in ProjectInfoColumns) - { - if (!existCols.Contains(c)) continue; - object v = reader[c]; - info[c] = (v == null || v == DBNull.Value) ? "" : v.ToString(); - } - } - } - } - } - } - catch { } - return info; - } - - private void LoadPriceFormatConfig(string projectId) - { - _单台小数位文本 = "保留2位小数"; - _单台取整方式 = "不取整"; - _项目小数位文本 = "保留2位小数"; - _项目取整方式 = "不取整"; - try - { - var info = GetProjectInfoFromQuoteDb(projectId); - if (info == null || info.Count == 0) return; - string v; - if (info.TryGetValue("单台小数位", out v) && !string.IsNullOrWhiteSpace(v)) _单台小数位文本 = v; - if (info.TryGetValue("单台取整方式", out v) && !string.IsNullOrWhiteSpace(v)) _单台取整方式 = v; - if (info.TryGetValue("项目小数位", out v) && !string.IsNullOrWhiteSpace(v)) _项目小数位文本 = v; - if (info.TryGetValue("项目取整方式", out v) && !string.IsNullOrWhiteSpace(v)) _项目取整方式 = v; - } - catch { } - } - - // ============================================================ - // 项目库 CRUD - // ============================================================ - - private int InsertProjectToDatabase(Dictionary values) - { - if (values == null || values.Count == 0) return 0; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) - { - EnsureProjectDbExists(dbPath); - if (!File.Exists(dbPath)) - throw new FileNotFoundException("无法创建项目数据库文件: " + dbPath, dbPath); - } - int affected; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var allowed = new HashSet(GetProjectTableColumns(conn), StringComparer.OrdinalIgnoreCase); - var colNames = new List(); - var paramNames = new List(); - foreach (string col in values.Keys) - { - if (allowed.Contains(col)) { colNames.Add(col); paramNames.Add("@" + col); } - } - if (colNames.Count == 0) { affected = 0; } - else - { - string sql = "INSERT INTO " + ProjectsTableName + " (" + - string.Join(", ", colNames.ToArray()) + ") VALUES (" + - string.Join(", ", paramNames.ToArray()) + ");"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - foreach (string col in colNames) cmd.Parameters.AddWithValue("@" + col, values[col]); - affected = cmd.ExecuteNonQuery(); - } - } - } - string projectId; - values.TryGetValue("项目编号", out projectId); - if (!string.IsNullOrWhiteSpace(projectId)) InsertProjectInfoToQuoteDb(projectId, values); - return affected; - } - - private int DeleteProjectFromDatabase(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return 0; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) throw new FileNotFoundException("找不到项目数据库文件: " + dbPath, dbPath); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "DELETE FROM " + ProjectsTableName + " WHERE 项目编号 = @id;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@id", projectId); - return cmd.ExecuteNonQuery(); - } - } - } - - private void CascadeDeleteByProject(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try { File.Delete(dbPath); } - catch { } - } - - private List> ReadAllProjectsFromDatabase() - { - var list = new List>(); - try - { - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT * FROM " + ProjectsTableName + " ORDER BY rowid;", conn)) - using (var rd = cmd.ExecuteReader()) - { - while (rd.Read()) - { - var dict = new Dictionary(StringComparer.Ordinal); - for (int i = 0; i < rd.FieldCount; i++) - { - object v = rd.GetValue(i); - if (v == null || v == DBNull.Value) v = ""; - dict[rd.GetName(i)] = v; - } - list.Add(dict); - } - } - } - } - catch { } - return list; - } - - private Dictionary ReadProjectMetaData(string pid) - { - var dict = new Dictionary(StringComparer.Ordinal); - try - { - string dbPath = GetDbFullPath(ProjectsDbPath); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT * FROM " + ProjectsTableName + " WHERE 项目编号 = @p LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@p", pid); - using (var rd = cmd.ExecuteReader()) - { - if (!rd.Read()) return null; - for (int i = 0; i < rd.FieldCount; i++) - { - object v = rd.GetValue(i); - if (v == null || v == DBNull.Value) v = ""; - dict[rd.GetName(i)] = v; - } - } - } - } - } - catch { return null; } - return dict; - } - - // ============================================================ - // 图号/箱号/元件 CRUD - // ============================================================ - - private string GetNextSeqNumber(string tableName, string nameCol, string projectId, string tuhao = null) - { - if (string.IsNullOrWhiteSpace(projectId)) return "1"; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return "1"; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql; - if (tuhao == null) - { - sql = "SELECT COUNT(*) FROM " + tableName + ";"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - else - { - sql = "SELECT COUNT(*) FROM " + tableName + " WHERE 图号 = @th;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - int n = 0; - object o = cmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - return (n + 1).ToString(); - } - } - } - } - catch { return "1"; } - } - - // ============================================================ - // 扒图号/扒箱号/扒元件:CAD 文本选择交互 - // ============================================================ - - /// - /// 向 CAD 发送扒数据命令,触发框选交互。 - /// ★ 关键:先发 ESC 取消当前可能正在进行的扒图循环,再发新命令 - /// 这样用户从"扒图号"循环里点"扒箱号"也能立即切换 - /// - private void SendCadPaCommand(string cmd) - { - try - { - if (!pdfbt.PdfBridge.IsViewerReady) - { - MessageBox.Show(this, "尚未打开 PDF 图纸,请先在文档区打开 PDF 文件。", - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // 转发到 PDF 查看器(patu/paxh/payj/pacl 模式) - pdfbt.PdfBridge.SendPaCommand(cmd); - } - catch (Exception ex) - { - MessageBox.Show(this, "发送扒图命令失败:\n" + ex.Message, - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - /// - /// CAD 选中文本后的回调:把选中的文本批量插入到对应表格。 - /// 由 CadPlugin.ExecutePaCommand 在 UI 线程调用。 - /// - public void OnPaTextsPicked(PaMode mode, List results) - { - if (results == null || results.Count == 0) return; - if (string.IsNullOrWhiteSpace(_currentProjectId)) - { - MessageBox.Show(this, "请先在项目表中双击选择一个项目,再扒数据。", - "扒数据", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - switch (mode) - { - case PaMode.Tuhao: - PaTuhaoInsert(results); - break; - case PaMode.Xianghao: - PaXianghaoInsert(results); - break; - case PaMode.Yuanjian: - PaYuanjianInsert(results); - break; - } - } - - /// 扒图号:把选中文本作为图号批量插入到当前项目,同时保存框Handle。 - /// ★ 重复扒图:如果图号已存在,删除旧框和数据库行(不新增)。 - private void PaTuhaoInsert(List results) - { - string lastInsertedTuhao = null; // ★ 记录最后插入的图号,用于自动选中联动 - try - { - _isReloading = true; - // 先 AcceptChanges,避免 SaveAllQuoteTablesIfDirty 把旧内存表回写 - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - - // ★ 新增框架Handle列表: PaTextSelector刚画的框,如果是重复,需要删除这些新框 - var newFramesToErase = new List(); - int deletedCount = 0; - int inserted = 0; - - foreach (var r in results) - { - if (string.IsNullOrWhiteSpace(r.Text)) continue; - string clean = r.Text.Trim(); - // ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - // 不同位置的相同内容文本 Handle 不同 → 不算重复,正常插入。 - string oldFrame = GetTuhaoFrameHandleByTextHandle(_currentProjectId, clean, r.TextHandle); - if (!string.IsNullOrEmpty(oldFrame)) - { - // ★ 重复(同一个文本再次选中):删除旧框+数据库行+新框 - DeleteTuhao(_currentProjectId, clean); - DeleteFrameByHandle(oldFrame); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - deletedCount++; - } - else - { - InsertTuhao(_currentProjectId, clean, r.FrameHandle, r.TextHandle); - lastInsertedTuhao = clean; // ★ 记录最后插入的图号 - inserted++; - } - } - - // ★ 删除重复图号对应的新框(PaTextSelector已经画出来了,但不需要保留)——批量一次删 - DeleteFramesByHandles(newFramesToErase); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - // 直接在数据库层面重算(不经过内存回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadTuhaoByProject(_currentProjectId); - - // 保存 - try - { - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_tuhaoTable != null) - { - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - _tuhaoTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0 && inserted == 0) - { - Log("[PaTuhaoInsert] 删除了 " + deletedCount + " 条重复图号"); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒图号失败:\n" + ex.Message, - "扒图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒完图号后自动选中刚插入的图号行,联动刷新箱号表 - if (!string.IsNullOrWhiteSpace(lastInsertedTuhao)) - { - _currentTuhao = lastInsertedTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", lastInsertedTuhao); - // 手动联动刷新箱号表(SelectRowByValue 在 _isReloading 下不触发 SelectionChanged) - ReloadXianghaoByTuhao(_currentProjectId, lastInsertedTuhao); - } - } - } - - /// 扒箱号:把选中文本作为箱号批量插入到当前图号,同时保存框Handle。 - /// ★ 重复扒图:如果箱号已存在,删除旧框和数据库行(不新增)。 - private void PaXianghaoInsert(List results) - { - string lastInsertedXianghao = null; // ★ 记录最后插入的箱号,用于自动选中联动 - if (string.IsNullOrWhiteSpace(_currentTuhao)) - { - MessageBox.Show(this, "请先在图号表中选择一个图号,再扒箱号。", - "扒箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - try - { - _isReloading = true; - // 先 AcceptChanges,避免 SaveAllQuoteTablesIfDirty 把旧内存表回写 - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - - var newFramesToErase = new List(); - int deletedCount = 0; - int inserted = 0; - - foreach (var r in results) - { - if (string.IsNullOrWhiteSpace(r.Text)) continue; - string clean = r.Text.Trim(); - // ★ 按"同一个文本实体"判断重复(不同位置的相同内容文本不算重复) - string oldFrame = GetXianghaoFrameHandleByTextHandle(_currentProjectId, _currentTuhao, clean, r.TextHandle); - if (!string.IsNullOrEmpty(oldFrame)) - { - // ★ 重复(同一个文本再次选中):删除旧框+数据库行+新框 - DeleteXianghao(_currentProjectId, _currentTuhao, clean); - DeleteFrameByHandle(oldFrame); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - deletedCount++; - } - else - { - InsertXianghao(_currentProjectId, _currentTuhao, clean, r.FrameHandle, r.TextHandle); - lastInsertedXianghao = clean; // ★ 记录最后插入的箱号 - inserted++; - } - } - - DeleteFramesByHandles(newFramesToErase); - - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - - try - { - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (_xianghaoTable != null && !string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) - { - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null, true); - _xianghaoTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0 && inserted == 0) - { - Log("[PaXianghaoInsert] 删除了 " + deletedCount + " 条重复箱号"); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒箱号失败:\n" + ex.Message, - "扒箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒完箱号后自动选中刚插入的箱号行,联动刷新元件表 - if (!string.IsNullOrWhiteSpace(lastInsertedXianghao)) - { - _currentXianghao = lastInsertedXianghao; - SelectRowByValue(this.advancedDataGridView4, "箱号", lastInsertedXianghao); - // 手动联动刷新元件表(SelectRowByValue 在 _isReloading 下不触发 SelectionChanged) - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, lastInsertedXianghao); - } - } - } - - /// 扒元件:把选中文本作为【规格】批量插入到当前箱号(写到规格列),同时保存框Handle。 - /// ★ 关键:在单个事务里按 results 顺序依次插入,保证序号连续。 - /// ★ 重复扒图:如果规格已存在,删除旧框+数据库行(不新增)。 - private void PaYuanjianInsert(List results) - { - if (string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先在箱号表中选择一个箱号,再扒元件。", - "扒元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - try - { - _isReloading = true; - // ★ 关键:先 AcceptChanges 清掉内存表的改动标记,避免 SaveAllQuoteTablesIfDirty - // 用旧的内存数据覆盖数据库 - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - EnsureQuoteDbExists(_currentProjectId); - string dbPath = GetQuoteDbPath(_currentProjectId); - EnsureYuanjianTableExists(_currentProjectId, _currentTuhao, _currentXianghao); - string tblName = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (string.IsNullOrEmpty(tblName)) - { - MessageBox.Show("元件表创建失败(表索引未注册),图号=" + _currentTuhao + " 箱号=" + _currentXianghao); - return; - } - - // ★ 确保旧元件表也有"框Handle"/"文本Handle"列 - using (var connEns = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - connEns.Open(); - EnsureColumns(connEns, "\"" + tblName + "\"", new[] { "框Handle", "文本Handle" }); - } - - // 过滤掉空文本,保留原始顺序(同时保留框Handle+文本Handle) - var cleanResults = new List(); - foreach (var r in results) - { - if (!string.IsNullOrWhiteSpace(r.Text)) - { - cleanResults.Add(new PaTextResult - { - Text = r.Text.Trim(), - FrameHandle = r.FrameHandle ?? "", - TextHandle = r.TextHandle ?? "" - }); - } - } - if (cleanResults.Count == 0) return; - - // ★ 判断是否是逆向合并模式(所有result共用同一个框Handle且数量>1) - bool isMergeMode = cleanResults.Count > 1; - string mergeHandle = cleanResults[0].FrameHandle; - if (isMergeMode) - { - foreach (var r in cleanResults) - { - if (r.FrameHandle != mergeHandle) { isMergeMode = false; break; } - } - } - - // ★ 新增:重复检测辅助集合 - // newFramesToErase: PaTextSelector刚画的框,如果是重复项,这些框要删除 - var newFramesToErase = new List(); - // oldFrameHandlesToDelete: 数据库里匹配到的旧框,要删除 - var oldFrameHandlesToDelete = new List(); - // toInsert: 不重复、需要插入的项 - var toInsert = new List(); - // ★ 本地匹配失败的规格(收集后交给 DeepSeek AI 兜底识别) - var aiFailedSpecs = new List(); - int deletedCount = 0; - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - - if (isMergeMode) - { - // ★ 合并模式:所有文本按图纸阅读顺序拼成一个规格 - // (PaTextSelector 已按列分组、列内从上到下排好序,保持此顺序 - // 与库中自然书写顺序一致,如 HD13BX-1500/31 + 1500A) - // 文本Handle串与文本一一对应拼接(同一批文本Handle集合相同即重复)。 - var orderedTexts = new List(); - var orderedHandles = new List(); - foreach (var r in cleanResults) - { - orderedTexts.Add(r.Text); - orderedHandles.Add(r.TextHandle ?? ""); - } - string mergedSpec = string.Join("", orderedTexts.ToArray()); - // ★ Handle串排序后拼接(Handle集合相同即同一批文本,与顺序无关) - var sortedHandles = new List(orderedHandles); - sortedHandles.Sort(StringComparer.Ordinal); - string mergedTextHandle = string.Join("|", sortedHandles.ToArray()); - - // ★ 1. 查"同一批文本实体"的合并规格是否已存在 - // (文本Handle拼接串相同 = 同一批文本再次被选中,才是真重复) - var matchFrames = new List(); - using (var selCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tblName + "\" WHERE 规格=@spec AND 文本Handle=@th;", conn)) - { - selCmd.Parameters.AddWithValue("@spec", mergedSpec); - selCmd.Parameters.AddWithValue("@th", mergedTextHandle); - using (var reader = selCmd.ExecuteReader()) - { - while (reader.Read()) - { - object v = reader["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s) && !matchFrames.Contains(s)) - matchFrames.Add(s); - } - } - } - } - - // ★ 2. 再查:本批每个文本实体是否已作为"独立元件"入库(按文本Handle精确匹配) - var perTextFrames = new List(); - var perTextSpecs = new List(); - foreach (var r in cleanResults) - { - List fhs = GetYuanjianFrameHandlesByTextHandle( - _currentProjectId, _currentTuhao, _currentXianghao, r.Text, r.TextHandle); - foreach (string fh in fhs) - { - if (!perTextFrames.Contains(fh)) perTextFrames.Add(fh); - } - if (fhs.Count > 0 && !perTextSpecs.Contains(r.Text)) perTextSpecs.Add(r.Text); - } - - // ★ 只要匹配到(1.同一批文本的合并规格 或 2.同一文本实体的独立元件) → 执行删除 - bool hitMergeMatch = matchFrames.Count > 0; - bool hitPerTextMatch = perTextSpecs.Count > 0; - - if (hitMergeMatch || hitPerTextMatch) - { - // ★ 删除:同一批文本的合并规格匹配的行(文本Handle+规格双条件) - if (hitMergeMatch) - { - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 规格=@spec AND 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@spec", mergedSpec); - delCmd.Parameters.AddWithValue("@th", mergedTextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - foreach (string fh in matchFrames) - if (!oldFrameHandlesToDelete.Contains(fh)) oldFrameHandlesToDelete.Add(fh); - } - // ★ 删除:同一文本实体的独立元件行(按文本Handle删除) - if (hitPerTextMatch) - { - foreach (var r in cleanResults) - { - if (string.IsNullOrWhiteSpace(r.TextHandle)) continue; - using (var selCmd2 = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - selCmd2.Parameters.AddWithValue("@th", r.TextHandle); - object cnt = selCmd2.ExecuteScalar(); - int n = (cnt != null && cnt != DBNull.Value) ? Convert.ToInt32(cnt) : 0; - if (n > 0) - { - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@th", r.TextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - } - } - } - foreach (string fh in perTextFrames) - if (!oldFrameHandlesToDelete.Contains(fh)) oldFrameHandlesToDelete.Add(fh); - } - // ★ 删除 PaTextSelector 刚画的新合并框 - if (!string.IsNullOrWhiteSpace(mergeHandle)) - if (!newFramesToErase.Contains(mergeHandle)) - newFramesToErase.Add(mergeHandle); - Log("[PaYuanjianInsert] 合并模式:删除重复项 mergedMatch=" + hitMergeMatch - + " perTextMatch=" + hitPerTextMatch + ", 删除行数=" + deletedCount - + ", 删除旧框数=" + oldFrameHandlesToDelete.Count); - } - else - { - // ★ 没有匹配:新增一行(合并规格) - toInsert.Add(new PaTextResult - { - Text = mergedSpec, - FrameHandle = mergeHandle, - TextHandle = mergedTextHandle - }); - } - } - else - { - // ★ 正向模式:每个文本一条记录,按"同一个文本实体"判断是否重复 - foreach (var r in cleanResults) - { - // ★ 按文本Handle精确匹配:同一文本实体才删除, - // 不同位置的相同内容文本(Handle不同)正常插入 - List matchFrames = GetYuanjianFrameHandlesByTextHandle( - _currentProjectId, _currentTuhao, _currentXianghao, r.Text, r.TextHandle); - if (matchFrames.Count > 0) - { - // 重复:按文本Handle删除数据库行 + 旧框 + 新画的框 - using (var delCmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + tblName + "\" WHERE 文本Handle=@th;", conn)) - { - delCmd.Parameters.AddWithValue("@th", r.TextHandle); - int aff = delCmd.ExecuteNonQuery(); - deletedCount += aff; - } - foreach (string fh in matchFrames) oldFrameHandlesToDelete.Add(fh); - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) newFramesToErase.Add(r.FrameHandle); - } - else - { - toInsert.Add(r); - } - } - } - - // ★ 写入需要新增的项 - if (toInsert.Count > 0) - { - // 先取当前最大序号(用MAX函数) - int startSeq = 0; - using (var cntCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT COALESCE(MAX(CAST(序号 AS INTEGER)), 0) FROM \"" + tblName + "\";", conn)) - { - object o = cntCmd.ExecuteScalar(); - if (o != null && o != DBNull.Value) startSeq = Convert.ToInt32(o); - } - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 规格, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型, 框Handle, 文本Handle) " + - "VALUES (@seq, @name, @spec, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件', @fh, @th);"; - for (int i = 0; i < toInsert.Count; i++) - { - // ★ 自动匹配元件名称(用户库CSV模糊匹配,匹配不上为空) - string matchedName = MatchSpecName(toInsert[i].Text) ?? ""; - if (matchedName.Length == 0) aiFailedSpecs.Add(toInsert[i].Text); - using (var insCmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - insCmd.Parameters.AddWithValue("@seq", (startSeq + i + 1).ToString()); - insCmd.Parameters.AddWithValue("@name", matchedName); - insCmd.Parameters.AddWithValue("@spec", toInsert[i].Text); - insCmd.Parameters.AddWithValue("@unit", "只"); - insCmd.Parameters.AddWithValue("@shuliang", "1"); - insCmd.Parameters.AddWithValue("@caigou", "1"); - insCmd.Parameters.AddWithValue("@baochu", "1"); - insCmd.Parameters.AddWithValue("@fh", toInsert[i].FrameHandle ?? ""); - insCmd.Parameters.AddWithValue("@th", toInsert[i].TextHandle ?? ""); - insCmd.ExecuteNonQuery(); - } - } - } - } - - // ★ 删除旧框和重复新框——合并成一次批量删除(单事务+单次刷新) - var framesToErase = new List(oldFrameHandlesToDelete); - framesToErase.AddRange(newFramesToErase); - DeleteFramesByHandles(framesToErase); - - // ★ 重新编号(删除后序号可能不连续) - RenumberTable(_currentProjectId, "\"" + tblName + "\""); - - _yuanjianCache.Clear(); - _xianghaoCache.Clear(); - - // 直接在数据库层面重算(不经过内存回写) - try { RecalcAllFromDatabase(_currentProjectId); } catch { } - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - - // ★ 收集新插入元件的框Handle(finally 里再统一选中, - // 避免被后续 SaveTable/AcceptChanges/表格刷新清掉选中) - foreach (var r in toInsert) - if (!string.IsNullOrWhiteSpace(r.FrameHandle)) - _pendingSelectYuanjianHandles.Add(r.FrameHandle); - - // 保存 - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (_yuanjianTable != null) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - } - } - catch { } - SaveCurrentDwg(); - - if (deletedCount > 0) - { - Log("[PaYuanjianInsert] 删除了 " + deletedCount + " 条重复元件(匹配框:" + oldFrameHandlesToDelete.Count + ")"); - } - - // ★ DeepSeek AI 兜底:本地未匹配到名称的规格,异步提交 AI 识别并回填 - if (aiFailedSpecs.Count > 0) - { - Log("[PaYuanjianInsert] " + aiFailedSpecs.Count + " 条本地未匹配,提交AI识别"); - AiFillMissingNames(aiFailedSpecs, tblName); - } - } - catch (Exception ex) - { - MessageBox.Show(this, "扒元件失败:\n" + ex.Message, - "扒元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _isReloading = false; - // ★ 扒到的元件行保持选中(供 F1 合并):延迟两拍执行, - // 等保存/刷新/绑定事件链全部走完,否则选中会被冲掉 - if (_pendingSelectYuanjianHandles.Count > 0) - { - var snapshot = new List(_pendingSelectYuanjianHandles); - _pendingSelectYuanjianHandles.Clear(); - BeginInvoke((Action)(() => - { - BeginInvoke((Action)(() => - { - SelectYuanjianRowsByFrameHandles(snapshot); - Log("[PaYuanjianInsert] 已选中 " + snapshot.Count + " 条新元件行(供F1合并)"); - })); - })); - } - } - } - - /// 查询图号是否已存在(避免重复插入)。 - private bool TuhaoExists(string projectId, string tuhao) - { - return !string.IsNullOrEmpty(GetTuhaoFrameHandle(projectId, tuhao)); - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - /// 命中返回旧框Handle(真重复);未命中返回 null(不同位置的相同内容文本,正常插入)。 - /// - private string GetTuhaoFrameHandleByTextHandle(string projectId, string tuhao, string textHandle) - { - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetTuhaoFrameHandle(projectId, tuhao); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧图号表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, TuhaoTableName, new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按内容兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM " + TuhaoTableName + - " WHERE 文本Handle=@th OR (图号=@t AND (文本Handle IS NULL OR 文本Handle='')) LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@t", tuhao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定图号的框Handle(不存在返回null)。 - private string GetTuhaoFrameHandle(string projectId, string tuhao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM " + TuhaoTableName + " WHERE 图号=@t LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@t", tuhao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询箱号是否已存在(避免重复插入)。 - private bool XianghaoExists(string projectId, string tuhao, string xianghao) - { - return !string.IsNullOrEmpty(GetXianghaoFrameHandle(projectId, tuhao, xianghao)); - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle是否已入库。 - /// 命中返回旧框Handle(真重复);未命中返回 null(不同位置的相同内容文本,正常插入)。 - /// - private string GetXianghaoFrameHandleByTextHandle(string projectId, string tuhao, string xianghao, string textHandle) - { - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetXianghaoFrameHandle(projectId, tuhao, xianghao); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - string tableName = GetQuoteTableName(projectId, tuhao); - if (string.IsNullOrEmpty(tableName)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧箱号表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, "\"" + tableName + "\"", new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按内容兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\"" + - " WHERE 文本Handle=@th OR (箱号=@x AND (文本Handle IS NULL OR 文本Handle='')) LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@x", xianghao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定箱号的框Handle(不存在返回null)。 - private string GetXianghaoFrameHandle(string projectId, string tuhao, string xianghao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return null; - string tableName = GetQuoteTableName(projectId, tuhao); - if (string.IsNullOrEmpty(tableName)) return null; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\" WHERE 箱号=@x LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@x", xianghao); - using (var rdr = cmd.ExecuteReader()) - { - if (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) return s; - } - } - } - } - } - } - catch { } - return null; - } - - /// 查询指定元件规格的所有框Handle(可能有多个重复行,返回List)。 - private List GetYuanjianFrameHandles(string projectId, string tuhao, string xianghao, string spec) - { - var list = new List(); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return list; - string tableName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tableName)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\" WHERE 规格=@s;", conn)) - { - cmd.Parameters.AddWithValue("@s", spec); - using (var rdr = cmd.ExecuteReader()) - { - while (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) list.Add(s); - } - } - } - } - } - } - catch { } - return list; - } - - /// - /// ★ 按"同一个文本实体"判断重复:查该文本实体Handle在元件表中是否已入库。 - /// 命中返回旧框Handle列表(真重复);未命中返回空列表(不同位置的相同内容文本,正常插入)。 - /// - private List GetYuanjianFrameHandlesByTextHandle(string projectId, string tuhao, string xianghao, string spec, string textHandle) - { - var list = new List(); - // 旧数据没有文本Handle → 按旧逻辑(文本内容)判断,保持旧行为 - if (string.IsNullOrWhiteSpace(textHandle)) return GetYuanjianFrameHandles(projectId, tuhao, xianghao, spec); - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return list; - string tableName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tableName)) return list; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先确保旧元件表有"文本Handle"列,避免查询报错 - EnsureColumns(conn, "\"" + tableName + "\"", new[] { "文本Handle" }); - // ★ 双条件:同一文本实体(Handle精确匹配) 或 旧数据行(无文本Handle,按规格兜底) - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + tableName + "\"" + - " WHERE 文本Handle=@th OR (规格=@s AND (文本Handle IS NULL OR 文本Handle=''));", conn)) - { - cmd.Parameters.AddWithValue("@th", textHandle); - cmd.Parameters.AddWithValue("@s", spec); - using (var rdr = cmd.ExecuteReader()) - { - while (rdr.Read()) - { - object v = rdr["框Handle"]; - if (v != null && v != DBNull.Value) - { - string s = v.ToString(); - if (!string.IsNullOrWhiteSpace(s)) list.Add(s); - } - } - } - } - } - } - catch { } - return list; - } - - // ============================================================ - // 扒元件自动匹配元件名称(用户库CSV模糊匹配) - // · 扫描插件上级目录/自身目录下最新的 用户库_*.csv(GBK编码) - // · 匹配策略:L1归一化相等 → L2包含(60%长度) → L3编辑距离≥0.70 - // · 硬保护:模糊匹配时数字序列必须完全一致(63A 不会配到 100A) - // ============================================================ - - /// 用户库条目:规格 → 元件名称 - private class SpecNameEntry - { - public string Name; - public string NormSpec; // 归一化后的规格 - public string[] Numbers; // 规格中的数字序列(模糊匹配保护用) - public string Skeleton; // 字母骨架(去数字/分隔符/尾部单位,如 DZ47-4P/C80A → DZPC) - } - - private static List _specNameLib = null; - private static string _specLibCsvPath = null; - private static DateTime _specLibCsvTime = DateTime.MinValue; - - /// - /// 确保用户库CSV已加载(取最新修改时间的 用户库_*.csv, - /// 文件时间戳变化时自动重新加载;文件被 Excel 占用时用共享读)。 - /// - private static void EnsureUserLibCsvLoaded() - { - try - { - // 候选目录:上级目录(成套报价软件根目录) + 插件目录自身 - var dirs = new List(); - try - { - var parent = Path.GetDirectoryName(_baseDir); - if (!string.IsNullOrEmpty(parent) && Directory.Exists(parent)) dirs.Add(parent); - } - catch { } - dirs.Add(_baseDir); - - string best = null; - DateTime bestTime = DateTime.MinValue; - foreach (string d in dirs) - { - try - { - string[] files = Directory.GetFiles(d, "用户库*.csv"); - foreach (string f in files) - { - DateTime t = File.GetLastWriteTime(f); - if (best == null || t > bestTime) { best = f; bestTime = t; } - } - } - catch { } - } - if (best == null) return; // 没找到CSV,保持空库 - - // 时间戳没变且已加载 → 不重复加载 - if (_specNameLib != null && - string.Equals(best, _specLibCsvPath, StringComparison.OrdinalIgnoreCase) && - bestTime == _specLibCsvTime) return; - - var lib = new List(); - var prefixRules = new List(); - // ★ 共享读:文件被 Excel 打开也能读 - using (var fs = new FileStream(best, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (var sr = new StreamReader(fs, DetectCsvEncoding(fs))) - { - string line; - bool first = true; - while ((line = sr.ReadLine()) != null) - { - if (string.IsNullOrWhiteSpace(line)) continue; - string[] cols = SplitCsvLine(line); - if (cols.Length < 2) continue; - string name = cols[0].Trim(); - string spec = cols[1].Trim(); - if (first) - { - first = false; - // 跳过表头 - if (name == "元件名称") continue; - } - if (name.Length == 0 || spec.Length == 0) continue; - - // ★ "元件类型"列 = "前缀" 的行是型号前缀规则(不是库条目) - string elemType = cols.Length >= 10 ? cols[9].Trim() : ""; - if (elemType == "前缀") - { - string pfx = spec.ToUpperInvariant(); - if (pfx.Length >= 2) prefixRules.Add(new[] { pfx, name }); - continue; - } - - string normSpec = NormalizeSpec(spec); - lib.Add(new SpecNameEntry - { - Name = name, - NormSpec = normSpec, - // ★ 必须用原始 spec 提取数字(保留空格/符号作数字边界); - // 用 normSpec 会导致 3300 800 粘连成 3300800,数字序列错位 - Numbers = ExtractNumbers(spec), - Skeleton = ExtractSkeleton(spec) - }); - } - } - _specNameLib = lib; - _prefixRules = prefixRules; - _specLibCsvPath = best; - _specLibCsvTime = bestTime; - WriteDebugLog("[用户库匹配] 加载CSV: " + best + " 条数=" + lib.Count + - " 前缀规则=" + prefixRules.Count); - } - catch (Exception ex) { WriteDebugLog("[用户库匹配] 加载CSV异常: " + ex.Message); } - } - - /// 检测CSV编码:有UTF-8 BOM用UTF8,否则按GBK(主程序导出编码)。 - private static System.Text.Encoding DetectCsvEncoding(FileStream fs) - { - try - { - long pos = fs.Position; - int b1 = fs.ReadByte(); - int b2 = fs.ReadByte(); - int b3 = fs.ReadByte(); - fs.Position = pos; - if (b1 == 0xEF && b2 == 0xBB && b3 == 0xBF) return System.Text.Encoding.UTF8; - } - catch { } - return System.Text.Encoding.GetEncoding("GBK"); - } - - /// 按CSV规则拆分一行(支持双引号包裹和转义"")。 - private static string[] SplitCsvLine(string line) - { - var parts = new List(); - var sb = new System.Text.StringBuilder(); - bool inQuotes = false; - for (int i = 0; i < line.Length; i++) - { - char c = line[i]; - if (c == '"') - { - if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { sb.Append('"'); i++; } - else inQuotes = !inQuotes; - } - else if (c == ',' && !inQuotes) - { - parts.Add(sb.ToString()); - sb.Length = 0; - } - else sb.Append(c); - } - parts.Add(sb.ToString()); - return parts.ToArray(); - } - - /// 规格归一化:全角→半角、统一大写、去空白和分隔符号(保留字母/数字/中文)。 - private static string NormalizeSpec(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(s.Length); - foreach (char c0 in s) - { - char c = c0; - // 全角→半角 - if (c >= 0xFF01 && c <= 0xFF5E) c = (char)(c - 0xFEE0); - else if (c == 0x3000) c = ' '; - if (c == ' ' || c == '\t') continue; - if (IsSpecSeparator(c)) continue; - sb.Append(char.ToUpperInvariant(c)); - } - return sb.ToString(); - } - - /// 规格中的分隔符号(归一化时删除;数字提取时作为数字段边界)。 - private static bool IsSpecSeparator(char c) - { - return c == '-' || c == '/' || c == '*' || c == '×' || c == '·' || c == '.' || - c == '、' || c == ',' || c == ',' || c == '(' || c == ')' || c == '(' || - c == ')' || c == '#' || c == '+' || c == '_' || c == ':' || c == ':' || - c == '~' || c == '~'; - } - - /// - /// 轻量归一化(保留分隔符和空格):全角→半角、统一大写。 - /// ★ 用于数字序列提取:分隔符和空格是数字段的天然边界, - /// 先删分隔符会导致 HYM1-63/3300 的 63 和 3300 粘连成 633300; - /// 删空格会导致 3300 800 粘连成 3300800(与 3300,800 数字序列不一致)。 - /// - private static string NormalizeKeepSeparators(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(s.Length); - foreach (char c0 in s) - { - char c = c0; - if (c >= 0xFF01 && c <= 0xFF5E) c = (char)(c - 0xFEE0); - else if (c == 0x3000) c = ' '; - if (c == '\t') c = ' '; // 制表符当空格 - sb.Append(char.ToUpperInvariant(c)); - } - return sb.ToString(); - } - - /// - /// 提取规格中的所有数字序列(在保留分隔符的版本上提取, - /// 如 HYM1-63/3300 63A → ["1","63","3300","63"])。 - /// - private static string[] ExtractNumbers(string spec) - { - var list = new List(); - if (string.IsNullOrEmpty(spec)) return list.ToArray(); - string light = NormalizeKeepSeparators(spec); - var sb = new System.Text.StringBuilder(); - foreach (char c in light) - { - if (c >= '0' && c <= '9') sb.Append(c); - else if (sb.Length > 0) { list.Add(sb.ToString()); sb.Length = 0; } - } - if (sb.Length > 0) list.Add(sb.ToString()); - return list.ToArray(); - } - - /// 两个数字序列是否完全一致。 - private static bool NumbersEqual(string[] a, string[] b) - { - if (a == null || b == null) return false; - if (a.Length != b.Length) return false; - for (int i = 0; i < a.Length; i++) - if (a[i] != b[i]) return false; - return true; - } - - /// - /// 数字序列兼容(子序列检查):短方的数字按顺序都能在长方中找到即通过。 - /// ★ 用于 L2 包含关系:一方文本是另一方的一部分,数字自然也可能少 - /// (如图纸只写 HD13BX-1500/31,库里是 HD13BX-1500/31 1500A)。 - /// ★ 依然防误配:63A vs 100A 时 63 不在对方序列对应位置,拒绝。 - /// - private static bool NumbersCompatible(string[] a, string[] b) - { - if (a == null || b == null) return false; - string[] shorter = a.Length <= b.Length ? a : b; - string[] longer = a.Length <= b.Length ? b : a; - if (longer.Length == 0) return shorter.Length == 0; - int i = 0; - foreach (string n in longer) - { - if (i < shorter.Length && n == shorter[i]) i++; - } - return i == shorter.Length; - } - - /// - /// 数字序列严格相等 + 两种容错(L3 模糊匹配用): - /// 1.粘连拆分:图纸连写导致数字粘连(如 0.66+1500 提取出 661500),拆成两段后对上即通过; - /// 2.壳架容错:图纸把额定电流写进型号段(如 HYW1-2500/3P 2500A,2500出现两次), - /// 库里型号段是壳架等级(HYW1-3200),删掉图纸型号段那个数字后能对上即通过。 - /// ★ 仅当该数字在图纸中出现≥2次才允许删,220V/380V 这类无重复差异依然拒绝。 - /// - private static bool NumbersEqualEx(string[] a, string[] b) - { - if (a == null || b == null) return false; - if (NumbersEqual(a, b)) return true; - // 容错1:粘连拆分 - if (TrySplitAndCompatible(a, b)) return true; - if (TrySplitAndCompatible(b, a)) return true; - // 容错2:壳架(删图纸中重复出现的电流数字之一) - if (TryDropFrameCurrent(a, b)) return true; - if (TryDropFrameCurrent(b, a)) return true; - return false; - } - - /// - /// 壳架容错:seq 中存在出现≥2次的数字 X,删掉其中一次后作为子序列能对上 other。 - /// 典型:图纸 HYW1-2500/3P 2500A(2500×2) vs 库 HYW1-3200/3P 2500A(3200×1,2500×1)。 - /// - private static bool TryDropFrameCurrent(string[] seq, string[] other) - { - for (int i = 0; i < seq.Length; i++) - { - string s = seq[i]; - if (s == null || s.Length < 2) continue; - // 该数字必须在 seq 中出现≥2次(型号段+电流段重复) - int cnt = 0; - foreach (string n in seq) if (n == s) cnt++; - if (cnt < 2) continue; - // 删掉第 i 个,其余保持顺序 - var list = new List(seq.Length - 1); - for (int k = 0; k < seq.Length; k++) - if (k != i) list.Add(seq[k]); - if (NumbersCompatible(list.ToArray(), other)) return true; - } - return false; - } - - /// 把 seq 中某个数字串拆成两段,拆分后作为子序列能对上 other 即返回 true。 - private static bool TrySplitAndCompatible(string[] seq, string[] other) - { - for (int i = 0; i < seq.Length; i++) - { - string s = seq[i]; - if (s == null || s.Length < 2) continue; - for (int cut = 1; cut < s.Length; cut++) - { - var list = new List(seq.Length + 1); - for (int k = 0; k < seq.Length; k++) - { - if (k == i) - { - list.Add(s.Substring(0, cut)); - list.Add(s.Substring(cut)); - } - else list.Add(seq[k]); - } - if (NumbersCompatible(list.ToArray(), other)) return true; - } - } - return false; - } - - /// - /// 提取字母骨架:去数字、去分隔符、去尾部单位词(A/V/kA 等)。 - /// ★ 用于图纸省略壳架等级的场景:DZ47-4P/C80A 与 DZ47-100 4P C80 - /// 骨架同为 DZPC,配合数字子序列保护可安全匹配。 - /// - private static string ExtractSkeleton(string spec) - { - if (string.IsNullOrEmpty(spec)) return ""; - string light = NormalizeKeepSeparators(spec); - var sb = new System.Text.StringBuilder(); - for (int i = 0; i < light.Length; i++) - { - char c = light[i]; - if (c >= 'A' && c <= 'Z') - { - // 单位词必须紧跟在数字后面才有效(如 80A、450V); - // 6L2-V 的 V 前面是分隔符,属于型号的一部分,不能截断 - bool prevIsDigit = i > 0 && light[i - 1] >= '0' && light[i - 1] <= '9'; - if (prevIsDigit && IsTailUnit(light.Substring(i))) break; - sb.Append(c); - } - // 数字、分隔符、中文等其他字符全部跳过 - } - return sb.ToString(); - } - - /// 判断剩余部分是否为纯尾部单位词(如 "A"、"80A" 里的 A、"0~450V" 里的 V)。 - private static bool IsTailUnit(string rest) - { - if (string.IsNullOrEmpty(rest)) return false; - string r = rest.Trim(); - if (r.Length > 2) return false; // 单位最多2字符(HZ/KA/KW/VA) - return r == "A" || r == "V" || r == "W" || r == "VA" || r == "HZ" || r == "KA" || r == "KW"; - } - - /// Levenshtein 编辑距离(滚动数组实现)。 - private static int LevenshteinDistance(string a, string b) - { - if (string.IsNullOrEmpty(a)) return string.IsNullOrEmpty(b) ? 0 : b.Length; - if (string.IsNullOrEmpty(b)) return a.Length; - int n = a.Length, m = b.Length; - int[] prev = new int[m + 1]; - int[] cur = new int[m + 1]; - for (int j = 0; j <= m; j++) prev[j] = j; - for (int i = 1; i <= n; i++) - { - cur[0] = i; - for (int j = 1; j <= m; j++) - { - int cost = (a[i - 1] == b[j - 1]) ? 0 : 1; - int v1 = prev[j] + 1; - int v2 = cur[j - 1] + 1; - int v3 = prev[j - 1] + cost; - cur[j] = Math.Min(v1, Math.Min(v2, v3)); - } - int[] tmp = prev; prev = cur; cur = tmp; - } - return prev[m]; - } - - /// - /// 规格匹配元件名称(模糊): - /// L1 归一化后完全相等 → 直接命中; - /// L2 包含关系(短方长度≥长方60%,数字序列一致); - /// L3 编辑距离相似度≥0.70(数字序列必须完全一致,唯一最高分才命中)。 - /// 都不中返回 null(不硬猜)。 - /// - /// - /// 粘连清洗:扒图可能把相邻文本粘连(如 "0mAVigiC65N-...")。 - /// 若文本开头是"数字+单位(mA/A/V/W)"且后面紧跟大写字母开头的型号, - /// 从型号处截取;否则原样返回。 - /// - private static string CleanLeadingNoise(string spec) - { - if (string.IsNullOrEmpty(spec)) return spec; - string s = spec.Trim(); - - // ★ 先剥"数量×"前缀:如 "3xLMZ1-0.5" → "LMZ1-0.5"、"2×AD16" → "AD16" - // (图纸常在型号前写元件数量,3x=3只) - if (s.Length > 2) - { - char c0 = s[0]; - if (c0 >= '0' && c0 <= '9') - { - int i = 0; - while (i < s.Length && s[i] >= '0' && s[i] <= '9') i++; - if (i < s.Length && (s[i] == 'x' || s[i] == 'X' || s[i] == '×' || s[i] == '*')) - { - int after = i + 1; - if (after < s.Length && s[after] >= 'A' && s[after] <= 'Z') - return s.Substring(after); - } - } - } - - // 找开头最长的"数字(可含小数点)+单位"模式 - int j = 0; - while (j < s.Length && ((s[j] >= '0' && s[j] <= '9') || s[j] == '.')) j++; - if (j == 0 || j >= s.Length) return spec; // 开头不是数字 - // 单位段(1~3个字母) - int u = j; - while (u < s.Length && u - j <= 3 && s[u] >= 'A' && s[u] <= 'z') u++; - if (u == j || u >= s.Length) return spec; // 没有单位或后面没内容 - string unit = s.Substring(j, u - j).ToUpperInvariant(); - if (unit != "MA" && unit != "A" && unit != "V" && unit != "W" && unit != "KW" && unit != "HZ") return spec; - // 单位后必须紧跟大写字母(型号开头) - char next = s[u]; - if (next < 'A' || next > 'Z') return spec; - return s.Substring(u); // 从型号处截取 - } - - // ★ 匹配结果缓存:同一规格文本(一批框选里重复文本很常见)只完整跑一次 L0-L5。 - // L3 会按库逐条算编辑距离(库大时是 CPU 热点),缓存能直接砍掉重复计算。 - private static readonly System.Collections.Generic.Dictionary _specMatchCache = - new System.Collections.Generic.Dictionary(System.StringComparer.Ordinal); - private static readonly object _specMatchCacheLock = new object(); - - /// 规格匹配元件名称(带结果缓存):相同规格文本第二次起直接返回缓存结果。 - private static string MatchSpecName(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string cached; - lock (_specMatchCacheLock) - { - if (_specMatchCache.TryGetValue(spec, out cached)) return cached; - } - string result = MatchSpecNameCore(spec); - lock (_specMatchCacheLock) - { - // 上限保护:超过2万条清空重来(规格文本总量有限,防内存无限增长) - if (_specMatchCache.Count > 20000) _specMatchCache.Clear(); - _specMatchCache[spec] = result; - } - return result; - } - - private static string MatchSpecNameCore(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - - // ★ 粘连清洗:扒图可能把相邻文本粘连(如 "0mAVigiC65N-...")。 - // 若文本前部含"数字+单位(mA/A/V)"后跟已知型号,从型号处截取 - spec = CleanLeadingNoise(spec); - - EnsureUserLibCsvLoaded(); - if (_specNameLib == null || _specNameLib.Count == 0) return null; - - string norm = NormalizeSpec(spec); - if (norm.Length == 0) return null; - string[] nums = ExtractNumbers(spec); - - string result = null; - string via = "none"; - - // L0: 型号前缀规则(本地权威,最优先,覆盖国标型号命名体系) - string ruleName = MatchByPrefixRule(spec); - if (ruleName != null) - { - WriteDebugLog("[用户库匹配] 「" + spec + "」 → " + ruleName + " via L0规则"); - return ruleName; - } - - // L0.5: JB/T 2930 国标类组代号(官方定义:前2位字母=品类代号) - string gbName = MatchByGbCode(spec); - if (gbName != null) - { - WriteDebugLog("[用户库匹配] 「" + spec + "」 → " + gbName + " via L0.5国标"); - return gbName; - } - - // L1: 归一化后完全相等 - foreach (var e in _specNameLib) - { - if (e.NormSpec == norm) { result = e.Name; via = "L1相等"; break; } - } - - // L2: 包含关系(如图纸只写型号主体,库里有完整版) - if (result == null) - { - foreach (var e in _specNameLib) - { - if (e.NormSpec.Length == 0) continue; - bool contains = e.NormSpec.Contains(norm) || norm.Contains(e.NormSpec); - if (!contains) continue; - int shortLen = Math.Min(e.NormSpec.Length, norm.Length); - int longLen = Math.Max(e.NormSpec.Length, norm.Length); - if (longLen == 0 || (double)shortLen / longLen < 0.6) continue; - if (!NumbersCompatible(nums, e.Numbers)) continue; // ★ 数字子序列兼容(允许少,不允许错) - result = e.Name; via = "L2包含"; break; - } - } - - // L3: 编辑距离模糊匹配(字母/符号容错,数字绝对不放过) - if (result == null) - { - string bestName = null; - double bestScore = 0.0; - int bestCount = 0; - foreach (var e in _specNameLib) - { - if (e.NormSpec.Length == 0) continue; - if (!NumbersEqualEx(nums, e.Numbers)) continue; // ★ 数字一致(含粘连拆分容错) - // ★ 长度差剪枝:编辑距离 ≥ 长度差,长度差已超过 0.30×maxLen 时 - // score 必然 < 0.70,直接跳过(编辑距离是 O(m×n),库里条目多时全算是卡顿热点) - int maxLen = Math.Max(norm.Length, e.NormSpec.Length); - if (Math.Abs(norm.Length - e.NormSpec.Length) * 10 > maxLen * 3) continue; - int dist = LevenshteinDistance(norm, e.NormSpec); - double score = 1.0 - (double)dist / maxLen; - if (score >= 0.70) - { - if (score > bestScore + 0.0001) { bestScore = score; bestName = e.Name; bestCount = 1; } - else if (Math.Abs(score - bestScore) <= 0.0001 && bestName != e.Name) bestCount++; - } - } - if (bestCount == 1 && bestName != null) { result = bestName; via = "L3模糊"; } - } - - // L4: 字母骨架匹配(图纸省略壳架等级的场景) - // DZ47-4P/C80A 与 DZ47-100 4P C80:骨架同为 DZPC, - // 且图纸数字 [47,4,80] 是库数字 [47,100,4,80] 的子序列 → 命中 - if (result == null) - { - string skel = ExtractSkeleton(spec); - if (skel.Length >= 3) - { - string bestName = null; - int bestLen = int.MaxValue; - foreach (var e in _specNameLib) - { - if (e.Skeleton == null || e.Skeleton.Length < 3) continue; - if (e.Skeleton != skel) continue; - if (!NumbersCompatible(nums, e.Numbers)) continue; // ★ 数字子序列保护 - // 多条同骨架时取数字数量最接近的 - int diff = Math.Abs(nums.Length - e.Numbers.Length); - if (diff < bestLen) { bestLen = diff; bestName = e.Name; } - } - if (bestName != null) { result = bestName; via = "L4骨架"; } - } - } - - // L5: 大电流启发式(最后兜底) - // 框架级特征:数字≥1600 + 3P/4P + 型号含W(万能式标记) → 万能式/智能断路器 - if (result == null) - { - string sUp = spec.Trim().ToUpperInvariant(); - bool hasBig = false; - foreach (string n in nums) - { - long v; - if (long.TryParse(n, out v) && v >= 1600 && v <= 6300) { hasBig = true; break; } - } - bool hasPole = sUp.Contains("/3P") || sUp.Contains("/4P") || sUp.Contains(" 3P") || sUp.Contains(" 4P") || - sUp.EndsWith("3P") || sUp.EndsWith("4P"); - bool hasW = sUp.IndexOf('W') >= 0; - if (hasBig && hasPole && hasW) - { - // 含 I/E(智能型标记,如 HUWI/CW1I) → 智能断路器 - bool hasSmart = sUp.IndexOf('I') >= 0 || sUp.IndexOf('E') >= 0; - result = hasSmart ? "智能断路器" : "万能式断路器"; - via = "L5大电流启发"; - } - } - - // ★ 匹配日志:输入/归一化/数字序列/结果,失败可从日志直接定位原因 - WriteDebugLog("[用户库匹配] 「" + spec + "」 norm=" + norm + - " nums=[" + string.Join(",", nums) + "] → " + - (result == null ? "(未匹配)" : result + " via " + via)); - return result; - } - - // ============================================================ - // DeepSeek AI 智能匹配(本地匹配失败后的兜底) - // · 设置窗口填 API Key,存插件目录 deepseek.json - // · 扒元件后本地未命中的规格批量提交 AI 识别元器件名称 - // · 结果缓存到 deepseek_cache.json(同规格只问一次) - // · AI 结果回填元件表"元件名称"列 - // ============================================================ - - private string DeepSeekConfigPath { get { return GetDbFullPath("deepseek.json"); } } - private string DeepSeekCachePath { get { return GetDbFullPath("deepseek_cache.json"); } } - - /// DeepSeek 设置(加载/保存 JSON) - private class DeepSeekConfig - { - public string ApiKey = ""; - public string BaseUrl = "https://api.deepseek.com"; - public string Model = "deepseek-v4-flash"; // ★ 支持联网搜索的模型 - public bool Enabled = false; - public bool WebSearch = true; // ★ 联网搜索(罕见型号也能查) - } - - private DeepSeekConfig _dsConfig; - private System.Collections.Hashtable _dsCache; - - private DeepSeekConfig LoadDsConfig() - { - if (_dsConfig != null) return _dsConfig; - var cfg = new DeepSeekConfig(); - try - { - if (File.Exists(DeepSeekConfigPath)) - { - string json = File.ReadAllText(DeepSeekConfigPath, System.Text.Encoding.UTF8); - var map = SimpleJsonParse(json); - if (map.ContainsKey("ApiKey")) cfg.ApiKey = (string)map["ApiKey"] ?? ""; - if (map.ContainsKey("BaseUrl")) cfg.BaseUrl = (string)map["BaseUrl"] ?? "https://api.deepseek.com"; - if (map.ContainsKey("Model")) cfg.Model = (string)map["Model"] ?? "deepseek-v4-flash"; - // ★ 布尔值无引号,解析出的 val 可能带换行/空格前缀,比较前必须 Trim - if (map.ContainsKey("Enabled")) cfg.Enabled = ((string)map["Enabled"] ?? "").Trim() == "true"; - if (map.ContainsKey("WebSearch")) cfg.WebSearch = ((string)map["WebSearch"] ?? "").Trim() != "false"; - // ★ 旧模型(deepseek-chat 不支持联网)自动迁移到 v4 - if (cfg.Model == "deepseek-chat" || cfg.Model == "deepseek-reasoner") cfg.Model = "deepseek-v4-flash"; - } - } - catch { } - _dsConfig = cfg; - return cfg; - } - - private void SaveDsConfig(DeepSeekConfig cfg) - { - try - { - string json = "{\n" + - " \"ApiKey\": \"" + (cfg.ApiKey ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"BaseUrl\": \"" + (cfg.BaseUrl ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"Model\": \"" + (cfg.Model ?? "").Replace("\"", "\\\"") + "\",\n" + - " \"Enabled\": " + (cfg.Enabled ? "true" : "false") + ",\n" + - " \"WebSearch\": " + (cfg.WebSearch ? "true" : "false") + "\n" + - "}"; - File.WriteAllText(DeepSeekConfigPath, json, System.Text.Encoding.UTF8); - _dsConfig = cfg; - } - catch (Exception ex) { Log("[DeepSeek配置] 保存失败: " + ex.Message); } - } - - /// AI 匹配缓存:规格 → 元件名称(未命中/失败也缓存,避免反复请求) - private System.Collections.Hashtable LoadDsCache() - { - if (_dsCache != null) return _dsCache; - var ht = new System.Collections.Hashtable(); - try - { - if (File.Exists(DeepSeekCachePath)) - { - string json = File.ReadAllText(DeepSeekCachePath, System.Text.Encoding.UTF8); - var map = SimpleJsonParse(json); - foreach (System.Collections.DictionaryEntry kv in map) - ht[kv.Key.ToString()] = (kv.Value ?? "").ToString(); - } - } - catch { } - _dsCache = ht; - return ht; - } - - private void SaveDsCache() - { - if (_dsCache == null) return; - try - { - var sb = new System.Text.StringBuilder("{\n"); - bool first = true; - foreach (System.Collections.DictionaryEntry kv in _dsCache) - { - if (!first) sb.Append(",\n"); - sb.Append(" \"" + kv.Key.ToString().Replace("\"", "\\\"") + "\": \"" + - kv.Value.ToString().Replace("\"", "\\\"") + "\""); - first = false; - } - sb.Append("\n}"); - File.WriteAllText(DeepSeekCachePath, sb.ToString(), System.Text.Encoding.UTF8); - } - catch (Exception ex) { Log("[DeepSeek缓存] 保存失败: " + ex.Message); } - } - - /// 极简 JSON 解析(扁平 key:value 结构,支持字符串/数字/布尔值) - private static System.Collections.Hashtable SimpleJsonParse(string json) - { - var ht = new System.Collections.Hashtable(); - if (string.IsNullOrEmpty(json)) return ht; - int depth = 0; bool inStr = false; - var key = new System.Text.StringBuilder(); - var val = new System.Text.StringBuilder(); - bool inKey = true; - for (int i = 0; i < json.Length; i++) - { - char c = json[i]; - if (inStr) - { - if (c == '\\' && i + 1 < json.Length) { val.Append(json[i + 1]); i++; continue; } - if (c == '"') { inStr = false; continue; } - (inKey ? key : val).Append(c); - continue; - } - if (c == '"') { inStr = true; continue; } - if (c == '{' || c == '[') { depth++; continue; } - if (c == '}' || c == ']') - { - // ★ 闭合括号收掉最后一个键值对(布尔值结尾无逗号) - if (depth == 1 && key.Length > 0) - { - ht[key.ToString()] = val.ToString().Trim(); - key.Length = 0; val.Length = 0; inKey = true; - } - depth--; continue; - } - if (c == ':' && depth == 1) { inKey = false; val.Length = 0; continue; } - if (c == ',' && depth == 1) - { - if (key.Length > 0) ht[key.ToString()] = val.ToString().Trim(); - key.Length = 0; val.Length = 0; inKey = true; - continue; - } - // ★ 无引号值(true/false/数字)必须累积,否则解析成空 - if (!inKey && !char.IsWhiteSpace(c)) val.Append(c); - } - if (key.Length > 0) ht[key.ToString()] = val.ToString().Trim(); - return ht; - } - - // ============================================================ - // 电器型号前缀规则(与用户库共用同一个 CSV 数据文件) - // ★ 用户库 CSV 中"元件类型"列 = "前缀" 的行即为前缀规则: - // 隔离开关,HGL,只,1,0,1,1,规则,0,前缀 - // (元件名称列=名称,规格列=型号前缀) - // ★ Excel 里直接编辑用户库即可增删规则,随库自动重载 - // ★ 规则结果与 AI 冲突时,以规则为准(根治 AI 误判) - // ============================================================ - - private static List _prefixRules = new List(); - - /// 内置最小规则集(仅当用户库无任何前缀行时兜底)。 - private static readonly string[,] s_BuiltinPrefixRules = - { - { "HGL", "隔离开关" }, { "DZ47", "小型断路器" }, { "NM1", "塑壳断路器" }, - { "CJX2", "交流接触器" }, { "RT16", "熔断器" }, { "LMZ", "电流互感器" }, - }; - - // ============================================================ - // ★ JB/T 2930 国标类组代号表(低压电器型号编制方法的官方定义) - // 国标型号前2位字母=品类代号:第1位类别+第2位组别。 - // 在前缀规则(L0)之后、CSV 库(L1)之前执行,覆盖所有国标型号。 - // ============================================================ - private static readonly System.Collections.Hashtable s_GbClassCodes = new System.Collections.Hashtable(StringComparer.OrdinalIgnoreCase) - { - // H 刀开关/隔离开关族 - { "HD", "隔离开关" }, // 单投刀开关 - { "HS", "隔离开关" }, // 双投刀开关(转换) - { "HR", "隔离开关" }, // 熔断器式刀开关 - { "HH", "隔离开关" }, // 封闭式负荷开关 - { "HK", "隔离开关" }, // 开启式负荷开关(胶盖闸) - { "HZ", "转换开关" }, // 组合开关 - { "HG", "隔离开关" }, // 熔断器式隔离器(另:HG1/HG13) - // R 熔断器族 - { "RC", "熔断器" }, // 插入式 - { "RL", "熔断器" }, // 螺旋式(RL6/RL8) - { "RM", "熔断器" }, // 密封管式 - { "RS", "快速熔断器" }, // 快速(RS0/RS3) - { "RT", "熔断器" }, // 有填料管式(RT0/RT16/RT18) - { "RX", "熔断器" }, // 限流 - { "RTO", "熔断器" }, - // D 断路器族 - { "DW", "万能式断路器" }, // 框架式(DW15/DW45) - { "DZ", "塑壳断路器" }, // 装置式/塑料外壳(DZ15/DZ20) - { "DX", "小型断路器" }, - { "DM", "塑壳断路器" }, - { "DC", "断路器" }, - // C 接触器族 - { "CJ", "交流接触器" }, // 交流(CJ20/CJX) - { "CZ", "直流接触器" }, // 直流 - { "CG", "接触器" }, // 高压 - { "CP", "接触器" }, // 中频 - { "CS", "接触器" }, // 时间 - // Q 起动器族 - { "QC", "电磁起动器" }, { "QS", "手动起动器" }, { "QX", "星三角起动器" }, - { "QJ", "自耦减压起动器" }, { "QT", "起动器" }, { "QU", "起动器" }, - // J 控制继电器族 - { "JL", "电流继电器" }, { "JR", "热过载继电器" }, { "JS", "时间继电器" }, - { "JT", "通用继电器" }, { "JW", "温度继电器" }, { "JZ", "中间继电器" }, - { "JX", "继电器" }, - // L 主令电器族 - { "LA", "按钮" }, // 按钮(LA38/LA39) - { "LK", "主令控制器" }, { "LT", "主令开关" }, { "LW", "转换开关" }, - { "LX", "行程开关" }, { "LU", "足踏开关" }, { "LS", "主令开关" }, - // Z 电阻/终端族 - { "ZB", "电阻器" }, { "ZG", "电阻器" }, { "ZC", "电阻器" }, - // B 变阻器族 - { "BL", "励磁变阻器" }, { "BP", "频敏变阻器" }, { "BQ", "起动变阻器" }, - { "BT", "变阻器" }, { "BC", "旋臂变阻器" }, - // M 电磁铁族 - { "MQ", "牵引电磁铁" }, { "MZ", "制动电磁铁" }, { "MW", "起重电磁铁" }, - // A 其他族 - { "AD", "指示灯" }, // 信号灯(AD11/AD16 习惯用) - { "AN", "按钮" }, - // P 仪用互感器(行业习惯,P 不在 JB/T2930 主表,单列) - { "LQG", "电流互感器" }, - // 变压器(控制变压器 BK 不在 JB/T2930,行业通用) - { "BK", "控制变压器" }, - }; - - /// - /// ★ 国标类组代号解析:按 JB/T 2930 定义,取型号前2位字母查类组表。 - /// 仅当:①前缀规则未命中 ②开头≥2位字母 ③类组表命中 时返回名称。 - /// 数字开头/单字母/进口品牌型号不适用(返回 null 交给后续层)。 - /// - private static string MatchByGbCode(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string s = spec.Trim(); - // 前2位必须是字母(国标类组代号为2位拼音) - if (s.Length < 3) return null; - if (!((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= 'a' && s[0] <= 'z'))) return null; - if (!((s[1] >= 'A' && s[1] <= 'Z') || (s[1] >= 'a' && s[1] <= 'z'))) return null; - // 第3位应是数字或分隔符(确认是类组代号+设计序号结构,排除品牌词) - if (s.Length > 2) - { - char c2 = s[2]; - bool ok = (c2 >= '0' && c2 <= '9') || c2 == '-' || c2 == ' ' || c2 == '/'; - if (!ok) return null; - } - string code = s.Substring(0, 2).ToUpperInvariant(); - object v = s_GbClassCodes[code]; - return v as string; - } - - /// - /// 按型号前缀规则查元器件名称。 - /// ★ 规则来自用户库 CSV"元件类型=前缀"的行(EnsureUserLibCsvLoaded 时提取), - /// 规则前缀直接与规格开头比对(支持字母+数字混合前缀,如 DZ47/CDM3/CJX2), - /// 最长前缀优先(7→2字符)。 - /// 返回 null 表示无规则。 - /// - private static string MatchByPrefixRule(string spec) - { - if (string.IsNullOrWhiteSpace(spec)) return null; - string s = spec.Trim().ToUpperInvariant(); - if (s.Length < 2) return null; - - var rules = _prefixRules; - if (rules.Count == 0) - { - // 用户库无前缀行 → 内置兜底 - for (int i = 0; i < s_BuiltinPrefixRules.GetLength(0); i++) - rules.Add(new[] { s_BuiltinPrefixRules[i, 0], s_BuiltinPrefixRules[i, 1] }); - _prefixRules = rules; - } - - for (int plen = 7; plen >= 2; plen--) - { - if (s.Length < plen) continue; - string head = s.Substring(0, plen); - foreach (var rule in rules) - { - if (rule[0].Length != plen || rule[0] != head) continue; - return rule[1]; - } - } - return null; - } - - /// 打开 DeepSeek 设置窗口(运行时创建,不改 ui.cs) - private void ShowDeepSeekSettings() - { - var cfg = LoadDsConfig(); - var form = new System.Windows.Forms.Form(); - form.Text = "DeepSeek AI 匹配设置"; - form.Size = new System.Drawing.Size(420, 260); - form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - form.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - form.MaximizeBox = false; form.MinimizeBox = false; - - var lblKey = new System.Windows.Forms.Label { Text = "API Key:", Location = new System.Drawing.Point(15, 18), AutoSize = true }; - var txtKey = new System.Windows.Forms.TextBox - { - Location = new System.Drawing.Point(80, 15), Size = new System.Drawing.Size(310, 23), - Text = cfg.ApiKey, UseSystemPasswordChar = true - }; - var chkShow = new System.Windows.Forms.CheckBox - { - Text = "显示密钥", Location = new System.Drawing.Point(80, 44), AutoSize = true - }; - chkShow.CheckedChanged += (s2, e2) => txtKey.UseSystemPasswordChar = !chkShow.Checked; - - var lblModel = new System.Windows.Forms.Label { Text = "模型:", Location = new System.Drawing.Point(15, 78), AutoSize = true }; - var cboModel = new System.Windows.Forms.ComboBox - { - Location = new System.Drawing.Point(80, 74), Size = new System.Drawing.Size(180, 23), - DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList - }; - cboModel.Items.Add("deepseek-v4-flash"); - cboModel.Items.Add("deepseek-v4-pro"); - cboModel.Items.Add("deepseek-chat"); - cboModel.SelectedItem = string.IsNullOrEmpty(cfg.Model) ? "deepseek-v4-flash" : cfg.Model; - - var chkEnable = new System.Windows.Forms.CheckBox - { - Text = "启用 AI 匹配(本地匹配失败后自动提交 DeepSeek 识别)", - Location = new System.Drawing.Point(15, 108), AutoSize = true, Checked = cfg.Enabled - }; - - var lblTip = new System.Windows.Forms.Label - { - Text = "提示:AI 结果会缓存到本地,相同规格只请求一次。\nAPI Key 从 platform.deepseek.com 获取。", - Location = new System.Drawing.Point(15, 138), AutoSize = true, ForeColor = System.Drawing.Color.Gray - }; - - var btnClear = new System.Windows.Forms.Button { Text = "清空AI缓存", Location = new System.Drawing.Point(80, 178), Size = new System.Drawing.Size(100, 28) }; - btnClear.Click += (s2, e2) => - { - try { if (File.Exists(DeepSeekCachePath)) File.Delete(DeepSeekCachePath); _dsCache = null; } - catch { } - MessageBox.Show(form, "AI 缓存已清空。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - }; - - var btnOk = new System.Windows.Forms.Button { Text = "保存", Location = new System.Drawing.Point(240, 178), Size = new System.Drawing.Size(75, 28) }; - var btnCancel = new System.Windows.Forms.Button { Text = "取消", Location = new System.Drawing.Point(325, 178), Size = new System.Drawing.Size(75, 28) }; - - btnOk.Click += (s2, e2) => - { - cfg.ApiKey = txtKey.Text.Trim(); - cfg.Model = cboModel.SelectedItem == null ? "deepseek-v4-flash" : cboModel.SelectedItem.ToString(); - cfg.Enabled = chkEnable.Checked && cfg.ApiKey.Length > 0; - SaveDsConfig(cfg); - form.Close(); - }; - btnCancel.Click += (s2, e2) => form.Close(); - - form.Controls.AddRange(new System.Windows.Forms.Control[] { lblKey, txtKey, chkShow, lblModel, cboModel, chkEnable, lblTip, btnClear, btnOk, btnCancel }); - form.ShowDialog(this); - } - - /// - /// 调 DeepSeek API 批量识别规格对应的元器件名称。 - /// 返回 规格→名称 的哈希表(失败的规格不在结果里)。 - /// - private System.Collections.Hashtable CallDeepSeekMatch(List specs) - { - var result = new System.Collections.Hashtable(); - var cfg = LoadDsConfig(); - if (!cfg.Enabled || string.IsNullOrWhiteSpace(cfg.ApiKey)) return result; - - // 构造提问:证据链推理法(查厂商→确认型号→按厂商定义归类) - var sb = new System.Text.StringBuilder(); - sb.Append("你是低压电器型号识别专家,精通 JB/T 2930《低压电器产品型号编制方法》。为每个规格型号返回【元器件名称】(中文标准品类词)。\n\n"); - sb.Append("【推理方法】(对每个型号按证据链三步走,不要直接猜):\n"); - sb.Append("第1步·识别厂商:从型号前缀判断是哪家厂(如 HUWI→沪工/环宇系、NM→正泰、CDM→德力西、CM→常熟、CW→常熟框架、SZRM→上海人民、XBK→湘湖/新宝凯、QAM→七仪);\n"); - sb.Append("第2步·确认系列:该厂商的此系列号是否存在、属于什么产品线(用你的产品知识回忆厂商型录:如 HUWI=沪工智能型万能式、YLEM=某厂智能框架、BM3=塑壳);\n"); - sb.Append("第3步·按厂商定义归类:厂商型录里该系列挂哪个品类就答什么,不要凭字母表面猜。\n\n"); - sb.Append("【辅助规律】(第2步无记忆时用):\n"); - sb.Append("· 国标类组:前2位字母=品类(DW万能断路器/DZ塑壳/CJ交流接触器/JR热继/LA按钮/HD-HS-HR隔离开关/RT熔断器);\n"); - sb.Append("· 结构特征:电流≥1600A+3P/4P+含W → 框架级(万能式/智能断路器);壳架≤630A+3P → 塑壳;63A以下+1P/2P → 微型;\n"); - sb.Append("· 派生代号:L/E=漏电或电子式,I=智能型,Z=直流/智能,N=可逆;\n"); - sb.Append("· 进口系列:施耐德(NSX/iC65/Vigi/LC1/LR)、ABB(S/SH)、西门子(3RT/5SL)、伊顿(IS)。\n\n"); - sb.Append("【输出格式】(严格遵守):\n"); - sb.Append("只返回纯 JSON 对象 {\"规格原文\":\"元器件名称\",...},不要任何解释、思考过程或其他文字;\n"); - sb.Append("每个规格都必须给出判断:按证据链推理,无法确认厂商和系列时按结构特征推断,实在无据可依才给空字符串;\n"); - sb.Append("名称用标准品类词:万能式断路器/智能断路器/塑壳断路器/小型断路器/漏电断路器/交流接触器/直流接触器/热过载继电器/时间继电器/中间继电器/电流互感器/电压互感器/熔断器/快速熔断器/隔离开关/负荷开关/转换开关/按钮/指示灯/行程开关/双电源/电磁起动器/自耦减压起动器/控制变压器/干式变压器/电涌保护器/电容器/电能表/软启动器/变频器等。\n"); - sb.Append("规格列表:\n"); - for (int i = 0; i < specs.Count; i++) - sb.Append((i + 1) + ". " + specs[i] + "\n"); - - try - { - // ★ 纯AI知识模式:chat/completions(不走联网搜索,快且稳) - // deepseek-v4 系列是思考模型:正式回答在 content,思考过程在 reasoning_content; - // 有时 content 空、答案藏在 reasoning_content 末尾 → 两处都提取 - string body = "{" + - "\"model\":\"" + cfg.Model + "\"," + - "\"messages\":[" + - "{\"role\":\"user\",\"content\":\"" + JsonEscape(sb.ToString()) + "\"}" + - "]," + - "\"temperature\":0.1," + - "\"max_tokens\":3000" + - "}"; - - string url = (cfg.BaseUrl ?? "https://api.deepseek.com").TrimEnd('/') + "/chat/completions"; - var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); - req.Method = "POST"; - req.ContentType = "application/json"; - req.Headers.Add("Authorization", "Bearer " + cfg.ApiKey); - req.Timeout = 60000; // 60秒 - req.ReadWriteTimeout = 60000; - req.Proxy = null; // ★ 不走系统代理(防代理环境卡死) - byte[] data = System.Text.Encoding.UTF8.GetBytes(body); - req.ContentLength = data.Length; - Log("[DeepSeek] 发起请求: " + specs.Count + " 条规格(AI知识模式), url=" + url); - using (var rs = req.GetRequestStream()) rs.Write(data, 0, data.Length); - - string respText; - using (var resp = (System.Net.HttpWebResponse)req.GetResponse()) - using (var sr = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8)) - respText = sr.ReadToEnd(); - Log("[DeepSeek] 响应长度: " + respText.Length + " 字符"); - - // 从响应提取 content(手工解析,取 choices[0].message.content) - string content = ExtractJsonContent(respText); - if (string.IsNullOrEmpty(content)) - { - Log("[DeepSeek] 响应解析失败: " + (respText.Length > 400 ? respText.Substring(0, 400) : respText)); - return result; - } - // ★ 诊断:AI原始输出(排查"返回0条"问题,只打前400字符) - Log("[DeepSeek] AI输出内容: " + (content.Length > 400 ? content.Substring(0, 400) + "..." : content)); - // content 里是 {"规格":"名称",...} - // ★ 思考模型(deepseek-v4)的 content 可能为空,答案在 reasoning_content 末尾: - // 思维链最后一般会写出最终 JSON,从 reasoning_content 里找 {...} 提取 - var map = SimpleJsonParse(content); - if (map.Count == 0) - { - // 从 reasoning_content 提取最后一个完整 JSON 对象 - int rIdx = respText.IndexOf("\"reasoning_content\":\"", System.StringComparison.Ordinal); - if (rIdx >= 0) - { - string reasoning = ExtractEscapedString(respText, rIdx + 21); - int braceStart = reasoning.LastIndexOf('{'); - if (braceStart >= 0) - { - // 从最后一个 { 找到配对的 } - int depth2 = 0; int end = -1; - for (int k = braceStart; k < reasoning.Length; k++) - { - if (reasoning[k] == '{') depth2++; - else if (reasoning[k] == '}') - { - depth2--; - if (depth2 == 0) { end = k; break; } - } - } - if (end > braceStart) - { - string jsonPart = reasoning.Substring(braceStart, end - braceStart + 1); - map = SimpleJsonParse(jsonPart); - Log("[DeepSeek] 从思维链提取到 " + map.Count + " 条结果"); - } - } - } - } - foreach (System.Collections.DictionaryEntry kv in map) - { - string key = kv.Key.ToString(); - string name = (kv.Value ?? "").ToString().Trim(); - if (name.Length == 0) continue; - - // ★ 防线:AI 结果先过本地前缀规则校验,冲突时以规则为准 - // (根治 AI 偶发误判,如把 HGL 隔离开关答成熔断器) - string rule = MatchByPrefixRule(key); - if (rule != null && rule != name) - { - Log("[DeepSeek校验] 「" + key + "」 AI答[" + name + "] 与规则冲突,已改用[" + rule + "]"); - name = rule; - } - result[key] = name; - } - Log("[DeepSeek] 识别 " + specs.Count + " 条,返回 " + result.Count + " 条结果"); - } - catch (Exception ex) - { - Log("[DeepSeek] 请求失败: " + ex.Message); - } - return result; - } - - /// - /// 从 API 响应中提取模型输出文本。 - /// 兼容两种格式: - /// · chat/completions: choices[0].message.content("content":"...") - /// · responses API: output[].content[].text("text":"...")或顶层"output_text" - /// - private static string ExtractJsonContent(string respText) - { - try - { - // 方式1:responses API 的 "output_text":"..." - int idx = respText.IndexOf("\"output_text\":\"", System.StringComparison.Ordinal); - if (idx >= 0) - { - string s = ExtractEscapedString(respText, idx + 15); - if (!string.IsNullOrEmpty(s)) return s; - } - // 方式2:responses API 的输出项文本 "text":"..."(跳过 summary/reasoning, - // 直接找最后一个大 text——输出 message 的正文通常最大) - int best = -1, bestLen = 0; - int pos = 0; - while (true) - { - int t = respText.IndexOf("\"text\":\"", pos, System.StringComparison.Ordinal); - if (t < 0) break; - // 取这个字符串的长度估算 - int len = EstimateEscapedLen(respText, t + 8); - if (len > bestLen) { bestLen = len; best = t; } - pos = t + 8; - } - if (best >= 0) - { - string s = ExtractEscapedString(respText, best + 8); - if (!string.IsNullOrEmpty(s)) return s; - } - // 方式3:chat 的 "content":"..." - idx = respText.IndexOf("\"content\":\"", System.StringComparison.Ordinal); - if (idx >= 0) - { - return ExtractEscapedString(respText, idx + 11); - } - return null; - } - catch { return null; } - } - - /// 从 start 位置读取一个 JSON 转义字符串(处理 \n \" \\ \uXXXX)。 - private static string ExtractEscapedString(string text, int start) - { - var sb = new System.Text.StringBuilder(); - int i = start; - while (i < text.Length) - { - char c = text[i]; - if (c == '\\' && i + 1 < text.Length) - { - char n = text[i + 1]; - if (n == 'n') sb.Append('\n'); - else if (n == 't') sb.Append('\t'); - else if (n == 'r') sb.Append('\r'); - else if (n == '"') sb.Append('"'); - else if (n == '\\') sb.Append('\\'); - else if (n == '/' ) sb.Append('/'); - else if (n == 'u' && i + 5 < text.Length) - { - int code = Convert.ToInt32(text.Substring(i + 2, 4), 16); - sb.Append((char)code); - i += 4; - } - else sb.Append(n); - i += 2; - continue; - } - if (c == '"') break; - sb.Append(c); - i++; - } - return sb.ToString(); - } - - /// 估算 start 位置转义字符串的长度(到未转义引号为止)。 - private static int EstimateEscapedLen(string text, int start) - { - int i = start, len = 0; - while (i < text.Length) - { - char c = text[i]; - if (c == '\\' && i + 1 < text.Length) { i += 2; len += 2; continue; } - if (c == '"') break; - i++; len++; - } - return len; - } - - private static string JsonEscape(string s) - { - if (string.IsNullOrEmpty(s)) return ""; - var sb = new System.Text.StringBuilder(); - foreach (char c in s) - { - if (c == '"') sb.Append("\\\""); - else if (c == '\\') sb.Append("\\\\"); - else if (c == '\n') sb.Append("\\n"); - else if (c == '\t') sb.Append("\\t"); - else if (c == '\r') sb.Append(""); - else sb.Append(c); - } - return sb.ToString(); - } - - /// - /// 扒元件插入后:对本地匹配失败的规格异步调用 DeepSeek 补名称, - /// 完成后回填数据库 + 刷新表格(UI 线程)。 - /// ★ 单飞+排队:上一个 AI 批次未完成时,后续规格累积到待办队列, - /// 完成后一并提交(防并发互踩/请求堆积)。 - /// - private static readonly object _aiLock = new object(); - private static bool _aiRunning = false; - private static List _aiPendingSpecs = new List(); - private static string _aiPendingTbl = null; - - private void AiFillMissingNames(List failedSpecs, string tblName) - { - if (failedSpecs == null || failedSpecs.Count == 0) return; - var cfg = LoadDsConfig(); - if (!cfg.Enabled || string.IsNullOrWhiteSpace(cfg.ApiKey)) return; - - lock (_aiLock) - { - // 并发防抖:AI 批次进行中 → 累积到待办,由运行中的批次完成后接力 - if (_aiRunning) - { - foreach (string sp in failedSpecs) - if (!_aiPendingSpecs.Contains(sp)) _aiPendingSpecs.Add(sp); - if (_aiPendingTbl == null) _aiPendingTbl = tblName; - Log("[AI队列] 批次进行中," + failedSpecs.Count + " 条已加入待办(累计 " + _aiPendingSpecs.Count + ")"); - return; - } - _aiRunning = true; - _aiPendingTbl = tblName; - } - - RunAiBatch(failedSpecs, tblName); - } - - /// 执行一个 AI 批次(完成后处理待办队列)。 - private void RunAiBatch(List specs, string tblName) - { - var bgw = new System.ComponentModel.BackgroundWorker(); - bgw.DoWork += (s, e) => - { - try - { - // 先查缓存,未缓存的才提交 AI - var cache = LoadDsCache(); - var toAsk = new List(); - var localHits = new System.Collections.Hashtable(); - lock (_aiLock) - { - foreach (string sp in specs) - { - if (cache.ContainsKey(sp)) - { - string cached = (cache[sp] ?? "").ToString(); - // ★ 规则有结果但缓存为空(AI曾未识别) → 用规则(补漏) - string rule = MatchByPrefixRule(sp); - if (rule != null && rule.Length > 0 && rule != cached) - { - Log("[缓存校验] 「" + sp + "」 缓存[" + cached + "]与规则冲突,已纠正为[" + rule + "]"); - cached = rule; - cache[sp] = rule; - } - if (cached.Length > 0) localHits[sp] = cached; - } - else if (!toAsk.Contains(sp)) toAsk.Add(sp); - } - } - - var ai = new System.Collections.Hashtable(); - if (toAsk.Count > 0) - { - ai = CallDeepSeekMatch(toAsk); - // 写缓存(包括未命中的,避免反复问) - lock (_aiLock) - { - foreach (string sp in toAsk) - cache[sp] = ai.Contains(sp) ? ai[sp].ToString() : ""; - SaveDsCache(); - } - } - - // 合并结果 - var final = new System.Collections.Hashtable(); - foreach (System.Collections.DictionaryEntry kv in localHits) final[kv.Key] = kv.Value; - foreach (System.Collections.DictionaryEntry kv in ai) final[kv.Key] = kv.Value; - e.Result = final; - } - catch (Exception ex) - { - Log("[AI回填] 后台异常: " + ex); - e.Result = new System.Collections.Hashtable(); - } - }; - bgw.RunWorkerCompleted += (s, e) => - { - // ★ 无论成败都处理:先取走待办队列并释放单飞标记 - List pending; - string pendingTbl; - lock (_aiLock) - { - pending = new List(_aiPendingSpecs); - pendingTbl = _aiPendingTbl; - _aiPendingSpecs = new List(); - _aiPendingTbl = null; - _aiRunning = false; - } - - try - { - var final = e.Result as System.Collections.Hashtable; - if (final == null || final.Count == 0) { if (pending.Count > 0) StartNextAiBatch(pending, pendingTbl); return; } - int updated = 0; - string dbPath = GetQuoteDbPath(_currentProjectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var tx = conn.BeginTransaction()) - { - foreach (System.Collections.DictionaryEntry kv in final) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "UPDATE \"" + tblName + "\" SET 元件名称=@name WHERE 规格=@spec AND (元件名称 IS NULL OR 元件名称='');", conn)) - { - cmd.Parameters.AddWithValue("@name", kv.Value.ToString()); - cmd.Parameters.AddWithValue("@spec", kv.Key.ToString()); - updated += cmd.ExecuteNonQuery(); - } - } - tx.Commit(); - } - } - if (updated > 0) - { - Log("[AI回填] 已回填 " + updated + " 条元件名称"); - _yuanjianCache.Clear(); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - - // ★ AI 识别成功的结果追加进用户库 CSV(库越用越全, - // 下次同规格本地直接命中,不再消耗 AI) - AppendAiResultsToUserLibCsv(final); - } - catch (Exception ex) { Log("[AI回填] 回填异常: " + ex.Message); } - - // ★ 接力:待办队列有货 → 继续下一个批次 - if (pending.Count > 0) StartNextAiBatch(pending, pendingTbl); - }; - bgw.RunWorkerAsync(); - } - - /// 启动下一个 AI 批次(带单飞保护)。 - private void StartNextAiBatch(List specs, string tblName) - { - lock (_aiLock) - { - if (_aiRunning) - { - foreach (string sp in specs) - if (!_aiPendingSpecs.Contains(sp)) _aiPendingSpecs.Add(sp); - return; - } - _aiRunning = true; - _aiPendingTbl = tblName; - } - Log("[AI队列] 接力下一批 " + specs.Count + " 条"); - RunAiBatch(specs, tblName); - } - - /// - /// 把 AI 识别结果(规格→名称)追加到最新用户库 CSV(GBK 编码), - /// 并同步更新内存库 _specNameLib(当前会话立即生效)。 - /// 已存在的规格跳过;每条占一行:名称,规格,只,1,0,1,1,AI识别,0,元件 - /// - private void AppendAiResultsToUserLibCsv(System.Collections.Hashtable aiResults) - { - try - { - if (aiResults == null || aiResults.Count == 0) return; - - // 找最新 CSV(与 EnsureUserLibCsvLoaded 同规则:上级目录+插件目录取最新) - string best = null; DateTime bestTime = DateTime.MinValue; - var dirs = new List(); - try - { - var parent = Path.GetDirectoryName(_baseDir); - if (!string.IsNullOrEmpty(parent) && Directory.Exists(parent)) dirs.Add(parent); - } - catch { } - dirs.Add(_baseDir); - foreach (string d in dirs) - { - try - { - foreach (string f in Directory.GetFiles(d, "用户库*.csv")) - { - DateTime t = File.GetLastWriteTime(f); - if (best == null || t > bestTime) { best = f; bestTime = t; } - } - } - catch { } - } - if (best == null) { Log("[AI入库] 未找到用户库CSV,跳过"); return; } - - // ★ 共享读写:文件可能被 Excel 打开 - var gbk = System.Text.Encoding.GetEncoding("GBK"); - var existing = new HashSet(StringComparer.OrdinalIgnoreCase); - var fs = System.IO.File.Open(best, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using (var sr = new StreamReader(fs, gbk)) - { - string line; - while ((line = sr.ReadLine()) != null) - { - if (string.IsNullOrWhiteSpace(line)) continue; - int comma = line.IndexOf(','); - if (comma > 0) existing.Add(line.Substring(comma + 1).Trim()); - } - } - - // 组装新增行 - var newLines = new List(); - foreach (System.Collections.DictionaryEntry kv in aiResults) - { - string spec = kv.Key.ToString().Trim(); - string name = kv.Value.ToString().Trim(); - if (spec.Length == 0 || name.Length == 0) continue; - if (existing.Contains(spec)) continue; - newLines.Add(name + "," + spec + ",只,1,0,1,1,AI识别,0,元件"); - existing.Add(spec); // 防同批重复 - } - if (newLines.Count == 0) { Log("[AI入库] 全部已存在,无新增"); return; } - - // 追加写(共享读写防 Excel 锁;失败重试3次——扒图进程可能正读CSV) - bool written = false; - for (int attempt = 0; attempt < 3 && !written; attempt++) - { - try - { - using (var fs2 = new FileStream(best, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) - using (var sw = new StreamWriter(fs2, gbk)) - { - foreach (string nl in newLines) sw.WriteLine(nl); - } - written = true; - } - catch (System.IO.IOException) - { - System.Threading.Thread.Sleep(300); // 等 CSV 读取方释放 - } - } - if (!written) Log("[AI入库] 写入失败(文件被占用),跳过本次(下次扒图会再尝试)"); - - // ★ 同步内存库:当前会话的本地匹配立即可用 - try - { - EnsureUserLibCsvLoaded(); - if (_specNameLib != null) - { - foreach (string nl in newLines) - { - string[] cols = nl.Split(','); - if (cols.Length >= 2) - _specNameLib.Add(new SpecNameEntry - { - Name = cols[0], - NormSpec = NormalizeSpec(cols[1]), - Numbers = ExtractNumbers(cols[1]), - Skeleton = ExtractSkeleton(cols[1]) - }); - } - } - } - catch { } - - Log("[AI入库] 新增 " + newLines.Count + " 条到 " + Path.GetFileName(best)); - } - catch (Exception ex) { Log("[AI入库] 失败: " + ex.Message); } - } - - /// 根据项目ID和图号获取箱号表名(查"表索引"表)。 - private string GetQuoteTableName(string projectId, string tuhao) - { - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return ""; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 表名 FROM " + IndexTableName + " WHERE 图号=@t LIMIT 1;", conn)) - { - cmd.Parameters.AddWithValue("@t", tuhao); - object o = cmd.ExecuteScalar(); - return o == null ? "" : o.ToString(); - } - } - } - catch { return ""; } - } - - private void InsertTuhao(string projectId, string tuhao, string frameHandle, string textHandle) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - string sql = "INSERT INTO " + TuhaoTableName + - " (序号, 图号, 台数, 箱柜数量, 单价, 总价, 成本总价, 毛利, 毛利率, 框Handle, 文本Handle) " + - "VALUES (@seq, @th, @taishu, 0, 0, 0, 0, 0, 0, @frameHandle, @textHandle);"; - string seq = GetNextSeqNumber(TuhaoTableName, "图号", projectId); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.Parameters.AddWithValue("@taishu", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.Parameters.AddWithValue("@textHandle", textHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteTuhao(string projectId, string tuhao) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var tablesToDrop = new List(); - string selIdx = "SELECT 实际表名 FROM 表索引 WHERE 图号 = @th;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selIdx, conn)) - { - sel.Parameters.AddWithValue("@th", tuhao); - using (var reader = sel.ExecuteReader()) - { - while (reader.Read()) - { - string realTbl = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(realTbl)) tablesToDrop.Add(realTbl); - } - } - } - foreach (string realTbl in tablesToDrop) - { - using (var dropCmd = new System.Data.SQLite.SQLiteCommand( - "DROP TABLE IF EXISTS \"" + realTbl + "\";", conn)) - dropCmd.ExecuteNonQuery(); - } - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM " + TuhaoTableName + " WHERE 图号 = @th;", conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.ExecuteNonQuery(); - } - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM 表索引 WHERE 图号 = @th;", conn)) - { - cmd.Parameters.AddWithValue("@th", tuhao); - cmd.ExecuteNonQuery(); - } - } - } - - private void InsertXianghao(string projectId, string tuhao, string xianghao, string frameHandle, string textHandle) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - string tblName = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(tblName)) - { - tblName = GetNextTableId(projectId, "xh"); - CreateXianghaoTable(projectId, tblName); - AddTableIndex(projectId, "箱号", tuhao, "", tblName); - } - // ★ 确保旧箱号表也有"箱名"/"框Handle"/"文本Handle"列 - using (var connEns = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - connEns.Open(); - EnsureColumns(connEns, "\"" + tblName + "\"", new[] { "箱名", "框Handle", "文本Handle" }); - } - string seq = GetXianghaoCount(projectId, tuhao); - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 箱号, 箱名, 单位, 数量," + - " 单台成本, 成本价, 单台报出, 报出价, 利润, 利润率, 毛利率, 框Handle, 文本Handle) " + - "VALUES (@seq, @xh, @xm, @unit, @shuliang, 0, 0, 0, 0, 0, 0, 0, @frameHandle, @textHandle);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@xh", xianghao); - cmd.Parameters.AddWithValue("@xm", ""); // 箱名默认空,由用户在表格里填写 - cmd.Parameters.AddWithValue("@unit", "台"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.Parameters.AddWithValue("@textHandle", textHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteXianghao(string projectId, string tuhao, string xianghao) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - if (!string.IsNullOrEmpty(yjTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DROP TABLE IF EXISTS \"" + yjTbl + "\";", conn)) - cmd.ExecuteNonQuery(); - } - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (!string.IsNullOrEmpty(xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + xhTbl + "\" WHERE 箱号 = @xh;", conn)) - { - cmd.Parameters.AddWithValue("@xh", xianghao); - cmd.ExecuteNonQuery(); - } - } - } - RemoveTableIndex(projectId, "元件", tuhao, xianghao); - } - - private void InsertYuanjian(string projectId, string tuhao, string xianghao, string name) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - EnsureYuanjianTableExists(projectId, tuhao, xianghao); - string tblName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tblName)) - { - System.Windows.Forms.MessageBox.Show("元件表创建失败(表索引未注册),图号=" + tuhao + " 箱号=" + xianghao); - return; - } - string seq; - using (var conn0 = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn0.Open(); - using (var c = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\";", conn0)) - { - int n = 0; - object o = c.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - seq = (n + 1).ToString(); - } - } - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型) " + - "VALUES (@seq, @name, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件');"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@name", name); - cmd.Parameters.AddWithValue("@unit", "只"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@caigou", "1"); - cmd.Parameters.AddWithValue("@baochu", "1"); - cmd.ExecuteNonQuery(); - } - } - } - - /// 扒元件专用:把文本写到【规格】列(元件名称留空),同时写入框Handle。 - private void InsertYuanjianSpec(string projectId, string tuhao, string xianghao, string spec, string frameHandle) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || string.IsNullOrWhiteSpace(xianghao)) return; - EnsureQuoteDbExists(projectId); - string dbPath = GetQuoteDbPath(projectId); - EnsureYuanjianTableExists(projectId, tuhao, xianghao); - string tblName = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(tblName)) - { - System.Windows.Forms.MessageBox.Show("元件表创建失败(表索引未注册),图号=" + tuhao + " 箱号=" + xianghao); - return; - } - string seq; - using (var conn0 = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn0.Open(); - using (var c = new System.Data.SQLite.SQLiteCommand( - "SELECT COUNT(*) FROM \"" + tblName + "\";", conn0)) - { - int n = 0; - object o = c.ExecuteScalar(); - if (o != null && o != DBNull.Value) n = Convert.ToInt32(o); - seq = (n + 1).ToString(); - } - } - // ★ 写入"规格"列 + 框Handle - string sql = "INSERT INTO \"" + tblName + "\"" + - " (序号, 元件名称, 规格, 单位, 数量, 采购系数, 报出系数," + - " 表价, 采购单价, 采购价, 报出单价, 报出价, 类型, 框Handle) " + - "VALUES (@seq, '', @spec, @unit, @shuliang, @caigou, @baochu, 0, 0, 0, 0, 0, '元件', @frameHandle);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.Parameters.AddWithValue("@spec", spec); - cmd.Parameters.AddWithValue("@unit", "只"); - cmd.Parameters.AddWithValue("@shuliang", "1"); - cmd.Parameters.AddWithValue("@caigou", "1"); - cmd.Parameters.AddWithValue("@baochu", "1"); - cmd.Parameters.AddWithValue("@frameHandle", frameHandle ?? ""); - cmd.ExecuteNonQuery(); - } - } - } - - private void DeleteYuanjian(string projectId, string tuhao, string xianghao, string seq) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(xianghao)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - if (string.IsNullOrEmpty(realTbl)) return; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "DELETE FROM \"" + realTbl + "\" WHERE 序号 = @seq;", conn)) - { - cmd.Parameters.AddWithValue("@seq", seq); - cmd.ExecuteNonQuery(); - } - } - } - - // ============================================================ - // 数据库回写:把内存 DataTable 的改动写回报价库 - // ============================================================ - - private void SaveTableToDatabase(DataTable table, string projectId, string tableName, - string whereClause, Dictionary whereParams, bool force = false) - { - if (table == null || string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - - DataGridView dgv = null; - if (table == _tuhaoTable) dgv = this.advancedDataGridView9; - else if (table == _xianghaoTable) dgv = this.advancedDataGridView4; - else if (table == _yuanjianTable) dgv = this.advancedDataGridView5; - if (dgv != null) dgv.EndEdit(); - - if (table.Rows.Count == 0) return; - if (!force && table.GetChanges() == null) return; - - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var tx = conn.BeginTransaction()) - { - string delSql = "DELETE FROM " + tableName; - if (!string.IsNullOrWhiteSpace(whereClause)) delSql += " WHERE " + whereClause; - delSql += ";"; - using (var delCmd = new System.Data.SQLite.SQLiteCommand(delSql, conn)) - { - if (whereParams != null) - { - foreach (var kv in whereParams) delCmd.Parameters.AddWithValue(kv.Key, kv.Value); - } - delCmd.ExecuteNonQuery(); - } - if (table.Rows.Count > 0) - { - var colNames = new List(table.Columns.Count); - foreach (DataColumn c in table.Columns) colNames.Add(c.ColumnName); - var paramList = new List(colNames.Count); - foreach (string c in colNames) paramList.Add("@" + c); - string insertSql = "INSERT INTO " + tableName + " (" + - string.Join(", ", colNames.ToArray()) + ") VALUES (" + - string.Join(", ", paramList.ToArray()) + ");"; - using (var insCmd = new System.Data.SQLite.SQLiteCommand(insertSql, conn)) - { - foreach (string col in colNames) - insCmd.Parameters.Add("@" + col, System.Data.DbType.String); - try { insCmd.Prepare(); } catch { } - foreach (DataRow row in table.Rows) - { - if (row.RowState == DataRowState.Deleted) continue; - foreach (string col in colNames) - { - object v = row[col]; - insCmd.Parameters["@" + col].Value = - (v == null || v == DBNull.Value) ? "" : v.ToString(); - } - insCmd.ExecuteNonQuery(); - } - } - } - tx.Commit(); - } - table.AcceptChanges(); - } - } - - private void SaveTuhaoTableIfDirty() - { - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null); - } - - private void SaveXianghaoTableIfDirty() - { - if (_xianghaoTable == null || string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) return; - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null); - } - - private void SaveYuanjianTableIfDirty() - { - if (_yuanjianTable == null || string.IsNullOrWhiteSpace(_yuanjianTable.TableName)) return; - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null); - } - - private void SaveAllQuoteTablesIfDirty(bool force = true) - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_yuanjianTable != null && !string.IsNullOrWhiteSpace(_yuanjianTable.TableName)) - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + _yuanjianTable.TableName + "\"", null, null, force); - if (_xianghaoTable != null && !string.IsNullOrWhiteSpace(_xianghaoTable.TableName)) - SaveTableToDatabase(_xianghaoTable, _currentProjectId, - "\"" + _xianghaoTable.TableName + "\"", null, null, force); - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, force); - } - catch { } - } - - private void SaveAllToDatabaseSilent() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - try - { - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - foreach (var kv in _xianghaoCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - foreach (var kv in _yuanjianCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - RecalcAllFromDatabase(_currentProjectId); - ReloadProjectsFromDatabase(); - } - catch { } - } - - // ============================================================ - // 联动刷新:项目 → 图号 → 箱号 → 元件 - // ============================================================ - - private void ReloadProjectsFromDatabase() - { - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return; - - var indexTable = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "SELECT 项目编号, 箱柜台数, 成本总价, 报出总价, 利润, 利润率 FROM " + - ProjectsTableName + " ORDER BY rowid;"; - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(sql, conn)) - adapter.Fill(indexTable); - } - - var table = new DataTable(); - table.Columns.Add("项目编号", typeof(string)); - table.Columns.Add("项目名称", typeof(string)); - table.Columns.Add("客户名称", typeof(string)); - table.Columns.Add("客户地址", typeof(string)); - table.Columns.Add("联系人", typeof(string)); - table.Columns.Add("联系电话", typeof(string)); - table.Columns.Add("项目日期", typeof(string)); - table.Columns.Add("箱柜台数", typeof(string)); - table.Columns.Add("成本总价", typeof(string)); - table.Columns.Add("报出总价", typeof(string)); - table.Columns.Add("利润", typeof(string)); - table.Columns.Add("利润率", typeof(string)); - table.Columns.Add("备注", typeof(string)); - - foreach (DataRow idxRow in indexTable.Rows) - { - string projectId = idxRow["项目编号"] == null ? "" : idxRow["项目编号"].ToString().Trim(); - if (string.IsNullOrEmpty(projectId)) continue; - var info = GetProjectInfoFromQuoteDb(projectId); - var row = table.NewRow(); - row["项目编号"] = projectId; - row["项目名称"] = GetInfoOrDefault(info, "项目名称"); - row["客户名称"] = GetInfoOrDefault(info, "客户名称"); - row["客户地址"] = GetInfoOrDefault(info, "客户地址"); - row["联系人"] = GetInfoOrDefault(info, "联系人"); - row["联系电话"] = GetInfoOrDefault(info, "联系电话"); - row["项目日期"] = GetInfoOrDefault(info, "项目日期"); - row["备注"] = GetInfoOrDefault(info, "备注"); - row["箱柜台数"] = idxRow["箱柜台数"] == null ? "" : idxRow["箱柜台数"].ToString(); - row["成本总价"] = idxRow["成本总价"] == null ? "" : idxRow["成本总价"].ToString(); - row["报出总价"] = idxRow["报出总价"] == null ? "" : idxRow["报出总价"].ToString(); - row["利润"] = idxRow["利润"] == null ? "" : idxRow["利润"].ToString(); - row["利润率"] = idxRow["利润率"] == null ? "" : idxRow["利润率"].ToString(); - table.Rows.Add(row); - } - - this.advancedDataGridView6.AutoGenerateColumns = false; - table = ConvertFormulaColumnsToDouble(table); - this.advancedDataGridView6.DataSource = table; - } - - private static string GetInfoOrDefault(Dictionary info, string key) - { - if (info == null) return ""; - string v; - return info.TryGetValue(key, out v) ? (v ?? "") : ""; - } - - private void ReloadTuhaoByProject(string projectId) - { - bool outerGuard = _isReloading; - _isReloading = true; - try - { - if (string.IsNullOrWhiteSpace(projectId) || !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView9.DataSource = null; - _tuhaoTable = null; - _currentTuhao = ""; - ReloadXianghaoByTuhao("", ""); - return; - } - string dbPath = GetQuoteDbPath(projectId); - string sql = "SELECT * FROM " + TuhaoTableName + " ORDER BY CAST(序号 AS INTEGER);"; - var table = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - this.advancedDataGridView9.AutoGenerateColumns = false; - this.advancedDataGridView9.DataSource = table; - _tuhaoTable = table; - ApplyPriceFormat(this.advancedDataGridView9, _单台小数位文本); - - _currentTuhao = ""; - if (this.advancedDataGridView9.Rows.Count > 0) - { - SetCurrentCell(this.advancedDataGridView9, 0); - _currentTuhao = GetCellValueAsString(this.advancedDataGridView9.Rows[0], "图号"); - } - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - finally { _isReloading = outerGuard; } - } - - private void ReloadXianghaoByTuhao(string projectId, string tuhao) - { - bool outerGuard = _isReloading; - _isReloading = true; - try - { - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView4.DataSource = null; - _xianghaoTable = null; - _currentXianghao = ""; - ReloadYuanjianByXianghao("", "", ""); - return; - } - string dbPath = GetQuoteDbPath(projectId); - string realTbl = GetXianghaoTableByIndex(projectId, tuhao); - if (string.IsNullOrEmpty(realTbl)) - { - realTbl = GetNextTableId(projectId, "xh"); - CreateXianghaoTable(projectId, realTbl); - AddTableIndex(projectId, "箱号", tuhao, "", realTbl); - } - - DataTable table; - // ★ 禁用缓存命中:每次都从数据库重新读取,确保删除/变更能及时反映到UI - if (_xianghaoCache.ContainsKey(tuhao)) _xianghaoCache.Remove(tuhao); - { - string sql = "SELECT * FROM \"" + realTbl + "\" ORDER BY CAST(序号 AS INTEGER);"; - table = new DataTable(); - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 老库结构兼容:箱号表可能还没有"箱名"列,读取前幂等补列(表格绑定依赖该列) - EnsureColumns(conn, "\"" + realTbl + "\"", new[] { "箱名" }); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - table.TableName = realTbl; - _xianghaoCache[tuhao] = table; - } - - this.advancedDataGridView4.AutoGenerateColumns = false; - this.advancedDataGridView4.DataSource = table; - _xianghaoTable = table; - ApplyPriceFormat(this.advancedDataGridView4, _单台小数位文本); - - _currentXianghao = ""; - if (this.advancedDataGridView4.Rows.Count > 0) - { - SetCurrentCell(this.advancedDataGridView4, 0); - _currentXianghao = GetCellValueAsString(this.advancedDataGridView4.Rows[0], "箱号"); - } - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - finally { _isReloading = outerGuard; } - } - - private void ReloadYuanjianByXianghao(string projectId, string tuhao, string xianghao) - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - string.IsNullOrWhiteSpace(xianghao) || !File.Exists(GetQuoteDbPath(projectId))) - { - this.advancedDataGridView5.DataSource = null; - _yuanjianTable = null; - return; - } - string realTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - string dbPath = GetQuoteDbPath(projectId); - string cacheKey = tuhao + "\n" + xianghao; - DataTable table; - // ★ 禁用缓存命中:每次都从数据库重新读取,确保删除/变更能及时反映到UI - if (_yuanjianCache.ContainsKey(cacheKey)) _yuanjianCache.Remove(cacheKey); - { - table = new DataTable(); - if (!string.IsNullOrEmpty(realTbl)) - { - string sql = "SELECT * FROM \"" + realTbl + "\" ORDER BY CAST(序号 AS INTEGER);"; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(cmd)) - adapter.Fill(table); - } - table = ConvertFormulaColumnsToDouble(table); - } - table.TableName = realTbl; - _yuanjianCache[cacheKey] = table; - } - this.advancedDataGridView5.AutoGenerateColumns = false; - this.advancedDataGridView5.DataSource = table; - _yuanjianTable = table; - ApplyPriceFormat(this.advancedDataGridView5, _单台小数位文本); - } - - // ============================================================ - // 公式重算 - // ============================================================ - - private void RecalcYuanjianRow(DataGridViewRow row) - { - if (row == null) return; - decimal biaoJia = GetCellDecimal(row, "表价"); - decimal caiGouXiShu = GetCellDecimal(row, "采购系数"); - decimal baoChuXiShu = GetCellDecimal(row, "报出系数"); - decimal shuLiang = GetCellDecimal(row, "数量"); - decimal caiGouDanJia = biaoJia * caiGouXiShu; - decimal caiGouJia = caiGouDanJia * shuLiang; - decimal baoChuDanJia = caiGouDanJia * baoChuXiShu; - decimal baoChuJia = baoChuDanJia * shuLiang; - SetCell(row, "采购单价", caiGouDanJia); - SetCell(row, "采购价", caiGouJia); - SetCell(row, "报出单价", baoChuDanJia); - SetCell(row, "报出价", baoChuJia); - } - - private void RecalcXianghaoRowFromYuanjian(DataGridViewRow xianghaoRow) - { - if (xianghaoRow == null) return; - decimal sumCaiGouJia = 0m; - decimal sumBaoChuJia = 0m; - DataGridView dgv5 = this.advancedDataGridView5; - if (dgv5 != null && dgv5.Rows != null) - { - foreach (DataGridViewRow yj in dgv5.Rows) - { - if (yj == null || yj.IsNewRow) continue; - sumCaiGouJia += GetCellDecimal(yj, "采购价"); - sumBaoChuJia += GetCellDecimal(yj, "报出价"); - } - } - decimal shuLiang = GetCellDecimal(xianghaoRow, "数量"); - decimal danTaiChengBen = sumCaiGouJia; - decimal chengBenJia = danTaiChengBen * shuLiang; - decimal danTaiBaoChu = sumBaoChuJia; - decimal baoChuJia = danTaiBaoChu * shuLiang; - decimal liRun = baoChuJia - chengBenJia; - decimal liRunLv = chengBenJia == 0m ? 0m : liRun / chengBenJia; - decimal maoLiLv = baoChuJia == 0m ? 0m : liRun / baoChuJia; - SetCell(xianghaoRow, "单台成本", danTaiChengBen); - SetCell(xianghaoRow, "成本价", chengBenJia); - SetCell(xianghaoRow, "单台报出", danTaiBaoChu); - SetCell(xianghaoRow, "报出价", baoChuJia); - SetCell(xianghaoRow, "利润", liRun); - SetCell(xianghaoRow, "利润率", liRunLv); - SetCell(xianghaoRow, "毛利率", maoLiLv); - } - - private void RecalcTuhaoRowFromXianghao(DataGridViewRow tuhaoRow) - { - if (tuhaoRow == null) return; - decimal sumShuLiang = 0m; - decimal sumBaoChuJia = 0m; - decimal sumChengBenJia = 0m; - DataGridView dgv4 = this.advancedDataGridView4; - if (dgv4 != null && dgv4.Rows != null) - { - foreach (DataGridViewRow xh in dgv4.Rows) - { - if (xh == null || xh.IsNewRow) continue; - sumShuLiang += GetCellDecimal(xh, "数量"); - sumBaoChuJia += GetCellDecimal(xh, "报出价"); - sumChengBenJia += GetCellDecimal(xh, "成本价"); - } - } - decimal taiShu = GetCellDecimal(tuhaoRow, "台数"); - decimal xiangGuiShuLiang = sumShuLiang; - decimal danJia = sumBaoChuJia; - decimal zongJia = danJia * taiShu; - decimal chengBenZongJia = sumChengBenJia * taiShu; - decimal maoLi = zongJia - chengBenZongJia; - decimal maoLiLv = zongJia == 0m ? 0m : maoLi / zongJia; - SetCell(tuhaoRow, "箱柜数量", xiangGuiShuLiang); - SetCell(tuhaoRow, "单价", danJia); - SetCell(tuhaoRow, "总价", zongJia); - SetCell(tuhaoRow, "成本总价", chengBenZongJia); - SetCell(tuhaoRow, "毛利", maoLi); - SetCell(tuhaoRow, "毛利率", maoLiLv); - RecalcProjectRowFromTuhao(); - } - - private void RecalcProjectRowFromTuhao() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - decimal sumXiangGuiShuLiang = 0m; - decimal sumChengBenZongJia = 0m; - decimal sumZongJia = 0m; - DataGridView dgv9 = this.advancedDataGridView9; - if (dgv9 != null && dgv9.Rows != null) - { - foreach (DataGridViewRow th in dgv9.Rows) - { - if (th == null || th.IsNewRow) continue; - sumXiangGuiShuLiang += GetCellDecimal(th, "箱柜数量"); - sumChengBenZongJia += GetCellDecimal(th, "成本总价"); - sumZongJia += GetCellDecimal(th, "总价"); - } - } - decimal xiangGuiTaiShu = sumXiangGuiShuLiang; - decimal baoChuZongJia = sumZongJia; - decimal liRun = baoChuZongJia - sumChengBenZongJia; - decimal liRunLv = sumChengBenZongJia == 0m ? 0m : liRun / sumChengBenZongJia; - DataGridViewRow projRow = FindProjectRowById(_currentProjectId); - if (projRow != null) - { - SetCell(projRow, "箱柜台数", xiangGuiTaiShu); - SetCell(projRow, "成本总价", sumChengBenZongJia); - SetCell(projRow, "报出总价", baoChuZongJia); - SetCell(projRow, "利润", liRun); - SetCell(projRow, "利润率", liRunLv); - } - } - - private void RecalcAllAfterReload() - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) return; - _isRecalculating = true; - _isReloading = true; - try - { - DataGridView dgv5 = this.advancedDataGridView5; - if (dgv5 != null && dgv5.Rows != null) - { - foreach (DataGridViewRow yj in dgv5.Rows) - { - if (yj == null || yj.IsNewRow) continue; - RecalcYuanjianRow(yj); - } - } - var xhRow = GetFirstSelectedRow(this.advancedDataGridView4); - if (xhRow != null) RecalcXianghaoRowFromYuanjian(xhRow); - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - - SaveYuanjianTableIfDirty(); - SaveXianghaoTableIfDirty(); - SaveTuhaoTableIfDirty(); - if (_yuanjianTable != null) _yuanjianTable.AcceptChanges(); - if (_xianghaoTable != null) _xianghaoTable.AcceptChanges(); - if (_tuhaoTable != null) _tuhaoTable.AcceptChanges(); - } - finally - { - _isRecalculating = false; - _lastRecalcTime = DateTime.Now; - _isReloading = false; - } - } - - // ---------- 全量数据库重算 ---------- - - private class TuhaoCalcRow { public long RowId; public decimal TaiShu; public string Tuhao; } - private class XianghaoCalcRow { public long RowId; public decimal ShuLiang; public string Xianghao; } - - private void RecalcAllFromDatabase(string projectId) - { - if (string.IsNullOrWhiteSpace(projectId)) projectId = _currentProjectId; - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - var tuhaoRows = new List(); - string selTuhao = "SELECT rowid, 台数, 图号 FROM " + TuhaoTableName + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selTuhao, conn)) - using (var rdr = sel.ExecuteReader()) - { - while (rdr.Read()) - { - var t = new TuhaoCalcRow(); - t.RowId = rdr.GetInt64(0); - t.TaiShu = ParseDecimal(rdr.IsDBNull(1) ? "" : rdr.GetValue(1)); - t.Tuhao = rdr.IsDBNull(2) ? "" : rdr.GetValue(2).ToString().Trim(); - tuhaoRows.Add(t); - } - } - decimal sumProjXiangGui = 0m; - decimal sumProjChengBen = 0m; - decimal sumProjZongJia = 0m; - foreach (var t in tuhaoRows) - { - if (string.IsNullOrWhiteSpace(t.Tuhao)) continue; - try - { - string xhTable = GetXianghaoTableByIndex(t.Tuhao, conn); - if (string.IsNullOrEmpty(xhTable)) - { - UpdateTuhaoCalc(conn, t.RowId, 0m, 0m, 0m, 0m, 0m, 0m); - continue; - } - string xhQuoted = "\"" + xhTable + "\""; - decimal sumThXiangGuiShuLiang = 0m; - decimal sumThBaoChuJia = 0m; - decimal sumThChengBenJia = 0m; - var xhRows = new List(); - string selXh = "SELECT rowid, 数量, 箱号 FROM " + xhQuoted + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selXh, conn)) - using (var rdr = sel.ExecuteReader()) - { - while (rdr.Read()) - { - var x = new XianghaoCalcRow(); - x.RowId = rdr.GetInt64(0); - x.ShuLiang = ParseDecimal(rdr.IsDBNull(1) ? "" : rdr.GetValue(1)); - x.Xianghao = rdr.IsDBNull(2) ? "" : rdr.GetValue(2).ToString(); - xhRows.Add(x); - } - } - foreach (var x in xhRows) - { - try - { - sumThXiangGuiShuLiang += x.ShuLiang; - string yjTable = GetYuanjianTableByIndex(t.Tuhao, x.Xianghao, conn); - decimal sumCaiGou = 0m; - decimal sumBaoChu = 0m; - if (!string.IsNullOrEmpty(yjTable)) - { - string yjQuoted = "\"" + yjTable + "\""; - string selYj = "SELECT rowid, 表价, 采购系数, 报出系数, 数量 FROM " + - yjQuoted + " ORDER BY rowid;"; - using (var sel = new System.Data.SQLite.SQLiteCommand(selYj, conn)) - using (var sr = sel.ExecuteReader()) - { - while (sr.Read()) - { - long yjRid = sr.GetInt64(0); - decimal yjBiaoJia = ParseDecimal(sr.IsDBNull(1) ? "" : sr.GetValue(1)); - decimal yjCgXs = ParseDecimal(sr.IsDBNull(2) ? "" : sr.GetValue(2)); - decimal yjBcXs = ParseDecimal(sr.IsDBNull(3) ? "" : sr.GetValue(3)); - decimal yjSl = ParseDecimal(sr.IsDBNull(4) ? "" : sr.GetValue(4)); - decimal yjCaiGouDanJia = yjBiaoJia * yjCgXs; - decimal yjCaiGouJia = yjCaiGouDanJia * yjSl; - decimal yjBaoChuDanJia = yjCaiGouDanJia * yjBcXs; - decimal yjBaoChuJia = yjBaoChuDanJia * yjSl; - sumCaiGou += yjCaiGouJia; - sumBaoChu += yjBaoChuJia; - UpdateYuanjianCalc(conn, yjQuoted, yjRid, - yjCaiGouDanJia, yjCaiGouJia, yjBaoChuDanJia, yjBaoChuJia); - } - } - } - decimal danTaiChengBen = sumCaiGou; - decimal chengBenJia = danTaiChengBen * x.ShuLiang; - decimal danTaiBaoChu = sumBaoChu; - decimal baoChuJia = danTaiBaoChu * x.ShuLiang; - decimal xhLiRun = baoChuJia - chengBenJia; - decimal xhLiRunLv = chengBenJia == 0m ? 0m : xhLiRun / chengBenJia; - decimal xhMaoLiLv = baoChuJia == 0m ? 0m : xhLiRun / baoChuJia; - sumThBaoChuJia += baoChuJia; - sumThChengBenJia += chengBenJia; - UpdateXianghaoCalc(conn, xhQuoted, x.RowId, - danTaiChengBen, chengBenJia, danTaiBaoChu, baoChuJia, - xhLiRun, xhLiRunLv, xhMaoLiLv); - } - catch { } - } - decimal xiangGuiShuLiang = sumThXiangGuiShuLiang; - decimal danJia = sumThBaoChuJia; - decimal zongJia = danJia * t.TaiShu; - decimal chengBenZongJia = sumThChengBenJia * t.TaiShu; - decimal maoLi = zongJia - chengBenZongJia; - decimal maoLiLv = zongJia == 0m ? 0m : maoLi / zongJia; - sumProjXiangGui += xiangGuiShuLiang; - sumProjChengBen += chengBenZongJia; - sumProjZongJia += zongJia; - UpdateTuhaoCalc(conn, t.RowId, xiangGuiShuLiang, danJia, - zongJia, chengBenZongJia, maoLi, maoLiLv); - } - catch { } - } - decimal projLiRun = sumProjZongJia - sumProjChengBen; - decimal projLiRunLv = sumProjChengBen == 0m ? 0m : projLiRun / sumProjChengBen; - UpdateProjectQuoteTotalsById(projectId, sumProjXiangGui, - sumProjChengBen, sumProjZongJia, projLiRun, projLiRunLv); - } - } - catch { } - } - - private static void UpdateYuanjianCalc(System.Data.SQLite.SQLiteConnection conn, - string yjQuoted, long rowId, - decimal caiGouDanJia, decimal caiGouJia, decimal baoChuDanJia, decimal baoChuJia) - { - string sql = "UPDATE " + yjQuoted + " SET " + - "采购单价=@a, 采购价=@b, 报出单价=@c, 报出价=@d WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", caiGouDanJia == 0m ? (object)DBNull.Value : (object)caiGouDanJia); - cmd.Parameters.AddWithValue("@b", caiGouJia == 0m ? (object)DBNull.Value : (object)caiGouJia); - cmd.Parameters.AddWithValue("@c", baoChuDanJia == 0m ? (object)DBNull.Value : (object)baoChuDanJia); - cmd.Parameters.AddWithValue("@d", baoChuJia == 0m ? (object)DBNull.Value : (object)baoChuJia); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private static void UpdateXianghaoCalc(System.Data.SQLite.SQLiteConnection conn, - string xhQuoted, long rowId, - decimal danTaiChengBen, decimal chengBenJia, decimal danTaiBaoChu, decimal baoChuJia, - decimal liRun, decimal liRunLv, decimal maoLiLv) - { - string sql = "UPDATE " + xhQuoted + " SET " + - "单台成本=@a, 成本价=@b, 单台报出=@c, 报出价=@d, " + - "利润=@e, 利润率=@f, 毛利率=@g WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", danTaiChengBen == 0m ? (object)DBNull.Value : (object)danTaiChengBen); - cmd.Parameters.AddWithValue("@b", chengBenJia == 0m ? (object)DBNull.Value : (object)chengBenJia); - cmd.Parameters.AddWithValue("@c", danTaiBaoChu == 0m ? (object)DBNull.Value : (object)danTaiBaoChu); - cmd.Parameters.AddWithValue("@d", baoChuJia == 0m ? (object)DBNull.Value : (object)baoChuJia); - cmd.Parameters.AddWithValue("@e", liRun == 0m ? (object)DBNull.Value : (object)liRun); - cmd.Parameters.AddWithValue("@f", liRunLv.ToString()); - cmd.Parameters.AddWithValue("@g", maoLiLv.ToString()); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private static void UpdateTuhaoCalc(System.Data.SQLite.SQLiteConnection conn, - long rowId, decimal xiangGuiShuLiang, decimal danJia, - decimal zongJia, decimal chengBenZongJia, decimal maoLi, decimal maoLiLv) - { - string sql = "UPDATE " + TuhaoTableName + " SET " + - "箱柜数量=@a, 单价=@b, 总价=@c, 成本总价=@d, 毛利=@e, 毛利率=@f " + - "WHERE rowid=@rid;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@a", xiangGuiShuLiang == 0m ? (object)DBNull.Value : (object)xiangGuiShuLiang); - cmd.Parameters.AddWithValue("@b", danJia == 0m ? (object)DBNull.Value : (object)danJia); - cmd.Parameters.AddWithValue("@c", zongJia == 0m ? (object)DBNull.Value : (object)zongJia); - cmd.Parameters.AddWithValue("@d", chengBenZongJia == 0m ? (object)DBNull.Value : (object)chengBenZongJia); - cmd.Parameters.AddWithValue("@e", maoLi == 0m ? (object)DBNull.Value : (object)maoLi); - cmd.Parameters.AddWithValue("@f", maoLiLv.ToString()); - cmd.Parameters.AddWithValue("@rid", rowId); - cmd.ExecuteNonQuery(); - } - } - - private void UpdateProjectQuoteTotalsById(string projectId, - decimal xiangGuiTaiShu, decimal chengBenZongJia, - decimal baoChuZongJia, decimal liRun, decimal liRunLv) - { - if (string.IsNullOrWhiteSpace(projectId)) return; - string dbPath = GetDbFullPath(ProjectsDbPath); - if (!File.Exists(dbPath)) return; - try - { - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - string sql = "UPDATE " + ProjectsTableName + " SET " + - "箱柜台数=@xgts, 成本总价=@cbzj, 报出总价=@bczj, " + - "利润=@lr, 利润率=@lrl WHERE 项目编号=@id;"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@xgts", xiangGuiTaiShu == 0m ? (object)DBNull.Value : (object)xiangGuiTaiShu); - cmd.Parameters.AddWithValue("@cbzj", chengBenZongJia == 0m ? (object)DBNull.Value : (object)chengBenZongJia); - cmd.Parameters.AddWithValue("@bczj", baoChuZongJia == 0m ? (object)DBNull.Value : (object)baoChuZongJia); - cmd.Parameters.AddWithValue("@lr", liRun == 0m ? (object)DBNull.Value : (object)liRun); - cmd.Parameters.AddWithValue("@lrl", liRunLv.ToString()); - cmd.Parameters.AddWithValue("@id", projectId); - cmd.ExecuteNonQuery(); - } - } - } - catch { } - } - - // ============================================================ - // 事件:CellValueChanged / DirtyStateChanged / CellEndEdit - // ============================================================ - - private void Grid_DirtyStateChanged(object sender, EventArgs e) - { - if (_isRecalculating || _isReloading) return; - var msSinceRecalc = (DateTime.Now - _lastRecalcTime).TotalMilliseconds; - if (msSinceRecalc < 2000) return; - var dgv = sender as DataGridView; - if (dgv != null && dgv.IsCurrentCellDirty) - dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); - } - - private void Yuanjian_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView5; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - _isRecalculating = true; - try - { - RecalcYuanjianRow(row); - var xhRow = GetFirstSelectedRow(this.advancedDataGridView4); - if (xhRow != null) - { - RecalcXianghaoRowFromYuanjian(xhRow); - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - } - } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - private void Xianghao_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView4; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - _isRecalculating = true; - try - { - var thRow = GetFirstSelectedRow(this.advancedDataGridView9); - if (thRow != null) RecalcTuhaoRowFromXianghao(thRow); - } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - private void Tuhao_CellValueChanged(object sender, DataGridViewCellEventArgs e) - { - if (_isRecalculating || _isReloading) return; - if (e.RowIndex < 0) return; - var dgv = this.advancedDataGridView9; - if (dgv == null || e.RowIndex >= dgv.Rows.Count) return; - var row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - DataGridViewColumn col = e.ColumnIndex >= 0 ? dgv.Columns[e.ColumnIndex] : null; - string colName = col == null ? "" : - (!string.IsNullOrEmpty(col.DataPropertyName) ? col.DataPropertyName : col.HeaderText); - if (colName != "台数") return; - _isRecalculating = true; - try { RecalcTuhaoRowFromXianghao(row); } - finally { _isRecalculating = false; _lastRecalcTime = DateTime.Now; } - } - - /// CellEndEdit:把公式列的字符串值转为 double,让 DefaultCellStyle.Format 生效。 - private void Grid_CellEndEdit(object sender, DataGridViewCellEventArgs e) - { - var dgv = sender as DataGridView; - if (dgv == null || e.ColumnIndex < 0 || e.ColumnIndex >= dgv.Columns.Count) return; - string dp = dgv.Columns[e.ColumnIndex].DataPropertyName; - string cn = dgv.Columns[e.ColumnIndex].HeaderText; - string colKey = !string.IsNullOrEmpty(dp) ? dp : cn; - if (!s_公式列集合.Contains(colKey)) return; - if (e.RowIndex < 0 || e.RowIndex >= dgv.Rows.Count) return; - object v = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; - if (v == null || v is double) return; - string str = v.ToString().Trim(); - if (string.IsNullOrEmpty(str)) return; - double d; - if (double.TryParse(str, out d)) - dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = d; - } - - // ============================================================ - // SelectionChanged 联动 - // ============================================================ - - private void advancedDataGridView9_SelectionChanged(object sender, EventArgs e) - { - if (_isReloading) return; - if (this.advancedDataGridView9 != null && this.advancedDataGridView9.SelectedCells.Count > 1) return; - DataGridViewRow row = GetFirstSelectedRow(this.advancedDataGridView9); - if (row == null) return; - string tuhao = GetCellValueAsString(row, "图号"); - if (tuhao == _currentTuhao) return; - _currentTuhao = tuhao; - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - - private void advancedDataGridView4_SelectionChanged(object sender, EventArgs e) - { - if (_isReloading) return; - if (this.advancedDataGridView4 != null && this.advancedDataGridView4.SelectedCells.Count > 1) return; - DataGridViewRow row = GetFirstSelectedRow(this.advancedDataGridView4); - if (row == null) return; - string xh = GetCellValueAsString(row, "箱号"); - if (xh == _currentXianghao) return; - _currentXianghao = xh; - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - - private void advancedDataGridView5_SelectionChanged(object sender, EventArgs e) { } - - // ============================================================ - // ★ 点击表格行 → 定位到对应的扒图框(缩放居中) - // 读取数据行的"框Handle"列,用 Handle 反查 CAD 实体,缩放到实体范围 - // ============================================================ - private void Grid_CellClick_Zoom(object sender, DataGridViewCellEventArgs e) - { - if (_isReloading) return; - if (e.RowIndex < 0) return; - DataGridView dgv = sender as DataGridView; - if (dgv == null) return; - DataGridViewRow row = dgv.Rows[e.RowIndex]; - if (row == null || row.IsNewRow) return; - // ★ 直接从 DataRow 读取"框Handle"(不依赖 DataGridView 列映射) - string handle = ""; - var drv = row.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) handle = v.ToString().Trim(); - } - if (!string.IsNullOrWhiteSpace(handle)) - { - ZoomToFrameHandle(handle); - } - } - - /// - /// 根据框 Handle 字符串定位网页 CAD 视图:缩放居中到框的位置并高亮。 - /// Handle 是扒图时绘制的彩色矩形框的句柄(十六进制字符串), - /// 与网页端实体 objectId 一致,通过 CadBridge 转发给网页 CAD 执行。 - /// - private static void ZoomToFrameHandle(string handle) - { - if (string.IsNullOrWhiteSpace(handle)) return; - try - { - pdfbt.PdfBridge.ZoomToFrameHandle(handle); - } - catch { } - } - - /// - /// ★ 网页 CAD 会话内的扒图框由网页端持有,无需像 AutoCAD 版那样 - /// 定期 SaveAs 整个 DWG(原为防止 CAD 关闭时框丢失)。保留空实现 - /// 以兼容调用点。 - /// - private static DateTime _lastDwgSaveTime = DateTime.MinValue; - - // ★ 扒元件后待选中的行(框Handle),finally 延迟执行选中 - private List _pendingSelectYuanjianHandles = new List(); - - private static void SaveCurrentDwg() - { - // 网页版:扒图框保存在网页 CAD 会话中,无需保存 DWG 文件。 - } - - /// - /// ★ 删除指定 Handle 对应的 CAD 框实体(单个,转发到批量方法)。 - /// - private void DeleteFrameByHandle(string handle) - { - DeleteFramesByHandles(new string[] { handle }); - } - - /// - /// ★ 批量删除多个 Handle 对应的框:打包成一条消息发给网页 CAD, - /// 网页端逐个 erase 后只 regen 一次(保持原版"批量一次刷新"的优化)。 - /// - private void DeleteFramesByHandles(System.Collections.Generic.IEnumerable handles) - { - var list = new List(); - if (handles != null) - foreach (string h in handles) - if (!string.IsNullOrWhiteSpace(h)) list.Add(h); - if (list.Count == 0) { Log("[DeleteFramesByHandles] 无有效 handle,跳过"); return; } - try - { - pdfbt.PdfBridge.DeleteFramesByHandles(list); - Log("[DeleteFramesByHandles] 已发送网页删除请求: 请求=" + list.Count); - } - catch (System.Exception ex) { Log("[DeleteFramesByHandles] 异常: " + ex.Message); } - } - - /// - /// ★ 收集指定图号下所有箱号表和元件表的框Handle(级联删框用)。 - /// 不包含图号表自身的框(图号行框由调用方从内存表收集)。 - /// - private void CollectFrameHandlesForTuhao(string projectId, string tuhao, List handles) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao)) return; - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) { Log("[CollectFrameHandlesForTuhao] 数据库不存在: " + dbPath); return; } - int beforeCount = handles.Count; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // 箱号表 - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - Log("[CollectFrameHandlesForTuhao] 图号=" + tuhao + " 箱号表名=" + (xhTbl ?? "(null)")); - if (!string.IsNullOrEmpty(xhTbl) && TableExists(conn, xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle, 箱号 FROM \"" + xhTbl + "\";", conn)) - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - string xh = reader.IsDBNull(1) ? "" : reader.GetString(1); - Log("[CollectFrameHandlesForTuhao] 箱号=" + xh + " 框Handle=" + h); - // 查该箱号的元件表 - if (!string.IsNullOrWhiteSpace(xh)) - { - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xh); - if (!string.IsNullOrEmpty(yjTbl) && TableExists(conn, yjTbl)) - { - using (var yjCmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + yjTbl + "\";", conn)) - using (var yjReader = yjCmd.ExecuteReader()) - while (yjReader.Read()) - { - string yh = yjReader.IsDBNull(0) ? "" : yjReader.GetString(0); - if (!string.IsNullOrWhiteSpace(yh)) handles.Add(yh); - Log("[CollectFrameHandlesForTuhao] 元件框Handle=" + yh); - } - } - } - } - } - } - } - Log("[CollectFrameHandlesForTuhao] 新增框Handle数: " + (handles.Count - beforeCount)); - } - catch (Exception ex) { Log("[CollectFrameHandlesForTuhao] 异常: " + ex.Message); } - } - - /// - /// ★ 收集指定箱号下元件表的框Handle(级联删框用)。 - /// 不包含箱号表自身的框(箱号行框由调用方从内存表收集)。 - /// - private void CollectFrameHandlesForXianghao(string projectId, string tuhao, string xianghao, List handles) - { - if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(tuhao) || - string.IsNullOrWhiteSpace(xianghao)) return; - try - { - string dbPath = GetQuoteDbPath(projectId); - if (!File.Exists(dbPath)) { Log("[CollectFrameHandlesForXianghao] 数据库不存在: " + dbPath); return; } - int beforeCount = handles.Count; - using (var conn = new System.Data.SQLite.SQLiteConnection(GetConnString(dbPath))) - { - conn.Open(); - // ★ 先收集箱号表自身该箱号的框Handle(之前遗漏,导致删箱号时蒙版不删) - string xhTbl = GetXianghaoTableByIndex(projectId, tuhao); - Log("[CollectFrameHandlesForXianghao] 图号=" + tuhao + " 箱号=" + xianghao + " 箱号表名=" + (xhTbl ?? "(null)")); - if (!string.IsNullOrEmpty(xhTbl) && TableExists(conn, xhTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + xhTbl + "\" WHERE 箱号=@xh;", conn)) - { - cmd.Parameters.AddWithValue("@xh", xianghao); - using (var reader = cmd.ExecuteReader()) - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - Log("[CollectFrameHandlesForXianghao] 箱号自身框Handle=" + h); - } - } - } - // ★ 再收集该箱号下元件表的框Handle - string yjTbl = GetYuanjianTableByIndex(projectId, tuhao, xianghao); - Log("[CollectFrameHandlesForXianghao] 元件表名=" + (yjTbl ?? "(null)")); - if (!string.IsNullOrEmpty(yjTbl) && TableExists(conn, yjTbl)) - { - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT 框Handle FROM \"" + yjTbl + "\";", conn)) - using (var reader = cmd.ExecuteReader()) - while (reader.Read()) - { - string h = reader.IsDBNull(0) ? "" : reader.GetString(0); - if (!string.IsNullOrWhiteSpace(h)) handles.Add(h); - Log("[CollectFrameHandlesForXianghao] 元件框Handle=" + h); - } - } - } - Log("[CollectFrameHandlesForXianghao] 新增框Handle数: " + (handles.Count - beforeCount)); - } - catch (Exception ex) { Log("[CollectFrameHandlesForXianghao] 异常: " + ex.Message); } - } - - /// 检查表是否存在(SQLite)。 - private static bool TableExists(System.Data.SQLite.SQLiteConnection conn, string tableName) - { - if (conn == null || string.IsNullOrWhiteSpace(tableName)) return false; - try - { - string name = tableName.Trim().Trim('"'); - using (var cmd = new System.Data.SQLite.SQLiteCommand( - "SELECT name FROM sqlite_master WHERE type='table' AND name=@n;", conn)) - { - cmd.Parameters.AddWithValue("@n", name); - object o = cmd.ExecuteScalar(); - return o != null && o != DBNull.Value; - } - } - catch { return false; } - } - - // ============================================================ - // 双击项目行 → 进入项目 - // ============================================================ - - private void advancedDataGridView6_CellDoubleClick(object sender, DataGridViewCellEventArgs e) - { - if (e.RowIndex < 0) return; - DataGridViewRow row = this.advancedDataGridView6.Rows[e.RowIndex]; - string pid = GetCellValueAsString(row, "项目编号"); - if (string.IsNullOrWhiteSpace(pid)) return; - - // 切项目前:先把当前项目的所有改动回写库,然后清空缓存 - if (!string.IsNullOrWhiteSpace(_currentProjectId) && _currentProjectId != pid) - { - try - { - if (this.advancedDataGridView5 != null) this.advancedDataGridView5.EndEdit(); - if (this.advancedDataGridView4 != null) this.advancedDataGridView4.EndEdit(); - if (this.advancedDataGridView9 != null) this.advancedDataGridView9.EndEdit(); - if (_tuhaoTable != null) - SaveTableToDatabase(_tuhaoTable, _currentProjectId, TuhaoTableName, null, null, true); - foreach (var kv in _xianghaoCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - foreach (var kv in _yuanjianCache) - if (kv.Value != null && !string.IsNullOrWhiteSpace(kv.Value.TableName)) - SaveTableToDatabase(kv.Value, _currentProjectId, - "\"" + kv.Value.TableName + "\"", null, null, true); - } - catch { } - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - _tuhaoTable = null; - } - _currentProjectId = pid; - EnterProjectCore(pid); - } - - private void EnterProjectCore(string pid) - { - // 切换主区域到报价页(tabPage4) - this.tabControl2.SelectedTab = this.tabPage4; - EnsureQuoteDbExists(pid); - LoadPriceFormatConfig(pid); - RecalcAllFromDatabase(pid); - ReloadTuhaoByProject(pid); - ApplyPriceFormat(this.advancedDataGridView9, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView4, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView5, _单台小数位文本); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - } - - // ============================================================ - // ★ 右键点击时保持多行选中 - // WinForms 默认行为:右键点击未选中行 → 清除多选,只选一行 - // 修正:右键点击已选中行 → 保持多选;点击未选中行 → 正常切换 - // ============================================================ - private void Grid_MouseDown_KeepMultiSelect(object sender, MouseEventArgs e) - { - if (e.Button != MouseButtons.Right) return; - var dgv = sender as DataGridView; - if (dgv == null) return; - var hit = dgv.HitTest(e.X, e.Y); - if (hit.Type != DataGridViewHitTestType.Cell && hit.Type != DataGridViewHitTestType.RowHeader) return; - if (hit.RowIndex < 0) return; - // 如果右键点击的行已经在选中行中,不做任何操作(保持多选) - // 如果不在选中行中,让默认行为生效(选中该行) - foreach (DataGridViewRow r in dgv.SelectedRows) - { - if (r.Index == hit.RowIndex) return; - } - // 选中行中没有包含右键点击的行 → 手动选中该行 - dgv.ClearSelection(); - dgv.Rows[hit.RowIndex].Selected = true; - dgv.CurrentCell = dgv.Rows[hit.RowIndex].Cells[0]; - } - - // ============================================================ - // ★ 键盘 Delete 键批量删除选中行 - // 图号表→MenuTuhao_Delete_Click;箱号表→MenuXianghao_Delete_Click;元件表→MenuYuanjian_Delete_Click - // ============================================================ - // 连续批量模式标记:Shift+F1 触发,或 1 秒内连按 F1 触发 - private DateTime _lastF1Time = DateTime.MinValue; - private bool _f1BatchMode; - - /// F1:元件两两配对合并;F2:元件三个一组配对合并。 - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - if ((keyData & Keys.KeyCode) == Keys.F1 && this.advancedDataGridView5 != null) - { - try { RunF1Merge(); } catch (Exception ex) { Log("[F1] " + ex.Message); } - return true; - } - if ((keyData & Keys.KeyCode) == Keys.F2 && this.advancedDataGridView5 != null) - { - try { MergeYuanjianByGroup(3); } catch (Exception ex) { Log("[F2] " + ex.Message); } - return true; - } - if ((keyData & Keys.KeyCode) == Keys.F3 && this.advancedDataGridView5 != null) - { - try { MergeYuanjianByGroup(4); } catch (Exception ex) { Log("[F3] " + ex.Message); } - return true; - } - return base.ProcessCmdKey(ref msg, keyData); - } - - // ★ 合并防抖时间戳(MergeYuanjianByGroup 统一闸门用) - private DateTime _lastFKeyTime = DateTime.MinValue; - - /// 统一 F1 入口(宿主按键/网页转发共用)。 - private void RunF1Merge() - { - MergeAdjacentYuanjianByF1(); - } - - private void Grid_KeyDown_Delete(object sender, KeyEventArgs e) - { - if (e.KeyCode != Keys.Delete) return; - var dgv = sender as DataGridView; - if (dgv == null) return; - if (dgv.SelectedRows.Count == 0 && dgv.SelectedCells.Count == 0) return; - if (dgv.IsCurrentCellInEditMode) return; // 编辑模式下不拦截 Delete - - e.SuppressKeyPress = true; - e.Handled = true; - - if (dgv == this.advancedDataGridView9) - MenuTuhao_Delete_Click(null, null); - else if (dgv == this.advancedDataGridView4) - MenuXianghao_Delete_Click(null, null); - else if (dgv == this.advancedDataGridView5) - MenuYuanjian_Delete_Click(null, null); - } - - // ============================================================ - // 右键菜单:创建 + 行移动 - // ============================================================ - - private void BuildContextMenus() - { - // 图号菜单(advancedDataGridView9) - _menuTuhao = new ContextMenuStrip(); - _menuTuhao.Items.Add("新建图号", null, MenuTuhao_New_Click); - _menuTuhao.Items.Add("删除图号", null, MenuTuhao_Delete_Click); - _menuTuhao.Items.Add(new ToolStripSeparator()); - _menuTuhao.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Top)); - _menuTuhao.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Up)); - _menuTuhao.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Down)); - _menuTuhao.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.Bottom)); - _menuTuhao.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView9, RowMoveAction.To)); - this.advancedDataGridView9.ContextMenuStrip = _menuTuhao; - - // 箱号菜单(advancedDataGridView4) - _menuXianghao = new ContextMenuStrip(); - _menuXianghao.Items.Add("新建箱号", null, MenuXianghao_New_Click); - _menuXianghao.Items.Add("删除箱号", null, MenuXianghao_Delete_Click); - _menuXianghao.Items.Add(new ToolStripSeparator()); - _menuXianghao.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Top)); - _menuXianghao.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Up)); - _menuXianghao.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Down)); - _menuXianghao.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.Bottom)); - _menuXianghao.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView4, RowMoveAction.To)); - this.advancedDataGridView4.ContextMenuStrip = _menuXianghao; - - // 元件菜单(advancedDataGridView5) - _menuYuanjian = new ContextMenuStrip(); - _menuYuanjian.Items.Add("新建元件", null, MenuYuanjian_New_Click); - _menuYuanjian.Items.Add("删除元件", null, MenuYuanjian_Delete_Click); - _menuYuanjian.Items.Add("合并元件", null, MenuYuanjian_Merge_Click); - _menuYuanjian.Items.Add(new ToolStripSeparator()); - _menuYuanjian.Items.Add("置顶", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Top)); - _menuYuanjian.Items.Add("向上移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Up)); - _menuYuanjian.Items.Add("向下移动", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Down)); - _menuYuanjian.Items.Add("置底", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.Bottom)); - _menuYuanjian.Items.Add("移动到...", null, (s, e) => MoveSelectedRowInGrid(this.advancedDataGridView5, RowMoveAction.To)); - this.advancedDataGridView5.ContextMenuStrip = _menuYuanjian; - } - - private enum RowMoveAction { Top, Up, Down, Bottom, To } - - private void MoveSelectedRowInGrid(DataGridView dgv, RowMoveAction action) - { - if (dgv == null || string.IsNullOrWhiteSpace(_currentProjectId)) return; - DataTable table = null; - System.Action reloadAction = null; - if (dgv == this.advancedDataGridView5) - { - table = _yuanjianTable; - reloadAction = () => ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - } - else if (dgv == this.advancedDataGridView4) - { - table = _xianghaoTable; - reloadAction = () => ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - } - else if (dgv == this.advancedDataGridView9) - { - table = _tuhaoTable; - reloadAction = () => ReloadTuhaoByProject(_currentProjectId); - } - if (table == null || table.Rows.Count == 0) - { - MessageBox.Show(this, "没有数据可移动。", "移动行", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var dgvRow = GetFirstSelectedRow(dgv); - if (dgvRow == null) - { - MessageBox.Show(this, "请先选择要移动的行。", "移动行", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - int dataCount = dgv.Rows.Count; - if (dgv.AllowUserToAddRows) dataCount--; - if (dataCount <= 0) return; - int oldIndex = dgvRow.Index; - if (oldIndex >= dataCount) return; - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - int newIndex = -1; - _isReloading = true; - try - { - dgv.EndEdit(); - newIndex = oldIndex; - switch (action) - { - case RowMoveAction.Top: newIndex = 0; break; - case RowMoveAction.Up: newIndex = Math.Max(0, oldIndex - 1); break; - case RowMoveAction.Down: newIndex = Math.Min(dataCount - 1, oldIndex + 1); break; - case RowMoveAction.Bottom: newIndex = dataCount - 1; break; - case RowMoveAction.To: - string input = ShowInputDialog("移动到", - "请输入目标行号(1-" + dataCount + "):", (oldIndex + 1).ToString()); - if (string.IsNullOrEmpty(input)) { newIndex = -1; return; } - int target; - if (!int.TryParse(input.Trim(), out target)) - { - MessageBox.Show(this, "请输入有效数字。", "移动到", MessageBoxButtons.OK, MessageBoxIcon.Warning); - newIndex = -1; - return; - } - newIndex = Math.Max(0, Math.Min(dataCount - 1, target - 1)); - break; - } - if (newIndex == oldIndex) { newIndex = -1; return; } - - DataRow rowToMove = table.Rows[oldIndex]; - object[] savedValues = rowToMove.ItemArray; - table.Rows.Remove(rowToMove); - DataRow newRow = table.NewRow(); - newRow.ItemArray = savedValues; - table.Rows.InsertAt(newRow, newIndex); - - if (table.Columns.Contains("序号")) - { - for (int i = 0; i < table.Rows.Count; i++) table.Rows[i]["序号"] = (i + 1).ToString(); - } - if (dgv == this.advancedDataGridView9) - SaveTableToDatabase(table, _currentProjectId, TuhaoTableName, null, null, true); - else - SaveTableToDatabase(table, _currentProjectId, "\"" + table.TableName + "\"", null, null, true); - } - catch (Exception ex) - { - MessageBox.Show(this, "移动行失败:\n" + ex.Message, "移动行", MessageBoxButtons.OK, MessageBoxIcon.Error); - newIndex = -1; - } - finally - { - _isReloading = false; - if (newIndex >= 0) - { - if (dgv == this.advancedDataGridView9) - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - else if (dgv == this.advancedDataGridView4) - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - else if (dgv == this.advancedDataGridView5) - SelectRowByValue(this.advancedDataGridView5, "序号", (newIndex + 1).ToString()); - } - } - } - - private void MoveLastRowBelowSelected(DataGridView dgv, DataTable table, - int afterIndex, string dbTableName, string projectId) - { - if (dgv == null || table == null || afterIndex < 0 || table.Rows.Count < 2) return; - int lastIndex = table.Rows.Count - 1; - int targetIndex = afterIndex + 1; - if (targetIndex >= lastIndex) return; - object[] savedValues = table.Rows[lastIndex].ItemArray; - table.Rows.RemoveAt(lastIndex); - DataRow newRow = table.NewRow(); - newRow.ItemArray = savedValues; - table.Rows.InsertAt(newRow, targetIndex); - if (table.Columns.Contains("序号")) - { - for (int i = 0; i < table.Rows.Count; i++) table.Rows[i]["序号"] = (i + 1).ToString(); - } - SaveTableToDatabase(table, projectId, dbTableName, null, null, true); - try { if (targetIndex < dgv.Rows.Count) dgv.FirstDisplayedScrollingRowIndex = targetIndex; } catch { } - } - - // ---------- 图号菜单事件 ---------- - - private void MenuTuhao_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId)) - { - MessageBox.Show(this, "请先在项目表中双击选择一个项目,再新建图号。", - "新建图号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string newTuhao = "新图号" + GetNextSeqNumber(TuhaoTableName, "图号", _currentProjectId); - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView9); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertTuhao(_currentProjectId, newTuhao, "", ""); - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - ReloadTuhaoByProject(_currentProjectId); - MoveLastRowBelowSelected(this.advancedDataGridView9, _tuhaoTable, selectedIndex, TuhaoTableName, _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建图号失败:\n" + ex.Message, - "新建图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = newTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", newTuhao); - _isReloading = false; - ReloadXianghaoByTuhao(_currentProjectId, newTuhao); - } - } - - private void MenuTuhao_Delete_Click(object sender, EventArgs e) - { - var rows = GetAllSelectedRows(this.advancedDataGridView9); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的图号。", - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var tuhaos = new List(); - foreach (var r in rows) - { - string th = GetCellValueAsString(r, "图号"); - if (!string.IsNullOrWhiteSpace(th) && !tuhaos.Contains(th)) tuhaos.Add(th); - } - if (tuhaos.Count == 0) - { - MessageBox.Show(this, "选中行没有图号,无法删除。", - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // ★ 收集选中图号行自己的框Handle - var frameHandles = new List(); - foreach (var r in rows) - { - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - // ★ 收集每个图号下所有箱号和元件的框Handle(级联删框) - foreach (string tuhao in tuhaos) - { - CollectFrameHandlesForTuhao(_currentProjectId, tuhao, frameHandles); - } - Log("[MenuTuhao_Delete] 删除图号: " + string.Join(",", tuhaos) + " 收集到框Handle数: " + frameHandles.Count); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string tuhao in tuhaos) - { - DeleteTuhao(_currentProjectId, tuhao); - if (!string.IsNullOrEmpty(tuhao)) - { - _xianghaoCache.Remove(tuhao); - var keysToRemove = new List(); - foreach (var key in _yuanjianCache.Keys) - if (key.StartsWith(tuhao + "\n")) keysToRemove.Add(key); - foreach (var key in keysToRemove) _yuanjianCache.Remove(key); - } - } - RenumberTable(_currentProjectId, TuhaoTableName); - ReloadTuhaoByProject(_currentProjectId); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重) - var tuhaoDistinct = new HashSet(frameHandles); - foreach (string h in tuhaoDistinct) - { - Log("[MenuTuhao_Delete] 准备删除框Handle: " + h); - DeleteFrameByHandle(h); - } - Log("[MenuTuhao_Delete] 框实体删除完成,共 " + tuhaoDistinct.Count + " 个"); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除图号失败:\n" + ex.Message, - "删除图号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally { _isReloading = false; } - } - - // ---------- 箱号菜单事件 ---------- - - private void MenuXianghao_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || string.IsNullOrWhiteSpace(_currentTuhao)) - { - MessageBox.Show(this, "请先选择图号,再新建箱号。", - "新建箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string rememberTuhao = _currentTuhao; - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView4); - string newXh = "新箱号" + GetXianghaoCount(_currentProjectId, _currentTuhao); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertXianghao(_currentProjectId, _currentTuhao, newXh, "", ""); - if (!string.IsNullOrEmpty(rememberTuhao)) _xianghaoCache.Remove(rememberTuhao); - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - if (_xianghaoTable != null) - MoveLastRowBelowSelected(this.advancedDataGridView4, _xianghaoTable, selectedIndex, - "\"" + _xianghaoTable.TableName + "\"", _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建箱号失败:\n" + ex.Message, - "新建箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = newXh; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", newXh); - _isReloading = false; - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, newXh); - } - } - - private void MenuXianghao_Delete_Click(object sender, EventArgs e) - { - var rows = GetAllSelectedRows(this.advancedDataGridView4); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的箱号。", - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var xhs = new List(); - foreach (var r in rows) - { - string xh = GetCellValueAsString(r, "箱号"); - if (!string.IsNullOrWhiteSpace(xh) && !xhs.Contains(xh)) xhs.Add(xh); - } - if (xhs.Count == 0) - { - MessageBox.Show(this, "选中行没有箱号,无法删除。", - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - // ★ 收集选中箱号行自己的框Handle - var frameHandles = new List(); - foreach (var r in rows) - { - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - // ★ 收集每个箱号下元件表的框Handle(级联删框) - foreach (string xh in xhs) - { - CollectFrameHandlesForXianghao(_currentProjectId, _currentTuhao, xh, frameHandles); - } - Log("[MenuXianghao_Delete] 删除箱号: " + string.Join(",", xhs) + " 图号=" + _currentTuhao + " 收集到框Handle数: " + frameHandles.Count); - string rememberTuhao = _currentTuhao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string xh in xhs) - { - DeleteXianghao(_currentProjectId, _currentTuhao, xh); - string yjKey = _currentTuhao + "\n" + xh; - _yuanjianCache.Remove(yjKey); - } - string xhTbl = GetXianghaoTableByIndex(_currentProjectId, _currentTuhao); - if (!string.IsNullOrEmpty(xhTbl)) - RenumberTable(_currentProjectId, "\"" + xhTbl + "\""); - if (!string.IsNullOrEmpty(_currentTuhao)) _xianghaoCache.Remove(_currentTuhao); - Log("[MenuXianghao_Delete] 开始 ReloadXianghaoByTuhao..."); - ReloadXianghaoByTuhao(_currentProjectId, _currentTuhao); - Log("[MenuXianghao_Delete] ReloadXianghaoByTuhao 完成,开始删除框实体..."); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重,避免重复删除) - var distinctHandles = new HashSet(frameHandles); - foreach (string h in distinctHandles) - { - Log("[MenuXianghao_Delete] 准备删除框Handle: " + h); - DeleteFrameByHandle(h); - } - Log("[MenuXianghao_Delete] 框实体删除完成,共 " + distinctHandles.Count + " 个"); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - Log("[MenuXianghao_Delete] 异常: " + ex.Message + "\n" + ex.StackTrace); - MessageBox.Show(this, "删除箱号失败:\n" + ex.Message, - "删除箱号", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - _isReloading = false; - } - } - - // ---------- 元件菜单事件 ---------- - - private void MenuYuanjian_New_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再新建元件。", - "新建元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - int selectedIndex = GetSelectedRowIndex(this.advancedDataGridView5); - string newName = "新元件" + GetYuanjianCount(_currentProjectId, _currentTuhao, _currentXianghao); - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - InsertYuanjian(_currentProjectId, _currentTuhao, _currentXianghao, newName); - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - if (_yuanjianTable != null) - MoveLastRowBelowSelected(this.advancedDataGridView5, _yuanjianTable, selectedIndex, - "\"" + _yuanjianTable.TableName + "\"", _currentProjectId); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "新建元件失败:\n" + ex.Message, - "新建元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - private void MenuYuanjian_Delete_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再删除元件。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var rows = GetAllSelectedRows(this.advancedDataGridView5); - if (rows == null || rows.Count == 0) - { - MessageBox.Show(this, "请先选择要删除的元件。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var seqs = new List(); - var frameHandles = new List(); - foreach (var r in rows) - { - string seq = GetCellValueAsString(r, "序号"); - if (!string.IsNullOrWhiteSpace(seq) && !seqs.Contains(seq)) seqs.Add(seq); - // ★ 收集元件行的框Handle - var drv = r.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) frameHandles.Add(h); - } - } - } - if (seqs.Count == 0) - { - MessageBox.Show(this, "选中行没有序号,无法删除。", - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - foreach (string seq in seqs) - DeleteYuanjian(_currentProjectId, _currentTuhao, _currentXianghao, seq); - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - // ★ 删除所有收集到的框实体(去重) - foreach (string h in new HashSet(frameHandles)) DeleteFrameByHandle(h); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除元件失败:\n" + ex.Message, - "删除元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - // ============================================================ - // 合并元件:把选中的多行元件合并为一行 - // · 元件名称:所有非空名称直接拼接(去重,不加符号) - // · 规格:所有非空规格直接拼接(去重,不加符号) - // · 数量:保持为 1(合并后是一个元件,数量不变) - // · 其他列(单位/系数/价格):取第一行 - // · 删除被合并的其他行,重新编号,保存刷新 - // ============================================================ - /// 按框Handle集合选中元件表中的行(多选,滚动到第一行)。 - private void SelectYuanjianRowsByFrameHandles(List frameHandles) - { - var dgv = this.advancedDataGridView5; - if (dgv == null || frameHandles == null || frameHandles.Count == 0) return; - try - { - dgv.MultiSelect = true; - if (dgv.SelectionMode != DataGridViewSelectionMode.RowHeaderSelect && - dgv.SelectionMode != DataGridViewSelectionMode.FullRowSelect) - { - dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - } - dgv.ClearSelection(); - DataGridViewRow first = null; - foreach (DataGridViewRow row in dgv.Rows) - { - var drv = row.DataBoundItem as DataRowView; - if (drv == null || drv.Row == null) continue; - if (!drv.Row.Table.Columns.Contains("框Handle")) continue; - object v = drv.Row["框Handle"]; - string h = v != null && v != DBNull.Value ? v.ToString().Trim() : ""; - if (!string.IsNullOrWhiteSpace(h) && frameHandles.Contains(h)) - { - row.Selected = true; - if (first == null) first = row; - } - } - if (first != null && first.DataGridView != null) - first.DataGridView.FirstDisplayedScrollingRowIndex = Math.Max(0, first.Index); - } - catch (Exception ex) { Log("[SelectYuanjianRows] " + ex.Message); } - } - - /// 网页转发的 F1:转到统一入口(焦点在网页时 WinForms 收不到按键)。 - private void OnF1FromBridge() - { - try { RunF1Merge(); } - catch (Exception ex) { Log("[F1桥接] " + ex.Message); } - } - - /// 网页转发的 F2:三个一组配对合并。 - private void OnF2FromBridge() - { - try { MergeYuanjianByGroup(3); } - catch (Exception ex) { Log("[F2桥接] " + ex.Message); } - } - - /// 网页转发的 F3:四个一组配对合并。 - private void OnF3FromBridge() - { - try { MergeYuanjianByGroup(4); } - catch (Exception ex) { Log("[F3桥接] " + ex.Message); } - } - - /// - /// F1:合并元件表中相邻的两个元件(按序号顺序)。 - /// · 选中 ≥2 行 → 合并前两行 - /// · 选中 1 行 → 与它的下一行合并 - /// · 未选中 → 合并第 1、2 行 - /// 合并时网页 CAD 里的蒙版同步合并(保留行蒙版扩大到并集)。 - /// - private void MergeAdjacentYuanjianByF1() - { - MergeYuanjianByGroup(2); - } - - /// 按 groupSize 分组合并选中元件(F1=两两,F2=三个一组)。 - private void MergeYuanjianByGroup(int groupSize) - { - // ★ 防抖(300ms):所有触发路径(按键/桥/过滤器)的统一闸门, - // 防止一次按键双跑两遍合并(第二遍因选中已清而弹误提示) - if ((DateTime.Now - _lastFKeyTime).TotalMilliseconds < 300) return; - _lastFKeyTime = DateTime.Now; - - var dgv = this.advancedDataGridView5; - if (dgv == null) return; - var rows = GetAllSelectedRows(dgv); - if (rows == null || rows.Count < groupSize) - { - MessageBox.Show(this, "请先选中至少 " + groupSize + " 行元件(扒元件后会自动全选)。", "合并元件", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - // ★ F1 = 两两配对批量合并(1+2、3+4、5+6...),一次处理完所有选中行; - // 只想合并单独一对时,只选中那一对两行即可。 - // 合并会刷新表格使行对象失效,所以先记下配对的框Handle,再用 Handle 逐对定位。 - var orderedHandles = new List(); - foreach (var r in rows) - { - orderedHandles.Add(GetFrameHandleOfRow(r)); - } - int groups = orderedHandles.Count / groupSize; - int merged = 0; - for (int i = 0; i < groups; i++) - { - var groupRows = new List(); - var groupHandles = new List(); - for (int k = 0; k < groupSize; k++) - { - string h = orderedHandles[i * groupSize + k]; - if (string.IsNullOrWhiteSpace(h)) { groupRows = null; break; } - var rowK = FindRowByFrameHandle(dgv, h); - if (rowK == null) { groupRows = null; break; } - groupRows.Add(rowK); - groupHandles.Add(h); - } - if (groupRows == null) continue; - // 组内若含重复行(同句柄)跳过 - if (new HashSet(groupHandles).Count != groupSize) continue; - MergeYuanjianRows(groupRows); - merged++; - } - Log("[F1批量] " + groupSize + " 个一组配对合并完成: " + merged + "/" + groups + " 组"); - } - - /// 读行的框Handle:优先 DataRow("框Handle"可能不在显示列,Cells 读不到)。 - private static string GetFrameHandleOfRow(DataGridViewRow row) - { - if (row == null) return ""; - var drv = row.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null && drv.Row.Table.Columns.Contains("框Handle")) - { - object v = drv.Row["框Handle"]; - return v == null || v == DBNull.Value ? "" : v.ToString().Trim(); - } - return GetCellValueAsString(row, "框Handle"); - } - - /// 按框Handle在元件表中找行(找不到返回 null)。 - private DataGridViewRow FindRowByFrameHandle(DataGridView dgv, string frameHandle) - { - if (string.IsNullOrWhiteSpace(frameHandle)) return null; - foreach (DataGridViewRow row in dgv.Rows) - { - if (row == null || row.IsNewRow) continue; - string h = GetFrameHandleOfRow(row); - if (!string.IsNullOrWhiteSpace(h) && h == frameHandle) return row; - } - return null; - } - - /// 合并指定行(按序号排序):第一行为合并目标,其余删除;蒙版同步合并。 - private void MergeYuanjianRows(List rows) - { - // 按序号排序(保证合并顺序与表格顺序一致) - rows.Sort((a, b) => - { - int ia = 0, ib = 0; - int.TryParse(GetCellValueAsString(a, "序号"), out ia); - int.TryParse(GetCellValueAsString(b, "序号"), out ib); - return ia.CompareTo(ib); - }); - - // 收集要合并的内容(直接拼接,不加任何符号) - var names = new List(); - var specs = new List(); - foreach (var r in rows) - { - string nm = GetCellValueAsString(r, "元件名称"); - if (!string.IsNullOrWhiteSpace(nm) && !names.Contains(nm)) names.Add(nm); - string sp = GetCellValueAsString(r, "规格"); - if (!string.IsNullOrWhiteSpace(sp) && !specs.Contains(sp)) specs.Add(sp); - } - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - string keepHandle = GetFrameHandleOfRow(rows[0]); - var absorbedHandles = new List(); - for (int i = 1; i < rows.Count; i++) - { - string h = GetFrameHandleOfRow(rows[i]); - if (!string.IsNullOrWhiteSpace(h)) absorbedHandles.Add(h); - } - - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - - if (_yuanjianTable == null || _yuanjianTable.Rows.Count == 0) - { - MessageBox.Show(this, "元件表为空,无法合并。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 取出选中行对应的 DataRow - var dataRows = new List(); - foreach (var dgvRow in rows) - { - var drv = dgvRow.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null) dataRows.Add(drv.Row); - } - if (dataRows.Count < 2) - { - MessageBox.Show(this, "无法获取选中行的数据,请重试。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 第一行作为合并目标,更新名称/规格(直接拼接,不加任何符号) - // 数量保持为 1(合并后是一个元件) - DataRow target = dataRows[0]; - if (_yuanjianTable.Columns.Contains("元件名称")) - target["元件名称"] = string.Join("", names); - if (_yuanjianTable.Columns.Contains("规格")) - target["规格"] = string.Join("", specs); - if (_yuanjianTable.Columns.Contains("数量")) - target["数量"] = "1"; - - // 删除其他被合并的行 - for (int i = 1; i < dataRows.Count; i++) - { - dataRows[i].Delete(); - } - - // 保存到数据库 - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + realTbl + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - } - - // ★ 网页 CAD 蒙版同步合并:保留行蒙版扩大到并集,被合并行蒙版移除 - if (!string.IsNullOrWhiteSpace(keepHandle) && absorbedHandles.Count > 0) - { - pdfbt.PdfBridge.MergeMasks(keepHandle, absorbedHandles); - Log("[MergeYuanjianRows] 蒙版合并: 保留=" + keepHandle); - } - - // 刷新缓存与表格 - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "合并元件失败:\n" + ex.Message, - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - _isReloading = false; - // ★ 合并后的行保持选中(连续按 F1 可继续与下一行合并): - // 延迟到刷新事件链走完再选,否则会被清掉 - if (!string.IsNullOrWhiteSpace(keepHandle)) - { - var kh = keepHandle; - BeginInvoke((Action)(() => - { - BeginInvoke((Action)(() => - { - SelectYuanjianRowsByFrameHandles(new List { kh }); - })); - })); - } - } - } - - private void MenuYuanjian_Merge_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(_currentProjectId) || - string.IsNullOrWhiteSpace(_currentTuhao) || - string.IsNullOrWhiteSpace(_currentXianghao)) - { - MessageBox.Show(this, "请先选择箱号,再合并元件。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - var rows = GetAllSelectedRows(this.advancedDataGridView5); - if (rows == null || rows.Count < 2) - { - MessageBox.Show(this, "请先选择至少两行要合并的元件(按住 Ctrl/Shift 多选)。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - // 按序号排序(保证合并顺序与表格顺序一致) - rows.Sort((a, b) => - { - int ia = 0, ib = 0; - int.TryParse(GetCellValueAsString(a, "序号"), out ia); - int.TryParse(GetCellValueAsString(b, "序号"), out ib); - return ia.CompareTo(ib); - }); - - // 收集要合并的内容(直接拼接,不加任何符号) - var names = new List(); - var specs = new List(); - foreach (var r in rows) - { - string nm = GetCellValueAsString(r, "元件名称"); - if (!string.IsNullOrWhiteSpace(nm) && !names.Contains(nm)) names.Add(nm); - string sp = GetCellValueAsString(r, "规格"); - if (!string.IsNullOrWhiteSpace(sp) && !specs.Contains(sp)) specs.Add(sp); - } - - string rememberTuhao = _currentTuhao; - string rememberXianghao = _currentXianghao; - try - { - _isReloading = true; - SaveAllQuoteTablesIfDirty(false); - - if (_yuanjianTable == null || _yuanjianTable.Rows.Count == 0) - { - MessageBox.Show(this, "元件表为空,无法合并。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 取出选中行对应的 DataRow - var dataRows = new List(); - foreach (var dgvRow in rows) - { - var drv = dgvRow.DataBoundItem as DataRowView; - if (drv != null && drv.Row != null) dataRows.Add(drv.Row); - } - if (dataRows.Count < 2) - { - MessageBox.Show(this, "无法获取选中行的数据,请重试。", - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 第一行作为合并目标,更新名称/规格(直接拼接,不加符号) - // 数量保持为 1(合并后是一个元件) - DataRow target = dataRows[0]; - if (_yuanjianTable.Columns.Contains("元件名称")) - target["元件名称"] = string.Join("", names); - if (_yuanjianTable.Columns.Contains("规格")) - target["规格"] = string.Join("", specs); - if (_yuanjianTable.Columns.Contains("数量")) - target["数量"] = "1"; - - // ★ 收集被合并行(第2行起)的框Handle,合并后删除这些框 - var mergedFrameHandles = new List(); - if (_yuanjianTable.Columns.Contains("框Handle")) - { - for (int i = 1; i < dataRows.Count; i++) - { - object v = dataRows[i]["框Handle"]; - if (v != null && v != DBNull.Value) - { - string h = v.ToString().Trim(); - if (!string.IsNullOrWhiteSpace(h)) mergedFrameHandles.Add(h); - } - } - } - - // 删除其他被合并的行 - for (int i = 1; i < dataRows.Count; i++) - { - dataRows[i].Delete(); - } - - // 保存到数据库 - string realTbl = GetYuanjianTableByIndex(_currentProjectId, _currentTuhao, _currentXianghao); - if (!string.IsNullOrEmpty(realTbl)) - { - SaveTableToDatabase(_yuanjianTable, _currentProjectId, - "\"" + realTbl + "\"", null, null, true); - _yuanjianTable.AcceptChanges(); - RenumberTable(_currentProjectId, "\"" + realTbl + "\""); - } - - // ★ 删除被合并行的框实体 - foreach (string h in mergedFrameHandles) DeleteFrameByHandle(h); - // ★ 保存DWG,确保删框操作持久化 - SaveCurrentDwg(); - - // 刷新缓存与表格 - string cacheKey = _currentTuhao + "\n" + _currentXianghao; - _yuanjianCache.Remove(cacheKey); - ReloadYuanjianByXianghao(_currentProjectId, _currentTuhao, _currentXianghao); - RecalcAllAfterReload(); - } - catch (Exception ex) - { - MessageBox.Show(this, "合并元件失败:\n" + ex.Message, - "合并元件", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - _currentTuhao = rememberTuhao; - _currentXianghao = rememberXianghao; - SelectRowByValue(this.advancedDataGridView9, "图号", rememberTuhao); - SelectRowByValue(this.advancedDataGridView4, "箱号", rememberXianghao); - _isReloading = false; - } - } - - // ============================================================ - // 工具栏:新建项目 / 删除项目 / 导出数据 - // ============================================================ - - private void toolStripButton5_Click(object sender, EventArgs e) - { - // 用自定义对话框收集项目信息字段(无主项目的"新建项目"窗体可用) - var fields = ShowNewProjectDialog(); - if (fields == null) return; - try - { - int affected = InsertProjectToDatabase(fields); - if (affected <= 0) - { - MessageBox.Show(this, "未写入任何字段,请检查输入。", - "新建项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - ReloadProjectsFromDatabase(); - ApplyPriceFormat(this.advancedDataGridView6, _项目小数位文本); - } - catch (Exception ex) - { - MessageBox.Show(this, "保存项目失败:\n" + ex.Message, - "新建项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - /// 弹出新建项目窗口,收集项目信息 + 价格格式化配置。 - private Dictionary ShowNewProjectDialog() - { - string dbPath = GetDbFullPath(ProjectsDbPath); - using (var dlg = new 新建项目(dbPath, ProjectsTableName)) - { - if (dlg.ShowDialog(this) != DialogResult.OK) return null; - return dlg.GetInputValues(); - } - } - - private void toolStripButton6_Click(object sender, EventArgs e) - { - DataGridViewRow row = GetFirstSelectedProjectRow(); - if (row == null) - { - MessageBox.Show(this, "请先在项目表格中选择要删除的项目。", - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string projectId = GetCellValueAsString(row, "项目编号"); - if (string.IsNullOrWhiteSpace(projectId)) - { - MessageBox.Show(this, "选中行没有“项目编号”,无法定位要删除的数据库记录。", - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - DialogResult dr = MessageBox.Show(this, - "确定要删除项目编号为 “" + projectId + "” 的项目吗?\n" + - "该项目下的所有图号/箱号/元件数据也会一并删除!\n此操作不可恢复。", - "删除项目", MessageBoxButtons.YesNo, MessageBoxIcon.Question, - MessageBoxDefaultButton.Button2); - if (dr != DialogResult.Yes) return; - try - { - int affected = DeleteProjectFromDatabase(projectId); - CascadeDeleteByProject(projectId); - _currentProjectId = ""; - _currentTuhao = ""; - _currentXianghao = ""; - _xianghaoCache.Clear(); - _yuanjianCache.Clear(); - _tuhaoTable = null; - ReloadProjectsFromDatabase(); - ReloadTuhaoByProject(""); - } - catch (Exception ex) - { - MessageBox.Show(this, "删除项目失败:\n" + ex.Message, - "删除项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - // ---------- 项目表查找(button28)---------- - - private void button28_Click(object sender, EventArgs e) - { - string field = this.comboBox2.Text == null ? "" : this.comboBox2.Text.Trim(); - string colName = MapSearchFieldToColumn(field); - if (string.IsNullOrEmpty(colName)) - { - MessageBox.Show(this, - "请先在搜索条件下拉框中选择有效的搜索字段(项目名称 / 项目编号 / 客户名称)。", - "查找", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - string keyword = this.textBox1.Text == null ? "" : this.textBox1.Text.Trim(); - DataTable table = this.advancedDataGridView6.DataSource as DataTable; - if (table == null) - { - MessageBox.Show(this, "项目表暂无数据,无法搜索。", "查找", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - if (keyword.Length == 0) - { - if (table.DefaultView.RowFilter.Length > 0) table.DefaultView.RowFilter = ""; - return; - } - string escaped = EscapeLikeValue(keyword); - try { table.DefaultView.RowFilter = "[" + colName + "] LIKE '%" + escaped + "%'"; } - catch (System.Data.SyntaxErrorException ex) - { - MessageBox.Show(this, "搜索条件解析失败,请检查输入的关键词。\n详情:" + ex.Message, - "查找", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - if (table.DefaultView.Count == 0) - { - MessageBox.Show(this, "没有找到 " + field + " 包含 “" + keyword + "” 的项目。", - "查找", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - - private static string MapSearchFieldToColumn(string field) - { - if (string.IsNullOrEmpty(field)) return ""; - string f = field.Replace(" ", "").Trim(); - if (f == "项目名称" || f == "名称") return "项目名称"; - if (f == "项目编号" || f == "编号") return "项目编号"; - if (f == "客户名称" || f == "客户") return "客户名称"; - return ""; - } - - private static string EscapeLikeValue(string value) - { - if (string.IsNullOrEmpty(value)) return ""; - var sb = new System.Text.StringBuilder(value.Length * 2); - foreach (char c in value) - { - if (c == '\'') sb.Append("''"); - else if (c == '%' || c == '_' || c == '[' || c == ']') sb.Append('[').Append(c).Append(']'); - else sb.Append(c); - } - return sb.ToString(); - } - - // ---------- 导出数据(toolStripButton1)---------- - - private void toolStripButton1_Click(object sender, EventArgs e) - { - string pid = ""; - try - { - var projects = ReadAllProjectsFromDatabase(); - if (projects == null || projects.Count == 0) - { - MessageBox.Show(this, "项目列表为空,无项目可导出。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - if (projects.Count == 1) - { - pid = projects[0].ContainsKey("项目编号") ? (projects[0]["项目编号"] ?? "").ToString() : ""; - } - else - { - pid = PickProjectDialog(projects); - if (string.IsNullOrWhiteSpace(pid)) return; - } - if (string.IsNullOrWhiteSpace(pid)) - { - MessageBox.Show(this, "未能确定要导出的项目编号。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - // 先保存当前项目的所有改动 - SaveAllToDatabaseSilent(); - - string dbPath = GetQuoteDbPath(pid); - if (!File.Exists(dbPath)) - { - MessageBox.Show(this, "项目数据库文件不存在:\n" + dbPath, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - var meta = ReadProjectMetaData(pid); - if (meta == null) - { - MessageBox.Show(this, "项目元数据读取失败,项目编号:" + pid, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - string projName = meta.ContainsKey("项目名称") ? (meta["项目名称"] ?? "").ToString() : ""; - string safeName = MakeSafeFileName(projName + "_" + pid); - string defaultFileName = safeName + "_" + DateTime.Now.ToString("yyyyMMdd") + ".zip"; - - string initialDir = ""; - try - { - string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - if (!string.IsNullOrEmpty(desktop) && Directory.Exists(desktop)) initialDir = desktop; - } - catch { } - if (string.IsNullOrEmpty(initialDir)) - { - try - { - string docs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - if (!string.IsNullOrEmpty(docs) && Directory.Exists(docs)) initialDir = docs; - } - catch { } - } - - // ★ 打包到临时 zip(不弹保存对话框,直接联动主窗口) - string tempZip = Path.Combine(Path.GetTempPath(), "cadcj_导出_" + Guid.NewGuid().ToString("N") + ".zip"); - string tempDir = Path.Combine(Path.GetTempPath(), "cadcj_导出_" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(tempDir); - try - { - // 复制 db(用 SQL ATTACH 绕开文件锁,兜底 File.Copy) - string dstDb = Path.Combine(tempDir, "项目" + MakeSafeFileName(pid) + ".db"); - BackupSQLiteDb(dbPath, dstDb); - - // 写 meta.json - var sb = new System.Text.StringBuilder(); - sb.Append("{\n \"项目编号\": \""); - sb.Append(EscapeJsonString(pid)); - sb.Append("\",\n \"字段\": {"); - bool firstKv = true; - foreach (var kv in meta) - { - if (firstKv) firstKv = false; else sb.Append(","); - sb.Append("\n \""); - sb.Append(EscapeJsonString(kv.Key)); - sb.Append("\": \""); - sb.Append(EscapeJsonString((kv.Value ?? "").ToString())); - sb.Append("\""); - } - sb.Append("\n }\n}"); - File.WriteAllText(Path.Combine(tempDir, "meta.json"), sb.ToString(), new System.Text.UTF8Encoding(false)); - - // 打包 zip - if (File.Exists(tempZip)) File.Delete(tempZip); - System.IO.Compression.ZipFile.CreateFromDirectory(tempDir, tempZip); - - // ★ 查找主窗口 exe(cadcj 目录的上级目录) - string mainExePath = null; - try - { - string pluginDir = Path.GetDirectoryName( - new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath); - string parentDir = Path.GetFullPath(Path.Combine(pluginDir, "..")); - string candidate = Path.Combine(parentDir, "成套报价软件.exe"); - if (File.Exists(candidate)) mainExePath = candidate; - } - catch { } - - if (!string.IsNullOrEmpty(mainExePath)) - { - // ★ 启动主窗口并传递 zip 路径,主窗口自动导入并打开项目 - var psi = new System.Diagnostics.ProcessStartInfo - { - FileName = mainExePath, - Arguments = "\"" + tempZip + "\"", - UseShellExecute = true, - }; - System.Diagnostics.Process.Start(psi); - MessageBox.Show(this, - "已发送到主窗口!\n\n项目:" + projName + " (" + pid + ")\n主程序已打开该项目(若主程序未开会自动启动)。", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - else - { - // ★ 找不到主窗口 exe,退回到保存对话框模式 - using (var sfd = new SaveFileDialog - { - Title = "导出项目", - Filter = "项目包 (*.zip)|*.zip", - FileName = defaultFileName, - RestoreDirectory = true, - }) - { - if (!string.IsNullOrEmpty(initialDir)) sfd.InitialDirectory = initialDir; - if (sfd.ShowDialog(this) != DialogResult.OK) return; - string zipPath = sfd.FileName; - File.Copy(tempZip, zipPath, true); - MessageBox.Show(this, - "导出成功!\n\n项目:" + projName + " (" + pid + ")\n文件:" + zipPath + - "\n\n(未找到主窗口程序,已保存为zip文件,可手动导入)", - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - } - finally - { - try { Directory.Delete(tempDir, true); } catch { } - // 临时 zip 不立即删除(主窗口可能正在读取) - } - } - catch (Exception ex) - { - MessageBox.Show(this, "导出失败:\n" + ex.Message, - "导出项目", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private System.Collections.Generic.List _keepMultiHooks; - - private void HookKeepMulti(System.Windows.Forms.DataGridView dgv) - { - if (dgv == null) return; - var hook = new AdgvMsgHook(dgv); - _keepMultiHooks.Add(hook); // 存字段防 GC - } - - /// - /// ADGV 右键多选保持钩子(NativeWindow):吞掉"右键点已选中行"的 WM_RBUTTONDOWN, - /// 多选集合不被清空;右键菜单由 WM_CONTEXTMENU 正常弹出(与原 AdgvKeepMulti 子类语义一致)。 - /// - private class AdgvMsgHook : System.Windows.Forms.NativeWindow - { - private const int WM_RBUTTONDOWN = 0x0204; - private readonly System.Windows.Forms.DataGridView _dgv; - - public AdgvMsgHook(System.Windows.Forms.DataGridView dgv) - { - _dgv = dgv; - dgv.HandleCreated += (s, e) => AssignHandle(dgv.Handle); - dgv.HandleDestroyed += (s, e) => ReleaseHandle(); - if (dgv.IsHandleCreated) AssignHandle(dgv.Handle); - } - - protected override void WndProc(ref System.Windows.Forms.Message m) - { - if (m.Msg == WM_RBUTTONDOWN && _dgv != null && _dgv.MultiSelect) - { - try - { - int lp = m.LParam.ToInt32(); - var pos = new System.Drawing.Point(lp & 0xFFFF, (lp >> 16) & 0xFFFF); - var hit = _dgv.HitTest(pos.X, pos.Y); - if (hit.RowIndex >= 0 && _dgv.SelectedRows != null) - { - foreach (System.Windows.Forms.DataGridViewRow r in _dgv.SelectedRows) - { - if (r != null && r.Index == hit.RowIndex) - return; // ★ 吞掉:ADGV 不清多选 - } - } - } - catch { /* 异常时退回默认行为 */ } - } - base.WndProc(ref m); - } - } - - /// 用 SQL ATTACH 复制 SQLite 库,兜底 File.Copy。 - private void BackupSQLiteDb(string srcDbPath, string dstDbPath) - { - try { if (File.Exists(dstDbPath)) File.Delete(dstDbPath); } catch { } - Exception sqlErr = null; - try - { - using (var srcConn = new System.Data.SQLite.SQLiteConnection( - "Data Source=" + srcDbPath + ";Version=3;Pooling=False;ReadOnly=True;")) - { - srcConn.Open(); - using (var att = new System.Data.SQLite.SQLiteCommand("ATTACH DATABASE @path AS dst;", srcConn)) - { - att.Parameters.AddWithValue("@path", dstDbPath); - att.ExecuteNonQuery(); - } - string selAll = "SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"; - var tables = new List>(); - using (var sel = new System.Data.SQLite.SQLiteCommand(selAll, srcConn)) - using (var rd = sel.ExecuteReader()) - { - while (rd.Read()) - { - string tn = rd.IsDBNull(0) ? "" : rd.GetString(0); - string sql = rd.IsDBNull(1) ? "" : rd.GetString(1); - if (!string.IsNullOrEmpty(tn)) tables.Add(new KeyValuePair(tn, sql)); - } - } - foreach (var kv in tables) - { - string tn = kv.Key; - string sql = kv.Value; - if (!string.IsNullOrEmpty(sql)) - { - string dstSql = sql.Replace("CREATE TABLE " + tn, "CREATE TABLE dst." + tn); - using (var c = new System.Data.SQLite.SQLiteCommand(dstSql, srcConn)) c.ExecuteNonQuery(); - } - using (var c = new System.Data.SQLite.SQLiteCommand( - "INSERT INTO dst.\"" + tn + "\" SELECT * FROM main.\"" + tn + "\";", srcConn)) - c.ExecuteNonQuery(); - } - using (var det = new System.Data.SQLite.SQLiteCommand("DETACH DATABASE dst;", srcConn)) - det.ExecuteNonQuery(); - return; - } - } - catch (Exception ex) { sqlErr = ex; } - // 兜底:File.Copy - try { System.Data.SQLite.SQLiteConnection.ClearAllPools(); } catch { } - try { if (File.Exists(dstDbPath)) File.Delete(dstDbPath); } catch { } - File.Copy(srcDbPath, dstDbPath, true); - } - - /// 弹出一个简单对话框,让用户从项目列表中选一个项目,返回项目编号。 - private string PickProjectDialog(List> projects) - { - try - { - using (var dlg = new Form - { - Text = "选择要导出的项目", - StartPosition = FormStartPosition.CenterParent, - FormBorderStyle = FormBorderStyle.FixedDialog, - MaximizeBox = false, - MinimizeBox = false, - ClientSize = new Size(520, 360), - }) - { - var lbl = new Label - { - Text = "请选择要导出的项目:", - Location = new Point(12, 12), - Size = new Size(496, 23), - TextAlign = ContentAlignment.MiddleLeft, - }; - dlg.Controls.Add(lbl); - var lv = new ListView - { - Location = new Point(12, 40), - Size = new Size(496, 260), - View = View.Details, - FullRowSelect = true, - MultiSelect = false, - HideSelection = false, - }; - lv.Columns.Add("项目编号", 100); - lv.Columns.Add("项目名称", 160); - lv.Columns.Add("客户名称", 130); - lv.Columns.Add("项目日期", 90); - foreach (var p in projects) - { - string bh = p.ContainsKey("项目编号") ? (p["项目编号"] ?? "").ToString() : ""; - string mc = p.ContainsKey("项目名称") ? (p["项目名称"] ?? "").ToString() : ""; - string kh = p.ContainsKey("客户名称") ? (p["客户名称"] ?? "").ToString() : ""; - string rq = p.ContainsKey("项目日期") ? (p["项目日期"] ?? "").ToString() : ""; - var item = new ListViewItem(bh); - item.SubItems.Add(mc); - item.SubItems.Add(kh); - item.SubItems.Add(rq); - lv.Items.Add(item); - } - if (lv.Items.Count > 0) lv.Items[0].Selected = true; - dlg.Controls.Add(lv); - var btnOk = new Button - { - Text = "导出选中项", - DialogResult = DialogResult.OK, - Location = new Point(330, 310), - Size = new Size(85, 28), - }; - dlg.Controls.Add(btnOk); - var btnCancel = new Button - { - Text = "取消", - DialogResult = DialogResult.Cancel, - Location = new Point(425, 310), - Size = new Size(75, 28), - }; - dlg.Controls.Add(btnCancel); - dlg.AcceptButton = btnOk; - dlg.CancelButton = btnCancel; - if (dlg.ShowDialog(this) == DialogResult.OK && lv.SelectedItems.Count > 0) - return lv.SelectedItems[0].Text; - return ""; - } - } - catch { return ""; } - } - - // ============================================================ - // 窗体关闭:回写当前项目的所有改动 - // ============================================================ - - private void Form3_Disposed(object sender, EventArgs e) - { - try { SaveAllToDatabaseSilent(); } - catch { } - - // ★ 取消 CadBridge 事件订阅,避免事件泄漏 - try - { - pdfbt.PdfBridge.EntityErased -= Database_ObjectErased; - pdfbt.PdfBridge.PaPicked -= OnPaTextsPicked; - pdfbt.PdfBridge.F1Requested -= OnF1FromBridge; - pdfbt.PdfBridge.F2Requested -= OnF2FromBridge; - pdfbt.PdfBridge.F3Requested -= OnF3FromBridge; - } - catch { } - } - } -} diff --git a/pdfbt/Plugin/Form3.resx b/pdfbt/Plugin/Form3.resx deleted file mode 100644 index 1af7de1..0000000 --- a/pdfbt/Plugin/Form3.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/pdfbt/Plugin/PaTypes.cs b/pdfbt/Plugin/PaTypes.cs deleted file mode 100644 index 3c4e287..0000000 --- a/pdfbt/Plugin/PaTypes.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ============================================================ -// 扒图数据类型(与原 cadcj 插件 / 网页端 cadbridge.ts 保持一致) -// ============================================================ -using System.Collections.Generic; - -namespace MyApp -{ - /// - /// 扒数据模式:图号/箱号/元件 - /// - public enum PaMode - { - Tuhao, // 扒图号 - Xianghao, // 扒箱号 - Yuanjian // 扒元件 - } - - /// - /// 扒图结果:一条文本 + 它对应的彩色框的 Handle(句柄字符串) - /// 用于关联表格数据行与网页 CAD 框实体,实现点击行定位、删除行删框。 - /// ★ TextHandle:源文本实体自身的 Handle,用于判断"是否同一个文本"。 - /// - public class PaTextResult - { - public string Text; - public string FrameHandle; - public string TextHandle = ""; - } -} diff --git a/pdfbt/Plugin/新建项目.Designer.cs b/pdfbt/Plugin/新建项目.Designer.cs deleted file mode 100644 index d5641d3..0000000 --- a/pdfbt/Plugin/新建项目.Designer.cs +++ /dev/null @@ -1,609 +0,0 @@ -namespace MyApp -{ - public partial class 新建项目 : System.Windows.Forms.Form - { - /// 必需的设计器变量。 - private System.ComponentModel.IContainer components = null; - - /// 清理正在使用的资源。 - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows 窗体设计器生成的代码 - - private void InitializeComponent() - { - this.lbl项目编号 = new System.Windows.Forms.Label(); - this.txt项目编号 = new System.Windows.Forms.TextBox(); - this.lbl项目日期 = new System.Windows.Forms.Label(); - this.txt项目日期 = new System.Windows.Forms.TextBox(); - this.lbl项目名称 = new System.Windows.Forms.Label(); - this.txt项目名称 = new System.Windows.Forms.TextBox(); - this.lbl客户名称 = new System.Windows.Forms.Label(); - this.txt客户名称 = new System.Windows.Forms.TextBox(); - this.btn选择客户 = new System.Windows.Forms.Button(); - this.lbl客户地址 = new System.Windows.Forms.Label(); - this.txt客户地址 = new System.Windows.Forms.TextBox(); - this.lbl联系人 = new System.Windows.Forms.Label(); - this.txt联系人 = new System.Windows.Forms.TextBox(); - this.lbl联系电话 = new System.Windows.Forms.Label(); - this.txt联系电话 = new System.Windows.Forms.TextBox(); - this.lbl成套厂名称 = new System.Windows.Forms.Label(); - this.txt成套厂名称 = new System.Windows.Forms.TextBox(); - this.lbl成套厂地址 = new System.Windows.Forms.Label(); - this.txt成套厂地址 = new System.Windows.Forms.TextBox(); - this.lbl成套厂联系人 = new System.Windows.Forms.Label(); - this.txt成套厂联系人 = new System.Windows.Forms.TextBox(); - this.lbl成套厂联系电话 = new System.Windows.Forms.Label(); - this.txt成套厂联系电话 = new System.Windows.Forms.TextBox(); - this.lbl报出方式 = new System.Windows.Forms.Label(); - this.cmb报出方式 = new System.Windows.Forms.ComboBox(); - this.lbl箱柜模板 = new System.Windows.Forms.Label(); - this.cmb箱柜模板 = new System.Windows.Forms.ComboBox(); - this.lbl单台价格 = new System.Windows.Forms.Label(); - this.cmb单台价格 = new System.Windows.Forms.ComboBox(); - this.lbl项目总价 = new System.Windows.Forms.Label(); - this.lbl备注 = new System.Windows.Forms.Label(); - this.txt备注 = new System.Windows.Forms.TextBox(); - this.btn确定 = new System.Windows.Forms.Button(); - this.btn取消 = new System.Windows.Forms.Button(); - this.comboBox1 = new System.Windows.Forms.ComboBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.comboBox2 = new System.Windows.Forms.ComboBox(); - this.cmb项目总价 = new System.Windows.Forms.ComboBox(); - this.SuspendLayout(); - // - // lbl项目编号 - // - this.lbl项目编号.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目编号.Font = new System.Drawing.Font("宋体", 9F); - this.lbl项目编号.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目编号.Location = new System.Drawing.Point(20, 25); - this.lbl项目编号.Name = "lbl项目编号"; - this.lbl项目编号.Size = new System.Drawing.Size(70, 23); - this.lbl项目编号.TabIndex = 0; - this.lbl项目编号.Text = "项目编号:"; - this.lbl项目编号.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt项目编号 - // - this.txt项目编号.BackColor = System.Drawing.SystemColors.Window; - this.txt项目编号.Font = new System.Drawing.Font("宋体", 9F); - this.txt项目编号.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目编号.Location = new System.Drawing.Point(95, 25); - this.txt项目编号.Name = "txt项目编号"; - this.txt项目编号.Size = new System.Drawing.Size(220, 28); - this.txt项目编号.TabIndex = 0; - // - // lbl项目日期 - // - this.lbl项目日期.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目日期.Font = new System.Drawing.Font("宋体", 9F); - this.lbl项目日期.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目日期.Location = new System.Drawing.Point(380, 28); - this.lbl项目日期.Name = "lbl项目日期"; - this.lbl项目日期.Size = new System.Drawing.Size(70, 18); - this.lbl项目日期.TabIndex = 1; - this.lbl项目日期.Text = "项目日期:"; - // - // txt项目日期 - // - this.txt项目日期.BackColor = System.Drawing.SystemColors.Window; - this.txt项目日期.Font = new System.Drawing.Font("宋体", 9F); - this.txt项目日期.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目日期.Location = new System.Drawing.Point(455, 25); - this.txt项目日期.Name = "txt项目日期"; - this.txt项目日期.Size = new System.Drawing.Size(210, 28); - this.txt项目日期.TabIndex = 1; - // - // lbl项目名称 - // - this.lbl项目名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目名称.Font = new System.Drawing.Font("宋体", 9F); - this.lbl项目名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目名称.Location = new System.Drawing.Point(20, 55); - this.lbl项目名称.Name = "lbl项目名称"; - this.lbl项目名称.Size = new System.Drawing.Size(70, 23); - this.lbl项目名称.TabIndex = 2; - this.lbl项目名称.Text = "项目名称:"; - this.lbl项目名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt项目名称 - // - this.txt项目名称.BackColor = System.Drawing.SystemColors.Window; - this.txt项目名称.Font = new System.Drawing.Font("宋体", 9F); - this.txt项目名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt项目名称.Location = new System.Drawing.Point(95, 55); - this.txt项目名称.Name = "txt项目名称"; - this.txt项目名称.Size = new System.Drawing.Size(570, 28); - this.txt项目名称.TabIndex = 2; - // - // lbl客户名称 - // - this.lbl客户名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl客户名称.Font = new System.Drawing.Font("宋体", 9F); - this.lbl客户名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl客户名称.Location = new System.Drawing.Point(20, 85); - this.lbl客户名称.Name = "lbl客户名称"; - this.lbl客户名称.Size = new System.Drawing.Size(70, 23); - this.lbl客户名称.TabIndex = 3; - this.lbl客户名称.Text = "客户名称:"; - this.lbl客户名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt客户名称 - // - this.txt客户名称.BackColor = System.Drawing.SystemColors.Window; - this.txt客户名称.Font = new System.Drawing.Font("宋体", 9F); - this.txt客户名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt客户名称.Location = new System.Drawing.Point(95, 85); - this.txt客户名称.Name = "txt客户名称"; - this.txt客户名称.Size = new System.Drawing.Size(479, 28); - this.txt客户名称.TabIndex = 3; - // - // btn选择客户 - // - this.btn选择客户.BackColor = System.Drawing.SystemColors.Control; - this.btn选择客户.Font = new System.Drawing.Font("宋体", 9F); - this.btn选择客户.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn选择客户.Location = new System.Drawing.Point(580, 85); - this.btn选择客户.Name = "btn选择客户"; - this.btn选择客户.Size = new System.Drawing.Size(85, 28); - this.btn选择客户.TabIndex = 4; - this.btn选择客户.Text = "选择客户"; - this.btn选择客户.UseVisualStyleBackColor = true; - // - // lbl客户地址 - // - this.lbl客户地址.BackColor = System.Drawing.SystemColors.Control; - this.lbl客户地址.Font = new System.Drawing.Font("宋体", 9F); - this.lbl客户地址.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl客户地址.Location = new System.Drawing.Point(20, 115); - this.lbl客户地址.Name = "lbl客户地址"; - this.lbl客户地址.Size = new System.Drawing.Size(70, 23); - this.lbl客户地址.TabIndex = 5; - this.lbl客户地址.Text = "客户地址:"; - this.lbl客户地址.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt客户地址 - // - this.txt客户地址.BackColor = System.Drawing.SystemColors.Window; - this.txt客户地址.Font = new System.Drawing.Font("宋体", 9F); - this.txt客户地址.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt客户地址.Location = new System.Drawing.Point(95, 115); - this.txt客户地址.Name = "txt客户地址"; - this.txt客户地址.Size = new System.Drawing.Size(570, 28); - this.txt客户地址.TabIndex = 5; - // - // lbl联系人 - // - this.lbl联系人.BackColor = System.Drawing.SystemColors.Control; - this.lbl联系人.Font = new System.Drawing.Font("宋体", 9F); - this.lbl联系人.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl联系人.Location = new System.Drawing.Point(30, 145); - this.lbl联系人.Name = "lbl联系人"; - this.lbl联系人.Size = new System.Drawing.Size(60, 23); - this.lbl联系人.TabIndex = 6; - this.lbl联系人.Text = "联系人:"; - this.lbl联系人.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt联系人 - // - this.txt联系人.BackColor = System.Drawing.SystemColors.Window; - this.txt联系人.Font = new System.Drawing.Font("宋体", 9F); - this.txt联系人.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt联系人.Location = new System.Drawing.Point(95, 145); - this.txt联系人.Name = "txt联系人"; - this.txt联系人.Size = new System.Drawing.Size(220, 28); - this.txt联系人.TabIndex = 6; - // - // lbl联系电话 - // - this.lbl联系电话.BackColor = System.Drawing.SystemColors.Control; - this.lbl联系电话.Font = new System.Drawing.Font("宋体", 9F); - this.lbl联系电话.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl联系电话.Location = new System.Drawing.Point(380, 145); - this.lbl联系电话.Name = "lbl联系电话"; - this.lbl联系电话.Size = new System.Drawing.Size(70, 21); - this.lbl联系电话.TabIndex = 7; - this.lbl联系电话.Text = "联系电话:"; - // - // txt联系电话 - // - this.txt联系电话.BackColor = System.Drawing.SystemColors.Window; - this.txt联系电话.Font = new System.Drawing.Font("宋体", 9F); - this.txt联系电话.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt联系电话.Location = new System.Drawing.Point(455, 145); - this.txt联系电话.Name = "txt联系电话"; - this.txt联系电话.Size = new System.Drawing.Size(210, 28); - this.txt联系电话.TabIndex = 7; - // - // lbl成套厂名称 - // - this.lbl成套厂名称.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂名称.Font = new System.Drawing.Font("宋体", 9F); - this.lbl成套厂名称.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂名称.Location = new System.Drawing.Point(10, 175); - this.lbl成套厂名称.Name = "lbl成套厂名称"; - this.lbl成套厂名称.Size = new System.Drawing.Size(80, 23); - this.lbl成套厂名称.TabIndex = 8; - this.lbl成套厂名称.Text = "成套厂名称:"; - this.lbl成套厂名称.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt成套厂名称 - // - this.txt成套厂名称.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂名称.Font = new System.Drawing.Font("宋体", 9F); - this.txt成套厂名称.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂名称.Location = new System.Drawing.Point(95, 175); - this.txt成套厂名称.Name = "txt成套厂名称"; - this.txt成套厂名称.Size = new System.Drawing.Size(570, 28); - this.txt成套厂名称.TabIndex = 8; - // - // lbl成套厂地址 - // - this.lbl成套厂地址.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂地址.Font = new System.Drawing.Font("宋体", 9F); - this.lbl成套厂地址.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂地址.Location = new System.Drawing.Point(10, 205); - this.lbl成套厂地址.Name = "lbl成套厂地址"; - this.lbl成套厂地址.Size = new System.Drawing.Size(80, 23); - this.lbl成套厂地址.TabIndex = 9; - this.lbl成套厂地址.Text = "成套厂地址:"; - this.lbl成套厂地址.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt成套厂地址 - // - this.txt成套厂地址.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂地址.Font = new System.Drawing.Font("宋体", 9F); - this.txt成套厂地址.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂地址.Location = new System.Drawing.Point(95, 205); - this.txt成套厂地址.Name = "txt成套厂地址"; - this.txt成套厂地址.Size = new System.Drawing.Size(570, 28); - this.txt成套厂地址.TabIndex = 9; - // - // lbl成套厂联系人 - // - this.lbl成套厂联系人.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂联系人.Font = new System.Drawing.Font("宋体", 9F); - this.lbl成套厂联系人.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂联系人.Location = new System.Drawing.Point(30, 235); - this.lbl成套厂联系人.Name = "lbl成套厂联系人"; - this.lbl成套厂联系人.Size = new System.Drawing.Size(60, 23); - this.lbl成套厂联系人.TabIndex = 10; - this.lbl成套厂联系人.Text = "联系人:"; - this.lbl成套厂联系人.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt成套厂联系人 - // - this.txt成套厂联系人.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂联系人.Font = new System.Drawing.Font("宋体", 9F); - this.txt成套厂联系人.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂联系人.Location = new System.Drawing.Point(95, 235); - this.txt成套厂联系人.Name = "txt成套厂联系人"; - this.txt成套厂联系人.Size = new System.Drawing.Size(220, 28); - this.txt成套厂联系人.TabIndex = 10; - // - // lbl成套厂联系电话 - // - this.lbl成套厂联系电话.BackColor = System.Drawing.SystemColors.Control; - this.lbl成套厂联系电话.Font = new System.Drawing.Font("宋体", 9F); - this.lbl成套厂联系电话.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl成套厂联系电话.Location = new System.Drawing.Point(380, 235); - this.lbl成套厂联系电话.Name = "lbl成套厂联系电话"; - this.lbl成套厂联系电话.Size = new System.Drawing.Size(70, 21); - this.lbl成套厂联系电话.TabIndex = 11; - this.lbl成套厂联系电话.Text = "联系电话:"; - // - // txt成套厂联系电话 - // - this.txt成套厂联系电话.BackColor = System.Drawing.SystemColors.Window; - this.txt成套厂联系电话.Font = new System.Drawing.Font("宋体", 9F); - this.txt成套厂联系电话.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt成套厂联系电话.Location = new System.Drawing.Point(455, 232); - this.txt成套厂联系电话.Name = "txt成套厂联系电话"; - this.txt成套厂联系电话.Size = new System.Drawing.Size(210, 28); - this.txt成套厂联系电话.TabIndex = 11; - // - // lbl报出方式 - // - this.lbl报出方式.BackColor = System.Drawing.SystemColors.Control; - this.lbl报出方式.Font = new System.Drawing.Font("宋体", 9F); - this.lbl报出方式.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl报出方式.Location = new System.Drawing.Point(20, 265); - this.lbl报出方式.Name = "lbl报出方式"; - this.lbl报出方式.Size = new System.Drawing.Size(70, 23); - this.lbl报出方式.TabIndex = 12; - this.lbl报出方式.Text = "报出方式:"; - this.lbl报出方式.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // cmb报出方式 - // - this.cmb报出方式.BackColor = System.Drawing.SystemColors.Window; - this.cmb报出方式.DropDownWidth = 200; - this.cmb报出方式.Font = new System.Drawing.Font("宋体", 9F); - this.cmb报出方式.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb报出方式.ItemHeight = 18; - this.cmb报出方式.Location = new System.Drawing.Point(95, 265); - this.cmb报出方式.Name = "cmb报出方式"; - this.cmb报出方式.Size = new System.Drawing.Size(220, 26); - this.cmb报出方式.TabIndex = 12; - this.cmb报出方式.Text = "报出价=表价*采购系数*报出系数"; - // - // lbl箱柜模板 - // - this.lbl箱柜模板.BackColor = System.Drawing.SystemColors.Control; - this.lbl箱柜模板.Font = new System.Drawing.Font("宋体", 9F); - this.lbl箱柜模板.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl箱柜模板.Location = new System.Drawing.Point(380, 265); - this.lbl箱柜模板.Name = "lbl箱柜模板"; - this.lbl箱柜模板.Size = new System.Drawing.Size(70, 20); - this.lbl箱柜模板.TabIndex = 13; - this.lbl箱柜模板.Text = "箱柜模板:"; - // - // cmb箱柜模板 - // - this.cmb箱柜模板.BackColor = System.Drawing.SystemColors.Window; - this.cmb箱柜模板.DropDownWidth = 200; - this.cmb箱柜模板.Font = new System.Drawing.Font("宋体", 9F); - this.cmb箱柜模板.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb箱柜模板.ItemHeight = 18; - this.cmb箱柜模板.Location = new System.Drawing.Point(455, 262); - this.cmb箱柜模板.Name = "cmb箱柜模板"; - this.cmb箱柜模板.Size = new System.Drawing.Size(210, 26); - this.cmb箱柜模板.TabIndex = 13; - // - // lbl单台价格 - // - this.lbl单台价格.BackColor = System.Drawing.SystemColors.Control; - this.lbl单台价格.Font = new System.Drawing.Font("宋体", 9F); - this.lbl单台价格.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl单台价格.Location = new System.Drawing.Point(20, 293); - this.lbl单台价格.Name = "lbl单台价格"; - this.lbl单台价格.Size = new System.Drawing.Size(70, 23); - this.lbl单台价格.TabIndex = 14; - this.lbl单台价格.Text = "单台价格:"; - this.lbl单台价格.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // cmb单台价格 - // - this.cmb单台价格.BackColor = System.Drawing.SystemColors.Window; - this.cmb单台价格.DropDownWidth = 200; - this.cmb单台价格.Font = new System.Drawing.Font("宋体", 9F); - this.cmb单台价格.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb单台价格.ItemHeight = 18; - this.cmb单台价格.Location = new System.Drawing.Point(95, 293); - this.cmb单台价格.Name = "cmb单台价格"; - this.cmb单台价格.Size = new System.Drawing.Size(220, 26); - this.cmb单台价格.TabIndex = 14; - this.cmb单台价格.Text = "保留整数"; - // - // lbl项目总价 - // - this.lbl项目总价.BackColor = System.Drawing.SystemColors.Control; - this.lbl项目总价.Font = new System.Drawing.Font("宋体", 9F); - this.lbl项目总价.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl项目总价.Location = new System.Drawing.Point(379, 293); - this.lbl项目总价.Name = "lbl项目总价"; - this.lbl项目总价.Size = new System.Drawing.Size(70, 20); - this.lbl项目总价.TabIndex = 15; - this.lbl项目总价.Text = "项目总价:"; - // - // lbl备注 - // - this.lbl备注.BackColor = System.Drawing.SystemColors.Control; - this.lbl备注.Font = new System.Drawing.Font("宋体", 9F); - this.lbl备注.ForeColor = System.Drawing.SystemColors.ControlText; - this.lbl备注.Location = new System.Drawing.Point(44, 352); - this.lbl备注.Name = "lbl备注"; - this.lbl备注.Size = new System.Drawing.Size(46, 23); - this.lbl备注.TabIndex = 16; - this.lbl备注.Text = "备注:"; - this.lbl备注.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // txt备注 - // - this.txt备注.BackColor = System.Drawing.SystemColors.Window; - this.txt备注.Font = new System.Drawing.Font("宋体", 9F); - this.txt备注.ForeColor = System.Drawing.SystemColors.WindowText; - this.txt备注.Location = new System.Drawing.Point(95, 352); - this.txt备注.Multiline = true; - this.txt备注.Name = "txt备注"; - this.txt备注.Size = new System.Drawing.Size(570, 80); - this.txt备注.TabIndex = 16; - // - // btn确定 - // - this.btn确定.BackColor = System.Drawing.SystemColors.Control; - this.btn确定.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btn确定.Font = new System.Drawing.Font("宋体", 9F); - this.btn确定.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn确定.Location = new System.Drawing.Point(455, 449); - this.btn确定.Name = "btn确定"; - this.btn确定.Size = new System.Drawing.Size(100, 28); - this.btn确定.TabIndex = 17; - this.btn确定.Text = "确定"; - this.btn确定.UseVisualStyleBackColor = true; - // - // btn取消 - // - this.btn取消.BackColor = System.Drawing.SystemColors.Control; - this.btn取消.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btn取消.Font = new System.Drawing.Font("宋体", 9F); - this.btn取消.ForeColor = System.Drawing.SystemColors.ControlText; - this.btn取消.Location = new System.Drawing.Point(565, 449); - this.btn取消.Name = "btn取消"; - this.btn取消.Size = new System.Drawing.Size(100, 28); - this.btn取消.TabIndex = 18; - this.btn取消.Text = "取消"; - this.btn取消.UseVisualStyleBackColor = true; - // - // comboBox1 - // - this.comboBox1.BackColor = System.Drawing.SystemColors.Window; - this.comboBox1.DropDownWidth = 210; - this.comboBox1.Font = new System.Drawing.Font("宋体", 9F); - this.comboBox1.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox1.ItemHeight = 18; - this.comboBox1.Location = new System.Drawing.Point(455, 322); - this.comboBox1.Name = "comboBox1"; - this.comboBox1.Size = new System.Drawing.Size(210, 26); - this.comboBox1.TabIndex = 14; - this.comboBox1.Text = "四舍五入"; - // - // label1 - // - this.label1.BackColor = System.Drawing.SystemColors.Control; - this.label1.Font = new System.Drawing.Font("宋体", 9F); - this.label1.ForeColor = System.Drawing.SystemColors.ControlText; - this.label1.Location = new System.Drawing.Point(19, 320); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(70, 23); - this.label1.TabIndex = 14; - this.label1.Text = "单台取整:"; - this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // label2 - // - this.label2.BackColor = System.Drawing.SystemColors.Control; - this.label2.Font = new System.Drawing.Font("宋体", 9F); - this.label2.ForeColor = System.Drawing.SystemColors.ControlText; - this.label2.Location = new System.Drawing.Point(379, 324); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(70, 20); - this.label2.TabIndex = 15; - this.label2.Text = "项目取整:"; - // - // comboBox2 - // - this.comboBox2.BackColor = System.Drawing.SystemColors.Window; - this.comboBox2.DropDownWidth = 220; - this.comboBox2.Font = new System.Drawing.Font("宋体", 9F); - this.comboBox2.ForeColor = System.Drawing.SystemColors.WindowText; - this.comboBox2.ItemHeight = 18; - this.comboBox2.Location = new System.Drawing.Point(95, 324); - this.comboBox2.Name = "comboBox2"; - this.comboBox2.Size = new System.Drawing.Size(220, 26); - this.comboBox2.TabIndex = 14; - this.comboBox2.Text = "四舍五入"; - // - // cmb项目总价 - // - this.cmb项目总价.BackColor = System.Drawing.SystemColors.Window; - this.cmb项目总价.DropDownWidth = 200; - this.cmb项目总价.Font = new System.Drawing.Font("宋体", 9F); - this.cmb项目总价.ForeColor = System.Drawing.SystemColors.WindowText; - this.cmb项目总价.ItemHeight = 18; - this.cmb项目总价.Location = new System.Drawing.Point(455, 290); - this.cmb项目总价.Name = "cmb项目总价"; - this.cmb项目总价.Size = new System.Drawing.Size(210, 26); - this.cmb项目总价.TabIndex = 14; - this.cmb项目总价.Text = "保留整数"; - // - // 新建项目 - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocusChange; - this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(678, 482); - this.Controls.Add(this.lbl项目编号); - this.Controls.Add(this.txt项目编号); - this.Controls.Add(this.lbl项目日期); - this.Controls.Add(this.txt项目日期); - this.Controls.Add(this.lbl项目名称); - this.Controls.Add(this.txt项目名称); - this.Controls.Add(this.lbl客户名称); - this.Controls.Add(this.txt客户名称); - this.Controls.Add(this.btn选择客户); - this.Controls.Add(this.lbl客户地址); - this.Controls.Add(this.txt客户地址); - this.Controls.Add(this.lbl联系人); - this.Controls.Add(this.txt联系人); - this.Controls.Add(this.lbl联系电话); - this.Controls.Add(this.txt联系电话); - this.Controls.Add(this.lbl成套厂名称); - this.Controls.Add(this.txt成套厂名称); - this.Controls.Add(this.lbl成套厂地址); - this.Controls.Add(this.txt成套厂地址); - this.Controls.Add(this.lbl成套厂联系人); - this.Controls.Add(this.txt成套厂联系人); - this.Controls.Add(this.lbl成套厂联系电话); - this.Controls.Add(this.txt成套厂联系电话); - this.Controls.Add(this.lbl报出方式); - this.Controls.Add(this.cmb报出方式); - this.Controls.Add(this.lbl箱柜模板); - this.Controls.Add(this.cmb箱柜模板); - this.Controls.Add(this.lbl单台价格); - this.Controls.Add(this.cmb单台价格); - this.Controls.Add(this.lbl项目总价); - this.Controls.Add(this.lbl备注); - this.Controls.Add(this.txt备注); - this.Controls.Add(this.btn确定); - this.Controls.Add(this.btn取消); - this.Controls.Add(this.comboBox1); - this.Controls.Add(this.label1); - this.Controls.Add(this.label2); - this.Controls.Add(this.comboBox2); - this.Controls.Add(this.cmb项目总价); - this.Font = new System.Drawing.Font("宋体", 9F); - this.ForeColor = System.Drawing.SystemColors.ControlText; - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "新建项目"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "新建项目"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label lbl项目编号; - private System.Windows.Forms.TextBox txt项目编号; - private System.Windows.Forms.Label lbl项目日期; - private System.Windows.Forms.TextBox txt项目日期; - private System.Windows.Forms.Label lbl项目名称; - private System.Windows.Forms.TextBox txt项目名称; - private System.Windows.Forms.Label lbl客户名称; - private System.Windows.Forms.TextBox txt客户名称; - private System.Windows.Forms.Button btn选择客户; - private System.Windows.Forms.Label lbl客户地址; - private System.Windows.Forms.TextBox txt客户地址; - private System.Windows.Forms.Label lbl联系人; - private System.Windows.Forms.TextBox txt联系人; - private System.Windows.Forms.Label lbl联系电话; - private System.Windows.Forms.TextBox txt联系电话; - private System.Windows.Forms.Label lbl成套厂名称; - private System.Windows.Forms.TextBox txt成套厂名称; - private System.Windows.Forms.Label lbl成套厂地址; - private System.Windows.Forms.TextBox txt成套厂地址; - private System.Windows.Forms.Label lbl成套厂联系人; - private System.Windows.Forms.TextBox txt成套厂联系人; - private System.Windows.Forms.Label lbl成套厂联系电话; - private System.Windows.Forms.TextBox txt成套厂联系电话; - private System.Windows.Forms.Label lbl报出方式; - private System.Windows.Forms.ComboBox cmb报出方式; - private System.Windows.Forms.Label lbl箱柜模板; - private System.Windows.Forms.ComboBox cmb箱柜模板; - private System.Windows.Forms.Label lbl单台价格; - private System.Windows.Forms.ComboBox cmb单台价格; - private System.Windows.Forms.Label lbl项目总价; - private System.Windows.Forms.Label lbl备注; - private System.Windows.Forms.TextBox txt备注; - private System.Windows.Forms.Button btn确定; - private System.Windows.Forms.Button btn取消; - private System.Windows.Forms.ComboBox comboBox1; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.ComboBox comboBox2; - private System.Windows.Forms.ComboBox cmb项目总价; - } -} diff --git a/pdfbt/Plugin/新建项目.cs b/pdfbt/Plugin/新建项目.cs deleted file mode 100644 index 494c388..0000000 --- a/pdfbt/Plugin/新建项目.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Forms; - -namespace MyApp -{ - /// - /// 新建项目 窗口(简化版,不依赖企业信息)。 - /// UI 布局见 新建项目.ui.cs,本文件只含交互逻辑。 - /// - public partial class 新建项目 : Form - { - // 价格格式化选项(与主项目 价格格式化.cs 保持一致) - private static readonly string[] 小数位选项 = - { - "保留整数", "保留1位小数", "保留2位小数", "保留3位小数", - "保留4位小数", "保留5位小数", "保留6位小数" - }; - private static readonly string[] 取整方式选项 = - { - "不取整", "四舍五入", "四舍五入到角", "四舍五入到元", - "四舍五入到十元", "向上取整到元", "最近5元", "最近10元" - }; - - private readonly string _dbPath; - private readonly string _tableName; - - public 新建项目() : this(null, null) { } - - /// 带数据库路径的构造函数(用于自动生成项目编号)。 - public 新建项目(string dbPath, string tableName) - { - InitializeComponent(); - _dbPath = dbPath; - _tableName = tableName; - InitPriceFormatCombos(); - this.Load += 新建项目_Load; - } - - private void InitPriceFormatCombos() - { - cmb单台价格.Items.Clear(); - cmb单台价格.Items.AddRange(小数位选项); - cmb项目总价.Items.Clear(); - cmb项目总价.Items.AddRange(小数位选项); - comboBox1.Items.Clear(); - comboBox1.Items.AddRange(取整方式选项); - comboBox2.Items.Clear(); - comboBox2.Items.AddRange(取整方式选项); - } - - private void 新建项目_Load(object sender, EventArgs e) - { - FillAutoFields(); - } - - /// 自动填充项目日期(当天)和项目编号(yyyyMMdd+3位序号)。 - private void FillAutoFields() - { - DateTime today = DateTime.Today; - txt项目日期.Text = today.ToString("yyyy-MM-dd"); - - string datePart = today.ToString("yyyyMMdd"); - int seq = GetNextSeqForDate(datePart); - txt项目编号.Text = datePart + seq.ToString("000"); - txt项目编号.ReadOnly = true; - txt项目编号.TabStop = false; - txt项目编号.BackColor = System.Drawing.SystemColors.Control; - } - - /// 查数据库当天最大序号+1,失败返回1。 - private int GetNextSeqForDate(string datePart) - { - if (string.IsNullOrEmpty(datePart) || - string.IsNullOrEmpty(_dbPath) || - string.IsNullOrEmpty(_tableName) || - !System.IO.File.Exists(_dbPath)) - { - return 1; - } - try - { - string connStr = "Data Source=" + _dbPath + ";Version=3;"; - using (var conn = new System.Data.SQLite.SQLiteConnection(connStr)) - { - conn.Open(); - string sql = - "SELECT MAX(CAST(SUBSTR(项目编号, 9) AS INTEGER)) " + - "FROM " + _tableName + " " + - "WHERE SUBSTR(项目编号, 1, 8) = '" + datePart + "';"; - using (var cmd = new System.Data.SQLite.SQLiteCommand(sql, conn)) - { - object result = cmd.ExecuteScalar(); - if (result == null || result == DBNull.Value) return 1; - int maxSeq; - if (int.TryParse(result.ToString(), out maxSeq)) return maxSeq + 1; - return 1; - } - } - } - catch { return 1; } - } - - /// 收集对话框字段,以列名为键返回(供 Form3 写入数据库)。 - public Dictionary GetInputValues() - { - var values = new Dictionary(); - AddIfNotEmpty(values, "项目编号", txt项目编号.Text); - AddIfNotEmpty(values, "项目日期", txt项目日期.Text); - AddIfNotEmpty(values, "项目名称", txt项目名称.Text); - AddIfNotEmpty(values, "客户名称", txt客户名称.Text); - AddIfNotEmpty(values, "客户地址", txt客户地址.Text); - AddIfNotEmpty(values, "联系人", txt联系人.Text); - AddIfNotEmpty(values, "联系电话", txt联系电话.Text); - AddIfNotEmpty(values, "备注", txt备注.Text); - AddIfNotEmpty(values, "成套厂名称", txt成套厂名称.Text); - AddIfNotEmpty(values, "成套厂地址", txt成套厂地址.Text); - AddIfNotEmpty(values, "成套厂联系人", txt成套厂联系人.Text); - AddIfNotEmpty(values, "成套厂联系电话", txt成套厂联系电话.Text); - values["单台小数位"] = (cmb单台价格.SelectedItem ?? cmb单台价格.Text ?? "").ToString(); - values["项目小数位"] = (cmb项目总价.SelectedItem ?? cmb项目总价.Text ?? "").ToString(); - values["单台取整方式"] = (comboBox1.SelectedItem ?? comboBox1.Text ?? "").ToString(); - values["项目取整方式"] = (comboBox2.SelectedItem ?? comboBox2.Text ?? "").ToString(); - return values; - } - - private static void AddIfNotEmpty(Dictionary dict, string key, string value) - { - if (!string.IsNullOrWhiteSpace(value)) dict[key] = value.Trim(); - } - } -} diff --git a/pdfbt/Plugin/新建项目.resx b/pdfbt/Plugin/新建项目.resx deleted file mode 100644 index 1af7de1..0000000 --- a/pdfbt/Plugin/新建项目.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/pdfbt/Program.cs b/pdfbt/Program.cs deleted file mode 100644 index 3d9f0ec..0000000 --- a/pdfbt/Program.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * pdfbt:PDF 扒图报价工具(由 cadbt 改造,CAD 查看器 → PDF 查看 + 框选 OCR) - */ -using System; -using System.Windows.Forms; - -namespace pdfbt -{ - internal sealed class Program - { - [STAThread] - private static int Main(string[] args) - { - // 自检模式:pdfbt.exe --selftest [输出目录] - if (args != null && args.Length >= 2 && args[0] == "--selftest") - { - return SelfTest.Run(args); - } - - // 单实例保护:重复启动时激活已有实例并退出 - bool createdNew; - using (var mutex = new System.Threading.Mutex(true, "pdfbt_SingleInstance", out createdNew)) - { - if (!createdNew) - { - MessageBox.Show("pdfbt 已在运行中。", "pdfbt", - MessageBoxButtons.OK, MessageBoxIcon.Information); - return 0; - } - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); - GC.KeepAlive(mutex); - } - return 0; - } - } -} diff --git a/pdfbt/Properties/AssemblyInfo.cs b/pdfbt/Properties/AssemblyInfo.cs deleted file mode 100644 index e587e5c..0000000 --- a/pdfbt/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -#region Using directives - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -#endregion - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("pdfbt")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("pdfbt")] -[assembly: AssemblyCopyright("Copyright 2026")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.*")] diff --git a/pdfbt/SelfTest.cs b/pdfbt/SelfTest.cs deleted file mode 100644 index 268744d..0000000 --- a/pdfbt/SelfTest.cs +++ /dev/null @@ -1,99 +0,0 @@ -// ============================================================ -// SelfTest:命令行自检(--selftest [outdir]) -// 无 UI 验证:pdfium 渲染 → PNG 落盘;OCR 工作进程识别 → JSON 落盘 -// 用法:pdfbt.exe --selftest test.pdf . -// 返回码:0 成功;1 失败 -// ============================================================ -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using 成套报价软件; // ★ A1:OCR/PDF 基础设施已链接共享主项目源码(类型在 成套报价软件 命名空间) -namespace pdfbt -{ - internal static class SelfTest - { - public static int Run(string[] args) - { - string pdf = args[1]; - string outDir = args.Length >= 3 ? args[2] : "."; - var log = new StringBuilder(); - int exit = 0; - - try - { - // 1) pdfium 渲染 - string renderPath = Path.Combine(outDir, "selftest_render.png"); - Bitmap page; - using (var doc = new PdfDocument()) - { - doc.Open(pdf, null); - log.AppendLine("[render] 打开成功: " + pdf + " 页数=" + doc.PageCount); - page = doc.RenderPage(0, 1.5f); - if (page == null) throw new Exception("渲染返回 null"); - } - using (page) - { - page.Save(renderPath, ImageFormat.Png); - log.AppendLine("[render] 已保存: " + renderPath + - " (" + page.Width + "x" + page.Height + ")"); - - // 2) OCR(渲染图上半区) - var crop = new Bitmap(page.Width, page.Height / 2, - System.Drawing.Imaging.PixelFormat.Format24bppRgb); - using (var g = Graphics.FromImage(crop)) - { - g.DrawImage(page, new Rectangle(0, 0, crop.Width, crop.Height), - new Rectangle(0, 0, page.Width, page.Height / 2), GraphicsUnit.Pixel); - } - - using (var ocr = new OcrClient()) - { - var items = ocr.RecognizeAsync(crop, 180000).Result; - var json = new StringBuilder(); - json.AppendLine("{"); - json.AppendLine(" \"count\": " + (items == null ? 0 : items.Count) + ","); - json.AppendLine(" \"items\": ["); - if (items != null) - { - for (int i = 0; i < items.Count; i++) - { - var it = items[i]; - var b = it.Bounds; - json.AppendLine(" {\"text\": \"" + - (it.Text ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"") + - "\", \"score\": " + it.Score.ToString("0.000") + - ", \"bounds\": [" + b.X.ToString("0") + "," + b.Y.ToString("0") + - "," + b.Width.ToString("0") + "," + b.Height.ToString("0") + "]}" + - (i < items.Count - 1 ? "," : "")); - } - } - json.AppendLine(" ]"); - json.AppendLine("}"); - string ocrPath = Path.Combine(outDir, "selftest_ocr.json"); - File.WriteAllText(ocrPath, json.ToString(), new UTF8Encoding(false)); - log.AppendLine("[ocr] 识别 " + (items == null ? 0 : items.Count) + - " 条,已保存: " + ocrPath); - if (items != null) - { - foreach (var it in items) - log.AppendLine(" - " + it.Text); - } - } - } - } - catch (Exception ex) - { - log.AppendLine("[FAIL] " + ex); - exit = 1; - } - - string resultPath = Path.Combine(outDir, "selftest_result.txt"); - File.WriteAllText(resultPath, log.ToString(), new UTF8Encoding(false)); - Console.Out.WriteLine(log.ToString()); - return exit; - } - } -} diff --git a/pdfbt/app.config b/pdfbt/app.config deleted file mode 100644 index 4e9fea4..0000000 --- a/pdfbt/app.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/pdfbt/app.manifest b/pdfbt/app.manifest deleted file mode 100644 index 6d88151..0000000 --- a/pdfbt/app.manifest +++ /dev/null @@ -1,8 +0,0 @@ - - - - - true - - - diff --git a/pdfbt/build.rsp b/pdfbt/build.rsp deleted file mode 100644 index beb4193..0000000 --- a/pdfbt/build.rsp +++ /dev/null @@ -1,60 +0,0 @@ --nologo --target:winexe --platform:x86 --utf8output --optimize+ --out:bin\Debug\pdfbt_new.exe --win32manifest:app.manifest --resource:MainForm.resx,pdfbt.MainForm.resources --resource:OcrSettingsForm.resx,pdfbt.OcrSettingsForm.resources --resource:Plugin\Form3.resx,pdfbt.Plugin.Form3.resources --resource:Plugin\新建项目.resx,pdfbt.Plugin.新建项目.resources --r:bin\Debug\Smart.CustomComponents.dll --r:bin\Debug\AdvancedDataGridView.dll --r:bin\Debug\WeifenLuo.WinFormsUI.Docking.dll --r:bin\Debug\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll --r:bin\Debug\System.Data.SQLite.dll --r:bin\Debug\System.Memory.dll --r:bin\Debug\System.Numerics.Vectors.dll --r:bin\Debug\System.Resources.Extensions.dll --r:bin\Debug\System.Runtime.CompilerServices.Unsafe.dll --r:System.dll --r:System.Configuration.dll --r:System.Data.dll --r:System.Data.DataSetExtensions.dll --r:System.Xml.Linq.dll --r:System.IO.Compression.dll --r:System.IO.Compression.FileSystem.dll --r:bin\Debug\log4net.dll --r:netstandard.dll --r:System.Core.dll --r:System.Drawing.dll --r:System.Windows.Forms.dll --r:System.Xml.dll --r:System.Web.Extensions.dll --r:Microsoft.CSharp.dll -MainForm.cs -MainForm.Designer.cs -MainForm.DockWindows.cs -Program.cs -SelfTest.cs -PdfBridge.cs -PdfiumNative.cs -PdfDocument.cs -OcrClient.cs -GlmOcrClient.cs -QianfanOcrClient.cs -UapisOcrClient.cs -UmiOcrClient.cs -UmiOcrHost.cs -OcrSettingsForm.cs -OcrSettingsForm.Designer.cs -PdfViewerWindow.cs -Properties\AssemblyInfo.cs -Plugin\Form3.cs -Plugin\Form3.Designer.cs -Plugin\PaTypes.cs -Plugin\新建项目.cs -Plugin\新建项目.Designer.cs -DockWindows\QuoteWindow.cs -DockWindows\QuoteWindow.Designer.cs diff --git a/pdfbt/lib/Smart.CustomComponents.dll b/pdfbt/lib/Smart.CustomComponents.dll deleted file mode 100644 index 717c96b..0000000 Binary files a/pdfbt/lib/Smart.CustomComponents.dll and /dev/null differ diff --git a/pdfbt/libs/AdvancedDataGridView.dll b/pdfbt/libs/AdvancedDataGridView.dll deleted file mode 100644 index f520283..0000000 Binary files a/pdfbt/libs/AdvancedDataGridView.dll and /dev/null differ diff --git a/pdfbt/libs/pdfium/pdfium.dll b/pdfbt/libs/pdfium/pdfium.dll deleted file mode 100644 index 0672b12..0000000 Binary files a/pdfbt/libs/pdfium/pdfium.dll and /dev/null differ diff --git a/pdfbt/pdfbt.csproj b/pdfbt/pdfbt.csproj deleted file mode 100644 index 40c630c..0000000 --- a/pdfbt/pdfbt.csproj +++ /dev/null @@ -1,194 +0,0 @@ - - - - {7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Debug - AnyCPU - WinExe - pdfbt - pdfbt - v4.8 - Properties - x86 - app.manifest - - - bin\Debug\ - True - Full - False - True - DEBUG;TRACE - - - bin\Release\ - False - None - True - False - TRACE - - - True - - - - 4.0 - - - - - 3.5 - - - - 3.5 - - - - - - 3.5 - - - 3.5 - - - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\Smart.CustomComponents.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Data.SQLite.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\log4net.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Resources.Extensions.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Memory.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Runtime.CompilerServices.Unsafe.dll - True - - - C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Numerics.Vectors.dll - True - - - libs\AdvancedDataGridView.dll - True - - - - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\Facades\netstandard.dll - False - - - - - - MainForm.cs - - - MainForm.cs - - - - - - - 共享扒图\PdfiumNative.cs - - - 共享扒图\PdfDocument.cs - - - 共享扒图\OcrClient.cs - - - 共享扒图\GlmOcrClient.cs - - - 共享扒图\QianfanOcrClient.cs - - - 共享扒图\UapisOcrClient.cs - - - 共享扒图\UmiOcrClient.cs - - - 共享扒图\UmiOcrHost.cs - - - 共享扒图\UmiOcrLauncher.cs - - - 共享扒图\OcrSettingsForm.cs - - - 共享扒图\OcrSettingsForm.Designer.cs - OcrSettingsForm.cs - - - - - - Form3.cs - - - - - 新建项目.cs - - - - QuoteWindow.cs - - - - - - - - - - pdfium.dll - PreserveNewest - - - - - - MainForm.cs - - - - Form3.cs - - - 新建项目.cs - - - - \ No newline at end of file diff --git a/pdfbt/pdfbt.sln b/pdfbt/pdfbt.sln deleted file mode 100644 index 7653d97..0000000 --- a/pdfbt/pdfbt.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -# SharpDevelop 5.2 -VisualStudioVersion = 12.0.20827.3 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pdfbt", "pdfbt.csproj", "{7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C2A9D4E-1F58-4B6A-9E77-3A5B10D9C8F1}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/pdfbt/repro.cs.patch b/pdfbt/repro.cs.patch deleted file mode 100644 index e69de29..0000000 diff --git a/pdfbt/showerr.cs b/pdfbt/showerr.cs deleted file mode 100644 index 850aa1d..0000000 --- a/pdfbt/showerr.cs +++ /dev/null @@ -1,31 +0,0 @@ -// 复现 OCR 设置窗报错,把完整异常写到文件 -using System; -using System.Windows.Forms; - -namespace pdfbt -{ - static class ShowErr - { - [STAThread] - static void Main() - { - try - { - var f = new OcrSettingsForm(null); - f.Show(); - Application.DoEvents(); - FileLog("窗口创建成功,无异常"); - } - catch (Exception ex) - { - FileLog("EX: " + ex); - var inner = ex.InnerException; - while (inner != null) { FileLog("INNER: " + inner); inner = inner.InnerException; } - } - } - static void FileLog(string s) - { - System.IO.File.AppendAllText(@"C:\Users\099978\Documents\SharpDevelop Projects\pdfbt\showerr.log", s + "\r\n"); - } - } -} diff --git a/release/成套报价软件/setup.iss b/release/成套报价软件/setup.iss index b2b4cd7..3749ab4 100644 --- a/release/成套报价软件/setup.iss +++ b/release/成套报价软件/setup.iss @@ -118,10 +118,8 @@ Source: "sjk\*"; DestDir: "{app}\sjk"; Flags: ignoreversion recursesubdirs creat Source: "shezhi\*"; DestDir: "{app}\shezhi"; Flags: ignoreversion recursesubdirs createallsubdirs ; 甲方报表 Excel 模板(按图号/按箱号/按箱号+箱体面积/按箱类型) Source: "xiangmu\*"; DestDir: "{app}\xiangmu"; Flags: ignoreversion recursesubdirs createallsubdirs -; CAD 扒图(独立程序,默认安装) +; CAD 网页引擎运行时(node+CAD-Viewer;2026-10-01 独立 cadbt.exe 退役,主程序内嵌扒图窗口用) Source: "cadbt\*"; DestDir: "{app}\cadbt"; Flags: ignoreversion recursesubdirs createallsubdirs -; PDF 扒图(独立程序+OCR 环境,默认安装) -Source: "pdfbt\*"; DestDir: "{app}\pdfbt"; Flags: ignoreversion recursesubdirs createallsubdirs ; AI 助手引擎(ZCode 开源版 zai-org/ZCode,Apache-2.0:zcode 发行包+捆绑 node+预置+启停 cmd;zcode数据 运行时自建不进包) Source: "ai助手\*"; DestDir: "{app}\ai助手"; Flags: ignoreversion recursesubdirs createallsubdirs ; 会员服务器不进包(2026-09-22 用户长期规则:客户端默认连云端 https://ss61.odn.cc,部署套件单独交付) diff --git a/tools/make_package.py b/tools/make_package.py index 1094ae3..934f88e 100644 --- a/tools/make_package.py +++ b/tools/make_package.py @@ -119,13 +119,9 @@ def main(): ignore=shutil.ignore_patterns("__pycache__", "*.pyc")) print("复制目录", d) - # ===== cadbt(CAD扒图独立程序,默认安装) ===== + # ===== cadbt(CAD 网页引擎运行时;2026-10-01 独立 cadbt.exe 退役,只装 node+CAD-Viewer) ===== cadbt_src = os.path.join(ROOT, "cadbt", "cadbt", "bin", "Debug") cadbt_dst = os.path.join(REL, "cadbt") - os.makedirs(cadbt_dst, exist_ok=True) - for f in os.listdir(cadbt_src): - if f.endswith((".exe", ".dll", ".config")): - shutil.copy2(os.path.join(cadbt_src, f), os.path.join(cadbt_dst, f)) os.makedirs(os.path.join(cadbt_dst, "node"), exist_ok=True) shutil.copy2(os.path.join(cadbt_src, "node", "node.exe"), os.path.join(cadbt_dst, "node", "node.exe")) dist_src = os.path.join(ROOT, "cadbt", "cadbt", "CAD-Viewer", "packages", "cad-viewer-example", "dist") @@ -148,18 +144,7 @@ def main(): print("补齐 dist/server.cjs") else: print("!! 运行目录缺少 server.cjs(CAD 网页服务起不来!)") - os.makedirs(os.path.join(cadbt_dst, "sjk", "bjb"), exist_ok=True) - print("复制目录 cadbt(exe+DLL+node+dist 网页+fonts/templates/server.cjs)") - - # ===== pdfbt(PDF扒图独立程序+OCR Python 环境,默认安装) ===== - pdfbt_src = os.path.join(ROOT, "pdfbt", "bin", "Debug") - pdfbt_dst = os.path.join(REL, "pdfbt") - os.makedirs(pdfbt_dst, exist_ok=True) - for f in os.listdir(pdfbt_src): - if f.endswith((".exe", ".dll", ".config")): - shutil.copy2(os.path.join(pdfbt_src, f), os.path.join(pdfbt_dst, f)) - os.makedirs(os.path.join(pdfbt_dst, "sjk", "bjb"), exist_ok=True) - print("复制目录 pdfbt(exe+pdfium,OCR=百度API无需本地环境)") + print("复制目录 cadbt(node+CAD-Viewer 网页引擎+fonts/templates/server.cjs;独立 exe 已退役)") # ===== AI 助手引擎目录(2026-09-26 OpenClaw→ZCode 开源版 zai-org/ZCode) ===== # ai助手\ = zcode\(官方 build:zcode 发行包:bin/web/server/agent/node_modules + 捆绑 node) diff --git a/tools/make_update_package.py b/tools/make_update_package.py index afd42e0..ceb54c3 100644 --- a/tools/make_update_package.py +++ b/tools/make_update_package.py @@ -48,9 +48,7 @@ def main(): # 主程序 shutil.copy2(os.path.join(REL, "成套报价软件.exe"), PKG) - - # PDF 扒图独立程序(2026-10-01 第2期:缩放卡顿同步修复) - shutil.copy2(os.path.join(REL, "pdfbt", "pdfbt.exe"), PKG) + # (2026-10-01 独立 pdfbt.exe 退役后不再随更新包分发) # 使用说明(GBK,记事本直接打开不乱码) with open(os.path.join(PKG, "使用说明.txt"), "w", encoding="gbk", newline="\r\n") as f: diff --git a/tools/扒图同步检查.ps1 b/tools/扒图同步检查.ps1 index 9e05ef1..33cc5bb 100644 --- a/tools/扒图同步检查.ps1 +++ b/tools/扒图同步检查.ps1 @@ -1,4 +1,4 @@ -# ============================================================ +# ============================================================ # 扒图同步检查.ps1 —— Cad/Pdf 扒图窗口 Form3.cs 漂移护栏 # ============================================================ # 背景: 扒图\Cad\Form3.cs 与 扒图\Pdf\Form3.cs 是约 98% 重复的双胞胎文件 @@ -18,8 +18,19 @@ $cadPath = Join-Path $root '成套报价软件\扒图\Cad\Form3.cs' $pdfPath = Join-Path $root '成套报价软件\扒图\Pdf\Form3.cs' $baseline = Join-Path $PSScriptRoot '扒图同步基线.txt' -foreach ($f in @($cadPath, $pdfPath)) { - if (-not (Test-Path $f)) { Write-Host "[FAIL] 缺少文件: $f" -ForegroundColor Red; exit 2 } +# ★ 2026-10-01 扩充:从只查 Form3.cs 扩展到全部 Cad/Pdf 双胞胎文件对 +# (新建项目.cs 与两对 Designer/ui.cs 此前是漂移盲区) +$pairs = @( + @('成套报价软件\扒图\Cad\Form3.cs', '成套报价软件\扒图\Pdf\Form3.cs'), + @('成套报价软件\扒图\Cad\新建项目.cs', '成套报价软件\扒图\Pdf\新建项目.cs'), + @('成套报价软件\扒图\Cad\Form3.ui.cs', '成套报价软件\扒图\Pdf\Form3.Designer.cs'), + @('成套报价软件\扒图\Cad\新建项目.ui.cs', '成套报价软件\扒图\Pdf\新建项目.Designer.cs') +) + +foreach ($p in $pairs) { + foreach ($f in @((Join-Path $root $p[0]), (Join-Path $root $p[1]))) { + if (-not (Test-Path $f)) { Write-Host "[FAIL] 缺少文件: $f" -ForegroundColor Red; exit 2 } + } } function Normalize([string]$path) { @@ -34,17 +45,20 @@ function Normalize([string]$path) { $tmpCad = Join-Path $env:TEMP 'baotu_cad_norm.cs' $tmpPdf = Join-Path $env:TEMP 'baotu_pdf_norm.cs' -Normalize $cadPath | Set-Content $tmpCad -Encoding UTF8 -Normalize $pdfPath | Set-Content $tmpPdf -Encoding UTF8 - $diffFile = Join-Path $env:TEMP 'baotu_drift.diff' -$null = git diff --no-index --unified=1 $tmpCad $tmpPdf 2>$null | Out-File $diffFile -Encoding UTF8 - -$numstat = git diff --no-index --numstat $tmpCad $tmpPdf 2>$null $added = 0; $deleted = 0 -if ($numstat) { - $parts = (@($numstat)[0]) -split "`t" - if ($parts.Count -ge 2) { $added = [int]$parts[0]; $deleted = [int]$parts[1] } +"" | Out-File $diffFile -Encoding UTF8 + +foreach ($p in $pairs) { + $cadF = Join-Path $root $p[0]; $pdfF = Join-Path $root $p[1] + Normalize $cadF | Set-Content $tmpCad -Encoding UTF8 + Normalize $pdfF | Set-Content $tmpPdf -Encoding UTF8 + $null = git diff --no-index --unified=1 $tmpCad $tmpPdf 2>$null | Out-File $diffFile -Append -Encoding UTF8 + $numstat = git diff --no-index --numstat $tmpCad $tmpPdf 2>$null + if ($numstat) { + $parts = (@($numstat)[0]) -split "`t" + if ($parts.Count -ge 2) { $added += [int]$parts[0]; $deleted += [int]$parts[1] } + } } $drift = $added + $deleted diff --git a/yjktool/MainForm.Designer.cs b/yjktool/MainForm.Designer.cs deleted file mode 100644 index c0c3916..0000000 --- a/yjktool/MainForm.Designer.cs +++ /dev/null @@ -1,269 +0,0 @@ -namespace yjktool -{ - partial class MainForm - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) components.Dispose(); - base.Dispose(disposing); - } - - #region Windows 窗体设计器生成的代码 - - private void InitializeComponent() - { - this.lbl搜索 = new System.Windows.Forms.Label(); - this.txt搜索 = new System.Windows.Forms.TextBox(); - this.lst厂家 = new System.Windows.Forms.ListView(); - this.btn全选 = new System.Windows.Forms.Button(); - this.btn反选 = new System.Windows.Forms.Button(); - this.lbl线程 = new System.Windows.Forms.Label(); - this.num线程 = new System.Windows.Forms.NumericUpDown(); - this.lbl输出 = new System.Windows.Forms.Label(); - this.txt输出 = new System.Windows.Forms.TextBox(); - this.btn开始 = new System.Windows.Forms.Button(); - this.btn打包 = new System.Windows.Forms.Button(); - this.chk代理 = new System.Windows.Forms.CheckBox(); - this.lbl代理 = new System.Windows.Forms.Label(); - this.chk清理 = new System.Windows.Forms.CheckBox(); - this.progress = new System.Windows.Forms.ProgressBar(); - this.lbl进度 = new System.Windows.Forms.Label(); - this.rtb日志 = new System.Windows.Forms.RichTextBox(); - this.lbl统计 = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.num线程)).BeginInit(); - this.SuspendLayout(); - // - // lbl搜索 - // - this.lbl搜索.AutoSize = true; - this.lbl搜索.Location = new System.Drawing.Point(12, 15); - this.lbl搜索.Name = "lbl搜索"; - this.lbl搜索.Size = new System.Drawing.Size(37, 17); - this.lbl搜索.TabIndex = 0; - this.lbl搜索.Text = "搜索:"; - // - // txt搜索 - // - this.txt搜索.Location = new System.Drawing.Point(55, 12); - this.txt搜索.Name = "txt搜索"; - this.txt搜索.Size = new System.Drawing.Size(200, 25); - this.txt搜索.TabIndex = 1; - this.txt搜索.TextChanged += new System.EventHandler(this.txt搜索_TextChanged); - // - // lst厂家 - // - this.lst厂家.CheckBoxes = true; - this.lst厂家.Columns.Add("厂家"); - this.lst厂家.Columns[0].Width = 240; - this.lst厂家.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; - this.lst厂家.HideSelection = true; - this.lst厂家.Location = new System.Drawing.Point(12, 44); - this.lst厂家.MultiSelect = false; - this.lst厂家.Name = "lst厂家"; - this.lst厂家.ShowGroups = false; - this.lst厂家.Size = new System.Drawing.Size(262, 470); - this.lst厂家.TabIndex = 2; - this.lst厂家.View = System.Windows.Forms.View.Details; - // - // btn全选 - // - this.btn全选.Location = new System.Drawing.Point(12, 520); - this.btn全选.Name = "btn全选"; - this.btn全选.Size = new System.Drawing.Size(75, 28); - this.btn全选.TabIndex = 3; - this.btn全选.Text = "全选"; - this.btn全选.UseVisualStyleBackColor = true; - this.btn全选.Click += new System.EventHandler(this.btn全选_Click); - // - // btn反选 - // - this.btn反选.Location = new System.Drawing.Point(96, 520); - this.btn反选.Name = "btn反选"; - this.btn反选.Size = new System.Drawing.Size(75, 28); - this.btn反选.TabIndex = 4; - this.btn反选.Text = "反选"; - this.btn反选.UseVisualStyleBackColor = true; - this.btn反选.Click += new System.EventHandler(this.btn反选_Click); - // - // lbl统计 - // - this.lbl统计.AutoSize = true; - this.lbl统计.ForeColor = System.Drawing.Color.DimGray; - this.lbl统计.Location = new System.Drawing.Point(180, 525); - this.lbl统计.Name = "lbl统计"; - this.lbl统计.Size = new System.Drawing.Size(0, 17); - this.lbl统计.TabIndex = 5; - // - // lbl线程 - // - this.lbl线程.AutoSize = true; - this.lbl线程.Location = new System.Drawing.Point(290, 15); - this.lbl线程.Name = "lbl线程"; - this.lbl线程.Size = new System.Drawing.Size(52, 17); - this.lbl线程.TabIndex = 6; - this.lbl线程.Text = "线程数:"; - // - // num线程 - // - this.num线程.Location = new System.Drawing.Point(348, 12); - this.num线程.Maximum = new decimal(new int[] { 16, 0, 0, 0 }); - this.num线程.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); - this.num线程.Name = "num线程"; - this.num线程.Size = new System.Drawing.Size(52, 25); - this.num线程.TabIndex = 7; - this.num线程.Value = new decimal(new int[] { 4, 0, 0, 0 }); - // - // lbl输出 - // - this.lbl输出.AutoSize = true; - this.lbl输出.Location = new System.Drawing.Point(418, 15); - this.lbl输出.Name = "lbl输出"; - this.lbl输出.Size = new System.Drawing.Size(67, 17); - this.lbl输出.TabIndex = 8; - this.lbl输出.Text = "输出目录:"; - // - // txt输出 - // - this.txt输出.Location = new System.Drawing.Point(487, 12); - this.txt输出.Name = "txt输出"; - this.txt输出.Size = new System.Drawing.Size(340, 25); - this.txt输出.TabIndex = 9; - // - // btn开始 - // - this.btn开始.Location = new System.Drawing.Point(290, 44); - this.btn开始.Name = "btn开始"; - this.btn开始.Size = new System.Drawing.Size(120, 32); - this.btn开始.TabIndex = 10; - this.btn开始.Text = "开始抓取"; - this.btn开始.UseVisualStyleBackColor = true; - this.btn开始.Click += new System.EventHandler(this.btn开始_Click); - // - // btn打包 - // - this.btn打包.Location = new System.Drawing.Point(420, 44); - this.btn打包.Name = "btn打包"; - this.btn打包.Size = new System.Drawing.Size(120, 32); - this.btn打包.TabIndex = 11; - this.btn打包.Text = "打包数据包"; - this.btn打包.UseVisualStyleBackColor = true; - this.btn打包.Click += new System.EventHandler(this.btn打包_Click); - // - // progress - // - this.progress.Location = new System.Drawing.Point(560, 50); - this.progress.Name = "progress"; - this.progress.Size = new System.Drawing.Size(180, 20); - this.progress.TabIndex = 12; - // - // lbl进度 - // - this.lbl进度.AutoSize = true; - this.lbl进度.Location = new System.Drawing.Point(750, 54); - this.lbl进度.Name = "lbl进度"; - this.lbl进度.Size = new System.Drawing.Size(0, 17); - this.lbl进度.TabIndex = 13; - // - // chk代理 - // - this.chk代理.AutoSize = true; - this.chk代理.Location = new System.Drawing.Point(290, 82); - this.chk代理.Name = "chk代理"; - this.chk代理.Size = new System.Drawing.Size(204, 21); - this.chk代理.TabIndex = 15; - this.chk代理.Text = "价格走旧代理(8081,自动启动)"; - this.chk代理.UseVisualStyleBackColor = true; - this.chk代理.CheckedChanged += new System.EventHandler(this.chk代理_CheckedChanged); - // - // lbl代理 - // - this.lbl代理.AutoSize = true; - this.lbl代理.ForeColor = System.Drawing.Color.Firebrick; - this.lbl代理.Location = new System.Drawing.Point(500, 85); - this.lbl代理.Name = "lbl代理"; - this.lbl代理.Size = new System.Drawing.Size(103, 17); - this.lbl代理.TabIndex = 16; - this.lbl代理.Text = "旧代理:未检测"; - // - // chk清理 - // - this.chk清理.AutoSize = true; - this.chk清理.Checked = true; - this.chk清理.CheckState = System.Windows.Forms.CheckState.Checked; - this.chk清理.Location = new System.Drawing.Point(620, 82); - this.chk清理.Name = "chk清理"; - this.chk清理.Size = new System.Drawing.Size(163, 21); - this.chk清理.TabIndex = 17; - this.chk清理.Text = "抓取前清空旧数据(缓存+输出)"; - this.chk清理.UseVisualStyleBackColor = true; - // - // rtb日志 - // - this.rtb日志.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(30)))), ((int)(((byte)(30))))); - this.rtb日志.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.rtb日志.ForeColor = System.Drawing.Color.Gainsboro; - this.rtb日志.Font = new System.Drawing.Font("Consolas", 9F); - this.rtb日志.Location = new System.Drawing.Point(290, 110); - this.rtb日志.Name = "rtb日志"; - this.rtb日志.ReadOnly = true; - this.rtb日志.Size = new System.Drawing.Size(537, 404); - this.rtb日志.TabIndex = 14; - this.rtb日志.Text = ""; - // - // MainForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(842, 561); - this.Controls.Add(this.lbl代理); - this.Controls.Add(this.chk代理); - this.Controls.Add(this.chk清理); - this.Controls.Add(this.rtb日志); - this.Controls.Add(this.lbl进度); - this.Controls.Add(this.progress); - this.Controls.Add(this.btn打包); - this.Controls.Add(this.btn开始); - this.Controls.Add(this.txt输出); - this.Controls.Add(this.lbl输出); - this.Controls.Add(this.num线程); - this.Controls.Add(this.lbl线程); - this.Controls.Add(this.lbl统计); - this.Controls.Add(this.btn反选); - this.Controls.Add(this.btn全选); - this.Controls.Add(this.lst厂家); - this.Controls.Add(this.txt搜索); - this.Controls.Add(this.lbl搜索); - this.MaximizeBox = false; - this.Name = "MainForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "元件库厂家数据工具"; - ((System.ComponentModel.ISupportInitialize)(this.num线程)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label lbl搜索; - private System.Windows.Forms.TextBox txt搜索; - private System.Windows.Forms.ListView lst厂家; - private System.Windows.Forms.Button btn全选; - private System.Windows.Forms.Button btn反选; - private System.Windows.Forms.Label lbl统计; - private System.Windows.Forms.Label lbl线程; - private System.Windows.Forms.NumericUpDown num线程; - private System.Windows.Forms.Label lbl输出; - private System.Windows.Forms.TextBox txt输出; - private System.Windows.Forms.Button btn开始; - private System.Windows.Forms.Button btn打包; - private System.Windows.Forms.ProgressBar progress; - private System.Windows.Forms.Label lbl进度; - private System.Windows.Forms.RichTextBox rtb日志; - private System.Windows.Forms.CheckBox chk代理; - private System.Windows.Forms.Label lbl代理; - private System.Windows.Forms.CheckBox chk清理; - } -} diff --git a/yjktool/MainForm.cs b/yjktool/MainForm.cs deleted file mode 100644 index c13c80a..0000000 --- a/yjktool/MainForm.cs +++ /dev/null @@ -1,352 +0,0 @@ -// 元件库数据工具:按厂家勾选抓取数据(树/系列/价格),打包成数据包 zip 供新服务读取 -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Threading; -using System.Windows.Forms; -using System.Text.RegularExpressions; - -namespace yjktool -{ - public partial class MainForm : Form - { - private List<厂家项> 全部厂家 = new List<厂家项>(); - private string 工作根; // 抓取落盘根(data 布局) - private 抓取器 抓; - private volatile bool 运行中; - - private class 厂家项 - { - public string 树id; - public string 名称; - public override string ToString() { return 名称; } - } - - public MainForm() - { - InitializeComponent(); - 工作根 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "抓取输出"); - txt输出.Text = 工作根; - 加载厂家清单(); - chk代理.Checked = true; // 默认走旧代理(抓取时会自动启动工具内置的旧代理) - 检测旧代理(); // 启动时显示旧代理在线状态 - FormClosing += (s, e) => 关闭内置旧代理(); - } - - // ---------- 旧代理(工具内置副本,8081;node 新服务占 8080 不能同端口) ---------- - private const int 代理端口 = 8081; - private System.Diagnostics.Process _代理进程; // 本工具拉起的内置旧代理(退出时收尾) - - private static bool 端口通(int 端口) - { - try - { - using (var c = new System.Net.Sockets.TcpClient()) - { - var ar = c.BeginConnect("127.0.0.1", 端口, null, null); - return ar.AsyncWaitHandle.WaitOne(600) && c.Connected; - } - } - catch { return false; } - } - - /// 8081 不通时自动启动工具旁的内置旧代理(旧代理\python\python.exe -u proxy_server.py --port 8081)。 - /// 阻塞最多约 15 秒等端口就绪,应在后台线程调用。 - private bool 确保旧代理运行() - { - if (端口通(代理端口)) return true; - string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "旧代理"); - string py = Path.Combine(dir, "python", "python.exe"); - if (!File.Exists(py) || !File.Exists(Path.Combine(dir, "proxy_server.py"))) - { - UI日志("! 工具旁没有内置旧代理目录(旧代理\\python\\python.exe),价格将全部落空"); - return false; - } - UI日志("正在启动内置旧代理(端口 " + 代理端口 + ")…"); - try - { - _代理进程 = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo - { - FileName = py, - Arguments = "-u proxy_server.py --port " + 代理端口, - WorkingDirectory = dir, - UseShellExecute = false, - CreateNoWindow = true, - }); - } - catch (Exception ex) { UI日志("! 启动旧代理失败: " + ex.Message); return false; } - for (int i = 0; i < 30 && !端口通(代理端口); i++) Thread.Sleep(500); - bool ok = 端口通(代理端口); - UI日志(ok ? "✅ 内置旧代理已启动(端口 " + 代理端口 + ")" : "! 内置旧代理 15 秒内未就绪(可能启动报错)"); - 检测旧代理(); - return ok; - } - - /// 工具退出时结束自己拉起的内置旧代理,避免留孤儿进程 - private void 关闭内置旧代理() - { - try - { - if (_代理进程 != null && !_代理进程.HasExited) _代理进程.Kill(); - } - catch { } - } - - /// 所有可用的种子目录:工具内置副本+根目录原件(预热缓存)+元件库网页 data(现成真价,含原始 t)。 - private static string[] 旧代理缓存目录们() - { - string baseDir = AppDomain.CurrentDomain.BaseDirectory; - string[] 候选 = { - Path.Combine(baseDir, @"旧代理\proxy_cache"), // 工具内置副本 - Path.Combine(baseDir, @"..\..\..\旧服务-python代理\src\proxy_cache"), // 根目录原件(预热流程) - Path.Combine(baseDir, @"..\..\..\成套报价软件\bin\Debug\元件库网页\data\dx2_webGetPrice"), // 新服务现成真价(开发机) - Path.Combine(baseDir, @"元件库网页\data\dx2_webGetPrice"), // 安装布局 - }; - return Array.FindAll(候选, p => Directory.Exists(p)); - } - - /// 清空旧数据:抓取输出两目录(树/系列包+价格)+两处旧代理缓存(proxy_cache)。 - /// 旧代理缓存会被直接回放成旧响应(等于抓到的还是旧价),要拿全新数据就得先清。在启动代理前执行。 - private int 清空旧数据() - { - int n = 0; - string baseDir = AppDomain.CurrentDomain.BaseDirectory; - string[] 目录们 = { - Path.Combine(工作根, @"dian\electricData_zips"), - Path.Combine(工作根, @"dx2_webGetPrice"), - Path.Combine(baseDir, @"旧代理\proxy_cache"), // 工具内置副本 - Path.Combine(baseDir, @"..\..\..\旧服务-python代理\src\proxy_cache"), // 根目录原件 - }; - foreach (string d in 目录们) - { - try - { - if (!Directory.Exists(d)) continue; - int 个数 = Directory.GetFiles(d, "*", SearchOption.AllDirectories).Length; - Directory.Delete(d, true); - Directory.CreateDirectory(d); - n++; - UI日志(" 已清空 " + 个数 + " 个文件: " + d); - } - catch (Exception ex) { UI日志(" ! 清空失败 " + d + ": " + ex.Message); } - } - return n; - } - - private void 检测旧代理() - { - if (InvokeRequired) { BeginInvoke((Action)(检测旧代理)); return; } - bool 在线 = 端口通(代理端口); - lbl代理.Text = 在线 ? "旧代理:在线 ✓" : "旧代理:离线"; - lbl代理.ForeColor = 在线 ? System.Drawing.Color.Green : System.Drawing.Color.Firebrick; - } - - private void chk代理_CheckedChanged(object sender, EventArgs e) - { - if (chk代理.Checked) 检测旧代理(); - else lbl代理.Text = "旧代理:未使用"; - } - - // ---------- 厂家清单:元件库网页\data(开发/安装布局)→exe旁→内置 f.zip 都无则提示 ---------- - private void 加载厂家清单() - { - string fzip = null; - string baseDir = AppDomain.CurrentDomain.BaseDirectory; - string[] 候选 = { - Path.Combine(baseDir, @"..\..\..\成套报价软件\bin\Debug\元件库网页\data\dian\electricData_zips\f.zip"), - Path.Combine(baseDir, @"..\..\..\..\..\..\成套报价软件\bin\Debug\元件库网页\data\dian\electricData_zips\f.zip"), - Path.Combine(baseDir, @"元件库网页\data\dian\electricData_zips\f.zip"), - Path.Combine(baseDir, "f.zip"), - }; - foreach (string p in 候选) - if (File.Exists(p)) { fzip = p; break; } - if (fzip == null) - { - MessageBox.Show(this, "找不到厂家清单 f.zip。\r\n请把工具放在 元件库网页\\ 目录旁,或把 f.zip 拷到工具旁。", - "元件库数据工具", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - try - { - string 文; - using (var z = ZipFile.OpenRead(fzip)) - using (var r = new StreamReader(z.Entries[0].Open(), System.Text.Encoding.UTF8)) - 文 = r.ReadToEnd(); - var 见过 = new HashSet(); - foreach (Match m in Regex.Matches(文, @"\{[^{}]*?""f""\s*:\s*(\d+)[^{}]*?""name""\s*:\s*""([^""]+)""[^{}]*?\}")) - { - string id = m.Groups[1].Value; - if (id == "0" || 见过.Contains(id)) continue; - 见过.Add(id); - 全部厂家.Add(new 厂家项 { 树id = id, 名称 = m.Groups[2].Value }); - } - // f 在 name 前的变体 - if (全部厂家.Count == 0) - { - foreach (Match m in Regex.Matches(文, @"\{[^{}]*?""name""\s*:\s*""([^""]+)""[^{}]*?""f""\s*:\s*(\d+)[^{}]*?\}")) - { - string id = m.Groups[2].Value; - if (id == "0" || 见过.Contains(id)) continue; - 见过.Add(id); - 全部厂家.Add(new 厂家项 { 树id = id, 名称 = m.Groups[1].Value }); - } - } - 填列表(""); - lbl统计.Text = "厂家 " + 全部厂家.Count + " 家"; - } - catch (Exception ex) - { - MessageBox.Show(this, "读取 f.zip 失败: " + ex.Message, "元件库数据工具"); - } - } - - private void 填列表(string 过滤) - { - lst厂家.BeginUpdate(); - lst厂家.Items.Clear(); - foreach (var f in 全部厂家) - { - if (过滤 != "" && f.名称.IndexOf(过滤, StringComparison.OrdinalIgnoreCase) < 0) continue; - var it = lst厂家.Items.Add(f.名称); - it.Checked = false; - it.Tag = f; - } - lst厂家.EndUpdate(); - } - - private void txt搜索_TextChanged(object sender, EventArgs e) - { - 填列表(txt搜索.Text.Trim()); - } - - private void btn全选_Click(object sender, EventArgs e) - { - foreach (ListViewItem it in lst厂家.Items) it.Checked = true; - } - - private void btn反选_Click(object sender, EventArgs e) - { - foreach (ListViewItem it in lst厂家.Items) it.Checked = !it.Checked; - } - - // ---------- UI 线程调度 ---------- - private void UI日志(string s) - { - if (InvokeRequired) { BeginInvoke((Action)(() => UI日志(s))); return; } - rtb日志.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + s + "\r\n"); - } - private void UI进度(int 厂完成, int 厂总数) - { - if (InvokeRequired) { BeginInvoke((Action)(() => UI进度(厂完成, 厂总数))); return; } - if (厂总数 > 0) progress.Value = Math.Min(progress.Maximum, 厂完成 * 100 / 厂总数); - lbl进度.Text = 厂完成 + " / " + 厂总数; - } - - private void btn开始_Click(object sender, EventArgs e) - { - if (运行中) { 抓.停止 = true; btn开始.Text = "正在停止…"; return; } - var 选中 = lst厂家.Items.Cast().Where(i => i.Checked).Select(i => (厂家项)i.Tag).ToList(); - if (选中.Count == 0) - { - MessageBox.Show(this, "请先勾选要抓取的厂家。", "元件库数据工具"); - return; - } - 工作根 = txt输出.Text.Trim(); - Directory.CreateDirectory(Path.Combine(工作根, "dian", "electricData_zips")); - Directory.CreateDirectory(Path.Combine(工作根, "dx2_webGetPrice")); - 抓 = new 抓取器(工作根) { 日志 = UI日志 }; - 抓.经旧代理 = chk代理.Checked; - 运行中 = true; - btn开始.Text = "停止"; - progress.Maximum = 100; progress.Value = 0; - int 线程 = (int)num线程.Value; - UI日志("开始抓取 " + 选中.Count + " 家,线程 " + 线程 + ",输出 " + 工作根 + (抓.经旧代理 ? ",价格走旧代理" : ",价格直连")); - int 总系 = 0, 总价 = 0; - ThreadPool.QueueUserWorkItem(_ => - { - // 先清旧数据(用户要求:旧代理缓存会回放旧响应、抓取输出留旧文件,要全新数据先清干净) - if (chk清理.Checked) - { - UI日志("清空旧数据…"); - 清空旧数据(); - } - // 代理仅在勾选时启动(终版机制直连+种子 t 即可命中,不依赖代理) - if (抓.经旧代理) 确保旧代理运行(); - // ★ 种子加载与代理无关,必须无条件执行:种子(系列有效时刻 t)决定价格能不能查, - // 不加载种子则所有系列按"无 t"跳过查价 → 0 价格 - string[] 缓存们 = 旧代理缓存目录们(); - if (缓存们.Length > 0) - { - int n种 = 0; - foreach (string 缓存 in 缓存们) n种 = 抓.加载种子(缓存); // 多处种子合并 - UI日志("已加载种子: " + n种 + " 个系列的有效时刻(来自 " + 缓存们.Length + " 处目录)"); - if (n种 == 0) - UI日志("! 种子为 0:价格将全部跳过。先在预热页面浏览目标厂家系列,或确认元件库网页 data 目录存在"); - } - else - UI日志("! 未找到种子目录(价格将全部跳过)"); - var sw = Stopwatch.StartNew(); - try - { - for (int i = 0; i < 选中.Count && !抓.停止; i++) - { - var kv = 抓.抓厂家(选中[i].树id, 选中[i].名称, 线程); - 总系 += kv.Key; 总价 += kv.Value; - UI进度(i + 1, 选中.Count); - } - UI日志((抓.停止 ? "已停止: " : "抓取完成: ") + "系列 " + 总系 + ", 价格组合 " + 总价 + - ", 用时 " + (int)sw.Elapsed.TotalMinutes + " 分钟。可点【打包数据包】。"); - } - catch (Exception ex) - { - UI日志("! 抓取中断: " + ex); - } - BeginInvoke((Action)(() => { 运行中 = false; btn开始.Text = "开始抓取"; })); - }); - } - - // ---------- 打包 ---------- - private void btn打包_Click(object sender, EventArgs e) - { - if (运行中) { MessageBox.Show(this, "抓取进行中,请先停止。"); return; } - if (!Directory.Exists(工作根)) - { - MessageBox.Show(this, "输出目录不存在,先抓取。"); return; - } - using (var dlg = new SaveFileDialog - { - Title = "打包数据包", - Filter = "元件库数据包 (*.zip)|*.zip", - FileName = "厂家数据包_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".zip", - InitialDirectory = AppDomain.CurrentDomain.BaseDirectory, - }) - { - if (dlg.ShowDialog(this) != DialogResult.OK) return; - try - { - int n = 0; - using (var zip = ZipFile.Open(dlg.FileName, ZipArchiveMode.Create)) - { - foreach (string f in Directory.GetFiles(工作根, "*", SearchOption.AllDirectories)) - { - if (f.EndsWith(".json")) continue; // 树缓存伴随文件不入包 - string rel = f.Substring(工作根.Length + 1).Replace('\\', '/'); - zip.CreateEntryFromFile(f, rel, CompressionLevel.Optimal); - n++; - } - } - MessageBox.Show(this, "打包完成: " + n + " 个文件\r\n" + dlg.FileName + - "\r\n\r\n把 zip 放进主程序 元件库网页\\ 目录,重启程序即自动导入。", "元件库数据工具"); - } - catch (Exception ex) - { - MessageBox.Show(this, "打包失败: " + ex.Message); - } - } - } - } -} diff --git a/yjktool/Program.cs b/yjktool/Program.cs deleted file mode 100644 index 0989db5..0000000 --- a/yjktool/Program.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Windows.Forms; - -namespace yjktool -{ - static class Program - { - [STAThread] - static void Main() - { - // 全局异常兜底:任何未捕获异常弹窗而不是闪退 - Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - Application.ThreadException += (s, e) => 弹(e.Exception); - AppDomain.CurrentDomain.UnhandledException += (s, e) => 弹(e.ExceptionObject as Exception); - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); - } - - private static void 弹(Exception ex) - { - try - { - MessageBox.Show("程序异常(可继续):\n\n" + (ex == null ? "?" : ex.ToString()), - "元件库数据工具", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - catch { } - } - } -} diff --git a/yjktool/yjktool.csproj b/yjktool/yjktool.csproj deleted file mode 100644 index ad6c6fc..0000000 --- a/yjktool/yjktool.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - {8A1E5C72-9D3B-4E7A-A0C1-5F6E7D8B9E01} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Debug - AnyCPU - WinExe - yjktool - 元件库数据工具 - v4.8 - x86 - - - bin\Debug\ - True - Full - False - - - bin\Release\ - False - None - True - - - - - 3.5 - - - - - - - - - - - - - MainForm.cs - - - - - diff --git a/yjktool/抓取器.cs b/yjktool/抓取器.cs deleted file mode 100644 index f27213b..0000000 --- a/yjktool/抓取器.cs +++ /dev/null @@ -1,422 +0,0 @@ -// 抓取器:抓厂家树/系列规格/价格,按新服务布局落盘(断点续抓,多线程安全) -// 两种价格通道:直连 dq123(默认) / 经内置旧代理 localhost:8081(带会话伪装,命中率高——工具自动启动它) -// 8081 是工具专用端口:node 新服务(元件库网页)占了 8080,两者须能同时跑 -// 种子模式:从旧代理 proxy_cache 提取真实查询过的组合(sid→bg 列表),优先按种子形状抓价(重放+单变化) -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net; -using System.Security.Cryptography; -using System.Text; -using System.Threading; - -namespace yjktool -{ - internal class 抓取器 - { - // 域名映射照旧 python 代理 - private const string 电数据 = "https://dian.dq123.com/electricData?v="; - private const string 价格口 = "https://dx2.dhub.com.cn/pcprice/default/dx2/interface/webGetPrice?infoJson="; - // 经旧代理(路径同源,代理按前缀转发到真实域名并注入会话头) - private const string 代电数据 = "http://127.0.0.1:8081/electricData?v="; - private const string 代价格口 = "http://127.0.0.1:8081/dx2/pcprice/default/dx2/interface/webGetPrice?infoJson="; - - public string 输出根 { get; private set; } - private string ZipDir { get { return Path.Combine(输出根, "dian", "electricData_zips"); } } - private string 价Dir { get { return Path.Combine(输出根, "dx2_webGetPrice"); } } - - /// 价格请求是否经旧代理(8081)。树/系列包恒直连(静态资源无会话要求)。 - public bool 经旧代理; - - /// 种子组合:旧代理缓存里真实查询过的 (系列→组合串列表),价格抓取优先按种子形状。 - /// 种子表:sid → [bg组合串, t历史时间戳] 列表。 - /// 终版机制(实测):命中 = 系列在有效时刻 t 查过(服务器按 sid+t 记录) AND 组合是真实型号—— - /// 系列只要有一个种子的 t,即可解锁它全部规格组组合的价格查询;t 用当前时间必返空。 - private Dictionary> 种子 = new Dictionary>(); - private int 无t系列数; - private int 无t提示过; - - // 进度/日志回调(UI 线程调度由调用方处理) - public Action 日志 { get; set; } - public Action 进度 { get; set; } // (当前,总数) - public volatile bool 停止; - - public 抓取器(string 输出目录) - { - 输出根 = 输出目录; - Directory.CreateDirectory(ZipDir); - Directory.CreateDirectory(价Dir); - // net48 下显式启用 TLS1.2(dq123 全站 https,不设会握手失败) - try { ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12; } - catch { } - ServicePointManager.DefaultConnectionLimit = 32; - } - - /// 从缓存/数据目录加载种子(webGetPrice 响应里的 bg 组合串+原始 t 时间戳)。 - /// 可多处调用合并(旧代理缓存+元件库网页 data 的现成真价都吃)。返回种子系列数。 - public int 加载种子(string 目录) - { - if (种子 == null) 种子 = new Dictionary>(); - try - { - foreach (string f in Directory.GetFiles(目录, "*webGetPrice*.data")) - { - try - { - string body = File.ReadAllText(f); - foreach (System.Text.RegularExpressions.Match m in - System.Text.RegularExpressions.Regex.Matches(body, "\"content\"\\s*:\\s*\"([A-Za-z0-9+/=]+)\"")) - { - string decoded; - try { decoded = Encoding.UTF8.GetString(Convert.FromBase64String(m.Groups[1].Value)); } - catch { continue; } - if (string.IsNullOrEmpty(decoded) || decoded.Trim() == "[]") continue; - // ★ JavaScriptSerializer.Deserialize 对顶层数组返回 Object[](不是 ArrayList), - // 按 IEnumerable 遍历两者通吃——之前 as ArrayList 恒 null,种子从来没加载成功过 - System.Collections.IEnumerable 条集 = 解析器.Deserialize(decoded) as System.Collections.IEnumerable; - if (条集 == null) continue; - foreach (object o in 条集) - { - var it = o as Dictionary; - if (it == null || !it.ContainsKey("sid")) continue; - string sid = Convert.ToString(it["sid"]); - string bg = it.ContainsKey("bg") ? Convert.ToString(it["bg"]) : ""; - // ★ t 是 13 位毫秒时间戳:JavaScriptSerializer 把 JSON 整数解析成 double, - // Convert.ToString(double) 会变成科学计数法(1.785401168E+12)拼进 time 服务器不认—— - // 必须经 ToDouble→ToInt64 还原成纯数字串 - string t = ""; - object tv; - if (it.TryGetValue("t", out tv) && tv != null) - { - try { t = Convert.ToInt64(Convert.ToDouble(tv)).ToString(); } - catch { } - } - if (string.IsNullOrEmpty(sid) || string.IsNullOrEmpty(bg) || bg.IndexOf('-') < 0) continue; - if (string.IsNullOrEmpty(t)) continue; // 没 t 的种子重放不了(当前时间必空),跳过 - List l; - if (!种子.TryGetValue(sid, out l)) { l = new List(); 种子[sid] = l; } - if (!l.Any(e => e[0] == bg)) l.Add(new[] { bg, t }); - } - } - } - catch { } - } - } - catch { } - return 种子.Count; - } - - private void L(string s) { if (日志 != null) 日志(s); } - - // ---------- HTTP(简单重试) ---------- - private byte[] Get(string url, int timeoutMs) - { - for (int 试 = 0; 试 < 3 && !停止; 试++) - { - try - { - var req = (HttpWebRequest)WebRequest.Create(url); - req.Method = "GET"; - req.Timeout = timeoutMs; - req.ReadWriteTimeout = timeoutMs; - req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0"; - req.Referer = "https://www.dq123.com/"; - req.Proxy = null; - using (var r = (HttpWebResponse)req.GetResponse()) - using (var ms = new MemoryStream()) - { - r.GetResponseStream().CopyTo(ms); - return ms.ToArray(); - } - } - catch (WebException we) - { - var hr = we.Response as HttpWebResponse; - if (hr != null && (int)hr.StatusCode >= 400 && (int)hr.StatusCode < 500) - return null; // 4xx(404 无此包)不重试,快速跳过 - Thread.Sleep(600); - } - catch (Exception) { return null; } - } - return null; - } - - // ---------- v 参数(base64 逻辑名去 padding) ---------- - private static string V参数(string 逻辑名) - { - string b = Convert.ToBase64String(Encoding.UTF8.GetBytes(逻辑名)); - return b.TrimEnd('='); - } - - /// 读 ZIP 字节数组里的首个文件文本(JSON)。失败返回 null。 - private static string 读Zip内文(byte[] zip) - { - try - { - using (var ms = new MemoryStream(zip)) - using (var z = new ZipArchive(ms)) - { - var e = z.Entries[0]; - using (var r = new StreamReader(e.Open(), Encoding.UTF8)) - return r.ReadToEnd(); - } - } - catch { return null; } - } - - // ---------- JSON 反序列化(JavaScriptSerializer) ---------- - private static readonly System.Web.Script.Serialization.JavaScriptSerializer 解析器 = - new System.Web.Script.Serialization.JavaScriptSerializer { MaxJsonLength = 64 * 1024 * 1024 }; - - /// 系列包 → 主规格组有序表(aq顺序号→as选项列表)。 - /// ★ 实测规则(1122 对照页面真实组合 337-350-15-9-29-30-37 破解): - /// 参与组合的组 = 顶层 c 键里 bc==0 且 p==2 的项;段顺序 = aq 字段升序; - /// bc!=0 / p!=2 的组(附件名称、延时类型等)不参与组合。 - /// 系列包名 = 4/z_p/{系列id}.jss(不是 z_seri)。 - private static SortedDictionary> 规格组(string 系文) - { - var g = new SortedDictionary>(); - try - { - var root = 解析器.Deserialize>(系文); - object co; - if (root == null || !root.TryGetValue("c", out co)) return g; - var cArr = co as System.Collections.ArrayList; - if (cArr == null) return g; - foreach (object o in cArr) - { - var 组 = o as Dictionary; - if (组 == null) continue; - // ★ 终版规则(SDK Ke 过滤器:z 数组=an==1;两厂实测 725/1122 真实组合段 100% 命中): - // p 各家不同(正泰=1 德力西=2),不能加 p 条件 - if (Convert.ToInt32(组.ContainsKey("an") ? 组["an"] : 0) != 1) continue; - int aq = Convert.ToInt32(组.ContainsKey("aq") ? 组["aq"] : 0); - var ar = 组.ContainsKey("ar") ? 组["ar"] as System.Collections.ArrayList : null; - if (ar == null || ar.Count == 0) continue; - var l = new List(); - foreach (object oo in ar) - { - var 选项 = oo as Dictionary; - if (选项 == null || !选项.ContainsKey("as")) continue; - l.Add(Convert.ToInt32(选项["as"])); - } - if (l.Count > 0 && !g.ContainsKey(aq)) g[aq] = l; - } - } - catch { } - return g; - } - - // ---------- 最小 JSON 取值(避免引第三方库;仅取固定结构字段) ---------- - private static System.Text.RegularExpressions.MatchCollection 正则匹配(string json, string pattern) - { - return System.Text.RegularExpressions.Regex.Matches(json, pattern); - } - - /// 解析厂家树 ZIP 文本 → 叶子系列号(s 字段非 0)列表。 - public static List 树系列(string 树文) - { - var r = new List(); - foreach (System.Text.RegularExpressions.Match m in 正则匹配(树文, "\"s\"\\s*:\\s*(\\d+)")) - { - string v = m.Groups[1].Value; - if (v != "0" && !r.Contains(v)) r.Add(v); - } - return r; - } - - /// 组合策略(照 preheat 脚本):默认组合 + 每组每选项单独变化。 - private static List 组合(SortedDictionary> g) - { - if (g.Count == 0) return new List(); - var 默认 = g.Values.Select(l => l[0].ToString()).ToList(); - var r = new List { string.Join("-", 默认) }; - for (int i = 0; i < g.Count; i++) - { - foreach (int ab in g.Values.ElementAt(i).Skip(1)) - { - var c = new List(默认) { }; - c[i] = ab.ToString(); - r.Add(string.Join("-", c)); - } - } - return r; - } - - // ---------- webGetPrice 哈希(复刻 python json.dumps 分隔符) ---------- - private static string PyDumps(string json) - { - // 本场景 JSON 只含 ASCII 字符串/数字/数组/对象,手工重排分隔符即可: - // 把 "," 与 ":" 后补空格(仅结构符,字符串内部不会出现裸的这些符号——base64 内容安全) - var sb = new StringBuilder(json.Length * 2); - bool 引号内 = false; - for (int i = 0; i < json.Length; i++) - { - char c = json[i]; - sb.Append(c); - if (c == '"') 引号内 = !引号内; - else if (!引号内 && (c == ',' || c == ':')) - { - char 后 = i + 1 < json.Length ? json[i + 1] : ' '; - if (后 != ' ') sb.Append(' '); - } - } - return sb.ToString(); - } - - public static string 价格哈希(string infoJsonB64) - { - string json = Encoding.UTF8.GetString(Convert.FromBase64String(infoJsonB64)); - // 剥 time 字段("time":123,) —— 手工正则 - json = System.Text.RegularExpressions.Regex.Replace(json, "\"time\"\\s*:\\s*\\d+\\s*,?\\s*", ""); - json = json.Replace(",}", "}").Replace(",]", "]"); - string 稳定 = "infoJson=" + Convert.ToBase64String(Encoding.UTF8.GetBytes(PyDumps(json))); - using (var md5 = MD5.Create()) - return BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(稳定))).Replace("-", "").ToLower().Substring(0, 8); - } - - // ---------- 抓取主流程 ---------- - /// 抓一个厂家:树+全部系列+全部组合价格。返回 (系列数, 价格数)。任何异常不外抛(记日志返回 0)。 - public KeyValuePair 抓厂家(string 树id, string 厂名, int 线程数) - { - try - { - return 抓厂家内部(树id, 厂名, 线程数); - } - catch (Exception ex) - { - L("! 厂家 " + 厂名 + " 抓取异常: " + ex.Message); - return new KeyValuePair(0, 0); - } - } - - private KeyValuePair 抓厂家内部(string 树id, string 厂名, int 线程数) - { - // 1) 厂家树(断点:已存在直接读) - string 树zip路径 = Path.Combine(ZipDir, 树id + ".zip"); - string 树文 = null; - if (File.Exists(树zip路径)) - { - 树文 = 读Zip内文(File.ReadAllBytes(树zip路径)); - } - if (树文 == null) - { - byte[] z = Get(电数据 + V参数("z_seri/" + 树id + ".jss") + "&t=" + 时间戳(), 20000); - if (z == null || z.Length < 100) { L("× 厂家 " + 厂名 + " 树拉取失败"); return new KeyValuePair(0, 0); } - File.WriteAllBytes(树zip路径, z); - 树文 = 读Zip内文(z); - Thread.Sleep(50); - } - if (树文 == null) { L("× 厂家 " + 厂名 + " 树解析失败"); return new KeyValuePair(0, 0); } - var 系列 = 树系列(树文); - L("▶ " + 厂名 + ": " + 系列.Count + " 个系列"); - 无t系列数 = 0; 无t提示过 = 0; - - // 2) 并发抓系列 - var 队列 = new ConcurrentQueue(系列); - var 计数 = new int[2]; - var 线程 = new List(); - for (int i = 0; i < Math.Max(1, 线程数); i++) - { - var t = new Thread(delegate() - { - string sid; - while (!停止 && 队列.TryDequeue(out sid)) - { - int 局系 = 0, 局价 = 0; - string szPath = Path.Combine(ZipDir, sid + ".zip"); - string 系文 = null; - try - { - 系文 = File.Exists(szPath) ? 读Zip内文(File.ReadAllBytes(szPath)) : null; - if (系文 == null) - { - byte[] z = Get(电数据 + V参数("4/z_p/" + sid + ".jss") + "&t=" + 时间戳(), 20000); - if (z != null && z.Length > 100) { File.WriteAllBytes(szPath, z); 系文 = 读Zip内文(z); Thread.Sleep(20); } - } - if (系文 != null && 系文.IndexOf("\"c\"") >= 0) - { - 局系 = 1; - // ★ 终版机制(实测):命中 = 系列在有效时刻 t 查过 AND 组合是真实型号。 - // 每个系列只要有一个种子的 t,就能解锁它全部规格组组合;无 t 的系列必空,跳过查价。 - List sd; - bool 有种子 = 种子.TryGetValue(sid, out sd) && sd.Count > 0; - if (!有种子) - { - Interlocked.Increment(ref 无t系列数); - if (无t提示过 == 0) - { - int n = Interlocked.Increment(ref 无t提示过); - if (n == 1) - L("· 提示: 无有效时刻(t)的系列跳过价格查询(服务器对没查过的系列+当前时间必返空)——已跳过 " + sid + " 等"); - } - } - else - { - string t种 = sd[0][1]; // 系列任一种子的 t(系列级会话标识,只配自己系列) - // ★ 组合恒用当前系列包规格组生成(默认+单变化):编号与页面渲染同源,查到的价页面必能命中。 - // 种子 bg(旧版本编号)不再作基底——跨版本编号混合的组合页面永远点不出来(725 教训:75条仅1条可用)。 - var cs = 组合(规格组(系文)); - foreach (string c in cs) - { - string info = 构造infoJson(sid, c, t种); - string h = 价格哈希(info); - string 价path = Path.Combine(价Dir, "dx2_pcprice_default_dx2_interface_webGetPrice_" + h + ".data"); - if (!File.Exists(价path)) - { - string 口 = 经旧代理 ? 代价格口 : 价格口; - byte[] body = Get(口 + info, 20000); - // ★ 空结果不落盘:content="W10="(base64("[]"))或 content="" 都表示该组合厂家无报价, - // 存了也是废数据(旧代理靠运行时合成兜底,新服务只需要真价格) - string 文 = body == null ? null : Encoding.UTF8.GetString(body); - bool 有价 = 文 != null && 文.Length > 30 && 文.Length < 300000 - && 文.IndexOf("\"content\":\"W10=\"") < 0 - && 文.IndexOf("\"content\": \"W10=\"") < 0 - && 文.IndexOf("\"content\":\"\"") < 0 - && 文.IndexOf("\"content\": \"\"") < 0; - if (有价) - { - File.WriteAllBytes(价path, body); - var mb = System.Text.RegularExpressions.Regex.Match(文, "\"bh\"\\s*:\\s*\"?([0-9.]+)"); - L(" ¥ 系列" + sid + " 命中真价" + (mb.Success ? " " + mb.Groups[1].Value + " 元" : "") + ": " + c); - } - Thread.Sleep(20); - } - 局价++; - } - } - } - } - catch (Exception ex_series) - { - L("· 系列 " + sid + " 异常: " + ex_series.Message); - } - Interlocked.Add(ref 计数[0], 局系); - Interlocked.Add(ref 计数[1], 局价); - if (进度 != null) 进度(0, 0); - } - }); - t.IsBackground = true; - 线程.Add(t); t.Start(); - } - foreach (var t in 线程) t.Join(); - if (无t系列数 > 0) - L("· " + 厂名 + ": " + 无t系列数 + " 个系列无有效时刻(t),已跳过价格查询(可先在预热页面浏览这些系列再抓)"); - return new KeyValuePair(计数[0], 计数[1]); - } - - private static long 时间戳() { return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; } - - /// 构造 infoJson 的 base64。t 必须传历史时间戳(种子的原始 t 或兜底 t): - /// 实测服务器只对「真实查过的组合+历史时间戳」返回真价,当前时间必空。 - private static string 构造infoJson(string 系列, string 组合串, string t) - { - // {"s": "1122", "options": ["337-350"], "time": 123, "from": "dx2jsapi"} —— 键序照 SDK - string json = "{\"s\": \"" + 系列 + "\", \"options\": [\"" + 组合串 + "\"], \"time\": " + t + ", \"from\": \"dx2jsapi\"}"; - return Convert.ToBase64String(Encoding.UTF8.GetBytes(json)); - } - } -} diff --git a/yjktool/测试入口.cs b/yjktool/测试入口.cs deleted file mode 100644 index f116880..0000000 --- a/yjktool/测试入口.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace yjktool -{ - static class 测试入口 - { - [STAThread] - static int Main(string[] args) - { - string 树id = args.Length > 0 ? args[0] : "10"; - Console.OutputEncoding = System.Text.Encoding.UTF8; - var g = new 抓取器(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "抓取输出")) - { 日志 = s => Console.WriteLine(s) }; - var kv = g.抓厂家(树id, "(测试厂" + 树id + ")", 4); - Console.WriteLine("== 结果: 系列 {0}, 价格 {1}", kv.Key, kv.Value); - return 0; - } - } -} diff --git a/yjktool/种子组合.json b/yjktool/种子组合.json deleted file mode 100644 index 02ae304..0000000 --- a/yjktool/种子组合.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "37141": [ - "5-10-14-15-19-21-23" - ], - "1506": [ - "10-15-19-21-460-26-44", - "8-15-19-21-460-26-44", - "230-15-19-21-460-26-39", - "230-331-19-21-460-446-39", - "11-15-19-21-460-26-48", - "182-313", - "11-17-19-21-460-27-50", - "11-17-19-21-460-27-48", - "9-12-19-21-460-26-28", - "7-15-19-21-460-26-39", - "10-15-19-21-460-26-48", - "11-17-19-21-460-26-48", - "11-329-19-21-460-26-48", - "159-285", - "230-14-19-21-460-26-39", - "119-279", - "7-331-19-21-460-446-28", - "114-115-267", - "11-330-19-21-460-26-48", - "8-15-19-21-460-26-39", - "382-384" - ], - "46805": [ - "5-7-14" - ], - "725": [ - "7-13-22-15-17-18-19-25-74-20-46-27-82-83-96-84-353", - "8-13-22-15-17-18-19-25-74-20-46-27-82-83-96-84-353", - "56-24-22-15-17-18-19-25-74-20-33-27-82-83-96-84-353", - "23-24-22-15-17-18-19-25-74-20-85-27-82-83-96-84-353", - "7-13-22-15-17-18-19-25-74-20-41-27-82-83-96-84-353", - "6-12-22-15-17-18-19-25-74-20-39-27-82-83-96-84-353", - "341-13-22-15-17-18-19-25-74-20-48-27-82-83-96-84-352", - "56-24-22-28-17-18-19-25-74-20-85-27-82-83-96-84-353", - "23-24-22-15-17-18-19-25-74-20-35-27-82-83-96-84-353", - "56-24-22-15-17-18-59-25-75-20-29-27-82-83-96-84-353", - "319-12-22-28-17-18-19-25-74-20-29-27-82-83-96-84-352", - "5-12-22-28-17-18-19-25-74-20-29-27-82-83-96-84-353", - "56-24-22-15-17-18-59-25-74-20-29-27-82-83-96-84-353", - "6-12-22-15-17-18-19-25-74-20-37-27-82-83-96-84-353", - "56-24-22-15-17-18-19-25-74-20-85-27-82-83-96-84-353", - "23-24-22-28-17-18-19-25-74-20-85-27-82-83-96-84-353", - "56-24-22-28-17-18-19-25-74-20-85-27-82-83-96-84-350", - "330-13-22-15-17-18-19-25-74-20-46-27-82-83-96-84-352", - "6-12-22-15-17-18-19-25-74-20-36-27-82-83-96-84-353" - ], - "47762": [ - "5-6-8-9-10" - ], - "42825": [ - "5-11-14", - "5-6-13", - "5-10-14", - "5-12-15" - ], - "3205": [ - "5-11-15-27", - "10-13-15-27" - ], - "56242": [ - "5-10-14-19-20-22-29-31-32" - ], - "1401": [ - "5-6-8-12-16" - ], - "2486": [ - "5-8-6-936-14-46-35-33" - ], - "1245": [ - "5-7-16-17" - ], - "10586": [ - "6-12" - ], - "48269": [ - "5-807-22-37-58-60-17-67-810" - ], - "47084": [ - "5-6-12-16-20" - ], - "1122": [ - "337-350-15-9-29-30-37", - "6-13-18-10-28-30-37" - ], - "40": [ - "5-8" - ], - "23641": [ - "7-163-10-12-14-164-19-21" - ], - "757": [ - "5-11-66-17-20-21-22-23-25-27-68-67-91-90-96-92-134" - ], - "1825": [ - "5-18-26-9-15-8" - ], - "733": [ - "18-37-32-39" - ], - "59163": [ - "5-11-13-16-19-21", - "5-11-15-17-20-27" - ], - "32339": [ - "7-124-8-34" - ], - "1427": [ - "5-7-24-17" - ], - "604": [ - "16-5-12-15", - "16-5-12-14" - ], - "71": [ - "5-15-50-154" - ], - "47960": [ - "5-12-10-20-23-26-37-63" - ], - "791": [ - "5-7-11-13" - ], - "1086": [ - "10-6-30", - "12-6-30" - ], - "735": [ - "5-7-17-12-13-15-16-119" - ] -} \ No newline at end of file diff --git a/yjktool/系列数据表.csv b/yjktool/系列数据表.csv deleted file mode 100644 index cc09f05..0000000 --- a/yjktool/系列数据表.csv +++ /dev/null @@ -1,1524 +0,0 @@ -编号,类型,名称,型号代码,规格组数,级联映射条数,真实价格条数,价格明细(型号=价格元) -1,树,(正泰厂家树·1859条),,,, -2,系列,NH1系列隔离开关,NH1,7,186,0, -4,系列,NA8系列智能型万能式断路器(按项目报价),NA8,53,242,0, -5,系列,NA1-2000X~6300X系列万能式断路器(带欠压),NA1,48,383,0, -6,系列,NA1-1000X系列万能式断路器,NA1,44,299,0, -7,系列,DW17系列万能式断路器,DW17,13,294,0, -8,系列,DW16系列万能式断路器(已停产,被DW15替代),DW16,5,30,0, -9,系列,DW15系列万能式断路器,DW15,19,314,0, -10,系列,DZ15LE系列漏电断路器,DZ15LE,12,29,0, -11,系列,NL18系列剩余电流动作断路器(已停产,建议选用NXBLE),NL18,3,4,0, -12,系列,NM8L、NM8SL系列塑壳漏电断路器(已停产,建议选用NM8NL),NM8,10,39,0, -13,系列,DZ267-32系列小型断路器(已停产,建议选用NXB-40),DZ267,4,0,0, -14,系列,DZ47-60系列型小型断路器(已停产,被NXB-63替代),DZ47,4,34,0, -15,系列,NBH8-40系列家用小型断路器,NBH8,11,12,0, -16,系列,NB1-63H系列高分断小型断路器(双汇流排),NB1,9,2,0, -17,系列,DZ267LE-32系列剩余电流动作断路器(已停产,建议选用NXBLE-40),DZ267LE,6,0,0, -19,系列,DZ47LE-63系列剩余电流动作断路器(已停产,被NXBLE-63替代),DZ47LE,5,23,0, -20,系列,NL1E-63系列剩余电流动作断路器,NL1E,4,2,0, -21,系列,NL1-63系列剩余电流动作断路器,NL1,6,2,0, -22,系列,NBH8LE-40系列剩余电流动作断路器,NBH8LE,5,2,0, -23,系列,NB47LE-63系列剩余电流动作断路器(已停产,建议选用NXBLE-63),NB47LE,4,18,0, -24,系列,NB1LE-63系列电子式剩余电流动作断路器,NB1LE,7,17,0, -25,系列,NB1LE-40系列电子式剩余电流动作断路器,NB1LE,7,11,0, -26,系列,NB1L-63系列电磁式剩余电流动作断路器,NB1L,5,6,0, -27,系列,NB1L-40系列电磁式剩余电流动作断路器,NB1L,8,339,0, -28,系列,NH3-63系列隔离开关,NH3,2,3,0, -29,系列,NH9-32系列隔离开关,NH9,3,4,0, -30,系列,NH4-125系列隔离开关,NH4,3,4,0, -31,系列,NH2-125系列隔离开关,NH2,3,4,0, -32,系列,DZ158S-100IC系列卡表专用断路器(已停产,建议选用NBP-100S),DZ158S,2,0,0, -33,系列,NB7S-100系列带分励脱扣断路器(已停产,建议选用NBP-100S),NB7S,3,0,0, -34,系列,NB7S-63系列带分励脱扣断路器(已停产,建议选用NBP-63S),NB7S,4,0,0, -36,系列,NU6-Ⅲ系列电涌保护器,NU6-Ⅲ,4,2,0, -37,系列,NU6-Ⅱ系列电涌保护器(已停产,建议选用NU6-ⅡG),NU6-Ⅱ,4,3,0, -38,系列,NX8系列配电箱(已停产),NX8,8,12,0, -39,系列,NX2系列配电箱(已停产,建议选用NX30),NX2,1,0,0, -40,系列,JR36系列热过载继电器,JR36,2,24,1,JR36-20 0.25-0.35A = 44.439998626709 元 -41,系列,JRS1系列热过载继电器(已停产,被NR2替代),JRS1,5,12,0, -42,系列,NR4系列热过载继电器(已停产,被NR4-G代替),NR4,3,28,0, -44,系列,NR2系列热过载继电器,NR2,4,39,0, -45,系列,CZ0系列直流接触器(已停产,建议选用NCZ2),CZ0,4,65,0, -46,系列,NJX-13FW系列无氧化零飞弧电磁继电器,NJX-13FW,5,101,0, -47,系列,NJB1-S系列时间继电器(已停产,建议选用NTE8),NJB1,2,0,0, -48,系列,NJB1-Y系列单相电压继电器,NJB1,2,9,0, -49,系列,NJB1-X/X1系列继电器,NJB1,2,2,0, -50,系列,NJB1-YW系列液位继电器,NJB1-YW,1,0,0, -51,系列,NJS1系列时间继电器(已停产,建议选用JSS48A),NJS1,4,31,0, -53,系列,DJ1系列电流时间转换装置(已停产),DJ1,4,9,0, -54,系列,KG316T系列时控开关,KG316T,4,6,0, -55,系列,KG10M系列时控开关,KG10M,2,2,0, -56,系列,KG10D系列时控开关,KG10D,2,0,0, -57,系列,NKG1系列时控开关,NKG1,1,0,0, -59,系列,JYB-714系列液位继电器,JYB-714,2,0,0, -60,系列,NJYW1系列液位继电器,NJYW1,3,6,0, -61,系列,JZF系列正反转控制继电器,JZF,2,16,0, -63,系列,XJ3系列断相与相序保护继电器,XJ3,3,9,0, -64,系列,JZC4系列接触器式继电器,JZC4,10,5,0, -65,系列,JZC1系列接触器式继电器,JZC1,3,30,0, -66,系列,JZ7系列中间继电器,JZ7,2,5,0, -68,系列,NRE8系列电子式过载继电器(按项目报价),NRE8,3,49,0, -70,系列,NB1-63系列小型断路器,NB1,14,27,0, -71,系列,CJX2系列交流接触器,CJX2,37,530,1,CJX2-0910 24V = 117.62999725342 元 -72,系列,CJX2系列机械联锁交流接触器,CJX2,19,14,0, -73,系列,CJ19系列电容交流接触器,CJ19,3,16,0, -74,系列,"CJT1系列交流接触器(已停产,被NXC代替)",CJT1,29,125,0, -75,系列,CJ20系列交流接触器,CJ20,34,354,0, -76,系列,NC3(CJ46)系列交流接触器(已停产,建议选用NXC),NC3(CJ46),21,109,0, -77,系列,CJ12系列交流接触器(已停产,建议选用NC2、NC7、NC8),CJ12,3,13,0, -79,系列,CJ40系列交流接触器,CJ40,19,124,0, -80,系列,NC2系列交流接触器,NC2,32,240,0, -81,系列,NC5系列交流接触器,NC5,19,181,0, -82,系列,NC6系列交流接触器(已停产,建议选用NXC-M),NC6,8,17,0, -83,系列,NC9系列真空交流接触器(已停产,建议选用CJX1-K),NC9,8,40,0, -84,系列,NCK3系列空调用交流接触器,NCK3,5,11,0, -85,系列,NCH8系列家用交流接触器,NCH8,3,12,0, -86,系列,CKJ5系列真空交流接触器(已停产),CKJ5,6,15,0, -87,系列,CJX1系列交流接触器,CJX1,18,170,0, -88,系列,CJX1-N系列交流接触器,CJX1,4,51,0, -89,系列,NCX1系列交流接触器(已停产,建议选用NCX1防尘型),NCX1,6,4,0, -90,系列,NC7系列交流接触器(已停产,建议选用NXC),NC7,24,220,0, -92,系列,DZ15系列塑壳断路器,DZ15,6,22,0, -93,系列,"NM10系列塑壳断路器(已停产,被NXM替换)",NM10,26,85,0, -95,系列,NJS2系列时间继电器(已停产,建议选用NJS1-M),NJS2,1,0,0, -97,系列,NTE8系列时间继电器,NTE8,3,14,0, -98,系列,JSS48A系列时间继电器(部分产品已停销),JSS48A,8,208,0, -99,系列,JSS48B系列时间继电器(已停产,建议选用JSS48A),JSS48B,1,0,0, -100,系列,JSZ3系列时间继电器,JSZ3,7,48,0, -104,系列,JS14A系列时间继电器,JS14A,5,25,0, -105,系列,JS14P系列时间继电器,JS14P,3,48,0, -106,系列,JS14S系列时间继电器(部分产品已停销),JS14S,3,37,0, -107,系列,LMZ1-0.66系列低压电流互感器(0.2级)(已停产,建议选用BH-0.66),LMZ1,2,22,0, -108,系列,JSS1系列时间继电器(已停产,建议选用JSS48A),JSS1,4,20,0, -109,系列,NDK系列控制变压器,NDK,3,258,0, -110,系列,NDKS系列控制变压器,NDKS,3,22,0, -111,系列,NDKG系列控制变压器,NDKG,3,35,0, -112,系列,NDKR系列控制变压器,NDKR,3,22,0, -113,系列,BKC系列控制变压器(已停产,建议选用NDK),BKC,2,10,0, -114,系列,JS11S系列时间继电器(部分产品已停销),JS11S,3,30,0, -115,系列,JBK1系列机床控制变压器(已停产,建议选用JBK4),JBK1,1,0,0, -116,系列,JBK3系列机床控制变压器,JBK3,3,98,0, -117,系列,JBK5系列机床控制变压器,JBK5,3,91,0, -118,系列,JBK6系列机床控制变压器,JBK6,3,11,0, -119,系列,JMB系列照明变压器,JMB,4,138,0, -120,系列,SG系列三相开启式干式变压器,SG,1,0,0, -121,系列,BKZ系列整流变压器,BKZ,3,6,0, -122,系列,LMZJ1-0.5系列低压电流互感器(0.2级),LMZJ1,5,68,0, -123,系列,JS11系列时间继电器(已停产,建议选用JS11S),JS11,3,22,0, -124,系列,LMZ1-0.66系列低压电流互感器(0.5级)(已停产,建议选用BH-0.66),LMZ1,3,42,0, -125,系列,JZX-22F系列小型中功率电磁继电器,JZX-22F,7,117,0, -126,系列,LMZ1-0.66系列低压电流互感器(0.5S级)(已停产,建议选用BH-0.66),LMZ1,2,19,0, -127,系列,JQX-10F系列通用型小型大功率电磁继电器,JQX-10F,4,8,0, -128,系列,LMZJ1-0.5系列低压电流互感器(0.5级),LMZJ1,5,167,0, -129,系列,JTX系列通用型小型大功率电磁继电器,JTX,4,6,0, -130,系列,JQX-13F系列小型电磁继电器,JQX-13F,5,36,0, -131,系列,QZB-J系列起动用自耦减压变压器,QZB-J,1,22,0, -132,系列,JMK系列通用型小型大功率电磁继电器,JMK,4,6,0, -133,系列,LMZJ1-0.5系列低压电流互感器(0.5S级),LMZJ1,5,75,0, -134,系列,BP8R1系列频敏变阻器(已停产,建议选用BP8Y),BP8R1,3,17,0, -136,系列,LMZJ1-0.66系列低压电流互感器(0.2级),LMZJ1,4,59,0, -137,系列,BP8R2系列频敏变阻器(已停产,建议选用BP8Y),BP8R2,3,4,0, -138,系列,BP8R3系列频敏变阻器(已停产,建议选用BP8Y),BP8R3,3,13,0, -142,系列,LMZJ1-0.66系列低压电流互感器(0.5级),LMZJ1,4,78,0, -144,系列,LMZJ1-0.66系列低压电流互感器(0.5S级),LMZJ1,4,59,0, -145,系列,BP8Y系列频敏变阻器,BP8Y,3,16,0, -146,系列,LQG-0.66系列低压电流互感器(0.2级),LQG,3,22,0, -148,系列,NJJ3系列计数继电器,NJJ3,1,0,0, -149,系列,NJJ5-J系列电子式计数器,NJJ5,4,0,0, -150,系列,JDM1-14系列计数继电器(已退市,建议选用JDM1-48),JDM1-14,3,0,0, -151,系列,JJ1系列自耦减压起动控制柜,JJ1,1,18,0, -152,系列,JDM1-48系列计数继电器,JDM1-48,4,0,0, -153,系列,JDM1-9系列计数继电器,JDM1-9,2,0,0, -154,系列,JDM15G系列计数继电器(已退市,建议选用NJJ3),JDM15G,1,0,0, -155,系列,JDM1-6系列计数继电器(已停产,建议选用NJJ5-J),JDM1-6,2,0,0, -156,系列,LQG-0.66系列低压电流互感器(0.5级),LQG,3,22,0, -157,系列,TDR系列电源变压器(已停产,建议选用NDK),TDR,1,12,0, -158,系列,JDM3系列超小型电子式计数器,JDM3,3,3,0, -159,系列,LQG-0.66系列低压电流互感器(0.5S级),LQG,3,22,0, -160,系列,HB系列环型电源变压器(已停产,建议选用NDK),HB,1,9,0, -161,系列,NJJ5-L系列电子式累时器,NJJ5,4,0,0, -163,系列,SC3L系列超小型电子式累时器,SC3L,3,6,0, -164,系列,TDGC2系列单相接触调压器,TDGC2,3,24,0, -165,系列,JD-5系列电动机综合保护器,JD-5,5,27,0, -166,系列,TSGC2系列三相接触调压器,TSGC2,2,11,0, -168,系列,NKY1系列开关电源,NKY1,3,34,0, -169,系列,JD-8系列电动机综合保护器,JD-8,1,5,0, -170,系列,JD-9系列电动机综合保护器(已停产,被JD-8代替),JD-9,1,0,0, -171,系列,NJBK2系列电动机保护继电器,NJBK2,6,16,0, -172,系列,NJBK5系列电动机控制器(已停产),NJBK5,4,0,0, -173,系列,NJBK6系列电动机保护继电器,NJBK6,3,0,0, -174,系列,LMZ3-0.66系列低压电流互感器(0.5级实芯)(已停产),LMZ3,4,0,0, -175,系列,LMZ3-0.66系列低压电流互感器(0.5级)(已停产,替换产品为LMZJ1),LMZ3,5,75,0, -176,系列,LMZW1-0.5系列户外低压电流互感器(0.5级),LMZW1,5,50,0, -177,系列,LMZW1-0.5系列户外低压电流互感器(0.5S级),LMZW1,4,18,0, -179,系列,NKG2系列时控开关(已停产,被NKG3-M代替),NKG2,1,0,0, -180,系列,NLH1-0.66系列电流互感器(0.2级)(已停产,被BH-I代替),NLH1,4,43,0, -181,系列,NLH1-0.66系列电流互感器(0.5级)(已停产,被BH-I代替),NLH1,4,46,0, -182,系列,NLH1-0.66系列电流互感器(0.5S级)(已停产,被BH-I代替),NLH1,4,43,0, -183,系列,JDG4-0.5系列电压互感器,JDG,3,0,0, -184,系列,JDZ-1系列电压互感器(即将停销,被JDZ6-1产品替代),JDZ,3,4,0, -185,系列,XD1系列限流电抗器,XD,3,10,0, -186,系列,TNSZ(SBW)系列三相大功率补偿型稳压器,TNSZ(SBW),1,18,0, -187,系列,RCT系列低压电流互感器(0.5级)(已停产,替换产品为BH-0.66),RCT,3,30,0, -188,系列,TNDZ(DBW)系列单相大功率补偿式稳压器,TNDZ(DBW),1,0,0, -190,系列,NPS系列交流精密稳压电源,NPS,2,2,0, -193,系列,TNS1(SVC)系列高精度全自动三相交流稳压电源,TNS1(SVC),2,10,0, -194,系列,TND1(SVC)系列高精度全自动单相交流稳压电源,TND1(SVC),4,32,0, -195,系列,TND3(TSD)系列挂壁式单相交流稳压电源,TND3(TSD),1,0,0, -196,系列,BH-0.66Ⅰ系列低压电流互感器(0.2级),BH,7,429,0, -199,系列,"LM-0.5系列低压电流互感器(即将停销,被NXLH-1产品替代)",LM,3,82,0, -200,系列,HD11系列开启式刀开关,HD,6,104,0, -201,系列,BH-0.66Ⅰ系列低压电流互感器(0.5级),BH,7,508,0, -202,系列,HD12系列开启式刀开关,HD,11,86,0, -203,系列,HD13系列开启式刀开关(HD其他各系列派生新型号),HD13,6,14,0, -204,系列,HD13/HD13BX系列开启式刀开关,HD,17,478,0, -205,系列,HD14系列开启式刀开关,HD,7,20,0, -206,系列,BH-0.66Ⅰ系列低压电流互感器(0.5S级),BH,7,433,0, -207,系列,HS11系列双投转换式刀开关,HS,9,143,0, -208,系列,HS13系列双投转换式刀开关(HS其他各系列派生新型号),HS13,5,13,0, -209,系列,HS13系列双投转换式刀开关,HS,14,287,0, -210,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.2级),BH,5,250,0, -211,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5级),BH,6,459,0, -212,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5S级),BH,5,198,0, -213,系列,BH-0.66Ⅲ系列低压电流互感器(0.2级),BH,5,113,0, -214,系列,BH-0.66Ⅲ系列低压电流互感器(0.5级),BH,5,138,0, -215,系列,BH-0.66Ⅲ系列低压电流互感器(0.5S级),BH,5,115,0, -216,系列,BH-0.66系列低压电流互感器(0.5级实心),BH,4,0,0, -217,系列,LMZW2-0.5系列电流互感器(0.5级),LMZW2,4,15,0, -218,系列,LQZJ1-0.66系列低压电流互感器(0.2级),LQZJ1,3,0,0, -219,系列,LQZJ1-0.66系列低压电流互感器(0.5级),LQZJ1,3,11,0, -220,系列,LQZJ1-0.66系列低压电流互感器(0.5S级),LQZJ1,3,0,0, -221,系列,HD13系列大电流开启式刀开关,HD13,6,32,0, -223,系列,BZMJ系列自愈式低压并联电容器,BZMJ,3,444,0, -224,系列,HF40系列防护式刀形隔离器,HF40,5,65,0, -225,系列,HR3系列熔断器式隔离开关,HR3,20,69,0, -226,系列,HR5系列熔断器式隔离开关,HR5,4,5,0, -227,系列,HR6系列熔断器式隔离开关,HR6,5,38,0, -228,系列,NHR17系列熔断器式隔离开关,NHR17,4,27,0, -230,系列,HH15(QSA)系列隔离开关熔断器组,HH15,4,8,0, -231,系列,HH15(QP)系列隔离开关,HH15,4,0,0, -232,系列,HH15(QA)系列隔离开关,HH15,4,2,0, -233,系列,HH15(QSS)系列隔离开关,HH15(QSS),2,12,0, -234,系列,GW9系列户外高压隔离开关,GW9,3,3,0, -235,系列,NH40SZ系列自动转换开关(PC级),NH40,11,1776,0, -236,系列,NHR40系列隔离开关熔断器组,NHR40,11,156,0, -237,系列,NH40系列隔离开关,NH40,11,230,0, -238,系列,NH40-F系列防护罩式隔离开关,NH40,6,2,0, -239,系列,NH50系列隔离开关长胶板,NH,6,0,0, -240,系列,HK18系列隔离开关,HK18,3,14,0, -245,系列,NWC1系列自愈式低压并联电容器,NWC1,4,217,0, -248,系列,NWC5系列自愈式低压并联电容器,NWC5,4,69,0, -249,系列,NWKL1系列智能型无功补偿控制器(无功电流型),NWKL1,2,0,0, -254,系列,JKF8系列智能型低压无功补偿控制器(复合控制型),JKF8,1,0,0, -257,系列,NWK1-G系列智能型低压无功补偿控制器,NWK1-G,1,0,0, -259,系列,LAY3系列按钮(已停产,建议选用NP2),LAY3,6,60,0, -260,系列,TBBX系列低压无功就地补偿装置(已停产,建议选用NWC6、BAGB450),TBBX,5,84,0, -265,系列,LA2系列按钮(已停产,建议选用NP2),LA,2,2,0, -266,系列,YBLX-K1系列行程开关,YBLX-K1,3,5,0, -269,系列,RT29系列圆筒形帽熔断器体,RT29,3,4,0, -270,系列,RT28系列熔断器体,RT28,4,26,0, -271,系列,RT36系列有填料封闭管式刀型触头熔断器体,RT36,2,16,0, -273,系列,YBLX-3系列行程开关,YBLX-3,2,0,0, -277,系列,HDLRT0系列有填料封闭管式熔断器体,HDLRT0,2,10,0, -278,系列,BZMJ-YN系列自愈式低压并联电容器,BZMJ,4,35,0, -279,系列,RS71(NGT)系列快速熔断器体,RS71,4,30,0, -280,系列,RT14系列熔断器底座,底座RT14,1,0,0, -281,系列,NH50系列隔离开关,NH,6,114,0, -283,系列,HDLRS3系列半导体设备保护用熔断体,HDLRS3,2,10,0, -284,系列,YBLX-12系列行程开关,YBLX-12,2,0,0, -285,系列,YBLX-19系列行程开关,YBLX-19,5,18,0, -286,系列,YBLX-22系列行程开关,YBLX-22,1,0,0, -287,系列,YBLX-33系列行程开关,YBLX-33,2,0,0, -288,系列,NRT36系列熔断体,NRT36,2,2,0, -290,系列,YBLXW-6系列微动开关,YBLXW,3,0,0, -291,系列,YBLXW-5系列微动开关,YBLXW,4,0,0, -292,系列,YBLX-JW2系列行程开关,YBLX-JW2,5,11,0, -293,系列,YBLX-K3系列行程开关,YBLX-K3,3,0,0, -294,系列,YBLX-P1系列行程开关,YBLX-P1,2,5,0, -295,系列,RT28(R)系列熔断器底座,底座RT28,4,0,0, -296,系列,RT28系列熔断体底座,底座RT28,3,0,0, -297,系列,RT29系列熔断体底座,底座RT29,1,0,0, -298,系列,YBLX-WL系列行程开关,YBLX-WL,1,0,0, -299,系列,NRT28系列熔断体底座,底座NRT28,3,6,0, -300,系列,YBLX-HL系列行程开关,YBLX-HL,1,6,0, -301,系列,NRT36系列熔断器底座,底座NRT36,2,0,0, -302,系列,HY23系列倒顺开关,HY23,4,8,0, -303,系列,HDLRT0系列有填料封闭管式熔断器底座,底座HDLRT0,1,5,0, -304,系列,HZ5系列组合开关,HZ5,4,5,0, -306,系列,HZ10系列组合开关,HZ10,7,129,0, -311,系列,HZ12系列组合开关,HZ12,2,2,0, -313,系列,LW5D系列万能转换开关,LW5D,4,29,0, -314,系列,LW6系列万能转换开关(已停产,被LW112替代),LW6,3,29,0, -316,系列,LW112系列万能转换开关,LW112,9,736,0, -321,系列,LW32系列万能转换开关,LW32,5,131,0, -330,系列,TB系列接线端子,TB,2,5,0, -338,系列,JCUK系列接线端子,JCUK,10,66,0, -340,系列,JCUK系列熔断器端子,JCUK,2,0,0, -344,系列,LA18系列按钮(已停产,建议选用NP2/NP4),LA18,3,8,0, -345,系列,LA19系列按钮(已停产,建议选用NP2),LA19,5,25,0, -351,系列,NP2系列塑料信号灯,NP2,16,16,0, -352,系列,HGW9系列户外高压隔离开关,HGW9,1,0,0, -358,系列,YBLT系列脚踏开关,YBLT,1,0,0, -359,系列,YBLT-EKW系列脚踏开关,YBLT-EKW,3,0,0, -360,系列,YBLT-YDT1系列脚踏开关,YBLT-YDT1,2,0,0, -361,系列,YBLT-JDK系列脚踏开关,YBLT-JDK,1,0,0, -378,系列,QJX2系列“星三角”减压起动器,QJX2,2,10,0, -379,系列,NQ2系列电磁起动器,NQ,6,64,0, -380,系列,QC36系列电磁起动器,QC36,4,18,0, -381,系列,NVF2G系列变频器,NVF2G,12,288,0, -382,系列,NZ7系列自动转换开关(CB级)(已停产,被NXZM替代),NZ7,8,48,0, -383,系列,NJR2-G系列软起动器控制柜,NJR,2,0,0, -387,系列,NA8G系列智能型万能式断路器(已停产,被NA8代替),NA8G,24,973,0, -388,系列,LAY3系列蘑菇头式按钮(已停产,建议选用NP2),LAY3,4,11,0, -389,系列,LAY3系列自锁式按钮(已停产,建议选用NP2),LAY3,4,12,0, -390,系列,LAY3系列旋柄开关(已停产,建议选用NP2),LAY3,4,31,0, -391,系列,LAY3系列钥匙式开关(已停产,建议选用NP2),LAY3,3,5,0, -392,系列,LA4系列按钮(已停产,建议选用NP2),LA,2,0,0, -393,系列,NP2系列平头式按钮,NP2,18,107,0, -394,系列,NP2系列蘑菇头式金属按钮,NP2,17,15,0, -395,系列,NP2系列旋钮(金属),NP2,17,34,0, -396,系列,NP2系列钥匙式按钮,NP2,16,12,0, -397,系列,NP2系列金属信号灯,NP2,16,9,0, -398,系列,NP2系列金属带灯平钮,NP2,19,25,0, -399,系列,NP2系列蘑菇头式塑料按钮,NP2,18,51,0, -400,系列,NP2系列旋钮(塑料),NP2,16,12,0, -402,系列,NP2系列塑料带灯平钮,NP2,19,23,0, -403,系列,NP2系列塑料双头带灯按钮,NP2,19,0,0, -404,系列,ND16系列信号灯,ND16,5,37,0, -405,系列,NP3系列控制按钮,NP3,2,4,0, -406,系列,NP4系列高、平钮,NP4,3,20,0, -407,系列,NP4系列蘑菇头式按钮,NP4,4,12,0, -408,系列,NP4系列旋钮,NP4,4,7,0, -409,系列,NP4系列带灯按钮,NP4,5,29,0, -410,系列,NP6系列平钮,NP6,4,0,0, -411,系列,NP6系列蘑菇头式按钮,NP6,3,0,0, -412,系列,NP6系列旋钮式按钮,NP6,4,2,0, -413,系列,NP6系列指示灯,NP6,5,6,0, -414,系列,NP8系列平钮,NP8,3,0,0, -415,系列,NP8系列蘑菇头式按钮,NP8,4,12,0, -416,系列,NP8系列双头钮,NP8,4,6,0, -417,系列,NP6系列钥匙钮,NP6,4,2,0, -418,系列,NP8系列旋钮,NP8,5,11,0, -419,系列,NP8系列钥匙钮,NP8,3,5,0, -420,系列,NP8系列指示灯,NP8,3,0,0, -421,系列,NP9系列按钮,NP9,5,22,0, -422,系列,ND9系列信号灯,ND9,5,40,0, -424,系列,HD11系列开启式长板刀开关,HD,5,0,0, -425,系列,HD11系列开启式保护型刀开关,HD,7,48,0, -426,系列,NHRT40系列熔断器式隔离开关,NHRT40,5,27,0, -428,系列,JBK2系列机床控制变压器(已停产,建议选用JBK4),JBK2,1,0,0, -429,系列,JBK4系列机床控制变压器,JBK4,3,22,0, -431,系列,YBLX-X2系列行程开关,YBLX,2,0,0, -432,系列,YBLX-ME系列行程开关,YBLX-ME,1,0,0, -433,系列,HY2系列倒顺开关,HY2,3,0,0, -436,系列,HS11系列保护型刀开关,HS,6,17,0, -445,系列,ND16系列超短型信号灯,ND16,6,42,0, -446,系列,ND16系列用于电容柜型信号灯,ND16,6,4,0, -447,系列,ND16系列双色灯信号灯,ND16,5,6,0, -448,系列,ND16系列快速接线型信号灯,ND16,5,2,0, -452,系列,RT36(NT)系列有填料封闭管式刀型触头熔断器底座,底座RT36,1,12,0, -453,系列,RT36(R)系列有填料封闭管式刀型触头熔断器底座,底座RT36,2,6,0, -454,系列,RT36(R)系列有填料封闭管式刀型触头熔断器体,RT36,4,16,0, -455,系列,RT36(NT00)系列底座,底座RT36-00(NT00),2,0,0, -458,系列,SG系列三相防护式干式变压器,SG,2,0,0, -459,系列,XJZ1系列自耦减压起动控制箱,XJZ1,1,15,0, -460,系列,NJL1系列漏电保护继电器,NJL1,1,0,0, -461,系列,NJL2系列漏电保护继电器,NJL2,4,4,0, -462,系列,LAY39系列平钮,LAY39,5,8,0, -463,系列,LAY39系列蘑菇头按钮,LAY39,4,6,0, -464,系列,LAY39系列瞬动型带灯钮,LAY39,6,0,0, -465,系列,LAY39系列瞬动型带灯蘑菇头钮,LAY39,6,0,0, -466,系列,LAY39系列旋钮,LAY39,5,8,0, -467,系列,LAY39系列钥匙钮,LAY39,5,0,0, -468,系列,NP4系列蘑菇头带灯按钮,NP4,5,3,0, -469,系列,NP4系列旋柄钮,NP4,4,18,0, -470,系列,NP4系列带灯旋钮,NP4,6,4,0, -471,系列,NP4系列钥匙钮,NP4,3,5,0, -472,系列,NP6系列带灯平钮,NP6,6,6,0, -473,系列,NP8系列高钮,NP8,3,0,0, -474,系列,NP8系列带灯平钮,NP8,4,0,0, -475,系列,NP8系列带灯高钮,NP8,4,0,0, -476,系列,NP8系列带灯蘑菇钮,NP8,5,0,0, -477,系列,NP2系列金属双头带灯按钮,NP2,19,0,0, -480,系列,YBLX-8系列行程开关,YBLX-8,1,0,0, -481,系列,YBLX-44系列行程开关,YBLX-44,1,3,0, -483,系列,YBLX-10系列行程开关,YBLX-10,3,7,0, -486,系列,DZ47LG系列带过压剩余动作电流断路器(已停产,建议选用NXBLG),DZ47LG,6,22,0, -488,系列,RT14(R)系列熔断器底座,底座RT14,2,0,0, -489,系列,RT28(N)系列熔断器底座,底座RT28N,3,0,0, -490,系列,NC8系列交流接触器(按项目报价),NC8,27,490,0, -492,系列,NC8系列可逆交流接触器(按项目报价),NC8,27,219,0, -493,系列,NC8系列小型交流接触器(按项目报价),NC8,13,24,0, -494,系列,NC8系列小型直流接触器(按项目报价),NC8,13,30,0, -495,系列,NC8系列小型交流可逆接触器(按项目报价),NC8,14,24,0, -496,系列,NC8系列小型直流可逆接触器(按项目报价),NC8,14,18,0, -497,系列,NC1系列交流接触器,NC1,25,83,0, -498,系列,NC1系列可逆交流接触器,NC1,25,60,0, -499,系列,NC1系列直流接触器,NC1,25,51,0, -500,系列,DZ20Y系列塑壳断路器,DZ20,13,494,0, -501,系列,DZ20J系列塑壳断路器(已停产,被DZ20Y改进型代替),DZ20,12,175,0, -502,系列,NM1LE系列漏电断路器(漏电报警不跳闸),NM1LE,15,115,0, -503,系列,NA1-2000X~6300X系列万能式断路器(不带欠压),NA1,43,156,0, -504,系列,NM1系列二极塑料外壳式断路器,NM1,11,40,0, -505,系列,NM1系列四极塑料外壳式断路器,NM1,31,389,0, -506,系列,NM1系列三极塑料外壳式断路器,NM1,50,852,0, -507,系列,DZ20L-4P系列塑壳漏电断路器,DZ20L,12,140,0, -508,系列,DZ20L-3N系列塑壳漏电断路器,DZ20L,13,87,0, -514,系列,ND16系列蜂鸣器式信号灯,ND16,4,28,0, -515,系列,NM8-630系列三极塑壳断路器(已停产,建议选用NM8N),NM8,10,52,0, -517,系列,NM8-630系列四极塑壳断路器(已停产,建议选用NM8N),NM8,10,134,0, -518,系列,NM8S系列智能型塑壳断路器(已停产,建议选用NM8N),NM8S,12,658,0, -519,系列,DZ108系列塑壳断路器,DZ108,4,25,0, -520,系列,NS2系列交流电动机起动器,NS2,20,86,0, -521,系列,"DZ158-100(R)系列小型断路器(已停产,被NXB-125G替代)",DZ158,7,2,0, -522,系列,"DZ158-125(R)系列小型断路器(已停产,被NXB-125替代)",DZ158,10,11,0, -523,系列,DZ158LE-100系列剩余电流动作断路器(已停产,建议选用DZ158LE-125),DZ158LE,4,2,0, -524,系列,"DZ47-60系列型小型断路器(透明外壳)(已停产,建议选用NXB-63T)",DZ47,5,34,0, -525,系列,DZ47-60(R)系列小型断路器(已停产),DZ47,4,23,0, -526,系列,NBH8-40H系列家用小型断路器,NBH8,11,12,0, -527,系列,DZ47LE-32系列剩余动作电流断路器(已停产,被NXBLE-32替代),DZ47LE,5,62,0, -528,系列,NB1Z-63系列交直流用小型断路器,NB1Z,8,4,0, -529,系列,NB7系列小型断路器,NB7,5,67,0, -530,系列,NB7LE-32系列微型漏电断路器,NB7LE,5,7,0, -531,系列,NB7LE-63系列微型漏电断路器,NB7LE,5,28,0, -532,系列,DZ20L系列透明型漏电断路器(部分型号已被NXMLE代替),DZ20L,14,186,0, -533,系列,LQG-0.66系列低压电流互感器(0.2S级),LQG,3,22,0, -534,系列,NJR2-D系列软起动器,NJR,6,23,0, -536,系列,NJBK7系列电动机保护继电器,NJBK7,6,6,0, -537,系列,NJBK10系列电动机保护继电器,NJBK10,3,3,0, -538,系列,NZ7B-63系列自动转换开关(CB级)(已停产,被NXZB替代),NZ7B,7,6,0, -539,系列,DZ20C系列塑壳断路器(已停产,被DZ20C改进型代替),DZ20,9,16,0, -540,系列,42L6系列模拟指示电流表(已停产),42,5,24,0, -541,系列,42L6系列模拟指示电压表,42,4,2,0, -542,系列,42L6系列模拟指示功率表(已停产),42,4,1,0, -543,系列,42L6系列模拟指示频率表,42,5,3,0, -544,系列,42L6系列模拟指示功率因数表(已停产),42,4,2,0, -545,系列,44L1系列模拟指示电流表,44,5,19,0, -546,系列,44L1系列模拟指示电压表,44,4,3,0, -551,系列,51T666系列模拟电测量仪表,51,4,4,0, -552,系列,59L1系列模拟指示电流表,59,4,1,0, -553,系列,59L1系列模拟指示电压表,59,3,1,0, -556,系列,62T51系列模拟指示电流表,62,4,2,0, -559,系列,65T666系列模拟指示电流表,65,4,2,0, -560,系列,65T666系列模拟指示电压表,65,4,1,0, -563,系列,69L9系列模拟指示电流表,69,5,10,0, -564,系列,69L9系列模拟指示电压表,69,5,11,0, -565,系列,69L9系列模拟指示频率表,69,6,6,0, -566,系列,6L2系列模拟指示电流表(已停产),6,4,2,0, -567,系列,6L2系列模拟指示电压表(已停产),6,4,2,0, -568,系列,6L2系列模拟指示功率表(已停产),6,4,0,0, -569,系列,6L2系列模拟指示频率表(已停产),6,3,0,0, -570,系列,6L2系列模拟指示功率因数表(已停产),6,3,3,0, -571,系列,85C1系列模拟指示电流表,85,4,0,0, -572,系列,85C1系列模拟指示电压表,85,4,0,0, -574,系列,85L1系列模拟指示电流表,85,4,2,0, -575,系列,85L1系列模拟指示电压表,85,4,0,0, -577,系列,99T666系列模拟指示电流表,99,4,3,0, -578,系列,99T666系列模拟指示电压表,99,4,2,0, -579,系列,PA666系列数显电流表(已停产),P,2,10,0, -580,系列,PZ666系列数显电压表(已停产),P,5,16,0, -581,系列,PD666系列数显多功能仪表(已停产),P,6,0,0, -592,系列,DD862系列单相电能表,DD862-4,4,7,0, -593,系列,DDS666系列单相电子式电能表(已停产),DDS666,3,20,0, -594,系列,DDS7777系列单相电子式电能表,DDS7777,3,5,0, -595,系列,DDSY666系列单相电子预付费电能表(已停产),DDSY666,3,4,0, -596,系列,DDM702系列单相亚长寿脉冲电能表,DDM702,2,12,0, -600,系列,DTSF666系列三相电子式多费率电能表(已停产),DTSF666,4,5,0, -601,系列,DSSD666系列三相电子式多功能电能表,DSSD666,5,6,0, -602,系列,DTSD666系列三相电子式多功能电能表,DTSD666,5,15,0, -603,系列,DSS633系列三相电子式有功电能表(已停产),DSS633,4,6,0, -604,系列,DTS634系列三相电子式有功电能表(已停产),DTS634,4,26,2,"DTS634 220/380V 1.5(6)A 1级 计度器 = 520.59997558594 元 -DTS634 220/380V 1.5(6)A 1级 LCD 红外/485 = 745.55999755859 元" -605,系列,DTSY666系列三相电子式预付费电能表(已停产),DTSY666,4,5,0, -608,系列,DS862系列三相三线有功电能表,DS862-4,4,8,0, -610,系列,DT666系列三相四线有功电能表(已停产),DT666,2,0,0, -611,系列,DT862系列三相四线有功电能表,DT862-4,2,10,0, -619,系列,XMT系列数字温度指示调节仪,XMT,9,81,0, -620,系列,TD、TE系列电子式温度指示调节仪,T,9,45,0, -621,系列,NM8-100系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,29,107,0, -622,系列,NM8-250系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,11,412,0, -623,系列,NM8-1250系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,10,62,0, -624,系列,RT36(CR)系列有填料封闭管式刀型触头熔断器体,RT36,4,14,0, -625,系列,NM7LE系列塑壳漏电断路器(已停产,建议选用NXMLE),NM7LE,9,16,0, -628,系列,RT36N系列熔断器底座,底座RT36N,2,5,0, -629,系列,NB1-63DC系列微型直流断路器,NB1,10,6,0, -632,系列,NM1系列塑料外壳式断路器(透明),NM1,13,61,0, -633,系列,NH20-2500系列万能式隔离开关(已停产,被NH1代替),NH20,5,28,0, -634,系列,PZ30系列配电箱,PZ30,6,52,0, -635,系列,PZ30系列配电箱(不锈钢)(已停产,建议选用PZ30),PZ30,2,10,0, -637,系列,PZ25系列配电箱(已停产,建议选用PZ30),PZ25,2,2,0, -638,系列,AC30系列插座,AC30,1,20,0, -641,系列,NH42系列隔离开关,NH42,2,0,0, -642,系列,NH42SZ系列自动转换开关(PC级),NH42,9,693,0, -643,系列,CRT36系列直流熔断器,CRT36,6,29,0, -647,系列,CJ20系列交流接触器(无磁系统),CJ20,2,16,0, -648,系列,"DZ158LE-125系列剩余电流动作断路器(已停产,被NXBLE-125替代)",DZ158LE,5,10,0, -650,系列,BZMJ2系列自愈式低压并联电容器,BZMJ,4,123,0, -651,系列,NJR2-ZX系列软起动器(已停产,被NJR5-ZX代替),NJR,3,0,0, -652,系列,NRZ36系列熔断体,NRZ36,3,6,0, -653,系列,NRZ28系列熔断体,NRZ28,2,0,0, -654,系列,NRZ28系列熔断器底座,底座NRZ28,3,0,0, -655,系列,RS71(NGT)系列快速熔断器体(直流),RS71,2,0,0, -656,系列,NC8系列直流接触器(按项目报价),NC8,19,97,0, -658,系列,NU210系列浪涌保护器,NU210,5,0,0, -661,系列,NQ3系列电磁起动器,NQ3,4,2,0, -662,系列,NQB1系列保护式起动器,NQB1,4,0,0, -677,系列,AZMJ系列低压交流滤波电容器,AZMJ,3,6,0, -678,系列,NWC6系列干式低电压并联电容器,NWC6,4,50,0, -679,系列,NB1L(2)系列剩余动作断路器,NB1L(2),5,0,0, -680,系列,LMZ□D系列电流互感器,LMZ,4,41,0, -682,系列,LFZ1D系列电流互感器(已停产,被LMZ1D代替),LFZ1D,3,9,0, -684,系列,NH43系列隔离开关,NH43,2,0,0, -685,系列,JDZ6-1系列电压互感器,JDZ6-1,2,0,0, -686,系列,NH41SZ系列自动转换开关(PC级),NH41,7,471,0, -687,系列,LQZJ4-0.66系列低压电流互感器(0.2S级),LQZJ4,3,0,0, -688,系列,LMZW2-0.5系列电流互感器(0.2级),LMZW2,4,15,0, -690,系列,LMZW2-0.5系列电流互感器(0.5S级),LMZW2,4,15,0, -691,系列,LMZW1-0.5系列户外低压电流互感器(0.2级),LMZW1,5,22,0, -692,系列,LMZS1系列电流互感器,LMZS1,3,10,0, -693,系列,HR20系列户外熔断器式隔离开关,HR20,2,0,0, -694,系列,HS12系列双投转换式刀开关,HS12,4,14,0, -695,系列,HS13D系列电动大电流刀开关,HS13D,2,0,0, -696,系列,NPH1系列按钮,NPH1,3,24,0, -698,系列,LAY39B系列平钮,LAY39,4,12,0, -699,系列,LAY39B系列带灯平钮,LAY39,5,10,0, -700,系列,LAY39B系列高钮,LAY39,4,5,0, -701,系列,LAY39B系列带灯高钮,LAY39,5,5,0, -702,系列,LAY39B系列蘑菇头钮,LAY39,5,16,0, -703,系列,LAY39B系列带灯蘑菇头钮,LAY39,6,10,0, -704,系列,LAY39B系列旋钮,LAY39,5,26,0, -705,系列,LAY39B系列带灯旋钮,LAY39,6,31,0, -706,系列,LAY39B系列钥匙钮,LAY39,4,3,0, -707,系列,LAY39B系列双头钮,LAY39,5,4,0, -709,系列,JDW2系列低压户外熔断器式隔离开关,JDW2,4,17,0, -710,系列,NH40-II/III系列隔离开关,NH40,3,7,0, -711,系列,NM1LE系列透明型漏电断路器(125S/250S已停产,建议选用NM1LE-G),NM1LE,11,10,0, -712,系列,NVF3系列变频器,NVF3,7,81,0, -713,系列,NVF3M系列变频器,NVF3M,5,2,0, -714,系列,NSK-BH系列低压非晶合金变压器,NSK,4,0,0, -715,系列,NSK-SG系列太阳能单晶硅炉配套专用变压器,NSK(SG),3,0,0, -716,系列,电磁继电器插座,,1,6,0, -717,系列,NJS5-M2系列时间继电器(已停产,建议选用NTE8),NJS5,2,0,0, -718,系列,JSZ6系列时间继电器,JSZ6,5,23,0, -719,系列,时间继电器插座,,1,14,0, -720,系列,挂钩,,1,0,0, -721,系列,NM1LE系列漏电断路器(漏电跳闸/可调),NM1LE,15,243,0, -722,系列,LW5D系列万能转换开关(特殊),LW5D,6,392,0, -723,系列,NH7系列隔离开关(已停产,建议选用NXHB),NH7,2,0,0, -725,系列,NXM系列塑壳断路器,NXM,61,4399,18,"NXM-400S/3300 400A = 1453 元 -NXM-630S/3300 400A = 2234 元 -NXM-63S/3300 63A = 322 元 -NXM-125S/3300 10A = 406 元 -NXM-400S/3300 250A = 1453 元 -NXM-250S/3300 200A = 659 元 -NXM-W800S/3300 630A(R) = 3200 元 -NXM-63S/2300 10A = 266 元 -NXM-125S/3300 100A = 406 元 -NXM-63S/33082 25A = 363 元 -NXM-W125S/2300 25A(R) = 376 元 -NXM-160S/2300 25A = 427 元 -NXM-63S/3308 25A = 363 元 -NXM-250S/3300 160A = 659 元 -NXM-63S/3300 10A = 322 元 -NXM-125S/2300 10A = 355 元 -NXM-W630S/3300 400A(R) = 2449 元 -NXM-250S/3300 125A = 659 元" -726,系列,NXB-40系列小型断路器,NXB,13,39,0, -727,系列,NXB-63系列小型断路器,NXB,15,51,0, -728,系列,NXB-125系列小型断路器,NXB,14,43,0, -729,系列,NXBLE-40系列剩余电流动作断路器,NXBLE,14,39,0, -730,系列,NXBLE-63YH系列剩余电流动作断路器,NXBLE,14,66,0, -731,系列,NXBLE-32系列剩余电流动作断路器,NXBLE,14,49,0, -732,系列,NXBLE-125系列剩余电流动作断路器,NXBLE,14,46,0, -733,系列,NXC系列交流接触器,NXC,28,405,1,NXC-06 24V = 92.540000915527 元 -734,系列,NXJ系列小型电磁继电器,NXJ,13,23,0, -735,系列,NXA系列万能式断路器,NXA,82,426,1,NXA16N04-MF3-AC220/230/240 = 16877 元 -736,系列,NXB-80系列小型断路器,NXB,15,61,0, -737,系列,NXB-63H系列高分断小型断路器,NXB,16,45,0, -738,系列,NXHB-125系列隔离开关,NXHB,3,4,0, -739,系列,NXU-Ⅱ系列电涌保护器(被NXU-ⅡG代替),NXU-Ⅱ,4,4,0, -740,系列,NXU-Ⅲ系列电涌保护器,NXU-Ⅲ,4,2,0, -741,系列,NXR系列热过载继电器,NXR,4,32,0, -742,系列,NXBLE-32H系列剩余电流动作断路器,NXBLE,15,39,0, -743,系列,NXBLG-32系列剩余电流动作断路器(带过压),NXBLG-32,6,0,0, -744,系列,NXBLE-63H系列剩余电流动作断路器,NXBLE,16,45,0, -745,系列,NXBLG-63系列剩余电流动作断路器(带过压),NXBLG-63,6,0,0, -746,系列,NXBLG-125系列剩余电流动作断路器,NXBLG,5,0,0, -747,系列,NXC系列迷你型3极交流接触器,NXC,12,7,0, -748,系列,NXC系列迷你型4极交流接触器,NXC,12,11,0, -749,系列,ZT-830系列智能低压无功功率自动补偿控制器,ZT,6,0,0, -750,系列,ZCK系列智能复合开关,ZCK,4,5,0, -751,系列,NR8系列热过载继电器(按项目报价),NR8,2,15,0, -752,系列,JXF系列户外终端箱,JXF,2,25,0, -753,系列,NX10系列配电箱箱体,NX10,1,0,0, -754,系列,JFF1系列户外终端箱,JFF1,2,26,0, -755,系列,JD1A系列电磁调速电动机控制装置,JD1A,3,3,0, -756,系列,JD2A系列电磁调速电动机控制装置,JD2A,2,0,0, -757,系列,NXMLE系列剩余电流动作断路器,NXMLE,32,870,1,NXMLE-125S/3300 10A A = 809 元 -758,系列,NXMS系列电子式塑壳断路器,NXMS,21,841,0, -759,系列,NXHM系列隔离开关,NXHM,3,16,0, -23303,系列,LMZ1-0.5系列低压电流互感器(已停产,建议选用BH-0.66),LMZ1,5,100,0, -23352,系列,NXU-Ⅰ+Ⅱ系列电涌保护器,NXU-Ⅰ+Ⅱ,4,2,0, -23353,系列,NXBLE-63Y系列剩余电流动作断路器,NXBLE,14,39,0, -23354,系列,DZ47-63系列小型断路器(已停产,建议选用NXB-63),DZ47,4,22,0, -23655,系列,NXB-125G系列小型断路器,NXB-125G,11,47,0, -25078,系列,NXB-63Z系列小型断路器(已停产,被NXB-63代替),NXB,5,6,0, -25359,系列,OUVR-1系列自恢复式过欠压保护器(专供),OUVR,6,2,0, -25402,系列,DZ267LG-32系列剩余电流动作断路器(已停产,建议选用NXBLG-40),DZ267,6,0,0, -25440,系列,NB1LG-40系列剩余电流动作断路器,NB1,6,0,0, -25547,系列,NP2系列带罩按钮,NP2,16,0,0, -25548,系列,NP2系列双头按钮,NP2,17,2,0, -25549,系列,NP2系列按钮盒,NP2,1,0,0, -25550,系列,ND16-16系列信号灯,ND16,5,6,0, -26159,系列,NH3-100系列隔离开关,NH3,3,3,0, -26164,系列,LMZJ1-0.5系列低压电流互感器(0.2S级),LMZJ1,4,29,0, -26185,系列,BH-0.66Ⅰ系列低压电流互感器(0.2S级),BH,7,433,0, -26394,系列,NXBLE-125G系列剩余电流动作断路器,NXBLE,9,34,0, -26395,系列,NXB-63系列小型断路器(煤改电),NXB,5,0,0, -26397,系列,NXBELG-32系列剩余电流动作断路器(带过压)电商(已停产),NXBELG,6,0,0, -26398,系列,NXBELG-63系列剩余电流动作断路器(带过压)电商(已停产),NXBELG,6,1,0, -26542,系列,DZ47-60M系列单磁式小型断路器(已停产,被NXB-63M替代),DZ47,5,36,0, -26544,系列,NB1G-80系列小型断路器,NB1G,5,2,0, -26550,系列,CJX1-K系列交流真空接触器,CJX1,10,19,0, -26572,系列,CJX1F系列交流接触器(已停产,被NCX1替代),CJX1,4,0,0, -26606,系列,TD系列接线端子,TD,4,7,0, -26621,系列,SR2系列浪涌抑制器,SR2,3,3,0, -26632,系列,DW16系列万能式断路器(整定值)(已停产,被DW15替代),DW16,6,19,0, -26637,系列,DW15系列万能式断路器(整定值),DW15,7,172,0, -26638,系列,DW17系列万能式断路器(整定值),DW17,6,195,0, -26793,系列,TC系列接线端子,TC,3,14,0, -26794,系列,JF5系列接线端子,JF5,5,5,0, -26800,系列,NPH1系列空盒,NPH1,2,2,0, -26803,系列,WRKT系列控制类仪表热电阻,WRKT,2,3,0, -26954,系列,NM1LE系列漏电断路器(漏电跳闸/不可调),NM1LE,15,245,0, -26956,系列,DZ47LE-63H系列剩余电流动作断路器(已停产,建议选用NXBLE-63H),DZ47LE,7,0,0, -26960,系列,YH系列避雷器(已停产,建议选用YH复合避雷器),YH,5,15,0, -26964,系列,TM系列超低压全自动交流稳压器,TM,1,8,0, -26965,系列,SAK系列接线端子,SAK,3,7,0, -26967,系列,NJBK1系列电动机保护继电器,NJBK1,3,2,0, -26968,系列,BAM系列高压电容器,BAM,4,123,0, -26991,系列,NJMC1系列脉冲继电器,NJMC1,4,16,0, -27093,系列,YJVR系列软导体电线电缆,YJVR,1,0,0, -27094,系列,YJV系列电力电缆,,5,10,0, -27096,系列,VVR系列软导体电线电缆,VVR,1,0,0, -27098,系列,YJV22系列电力电缆,,7,10,0, -27099,系列,PV1-F系列光伏电缆,PV1-F,2,0,0, -27100,系列,VV系列电力电缆,,4,2,0, -27101,系列,VV22系列电力电缆,,6,2,0, -27102,系列,Z-YJV系列电力电缆,,5,2,0, -27103,系列,Z-YJV22系列电力电缆,,7,2,0, -27104,系列,Z-VV系列电力电缆,,5,2,0, -27105,系列,Z-VV22系列电力电缆,,7,2,0, -27109,系列,BVN系列尼龙电线,BVN,1,0,0, -27111,系列,JK系列架空电缆,,5,113,0, -27115,系列,DJYVP-A系列计算机电缆,DJYVP-A,1,0,0, -27117,系列,KVV系列控制电缆,KVV,2,20,0, -27120,系列,N-YJV系列耐火电力电缆,,5,0,0, -27121,系列,N-YJV22系列耐火电力电缆,,7,0,0, -27122,系列,N-VV系列耐火电力电缆,,5,0,0, -27123,系列,N-VV22系列耐火电力电缆,,7,0,0, -27124,系列,ZN-YJV系列耐火电力电缆,,6,3,0, -27125,系列,ZN-YJV22系列耐火电力电缆,,8,3,0, -27126,系列,ZN-VV系列耐火电力电缆,,6,3,0, -27127,系列,ZN-VV22系列耐火电力电缆,,8,3,0, -27129,系列,KVVP系列控制电缆,KVVP,2,20,0, -27130,系列,KVV22系列控制电缆,KVV22,2,20,0, -27131,系列,KVVP2系列控制电缆,KVVP2,2,20,0, -27132,系列,KVVR系列控制电缆,KVVR,2,20,0, -27133,系列,KVVRP系列控制电缆,KVVRP,2,20,0, -27134,系列,KVVP2-22系列控制电缆,KVVP2-22,2,20,0, -27135,系列,KYJV系列控制电缆,KYJV,2,20,0, -27136,系列,KYJVP系列控制电缆,KYJVP,2,20,0, -27137,系列,KYJV22系列控制电缆,KYJV22,2,20,0, -27138,系列,KYJVP2系列控制电缆,KYJVP2,2,20,0, -27139,系列,KYJVP2-22系列控制电缆,KYJVP2-22,2,20,0, -27143,系列,BV系列聚氯乙烯绝缘电线,B,3,2,0, -27144,系列,BVR系列铜芯聚氯乙烯绝缘软电缆,BVR,1,0,0, -27145,系列,RV系列铜芯聚氯乙烯绝缘软电线,RV,1,0,0, -27146,系列,RVV系列铜芯聚氯乙烯绝缘护套软线,RVV,1,0,0, -27147,系列,N-KVV系列控制电缆,N-KVV,2,19,0, -27148,系列,N-KVVP系列控制电缆,N-KVVP,2,19,0, -27149,系列,N-KVVP2系列控制电缆,N-KVVP2,2,19,0, -27150,系列,N-KVV22系列控制电缆,N-KVV22,2,19,0, -27151,系列,N-KYJV系列控制电缆,N-KYJV,2,19,0, -27152,系列,N-KYJV22系列控制电缆,N-KYJV22,2,19,0, -27153,系列,N-KYJVP系列控制电缆,N-KYJVP,2,19,0, -27154,系列,N-KYJVP2系列控制电缆,N-KYJVP2,2,19,0, -27156,系列,N-BV系列聚氯乙烯绝缘耐火电线,N-BV,1,0,0, -27157,系列,N-BVR系列铜芯聚氯乙烯绝缘耐火软电缆,N-BVR,1,0,0, -27158,系列,RVVP系列铜芯聚氯乙烯绝缘护套屏蔽电线,RVVP,1,0,0, -27159,系列,RVS系列铜芯聚氯乙烯绝缘绞型连接用软电线,RVS,1,0,0, -27160,系列,BVVB系列铜芯聚氯乙烯绝缘护套扁型电缆,BVVB,1,0,0, -27161,系列,BVV系列铜芯聚氯乙烯绝缘护套电线,BVV,1,0,0, -27162,系列,N-RVS系列铜芯聚氯乙烯绝缘绞型连接用耐火软电线,N-RVS,1,0,0, -27163,系列,WDZ系列低压无卤电线,WDZ,4,2,0, -27164,系列,DJYPVP-A系列计算机电缆,DJYPVP-A,1,0,0, -27165,系列,DJYPV-A系列计算机电缆,DJYPV-A,1,0,0, -27166,系列,DJYVP2-A系列计算机电缆,DJYVP2-A,1,0,0, -27167,系列,DJYP2VP2-A系列计算机电缆,DJYP2VP2-A,1,0,0, -27168,系列,DJYP2V-A系列计算机电缆,DJYP2V-A,1,0,0, -27169,系列,DJYVP22-A系列计算机电缆,DJYVP22-A,1,0,0, -27170,系列,DJYPVP22-A系列计算机电缆,DJYPVP22-A,1,0,0, -27171,系列,DJYPV22-A系列计算机电缆,DJYPV22-A,1,0,0, -27172,系列,DJYVP2-22-A系列计算机电缆,DJYVP2-22-A,1,0,0, -27173,系列,DJYP2VP2-22-A系列计算机电缆,DJYP2VP2-22-A,1,0,0, -27175,系列,WDZ系列低烟无卤阻燃电缆,WDZ,6,4,0, -27176,系列,YC系列橡套电缆,YC,1,0,0, -27177,系列,YZ系列橡套电缆,YZ,1,0,0, -27178,系列,YH系列橡套电缆,YH,1,0,0, -27179,系列,BTRY系列柔性矿物绝缘电缆,BTRY,2,2,0, -27180,系列,WDZN系列低烟无卤阻燃耐火电缆,WDZ,7,4,0, -27181,系列,MC系列采煤机橡套软电缆,MC,2,0,0, -27182,系列,DT系列金具,DT,1,0,0, -27183,系列,OT系列金具,OT,1,0,0, -27184,系列,JG系列金具,JG,1,0,0, -27185,系列,MCP系列采煤机屏蔽橡套软电缆,MCP,2,3,0, -27186,系列,MY系列煤矿用移动橡套软电缆,MY,2,0,0, -27187,系列,MYP系列煤矿用移动屏蔽橡套软电缆,MYP,2,2,0, -27188,系列,MZ系列煤矿用电钻橡套软电缆,MZ,1,0,0, -27189,系列,MZP系列煤矿用电钻屏蔽橡套软电缆,MZP,1,0,0, -27190,系列,MYQ系列煤矿用移动轻型橡套软电缆,MYQ,1,0,0, -27191,系列,MCPT系列采煤机金属屏蔽橡套软电缆,MCPT,3,4,0, -27192,系列,MYPTJ系列煤矿用移动金属屏蔽监视型橡套软电缆,MYPTJ,2,3,0, -27194,系列,MYPT系列煤矿用移动金属屏蔽橡套软电缆,MYPT,2,0,0, -27195,系列,SC(JGK)系列金具,SC(JGK),2,12,0, -27196,系列,GT系列金具,GT,2,0,0, -27204,系列,YJHLV系列铝合金电缆,YJHLV,2,2,0, -27206,系列,YJHLV22系列铝合金电缆,YJHLV22,2,2,0, -27209,系列,YJHLV8系列铝合金电缆,YJHLV8,1,0,0, -27210,系列,YJHLV82系列铝合金电缆,YJHLV82,1,0,0, -27399,系列,DRDL系列地热电缆,DRDL,2,0,0, -27534,系列,YJV系列电力电缆(完整版),,8,154,0, -27845,系列,CKSG系列三相干式串联电抗器,CKSG,3,137,0, -27980,系列,BH-0.66系列低压电流互感器(0.2级实心),,5,20,0, -28208,系列,NXRC系列接触器式继电器,NXRC,7,12,0, -28265,系列,NJG2系列固态继电器,NJG2,8,39,0, -28269,系列,NJJ7-M系列计数继电器,NJJ7,2,0,0, -28270,系列,NJJ7-H系列计数继电器,NJJ7,2,0,0, -28271,系列,NJG1系列固态继电器,NJG1,8,3,0, -28272,系列,NJYB1系列电压保护继电器(已停产,被NJYB3代替),NJYB1,1,0,0, -28273,系列,NJYB3系列继电器,NJYB3,3,36,0, -28274,系列,NB1L(2H)系列剩余动作断路器,NB1L(2H),6,0,0, -28278,系列,NJS5系列时间继电器(已停产,建议选用NTE8),NJS5,3,12,0, -28279,系列,NJS3系列时间继电器(已停产,建议选用NTE8),NJS3,3,3,0, -28280,系列,NJS3-D系列时间继电器(已停产,建议选用NTE8),NJS3,2,0,0, -28281,系列,NJDC-12系列带测试按钮小型电磁继电器,NJDC-12,2,0,0, -28282,系列,NJDC-17系列带测试按钮小型电磁继电器,NJDC-17,7,22,0, -28294,系列,NCK5系列空调用交流接触器,NCK5,4,12,0, -28300,系列,NCZ1系列直流接触器(已停产,建议选用NCZ2),NCZ1,2,0,0, -28303,系列,NC11系列交流接触器,NC11,3,0,0, -28326,系列,NWK1-GR系列中文液晶低压无功补偿控制器,NWK1,5,7,0, -28344,系列,LMZJ1-0.5系列低压电流互感器(0.5级实芯),LMZJ1,4,0,0, -28461,系列,NKG3系列时控开关,NKG3,3,4,0, -28627,系列,DDS666系列单相电子式电能表(昆仑),DDS666,5,16,0, -28749,系列,NVF5系列通用型变频器,NVF5,13,42,0, -28756,系列,NXZ系列自动转换开关(PC级),NXZ,5,3,0, -28757,系列,NXZB-63系列自动转换开关(CB级)(即将停销,被NXZBN替代),NXZB,7,0,0, -28758,系列,NXZM系列自动转换开关(CB级)(即将停销,被NXZMN替代),NXZM,6,126,0, -28759,系列,NXZHB系列自动转换开关(PC级)(即将停销,被NXZHBN替代),NXZHB,6,2,0, -28760,系列,NXZHM系列自动转换开关(PC级)(即将停销,被NXZHMN替代),NXZHM,5,7,0, -29498,系列,OUVR-2系列自恢复式过欠压保护器,OUVR,5,9,0, -30302,系列,DDSY666系列单相电子预付费电能表(昆仑),DDSY666,5,19,0, -30310,系列,DSSF666系列三相电子式多费率电能表(昆仑),DSSF666,5,4,0, -30311,系列,DTSF666系列三相电子式多费率电能表(昆仑),DTSF666,5,8,0, -30312,系列,DSS633系列三相电子式有功电能表(昆仑),DSS633,5,39,0, -30313,系列,DTS634系列三相电子式有功电能表(昆仑),DTS634,5,65,0, -30314,系列,DTSY666系列三相电子式预付费电能表(昆仑),DTSY666,5,19,0, -30337,系列,DSS(X)666系列三相有功、无功电能表(昆仑),DSS(X)666,5,4,0, -30338,系列,DTS(X)666系列三相有功、无功电能表(昆仑),DTS(X)666,5,20,0, -30339,系列,NB1G-63系列小型断路器,NB1G,6,0,0, -31337,系列,NB1-63系列小型断路器(双汇流排),NB1,7,22,0, -32370,系列,ZCT系列零序电流互感器,ZCT,2,2,0, -32371,系列,TND6系列交流稳压器,TND6,2,2,0, -32372,系列,NSDK系列三相干式电抗器,NSDK,2,3,0, -32373,系列,BAGB(BAFB)系列智能组合低电压并联电容器,BA,6,169,0, -32374,系列,BKMJ系列干式低电压并联电容器,BKMJ,4,81,0, -32375,系列,TH35-7.5系列导轨,TH35,2,0,0, -32377,系列,JXB系列接线端子,JXB,3,16,0, -32394,系列,NPM8-12A系列高钮,NPM8,5,0,0, -32395,系列,NPM8-12A系列环形灯高钮,NPM8,7,0,0, -32396,系列,NPM8-12Z系列指示灯,NPM8,4,0,0, -32397,系列,NPM8-16A系列平钮,NPM8,5,0,0, -32398,系列,NPM8-16A系列单点灯平钮,NPM8,7,0,0, -32399,系列,NPM8-16A系列单点灯高钮(已停产),NPM8,7,0,0, -32400,系列,NPM8-16A系列环形灯平钮,NPM8,7,0,0, -32401,系列,NPM8-16A系列环形灯高钮,NPM8,7,0,0, -32402,系列,NPM8-16A系列电源标识平钮,NPM8,7,0,0, -32403,系列,NPM8-16Z系列指示灯,NPM8,4,0,0, -32404,系列,NPM8-19A系列平钮,NPM8,5,0,0, -32405,系列,NPM8-19A系列单点灯平钮,NPM8,7,0,0, -32406,系列,NPM8-19A系列环形灯平钮,NPM8,7,0,0, -32407,系列,NPM8-19A系列电源标识平钮,NPM8,7,0,0, -32408,系列,NPM8-19J系列急停钮,NPM8,4,0,0, -32409,系列,NPM8-19Y系列钥匙钮,NPM8,3,0,0, -32410,系列,NPM8-19X系列旋钮,NPM8,3,0,0, -32411,系列,NPM8-19Z系列指示灯,NPM8,4,0,0, -32412,系列,NPM8-22A系列平钮,NPM8,5,0,0, -32413,系列,NPM8-22A系列单点灯平钮,NPM8,7,0,0, -32414,系列,NPM8-22A系列环形灯平钮,NPM8,7,0,0, -32415,系列,NPM8-22A系列电源标识平钮,NPM8,7,0,0, -32416,系列,NPM8-22J系列急停钮,NPM8,4,0,0, -32417,系列,NPM8-22Z系列指示灯,NPM8,4,0,0, -32418,系列,NPM8-22Y系列钥匙钮,NPM8,3,0,0, -32419,系列,NPM8-22X系列旋钮,NPM8,3,0,0, -32554,系列,NM1B系列塑壳断路器(表箱专用),NM1B,22,137,0, -32606,系列,NKB1系列控制与保护开关,NKB1,12,105,0, -32608,系列,NKX2系列行程开关,NKX2,1,0,0, -32615,系列,NB3LE-63M系列剩余电流动作断路器,NB3LE,9,162,0, -32639,系列,NKB300系列控制与保护开关(已停产,建议选用NKB1或NKB8),NKB300,4,5,0, -32640,系列,NH45系列隔离开关,NH45,4,41,0, -32641,系列,NH51系列隔离开关,NH51,3,0,0, -33017,系列,DZ47-60系列型小型断路器(煤改电专供)(已停产,建议选用NXB-63煤改电),DZ47,5,9,0, -33018,系列,NXBLE-32系列剩余电流动作断路器(煤改电专供),NXBLE,6,0,0, -33019,系列,NXBLE-32H系列剩余电流动作断路器(煤改电专供),NXBLE,7,0,0, -33020,系列,NXBLE-63系列剩余电流动作断路器(煤改电专供),NXBLE,6,0,0, -33021,系列,NXBLG-32系列剩余电流动作断路器(带过压)(煤改电专供),NXBLG-32,5,0,0, -33022,系列,NXBLG-63系列剩余电流动作断路器(带过压)(煤改电专供),NXBLG-63,5,0,0, -33023,系列,NXBLE-63H系列剩余电流动作断路器(煤改电专供),NXBLE,7,0,0, -33024,系列,TND5(SVC)系列交流稳压器(已停产,建议选用TND1(SVC)),TND5(SVC),2,6,0, -33025,系列,TD系列接线端子(组合型),TD,4,38,0, -33026,系列,LW32系列万能转换开关(电机用),LW32,4,3,0, -33027,系列,TNS5系列稳压器(已停产,建议选用TNS1(SVC)),TNS5,1,0,0, -33028,系列,OCLSG系列三相干式出线电抗器,OCLSG,2,0,0, -33029,系列,ACLSG系列三相干式进线电抗器,ACLSG,2,0,0, -33030,系列,BH-1.0Ⅰ系列低压电流互感器(0.5级),,6,137,0, -33441,系列,QSA系列隔离开关熔断器组,QSA,16,55,0, -33442,系列,QP系列隔离开关,QP,6,17,0, -33443,系列,QA系列隔离开关,QA,4,6,0, -33444,系列,HH15D系列电动式隔离开关熔断器组,HH15D,3,0,0, -35543,系列,JD6A系列电磁调速电动机控制装置(已停产,建议选用JD2A),JD6A,2,0,0, -35546,系列,NCC2系列磁保持继电器,NCC2,6,7,0, -35548,系列,NZ7HB系列自动转换开关(已停产,被NXZHB替代),NZ7HB,4,0,0, -35552,系列,DK系列接线端子,DK,3,0,0, -35553,系列,AP系列接线端子挡板,AP,2,0,0, -35556,系列,NF1系列负荷开关,NF1,6,19,0, -35572,系列,PC-UPS系列不间断电源(已停销),PC-UPS,1,6,0, -35575,系列,GP-UPS系列在线式不间断电源(已停销),GP-UPS,4,98,0, -35586,系列,HP-UPS系列在线式不间断电源(已停销),HP-UPS,2,0,0, -42887,系列,JN15-12系列户内高压交流接地开关,JN15,5,4,0, -42894,系列,ZN85-40.5系列户内高压交流真空断路器,ZN85,5,31,0, -42896,系列,ZN63A-12系列户内高压交流真空断路器,ZN63A,4,25,0, -45189,系列,ND2系列警示灯,ND2,7,0,0, -45190,系列,NTF2系列轴流风扇,NTF2,11,104,0, -45296,系列,LKB1-0.66系列电流互感器,LKB1,5,38,0, -45888,系列,JCUK系列接地端子,JCUK,2,0,0, -45890,系列,SAK系列熔断器端子,SAK,4,0,0, -45891,系列,JF5系列熔断器端子,JF5,3,0,0, -45892,系列,JF5系列试验端子,JF5,4,0,0, -45901,系列,RT28系列圆筒形帽熔断器,RT28,9,10,0, -45962,系列,NTP1系列工业触摸屏,NTP1,1,18,0, -45964,系列,NSC1系列运动控制器,NSC1,1,0,0, -45965,系列,NKB8-12、32系列控制与保护开关电器(按项目报价),NKB8,19,10,0, -45971,系列,NKB8-63系列控制与保护开关电器(按项目报价),NKB8,5,0,0, -46309,系列,NSD1系列伺服驱动器,NSD1,4,2,0, -46311,系列,NTC1系列工业插头、插座及耦合器,NTC1,6,11,0, -46312,系列,NM8N系列交流塑壳断路器(按项目报价),NM8N,123,1572,0, -46314,系列,NKZ1系列万能转换开关,NKZ1,7,18,0, -46317,系列,NJX2系列小型电磁继电器(已停产,建议选用JMK、JTX、JQX-10F),NJX2,6,4,0, -46321,系列,NJA1-KG系列继电器,NJA1,2,0,0, -46322,系列,NJA1-L系列继电器,NJA1,4,0,0, -46329,系列,NM8NL系列剩余电流保护断路器(按项目报价),NM8NL,115,461,0, -46519,系列,NTY1系列移动电缆盘,NTY1,2,3,0, -46595,系列,65L666系列电测量仪表,65L666,3,0,0, -46596,系列,DDSU666系列单相电子式电能表(导轨)(已停产),DDSU666,3,0,0, -46600,系列,DDSU666系列单相导轨电能表(昆仑),DDSU666,4,6,0, -46601,系列,DTSU666系列三相四线导轨电能表(昆仑),DTSU666,4,12,0, -46602,系列,CC系列转换连接器,CC,2,2,0, -46721,系列,NRZ28系列太阳能光伏系统保护用熔断器,底座NRZ28,6,3,0, -46748,系列,ND16系列信号灯(抗干扰),ND16,6,2,0, -46788,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.2S级),BH,5,166,0, -46789,系列,BH-0.66Ⅰ系列低压电流互感器(1级),,7,15,0, -46790,系列,BH-0.66Ⅲ系列低压电流互感器(1级),,7,1,0, -46791,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(1级),BH,6,6,0, -46792,系列,BH-0.66Ⅰ系列低压电流互感器(3级),,8,0,0, -46793,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(3级),BH,6,0,0, -46995,系列,NM8NDC系列直流塑壳断路器(按项目报价),NM8N,107,767,0, -46996,系列,NM8NSD系列隔离开关(按项目报价),NM8N,28,93,0, -47041,系列,NCZ2系列直流接触器,NCZ2,9,47,0, -47055,系列,NXBLE-63ZB系列自诊断剩余电流动作断路器,NXBLE,8,0,0, -47095,系列,NM2系列塑料外壳式断路器(已停产,建议选用NM3),NM2,9,4,0, -47111,系列,NKX3系列行程开关,NKX3,2,17,0, -47149,系列,LMZJ1-0.5系列低压电流互感器(1级),LMZJ1,5,4,0, -47150,系列,LMZJ1-0.5系列低压电流互感器(3级),LMZJ1,5,0,0, -47247,系列,DTM系列铜接线端子(堵油型)(已停产),DTM,4,40,0, -47249,系列,DTL系列铜铝接线端子(已停产),DTL,1,0,0, -47252,系列,DLM系列铝接线端子(堵油型)(已停产),DLM,1,10,0, -47262,系列,OT系列开口型端子(已停产),OT,4,30,0, -47264,系列,GL系列铝连接管(已停产),GL,1,12,0, -47265,系列,GTM系列铜连接管(已停产),GTM,1,0,0, -47266,系列,GTLM系列铜、铝连接管(已停产),GTLM,1,0,0, -47267,系列,GLM系列铝连接管(已停产),GLM,1,12,0, -47268,系列,GT系列铜连接管(已停产),GT,1,0,0, -47269,系列,C45插针(已停产),C45,1,0,0, -47344,系列,NX30系列明/暗装式配电箱,NX30,2,36,0, -47385,系列,NM1系列塑料外壳式断路器(升级型),NM1,46,538,0, -47545,系列,DZ20C系列塑壳断路器(改进型),DZ20,10,16,0, -47546,系列,DZ20Y系列塑壳断路器(改进型),DZ20,12,54,0, -47557,系列,NM2LC系列剩余电流保护断路器,NM2LC,5,60,0, -47638,系列,HD11-F系列防误操作型开启式刀开关,HD11,5,7,0, -47738,系列,NCH8-M系列家用接触器,NCH8,7,7,0, -47919,系列,NB8-40系列小型断路器(环保),NB8,15,26,0, -47928,系列,NB8-40J系列小型断路器,NB8,15,29,0, -47929,系列,NB8-63系列小型断路器(环保),NB8,15,26,0, -47930,系列,NB8-63H系列小型断路器(环保),NB8,16,26,0, -47931,系列,NB8-63M系列单磁式断路器(环保),NB8,16,26,0, -47932,系列,NH8-125系列隔离开关,NH8,4,0,0, -47933,系列,NB8LE-40系列剩余电流动作断路器,NB8LE,16,26,0, -47934,系列,NB8LE-63系列剩余电流动作断路器(环保),NB8LE,18,30,0, -47954,系列,NM1LE系列漏电断路器(升级型),NM1LE,17,435,0, -47964,系列,NRT28系列熔断器,NRT28,9,21,0, -47965,系列,NVF5-GS系列供水专用变频器(已停产),NVF5,8,24,0, -47968,系列,NVF3G-QZ系列起重专用变频器,NVF3G,2,17,0, -48088,系列,NCX1系列防尘交流接触器,NCX1,6,14,0, -48090,系列,NBHLE-32系列剩余电流动作断路器(H系列专供),NBHLE,15,65,0, -48093,系列,NBHLE-40系列剩余电流动作断路器(H系列专供),NBHLE,7,2,0, -48094,系列,NBHLE-40Y系列剩余电流动作断路器(H系列专供),NBHLE,16,26,0, -48095,系列,NBHLE-63系列剩余电流动作断路器(H系列专供),NBHLE,15,65,0, -48097,系列,NBHLE-63Y系列剩余电流动作断路器(H系列专供),NBHLE,16,28,0, -48206,系列,SV系列叉型预绝缘端头(已停产),SV,3,8,0, -48207,系列,RV系列圆型预绝缘端头(已停产),RV,3,8,0, -48208,系列,FDD系列母预绝缘端头(已停产),FDD,3,6,0, -48209,系列,PTV系列针型预绝缘端头(已停产),PTV,3,6,0, -48297,系列,NB8LE-63M系列剩余电流动作断路器,NB8LE,19,39,0, -48306,系列,NBH-40系列小型断路器(H系列专供),NBH,6,0,0, -48307,系列,NBH-63系列小型断路器(H系列专供),NBH,13,41,0, -48308,系列,NBH-63H系列小型断路器(H系列专供),NBH,14,34,0, -48310,系列,NBH-80系列小型断路器(H系列专供),NBH,12,28,0, -48311,系列,NBH-80H系列小型断路器(H系列专供),NBH,14,28,0, -48312,系列,NBH-80GQ系列小型断路器(H系列专供),NBH,6,0,0, -48314,系列,NA1H系列万能式断路器(H系列专供),NA1H,36,105,0, -48317,系列,SBW-JW系列工业级无触点智能稳压器,SBW,2,0,0, -48318,系列,NVF3G-LS系列拉丝专用变频器,NVF3G,2,0,0, -48319,系列,NDKQ系列控制变压器,NDKQ,3,0,0, -48329,系列,HD18系列隔离开关,HD18,2,3,0, -48330,系列,HS18系列隔离开关,HS18,2,8,0, -48344,系列,DZ20L系列塑壳漏电断路器(升级型),DZ20L,19,162,0, -48380,系列,NHH-125系列隔离开关(H系列专供),NHH,4,4,0, -48381,系列,NXZB-63系列自动转换开关(CB级)(H系列专供,已停产,被NZ1HB代替),NXZB,8,0,0, -48382,系列,NXZHB系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZHB,5,0,0, -48383,系列,NXZHM系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZHM,6,119,0, -48384,系列,NXZM系列自动转换开关(CB级)(H系列专供,已停产,被NZ1HM代替),NXZM,7,126,0, -48385,系列,NXZ系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZ,5,3,0, -48387,系列,WRET系列热电阻,WRET,2,3,0, -48388,系列,NL210系列剩余电流动作断路器(新能源专供),NL210,6,2,0, -48391,系列,NDDK1系列光伏逆变电抗器,NDDK1,1,0,0, -48412,系列,LMZJ1-0.66系列低压电流互感器(0.2S级),LMZJ1,4,57,0, -48450,系列,NXMH系列塑壳断路器(H系列专供),NXMH,38,259,0, -48567,系列,BH-0.66系列电流互感器(实芯 H系列专供),BH,6,0,0, -48587,系列,NPC系列气动接头,NPC,2,5,0, -48588,系列,NPCF系列气动接头,NPCF,2,5,0, -48589,系列,NPL系列气动接头,NPL,2,5,0, -48590,系列,NPLF系列气动接头,NPLF,2,5,0, -48593,系列,NPB系列气动接头,NPB,2,5,0, -48594,系列,NPX系列气动接头,NPX,2,5,0, -48595,系列,NPH系列气动接头,NPH,2,5,0, -48596,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5级 H系列专供),BH,7,7,0, -48614,系列,NUH-40B系列电涌保护器(H系列专供),NUH,7,0,0, -48628,系列,OUVR-3系列自恢复式过欠压保护器(专供),OUVR,5,0,0, -48630,系列,NBH-125系列塑料外壳式断路器(H系列专供),NBH,12,32,0, -48631,系列,NBH-100系列小型断路器(H系列专供),NBH,7,24,0, -48632,系列,NBO-63系列小型断路器(专供),NBO,5,0,0, -48663,系列,NB1-63H系列小型断路器(通讯专供),NB1,8,7,0, -48664,系列,NB1-63DC系列直流小型断路器(通讯专供),NB1,9,4,0, -48667,系列,CB-60A系列小型断路器(通讯专供),CB,7,0,0, -48668,系列,CB-60A系列小型断路器(交直流通讯专供),CB,7,0,0, -48669,系列,CB-60A(R)系列小型断路器(通讯专供),CB,8,0,0, -48670,系列,CB-60B系列小型断路器(通讯专供),CB,8,6,0, -48671,系列,CB-60G系列小型断路器(通讯专供),CB,7,0,0, -48672,系列,CB-60G系列小型断路器(交直流 通讯专供),CB,8,2,0, -48673,系列,CB-60Z系列小型断路器(交直流通讯专供),CB,7,0,0, -48674,系列,CB-125A系列小型断路器(交直流通讯专供),CB,7,0,0, -48675,系列,CB-63H系列小型断路器(通讯专供),CB,7,0,0, -48676,系列,CB-63HZ系列小型断路器(通讯专供),CB,7,2,0, -48677,系列,CB-60DC系列直流小型断路器(通讯专供),CB,7,2,0, -48678,系列,CB-125A系列小型断路器(通讯专供),CB,7,0,0, -48682,系列,CB-125G系列小型断路器(通讯专供),CB,6,4,0, -48685,系列,NXMHLE系列剩余电流动作断路器(H系列专供),NXMHLE,51,152,0, -48757,系列,NKC1系列直线导轨,NKC1,17,30,0, -48778,系列,NKC1系列滑块,NKC1,8,109,0, -49164,系列,LMZ-0.66系列电流互感器,LMZ,4,45,0, -49165,系列,BH(SDH)-1.0Ⅱ系列低压电流互感器(0.5级),,6,143,0, -49169,系列,NBP-100NGV系列带过失压保护断路器,NBP,5,4,0, -49170,系列,NBP-63R系列小型断路器,NBP,4,0,0, -49171,系列,CJX2e系列交流接触器,CJX2e,4,10,0, -49173,系列,NPM8-16A系列高钮,NPM8,5,0,0, -49174,系列,NXBF-40系列小型断路器,NXBF,18,26,0, -49176,系列,NXBF-63系列小型断路器,NXBF,17,32,0, -49177,系列,NXBF-125系列小型断路器,NXBF,17,30,0, -49178,系列,NXBFLE-32系列剩余电流动作断路器,NXBFLE,19,31,0, -49179,系列,NXBFLE-63系列剩余电流动作断路器,NXBFLE,19,31,0, -49182,系列,NXMF系列塑壳断路器,NXMF,41,284,0, -49200,系列,NSM1系列伺服电机,NSM1,1,0,0, -49201,系列,DJZ666系列直流智能电能表,DJZ666,4,28,0, -49231,系列,NXMFLE系列剩余电流动作断路器,NXMFLE,50,116,0, -49238,系列,NTK1系列温控器,NTK1,4,0,0, -49239,系列,NTR1系列加热器,NTR1,1,0,0, -49240,系列,热缩套管,热缩管,3,58,0, -49241,系列,行线槽,线槽,1,14,0, -49243,系列,FJ6G系列开关端子,FJ6G,4,14,0, -49730,系列,42L6系列模拟指示功率因数表(改进型),42,5,0,0, -49732,系列,42L6系列模拟指示电流表(改进型),42,6,25,0, -49733,系列,42L6系列模拟指示电压表(改进型),42,6,2,0, -49734,系列,42L6系列模拟指示功率表(改进型),42,6,0,0, -49735,系列,42L6系列模拟指示频率表(改进型),42,6,0,0, -49745,系列,6L2系列模拟指示电流表(改进型),6,6,2,0, -49746,系列,6L2系列模拟指示电压表(改进型),6,6,2,0, -49747,系列,6L2系列模拟指示频率表(改进型),6,6,2,0, -49748,系列,6L2系列模拟指示功率因数表(改进型),6,5,0,0, -49757,系列,NXW系列电能质量治理装置(已停产),NXW,4,12,0, -49758,系列,NM1系列塑壳断路器(消防专供),NM1,11,28,0, -49759,系列,NC1系列交流接触器(畜牧专用),NC1,5,0,0, -49760,系列,NP2系列带灯旋钮,NP2,20,17,0, -49761,系列,AC系列交流阀用电磁铁(已停产),AC,3,24,0, -49764,系列,NFV系列交流阀用电磁铁,NFV,1,0,0, -49767,系列,ACL系列交流输入电抗器,ACL,4,54,0, -49772,系列,DCL系列直流输入电抗器,DCL,4,42,0, -49794,系列,发光器,,3,0,0, -49795,系列,NEW系列电子组件板,,2,47,0, -50013,系列,YH系列复合避雷器,YH,7,21,0, -50276,系列,2V系列电磁阀,2V,3,0,0, -50277,系列,3V系列电磁阀,3V,5,12,0, -50278,系列,4V系列电磁阀,4V,5,58,0, -50279,系列,4M系列电磁阀,4M,4,2,0, -50291,系列,NJR5-ZX系列软起动器,NJR5,6,23,0, -50346,系列,AC30系列强电插座,,3,23,0, -50804,系列,NXU-ⅡG系列直流电涌保护器(通信专供)(按项目报价),NXU-ⅡG,5,0,0, -50860,系列,NZ1HP系列自动转换开关(PC级)(H系列专供),NZ1HP,6,14,0, -50864,系列,NZ1HM系列自动转换开关(塑壳型 CB级)(H系列专供,即将停销,被NXZMN替代),NZ1HM,7,12,0, -50865,系列,NZ1HB系列自动转换开关(微断 CB级)(H系列专供,即将停销,被NXZBN替代),NZ1HB,6,0,0, -50905,系列,NXAF系列万能式断路器,NXAF,24,49,0, -51149,系列,NKY2系列开关电源,NKY2,2,10,0, -51150,系列,NKY3系列薄型开关电源,NKY3,2,7,0, -51275,系列,TNSZ3系列柱式交流自动稳压器,TNSZ3,1,4,0, -51367,系列,NZ5-H系列自动转换开关(PC级),NZ5,8,15,0, -51453,系列,NB5-63系列小型断路器,NB5,16,34,0, -51456,系列,NB5LE-40系列剩余电流动作断路器,NB5LE,18,34,0, -51457,系列,NB5-40系列小型断路器,NB5,16,32,0, -51459,系列,NB5-63G系列塑料外壳式断路器,NB5,17,76,0, -51460,系列,NB5LE-40Y系列剩余电流动作断路器,NB5LE,18,28,0, -51461,系列,NB5LE-63系列剩余电流动作断路器,NB5LE,17,33,0, -51462,系列,NB5LG-63系列剩余电流动作断路器,NB5LG,16,28,0, -51463,系列,NB5LE-63Y系列剩余电流动作断路器,NB5LE,18,30,0, -51464,系列,NB5LE-63ZB系列自诊断剩余电流动作断路器,NB5LE,18,28,0, -51465,系列,NB5L-40Y系列电磁式剩余电流动作断路器,NB5L,18,28,0, -51466,系列,NB5L-40M系列电磁式剩余电流动作断路器,NB5L,18,28,0, -51468,系列,NH5-125系列隔离开关,NH5,4,4,0, -51469,系列,NU5-Ⅱ系列电涌保护器,NU5,6,28,0, -51470,系列,OUVR-5系列自恢复式过欠压保护器,OUVR-5,4,2,0, -51573,系列,NB2-40ZT/ZW系列智慧小型断路器,NB2,7,0,0, -51574,系列,NB2-80ZT/ZW系列智慧小型断路器(环保),NB2,7,2,0, -51575,系列,NB2LE系列剩余电流动作断路器,NB2LE,6,0,0, -51576,系列,NB2LE-80ZT系列智慧剩余电流动作断路器(环保),NB2LE,9,2,0, -51578,系列,NB2LE-40ZT系列智慧剩余电流动作断路器,NB2LE,7,0,0, -51579,系列,RX系列信号熔断器,RX,1,0,0, -51673,系列,NX50系列暗装式配电箱(箱体),NX50,6,274,0, -51698,系列,NR5系列热过载继电器,NR5,4,31,0, -51699,系列,NS5系列电动机起动器,NS5,12,14,0, -51712,系列,NB8-125系列小型断路器,NB8,14,26,0, -51719,系列,NB8LE-63H系列剩余电流动作断路器,NB8LE,18,26,0, -51720,系列,NB8LE-63YH系列剩余电流动作断路器,NB8LE,18,26,0, -51721,系列,NB8LG-63YH系列剩余电流动作断路器,NB8LG,8,0,0, -51931,系列,NDT1系列警示灯,NDT1,8,6,0, -51933,系列,NU6-ⅡG系列电涌保护器,NU6-ⅡG,4,0,0, -51934,系列,NXU-ⅡG系列电涌保护器,NXU-ⅡG,4,6,0, -52215,系列,NA5系列万能式断路器,NA5,114,182,0, -52245,系列,NBP-125GVS系列小型断路器,NBP,7,2,0, -52259,系列,NM5系列塑壳断路器,NM5,64,329,0, -52273,系列,JQX-13FA系列小型电磁继电器,JQX-13FA,6,4,0, -52447,系列,NB5L-40J系列电磁式剩余电流动作断路器,NB5L,18,28,0, -52495,系列,NB5-125G系列塑料外壳式断路器,NB5,16,32,0, -52496,系列,NB5LE/LG-125G系列剩余电流动作断路器,NB5,19,47,0, -52497,系列,NU5-Ⅰ+Ⅱ系列电涌保护器,NU5,6,0,0, -52498,系列,NSCB5系列电涌保护器专用保护装置,NSCB5,6,6,0, -52623,系列,FLN36-12D系列户内高压负荷开关,FLN36,5,0,0, -52624,系列,NFW1-12(F)系列户外分界交流负荷开关,NFW1,4,0,0, -52625,系列,NFW2-12系列户外高压交流真空负荷开关,NFW2,4,0,0, -52626,系列,NFW2-12(F)系列户外高压交流分界负荷开关,NFW2,5,0,0, -52627,系列,NFW2-12(Z)系列户外高压交流智能真空负荷开关,NFW2,5,0,0, -52628,系列,NFZ77-40.5D系列风电专用负荷开关,NFZ77,5,0,0, -52629,系列,NV1-24/T系列户内高压交流真空断路器,NV1,5,0,0, -52630,系列,NV1-24/T(P)系列户内固封极柱真空断路器,NV1,6,7,0, -52631,系列,NV2-12/T(P)系列户内固封极柱真空断路器,NV2,6,8,0, -52632,系列,NV3-40.5/T(P)系列户内固封极柱真空断路器,NV3,6,6,0, -52633,系列,NV6-12/T(P)系列环保型户内高压交流真空断路器,NV6,6,0,0, -52636,系列,ZN63S-12/T系列户内高压交流真空断路器,ZN63S,5,7,0, -52638,系列,ZW7-40.5系列户外高压交流真空断路器,ZW7,4,4,0, -52639,系列,ZW20A-12(F)系列户外分界高压交流真空断路器,ZW20A,5,0,0, -52643,系列,6L2系列模拟指示功率表(改进型),6,6,0,0, -52645,系列,BH-0.66Ⅲ系列低压电流互感器(0.2S级),BH,5,51,0, -52673,系列,NM2LC系列剩余电流保护断路器(光伏专用),NM2LC,5,10,0, -52674,系列,NJX3系列小型电磁继电器,NJX3,2,0,0, -52680,系列,RT29-16系列圆筒形帽熔断器,RT29,5,1,0, -52688,系列,RT36(R)系列熔断器,RT36,6,19,0, -52689,系列,RT36(NT00)系列熔断器,RT36-00(NT00),6,3,0, -52694,系列,RT36系列刀型触头熔断器,RT36,4,19,0, -52697,系列,NRT36系列刀型触头熔断器,NRT36,5,3,0, -52698,系列,HDLRT0系列刀型触头熔断器,HDLRT0,4,11,0, -52754,系列,NXB-63T系列透明壳小型断路器,NXB,13,61,0, -52755,系列,NXBLE-40T系列透明壳漏电断路器,NXBLE,14,46,0, -52756,系列,NXBLE-63T系列透明壳漏电断路器,NXBLE,14,44,0, -52757,系列,OUVR-2N系列自恢复式过欠压保护器,OUVR,4,2,0, -52758,系列,NB5NE-40S系列小型断路器,NB5NE,6,0,0, -52759,系列,"NM10系列塑壳断路器(升级型)(已停产,被NXM替换)",NM10,9,0,0, -52760,系列,NB5NE-63N系列小型断路器,NB5NE,6,6,0, -52761,系列,NB5NELE-40S系列剩余电流动作断路器,NB5NELE,8,0,0, -52762,系列,NB5NELE-63Y系列剩余电流动作断路器,NB5NELE,8,0,0, -52763,系列,NB5NELE-63系列剩余电流动作断路器,NB5NELE,7,4,0, -52764,系列,OUVR-1N系列自恢复式过欠压保护器(专供),OUVR,4,2,0, -52765,系列,NXBFLE-40系列剩余电流动作断路器,NXBFLE,19,26,0, -52766,系列,NXHBF-125系列小型隔离开关,NXHBF,3,4,0, -52767,系列,NU5NE-Ⅰ+Ⅱ系列电涌保护器,NU5NE,5,0,0, -52816,系列,ExASD E直流隔离开关,ExASD E,5,8,0, -52817,系列,ExBP E系列塑壳断路器,ExBP E,4,4,0, -52818,系列,ExBD125 E直流小型断路器,ExBD125 E,3,4,0, -52819,系列,ExlR50 E旋转隔离开关,ExlR50 E,2,8,0, -52821,系列,HD11-□E系列刀开关,HD11,6,0,0, -52822,系列,HK18-□E系列隔离开关,HK18,3,0,0, -52823,系列,HD18-□E系列光伏专供刀开关,HD18,3,0,0, -52824,系列,NA5PD系列万能式断路器,NA5PD,4,6,0, -53003,系列,NC5NE系列交流接触器,NC5NE,3,42,0, -53110,系列,NXB-63E系列小型断路器,NXB,13,39,0, -53111,系列,NXB-80E系列小型断路器,NXB,13,39,0, -53112,系列,NXB-125E系列小型断路器,NXB,12,39,0, -53135,系列,ExJPV E系列新能源专供板载继电器,ExJPV,2,8,0, -53213,系列,NBP-80NZSY系列电能表外置断路器,NBP,6,0,0, -54236,系列,NJX12系列小型电磁继电器,NJX12,6,0,0, -54237,系列,NXLH-1系列电流互感器,NXLH-1,5,284,0, -54245,系列,CKDG系列单相干式串联电抗器,CKDG,3,0,0, -54267,系列,NJYB2系列电压保护继电器,NJYB2,3,0,0, -54268,系列,JSZ3P系列时间继电器,JSZ3P,3,3,0, -54355,系列,NXCF系列交流接触器,NXCF,11,37,0, -54356,系列,NXRF系列热继电器,NXRF,4,10,0, -54428,系列,HR6系列熔断器式隔离开关(蓝色),HR6,5,12,0, -54429,系列,CB-63HB系列塑料外壳式断路器,CB,4,0,0, -54457,系列,NHM5系列隔离开关,NHM5,54,195,0, -54458,系列,NM5S系列电子式塑壳断路器,NM5S,60,196,0, -54459,系列,NM5LE系列剩余电流动作断路器,NM5LE,59,224,0, -54460,系列,NA5NE系列万能式断路器,NA5NE,9,15,0, -54463,系列,NB5LE-63□/B系列剩余电流动作断路器,NB5LE,18,31,0, -54465,系列,NWFBA系列智能组合式低压并联电容器,NWFBA,2,2,0, -54468,系列,KG316T-S系列时控开关,KG316T-S,1,0,0, -54469,系列,HD11G-□E系列光伏专用刀开关,HD11G,3,0,0, -54476,系列,NXCQ系列交流接触器应急启动装置(已停销,被NQ1替代),NXCQ,4,15,0, -54498,系列,NKB8G系列控制与保护开关电器,NKB8G,4,2,0, -54541,系列,HK18G系列刀开关,HK18G,3,0,0, -54542,系列,PES系列便携式储能电源(已停产),PES,1,4,0, -54567,系列,NB5-63M系列塑料外壳式断路器,NB5,17,32,0, -54569,系列,NU5-I系列电涌保护器,NU5,5,0,0, -54625,系列,NXMSF系列电子式塑壳断路器,NXMSF,44,120,0, -54832,系列,NA5T系列5G&通信专供万能断路器,NA5T,8,22,0, -54844,系列,NDK2系列控制变压器,NDK2,3,3,0, -54895,系列,NCH8G系列家用交流接触器,NCH8G,3,12,0, -54909,系列,NXTC系列工业插头插座和耦合器,NXTC,6,23,0, -54993,系列,TFD110系列简易矢量型变频器,TFD110,5,23,0, -54994,系列,TFD120系列变频器,TFD120,5,26,0, -54995,系列,TFD130系列变频器,TFD130,5,26,0, -54996,系列,TR150-ZX系列软起动器,TR150,3,0,0, -54997,系列,TR120-D系列软起动器,TR120,2,0,0, -54998,系列,DTSH666系列三相四线电子式多用户电能表,DTSH666,5,5,0, -55007,系列,NH3-125系列隔离开关,NH3,3,3,0, -55011,系列,NVFP5系列变频器,NVFP5,5,83,0, -55014,系列,NJRP5系列软起动器,NJRP5,3,0,0, -55019,系列,EV-TN系列绝缘护套双线管形冷压端子(已停产),EV-TN,3,33,0, -55021,系列,CKJ11系列真空交流接触器,CKJ11,3,6,0, -55027,系列,NXBLE-63系列剩余电流动作断路器,NXBLE,15,55,0, -55028,系列,NXBLE-63YHF系列剩余电流动作断路器(下进线),NXBLE,17,39,0, -55029,系列,NXBLG-63YH系列剩余电流动作断路器(带过压),NXBLG-63YH,6,0,0, -55167,系列,DDSYU666-B系列单相导轨电子式预付费电能表(昆仑),DDSYU666-B,4,0,0, -55168,系列,DJZU666X系列直流智能导轨电能表(昆仑),DJZU666X,4,0,0, -55169,系列,PA666系列电流数显表(昆仑),PA666,6,177,0, -55170,系列,PD666系列多功能数显表(昆仑),PD666,6,54,0, -55171,系列,PH666系列功率因数表(昆仑),PH666,6,11,0, -55172,系列,PP666系列频率数显表(昆仑),PP666,6,21,0, -55173,系列,PS666系列数显功率表(昆仑),PS666,5,6,0, -55174,系列,PZ666系列电压数显表(昆仑),PZ666,6,172,0, -55175,系列,NXMP系列塑壳断路器,NXMP,37,861,0, -55181,系列,RT36J系列低功耗熔断器体,RT36J,2,2,0, -55329,系列,NLH2-0.8系列电流互感器,NLH2,4,61,0, -55470,系列,NXSCB系列电涌保护器专用保护装置,NXSCB,5,6,0, -55645,系列,CKSG2系列三相干式串联电抗器,CKSG2,3,22,0, -55646,系列,ExMYHV E系列高电压系列塑料外壳式断路器,ExMY,7,8,0, -55647,系列,NJX5系列小型电磁继电器,NJX5,4,6,0, -55652,系列,NR4-G系列热过载继电器,NR4,3,18,0, -55655,系列,NH40DC系列直流隔离开关,NH40DC,3,0,0, -55750,系列,NBH-40J系列小型断路器,NBH,5,4,0, -55751,系列,NBHLU-63系列剩余电流动作断路器,NBHLU,5,0,0, -55752,系列,NX30H系列安装配电箱,NX30H,3,10,0, -55753,系列,NXMSH系列电子式塑壳断路器(H系列专供),NXMSH,43,86,0, -55754,系列,NBP-63S系列小型断路器,NBP,7,2,0, -55755,系列,HPD2000GH配网三相不平衡综合治理装置,HPD2000GH,4,2,0, -55756,系列,NBP-63系列微型断路器,NBP,6,0,0, -55757,系列,NBP-80RG系列小型断路器,NBP,5,7,0, -55758,系列,NBP-80系列小型断路器,NBP,6,2,0, -55759,系列,NBP-100HS系列小型断路器,NBP,7,2,0, -55760,系列,NBP-100NZS/L系列电能表外置断路器,NBP,8,7,0, -55761,系列,NBP-125NZS系列电能表外置断路器,NBP,7,4,0, -55762,系列,NBP-125系列塑料外壳式断路器,NBP,5,4,0, -55763,系列,NBPLE/LG-63系列剩余电流动作断路器,NBP,8,9,0, -55764,系列,NBPLE/LG-125系列剩余电流动作断路器,NBP,9,14,0, -55765,系列,NBPLE-63YH系列剩余电流动作断路器,NBP,9,0,0, -55766,系列,NBPLE-63系列剩余电流漏电断路器(FJ专供),NBPLE,8,0,0, -55767,系列,NHP-125G系列隔离开关,NHP,4,0,0, -55768,系列,NHP-125系列隔离开关,NHP,4,4,0, -55769,系列,ZCKP系列智能复合开关,ZCKP,3,0,0, -55781,系列,NM5NELE系列新能源专供塑壳漏电断路器,NM5NELE,97,296,0, -55782,系列,NM5NE系列新能源专供塑壳断路器,NM5NE,93,472,0, -55783,系列,NM3DC系列高电压直流塑壳断路器,NM3DC,13,16,0, -55784,系列,NM3FC系列费控塑壳断路器,NM3FC,10,25,0, -55785,系列,NM3LC系列剩余电流保护器断路器,NM3LC,14,25,0, -55787,系列,XMT-5000改进型系列数字温度指示控制仪,,8,50,0, -55788,系列,NM3系列塑壳断路器,NM3,19,20,0, -55789,系列,BWD系列干式变压器温度控制器,BWD,5,2,0, -55790,系列,EPEC100系列电力环境控制器(已停销),EPEC100,3,0,0, -55791,系列,EPEC200系列电力环境控制器(已停销),EPEC200,3,2,0, -55792,系列,NPR300-FV/H微机防孤岛保护装置,,3,2,0, -55793,系列,NPR300-M系列电动机保护器,,1,0,0, -55794,系列,NPR300系列微机保护装置,,3,12,0, -55795,系列,NPR500系列微机保护装置,,3,12,0, -55796,系列,NPR530系列微机保护装置,,3,18,0, -55797,系列,NPR550-FB系列微机保护装置,,1,0,0, -55798,系列,NPR550系列微机保护装置,,4,60,0, -55799,系列,NSC100系列智能操控装置,NSC,9,99,0, -55800,系列,WSG系列温湿度控制器,,6,53,0, -55801,系列,NDH50智能除湿器,,4,9,0, -55802,系列,NTD50/70系列无线测温装置,,3,12,0, -55803,系列,NS100-W系列无线测温传感器,,3,0,0, -55804,系列,DSN10系列户内电磁锁,,4,0,0, -55805,系列,DXN20系列高压带电显示器,,3,24,0, -55806,系列,EKL30系列故障指示器,,1,12,0, -55807,系列,HT系列加热器(板),,6,16,0, -55813,系列,NXCC系列切换电容器接触器,NXCC,3,8,0, -55962,系列,OCL系列交流输出电抗器(已停产),OCL,4,54,0, -55965,系列,NP2系列自锁按钮,NP2,7,4,0, -56061,系列,NXMN系列透明壳塑壳断路器,NXMN,10,60,0, -56149,系列,NXMNLE系列透明壳剩余电流动作断路器,NXMNLE,11,40,0, -56175,系列,CG系列电缆接头,CG,5,46,0, -56177,系列,NXTC2系列电缆接头,NXTC2,3,29,0, -56178,系列,NXTC2系列接插体,NXTC2,11,71,0, -56179,系列,NXTC2系列外壳底座,NXTC2,5,302,0, -56183,系列,NB2DC-100ZT系列直流小型断路器,NB2DC,6,0,0, -56184,系列,NXZF系列自动转换开关(PC级),NXZF,3,0,0, -56186,系列,NJR5-G系列在线式软起动控制柜,NJR5,2,0,0, -56189,系列,EV系列管形冷压端子(已停产),EV,2,14,0, -56191,系列,EV-N系列冷压端子(已停产),EV-N,3,28,0, -56195,系列,NB5NE-125G系列小型断路器,NB5NE,6,4,0, -56196,系列,NB5NELE-125G系列剩余电流动作断路器,NB5NELE,8,3,0, -56214,系列,NQ1系列智能型一体式星三角起动器,NQ1,6,9,0, -56404,系列,DSSU666系列三相电子式导轨电能表(昆仑),DSSU666,5,6,0, -56420,系列,HD13/E系列刀开关(已停产),HD13,6,5,0, -56422,系列,NRT30系列熔断体底座,底座NRT30,3,0,0, -56424,系列,RT28N系列熔断器底座,底座RT28N,4,6,0, -56426,系列,C型、G型导轨,,2,0,0, -56623,系列,NXBLE-125E系列小型漏电断路器,NXBLE,14,41,0, -56624,系列,NXB-125E系列小型直流断路器,NXB,13,41,0, -56627,系列,NXBLE-63E系列小型漏电断路器,NXBLE,15,43,0, -56698,系列,JXFG系列配电箱(箱体),JXFG,3,56,0, -56699,系列,NJX6系列配套插座,NJX6,2,0,0, -56700,系列,NJX6系列小型电磁继电器,NJX6,3,0,0, -56701,系列,NJX6系列整机,NJX6,3,0,0, -56702,系列,NJRM5-ZX系列通用型软起动器(15A-220A),NJRM5,3,0,0, -56703,系列,PZ30G系列配电箱,PZ30G,3,36,0, -56711,系列,NJRM5-D-SZ数智型软起动器(180A-1000A),NJRM5,4,0,0, -56714,系列,WPanel智慧终端箱,WPanel,5,47,0, -56715,系列,BP8R4系列频敏变阻器(已停产),特 BP8R4,2,10,0, -56716,系列,2W系列电磁阀,2W,4,41,0, -56717,系列,PU系列气管,PU,5,81,0, -56739,系列,NDKH系列控制变压器,NDKH,3,24,0, -56741,系列,NXKY系列开关电源,NXKY,2,0,0, -56774,系列,NCC2NE-90系列磁保持继电器,NCC2NE,4,0,0, -56976,系列,NXC-XM系列交流接触器,NXC,4,11,0, -56990,系列,NXR-XM系列热过载继电器,NXR,3,3,0, -57023,系列,NXC-R系列交流接触器,NXC,3,0,0, -57134,系列,NKY6系列开关电源,NKY6,2,23,0, -57135,系列,NXW系列模块化电能质量功率单元,NXW,7,24,0, -57136,系列,LMZ□G-ZTN1系列电流互感器,LMZ,5,10,0, -57137,系列,NKY2S系列开关电源,NKY2S,2,4,0, -57138,系列,NXW N系列模块化电能质量功率单元,NXW,6,2,0, -57142,系列,NXA-NE系列万能式断路器,NXA,82,112,0, -57147,系列,NZ5系列自动转换开关电器(PC级),NZ5,7,18,0, -57322,系列,TND2系列自动交流稳压器,TND2,2,11,0, -57324,系列,MA系列迷你气缸,MA,3,0,0, -57325,系列,HRQ系列回转气缸,HRQ,2,8,0, -57326,系列,MD系列多位置固定型气缸,MD,3,6,0, -57327,系列,RMS系列磁耦合无杆气缸,RMS,5,32,0, -57328,系列,MK系列多位置固定型气缸,MK,3,12,0, -57329,系列,QTR系列双轴气缸,QTR,3,12,0, -57330,系列,TN系列双轴气缸,TN,3,10,0, -57336,系列,SDA系列薄型气缸,SDA,4,547,0, -57337,系列,PB系列笔形气缸,PB,4,68,0, -57419,系列,NXZN系列自动转换开关(PC级),NXZN,5,21,0, -57457,系列,ExIZ HV E系列新能源专供隔离开关,ExIZ,14,52,0, -57461,系列,NXU-IIG E 电涌保护器,NXU-IIG,5,0,0, -57462,系列,NM8N高电压(HV)系列塑壳断路器,NM8N,16,90,0, -57463,系列,NM5T系列塑料外壳式断路器,NM5T,48,189,0, -57464,系列,CB-63DC系列直流断路器,CB,5,0,0, -57465,系列,NM8N系列高电压塑壳断路器(按项目报价),NM8N,24,38,0, -57466,系列,NBP-100NGV E光伏并网专用断路器,NBP,9,2,0, -57471,系列,NBP-125NGV E光伏并网专用断路器,NBP,8,2,0, -57477,系列,NGC5系列低压品牌柜,NGC5,3,0,0, -57478,系列,NGC8系列智能型成套开关柜,NGC8,2,0,0, -57487,系列,NXMSP系列电子式塑壳断路器,NXMSP,41,111,0, -57488,系列,RT36-T系列刀型触头熔断器,底座RT36,7,16,0, -57489,系列,NM3LFC系列剩余电流保护器断路器,NM3LFC,17,34,0, -57491,系列,SDH-0.66 T系列电流互感器,SDH,4,0,0, -57494,系列,NM3SD系列隔离开关,NM3SD,26,75,0, -57495,系列,NXMSPD系列塑壳断路器,NXMSPD,38,59,0, -57496,系列,NTCE系列储能连接器(插头),NTCE,4,5,0, -57497,系列,NTCE系列储能连接器(插座),NTCE,5,5,0, -57502,系列,NWP系列模块化电能质量功率单元,NWP,5,6,0, -57522,系列,NBP-100□ZW系列电能表外置断路器,NBP,5,4,0, -57523,系列,NBP-80ZSW系列电能表外置断路器,NBP,5,0,0, -57526,系列,NM5TS系列塑料外壳式断路器,NM5TS,48,189,0, -57529,系列,NM3N系列智能量测开关,NM3N,27,123,0, -57530,系列,LMZ□K-ZTN1系列抗直流偏磁低压电流互感器,LMZ,5,15,0, -57707,系列,NCZ5NE-F系列直流接触器,NCZ5NE,6,28,0, -57708,系列,NXMNS系列电子式塑壳断路器,NXMNS,97,919,0, -57709,系列,NXMN-1250、1600系列塑壳断路器,NXMN,13,75,0, -57896,系列,NXD-16系列信号灯,NXD,5,0,0, -57897,系列,NXD-22系列信号灯,NXD,7,136,0, -57898,系列,NXD-22系列蜂鸣器式信号灯,NXD,5,4,0, -57907,系列,NM2FC系列塑料外壳式断路器,NM2FC,5,4,0, -58062,系列,Ex9A-DC系列直流空气断路器,Ex9A,71,100,0, -58063,系列,Ex9A系列空气断路器,Ex9A,96,217,0, -58064,系列,Ex9MD3HV直流塑料外壳式断路器,Ex9M,34,216,0, -58065,系列,Ex9MDYHV系列高电压直流塑壳断路器,Ex9MDY,15,33,0, -58066,系列,Ex9MD系列直流塑料外壳式断路器,Ex9MD,5,28,0, -58067,系列,Ex9MHV高电压系列塑料外壳式断路器,Ex9M,17,34,0, -58068,系列,Ex9ML系列剩余电流保护模块,Ex9ML,6,6,0, -58069,系列,Ex9MV2S-PV/DC 1500V光伏专用直流塑料外壳式断路器,Ex9MV,11,21,0, -58070,系列,Ex9MV2S-PV10光伏专用直流塑料外壳式断路器,Ex9MV,10,8,0, -58071,系列,Ex9MYHV系列塑料外壳式断路器,Ex9MY,15,32,0, -58072,系列,Ex9M系列交流塑料外壳式断路器,Ex9M,78,1324,0, -58073,系列,ATSA自动电源转换系统组件,,4,51,0, -58074,系列,ExATS9B系列自动转换开关电器,ExATS9B,5,127,0, -58075,系列,ExATS9M系列自动转换开关电器(CB级),ExATS9M,4,5,0, -58076,系列,ExATSNH系列自动转换开关电器(PC级),ExATS,12,42,0, -58077,系列,ExATSN系列自动转换开关电器(PC级),ExATSN,4,4,0, -58078,系列,Ex9I(Z)HV系列隔离开关,Ex9I,14,52,0, -58079,系列,Ex9IRTZ隔离开关熔断器组,Ex9IRTZ,9,34,0, -58080,系列,Ex9IR隔离开关,Ex9I,12,6,0, -58081,系列,Ex9I隔离开关,Ex9I,9,17,0, -58082,系列,Ex9MSD系列隔离开关,Ex9M,7,25,0, -58083,系列,Ex9CF系列宽电压交流接触器,Ex9C,7,50,0, -58084,系列,Ex9CM系列模数化交流接触器,Ex9C,6,0,0, -58085,系列,Ex9CN系列交流接触器,Ex9CN,4,10,0, -58086,系列,Ex9C系列交流接触器,Ex9C,18,867,0, -58087,系列,Ex9RC系列中间继电器,Ex9RC,7,2,0, -58088,系列,Ex9RN系列热过载继电器,Ex9RN,3,6,0, -58089,系列,Ex9R系列热过载继电器,Ex9R,4,15,0, -58090,系列,Ex9S电动机保护用断路器,Ex9S,26,40,0, -58091,系列,Ex9IRZ系列隔离开关,Ex9IRZ,6,0,0, -58092,系列,Ex9JM系列小型电磁继电器,Ex9JM,7,6,0, -58093,系列,Ex9JPV系列光伏继电器,Ex9JPV,2,0,0, -58094,系列,Ex9JP系列电压保护继电器,Ex9JP,3,44,0, -58095,系列,Ex9P2系列按钮,Ex9P2,18,102,0, -58096,系列,Ex9PL系列信号灯及蜂鸣器,Ex9PL,3,12,0, -58097,系列,Ex9ZA系列万能转换开关,Ex9ZA,5,64,0, -58098,系列,Ex9VF3系列变频器,Ex9VF3,13,26,0, -58099,系列,Ex9VF6系列变频器,Ex9VF6,13,25,0, -58100,系列,Ex9QR系列软起动器,Ex9QR,5,26,0, -58101,系列,Ex9B40J小型断路器,Ex9B40J,13,33,0, -58102,系列,Ex9B125小型断路器,Ex9B,13,38,0, -58103,系列,Ex9BD125小型断路器,Ex9BD125,13,106,0, -58104,系列,Ex9BG小型断路器,Ex9B,18,42,0, -58105,系列,Ex9BH125小型断路器,Ex9B,4,0,0, -58106,系列,Ex9BM电动机保护小型断路器,Ex9BM,17,38,0, -58107,系列,Ex9BP-JX直流小型断路器,Ex9BP,16,37,0, -58108,系列,Ex9B小型断路器,Ex9B,24,120,0, -58109,系列,Ex9PN小型断路器(相线+中性线),Ex9PN,13,26,0, -58110,系列,Ex9BP直流小型断路器,Ex9BP,21,208,0, -58111,系列,Ex9B100+GQ自愈式过欠压保护断路器,Ex9B,5,0,0, -58112,系列,Ex9B100+GV光伏并网专用小型断路器,Ex9B,5,0,0, -58113,系列,Ex9B100+ZS电能表外置断路器,Ex9B,5,0,0, -58115,系列,Ex9BL40电磁式剩余电流动作断路器,Ex9BL40,5,4,0, -58116,系列,Ex9CBL电磁式剩余电流动作断路器,Ex9CBL,6,0,0, -58117,系列,Ex9NLE EL剩余电流动作断路器,Ex9NLE,6,0,0, -58118,系列,Ex9PLE电子式剩余电流动作保护断路器,Ex9PLE,4,2,0, -58119,系列,Ex9BI系列交流隔离开关,Ex9BI,2,0,0, -58120,系列,Ex9I40系列隔离开关,Ex9I,3,0,0, -58121,系列,Ex9I125系列隔离开关,Ex9I,3,0,0, -58122,系列,Ex9IP系列光伏专用隔离开关,Ex9IP,2,0,0, -58123,系列,Ex9IR50系列旋转式隔离开关,Ex9IR,5,6,0, -58124,系列,Ex9BT2框缘式双极开关,Ex9BT2,2,0,0, -58125,系列,Ex9UE1+2 12.5电涌保护器,Ex9UE,5,0,0, -58126,系列,Ex9UE1+2 25电涌保护器,Ex9UE,9,2,0, -58127,系列,Ex9UE2电涌保护器,Ex9UE,9,4,0, -58128,系列,Ex9UE3电涌保护器,Ex9UE,9,0,0, -58129,系列,Ex9UEP电涌保护器,Ex9UE,9,6,0, -58130,系列,Ex9FP30H系列熔断器式隔离器,Ex9FP,2,0,0, -58131,系列,Ex9FP30系列光伏直流熔断器,Ex9FP30,2,0,0, -58132,系列,Ex9XE终端箱,Ex9X,5,14,0, -58133,系列,AL31/AXL31报警触头,,2,2,0, -58134,系列,AX31辅助触头,,2,0,0, -58136,系列,Ex9LE电子式剩余电流动作附件,Ex9LE,6,82,0, -58137,系列,LK-I锁扣装置,,1,0,0, -58138,系列,OVT31过压脱扣器,,2,0,0, -58139,系列,SHT31分励脱扣器,,3,0,0, -58140,系列,UVT31欠压脱扣器,,3,0,0, -58141,系列,ExMVB-T01-12系列户内真空断路器(固封),ExMVB,23,46,0, -58142,系列,ExMPD系列微机保护装置,ExMPD,2,0,0, -58143,系列,PMA600系列三相数显多功能表,PMA600,3,0,0, -58144,系列,PMA710系列在线式电能质量检测仪,PMA710,2,0,0, -58145,系列,PMR700系列智能电动机保护器,PMR700,7,0,0, -58146,系列,PMR710系列智能电动机保护器,PMR710,10,0,0, -58147,系列,ExMCM-AI01-12系列中压开关柜,ExMCM,4,0,0, -58148,系列,InModule智能型低压开关柜,InModule,1,0,0, -58149,系列,Ex9TC快速连接器,Ex9TC,4,12,0, -58150,系列,ExMRM SF6充气式环网柜,ExMRM SF6I01,4,0,0, -58154,系列,ASD16 DC直流框架隔离开关,ASD16,37,26,0, -58155,系列,ASD25 DC直流框架隔离开关,ASD,35,28,0, -58159,系列,M1PVS壳架15~100A塑壳断路器(光伏专用),M,70,74,0, -58160,系列,M1壳架15~150A塑壳断路器,M,94,320,0, -58161,系列,M2G壳架100~250A塑壳断路器(接地保护),M2G,16,3,0, -58162,系列,M2HV壳架60~250A塑壳断路器(800Vac),M2HV,39,33,0, -58163,系列,M2壳架100~250A塑壳断路器,M,94,238,0, -58164,系列,M3HV壳架250~400A塑壳断路器(800Vac),M3HV,38,31,0, -58165,系列,M3壳架225~400A塑壳断路器,M,75,227,0, -58166,系列,M4壳架400~600A塑壳断路器,M,85,141,0, -58167,系列,M5壳架600~800A塑壳断路器,M,77,168,0, -58168,系列,M6壳架800~1200A塑壳断路器,M,76,158,0, -58169,系列,MD3HV壳架200~400A塑壳断路器(1500Vdc),MD3HV,36,29,0, -58170,系列,9FP系列熔断器组(UL认证),9FP,4,1,0, -58171,系列,B1B系列UL489 SC小型断路器(UL认证),B1B,14,22,0, -58172,系列,B1E系列UL1077小型断路器(UL认证),B1E,9,45,0, -58173,系列,B1系列UL489小型断路器(UL认证),B1,17,135,0, -58174,系列,B2系列UL489小型断路器(UL认证),B2,3,2,0, -58175,系列,B4系列UL489&UL1077液压式断路器(UL认证),B4,6,50,0, -58176,系列,CBA系列汇流排(UL认证),CBA,12,3,0, -58177,系列,Ex9BP系列UL1077小型断路器(UL认证),Ex9BP,13,24,0, -58179,系列,F30系列熔断器座(UL认证),F,4,0,0, -58181,系列,U4系列浪涌保护器(UL认证),U4,4,59,0, -58182,系列,UL489附件(UL认证),,4,8,0, -58183,系列,UL1077附件(UL认证),UL1077,4,8,0, -58184,系列,Ex9CA系列安全接触器,Ex9CA,5,2,0, -58185,系列,Ex9CKT系列专用接触器,Ex9CKT,7,35,0, -58186,系列,Ex9C系列交流接触器(UL认证),Ex9C,48,752,0, -58187,系列,Ex9QR5系列软起动器,Ex9QR,4,0,0, -58188,系列,Ex9RCA系列安全继电器,Ex9RCA,4,13,0, -58189,系列,Ex9RE系列电子式过载继电器,Ex9RE,4,0,0, -58190,系列,Ex9R系列热过载继电器(UL认证),Ex9R,5,15,0, -58191,系列,Ex9S电动机保护用断路器(UL认证),Ex9S,23,18,0, -58213,系列,Ex9MV2口-PV/DC 1200V光伏专用直流塑料外壳式断路器,Ex9MV,16,23,0, -58245,系列,NXZBN-63系列自动转换开关(CB级),NXZBN,7,11,0, -58246,系列,NXZHBN-63系列自动转换开关(PC级),NXZHBN,5,3,0, -58247,系列,NXZHBN-125系列自动转换开关(PC级),NXZHBN,5,3,0, -58483,系列,VF-3000(VF-5000) 系列电磁阀,VF,5,2,0, -58484,系列,4H系列手动阀,4H,3,2,0, -58485,系列,CV系列真空发生器,CV,3,0,0, -58486,系列,AF系列空气过滤器,AF,3,20,0, -58492,系列,LKS系列电子排水器,LKS,2,0,0, -58493,系列,4R系列手动阀,4R,3,8,0, -58494,系列,FV系列脚踏阀,FV,1,0,0, -58495,系列,HV系列手转阀,HV,1,0,0, -58498,系列,QE系列快速排气阀,QE,1,0,0, -58499,系列,RE系列单向节流阀,RE,1,0,0, -58507,系列,HFK系列起动手指,,3,36,0, -58508,系列,HLS、HLSL系列双轴型精密滑台气缸(滚柱型),,10,38,0, -58509,系列,MGP系列三杆带导杆气缸,,3,10,0, -58510,系列,MI系列不锈钢迷你气缸,,8,212,0, -58511,系列,MU系列小型自由安装气缸,,6,42,0, -58512,系列,SC系列标准复动型气缸,SC,4,12,0, -58515,系列,CS1系列感应开关,CS1,1,4,0, -58516,系列,200M系列阀座,200M,1,0,0, -58517,系列,TCL、TCM系列三轴气缸,TC,7,52,0, -58527,系列,YB系列油雾器,YB,2,20,0, -58528,系列,YB/BL系列油雾器,,2,2,0, -58529,系列,AC/BC系列三联件,,3,4,0, -58530,系列,AF/BF系列过滤器,,3,4,0, -58531,系列,AFC/BFC系列二联件,,3,4,0, -58532,系列,AFR/BFR系列调压过滤器,,3,4,0, -58533,系列,AR/BR系列调压阀,,3,2,0, -58534,系列,AR系列调压阀,AR,2,28,0, -58535,系列,AW系列过滤带调压阀,AW,3,18,0, -58662,系列,RDSD HV系列旋转式直流隔离开关,RDS,14,44,0, -58665,系列,RDS1系列UL98交流隔离开关(UL认证),RDS,16,30,0, -58672,系列,Ex9IR50N系列UL旋转式隔离开关,Ex9IR,4,1,0, -58752,系列,TNSC系列接触稳压器,TNSC,1,0,0, -58808,系列,ExMRM-AIRI01-12系列环保气体环网柜,ExMRM-AIRI01,9,0,0, -58810,系列,Ex9IL系列信号灯,Ex9IL,3,2,0, -58811,系列,Ex9PB系列按钮,Ex9PB,14,184,0, -58813,系列,B1HC系列UL489小型断路器(UL认证),B1HC,15,32,0, -58827,系列,NXB-63M系列单磁式断路器,NXB,14,43,0, -58845,系列,Ex9ASD-DC系列直流隔离开关,Ex9ASD,71,50,0, -58854,系列,Ex9ASD系列交流隔离开关,Ex9ASD,63,76,0, -59128,系列,M1C系列塑壳断路器,M,37,25,0, -59133,系列,M2C系列塑壳断路器,M,37,25,0, -59149,系列,PMA901系列智能电力参数测量仪,PMA901,5,4,0, -59150,系列,Ex9TJ系列低压智能接插件,Ex9TJ,4,3,0, -59152,系列,Ex9TJV系列智能接插件,Ex9TJV,4,2,0, -59155,系列,Ex9TF11L系列智能配电终端,,1,0,0, -59158,系列,WTS-1系列无线温度传感器,,2,0,0, -59162,系列,NXZMN系列自动转换开关电器(CB级),NXZMN,8,27,0, -59163,系列,NXZHMN系列自动转换开关电器(PC级),NXZHMN,6,12,2,"NXZHMN-63/3A 10 = 2064 元 -NXZHMN-63/3DTK 63 = 2652 元" -59241,系列,A系列框架断路器(UL认证),A,65,242,0, -59244,系列,A系列框架隔离开关(UL认证),ASD,65,223,0, -59255,系列,Ex9L电磁式剩余动作电流断路器,Ex9L,6,6,0, -59256,系列,Ex9IR-250隔离开关,Ex9IR,5,4,0, -59287,系列,Ex9MY系列塑料外壳式断路器,Ex9MY,28,139,0, -59288,系列,Ex9MLY系列剩余电流动作断路器,Ex9MLY,31,99,0, -59292,系列,Ex9CH系列家用接触器,Ex9CH,4,4,0, -59298,系列,Ex9BP80直流小型断路器,Ex9BP,18,32,0, -59299,系列,Ex9IR40系列旋转隔离开关,Ex9IR40,3,2,0, -59300,系列,Ex9IR40G系列旋转隔离开关,Ex9IR40G,3,4,0, -59301,系列,Ex9IRS50系列旋转隔离开关,Ex9IRS50,5,0,0, -59391,系列,NB5-63NFB系列小型断路器,NB5,17,34,0, -59393,系列,NKY2K系列开关电源,NKY2K,2,4,0, -59394,系列,NB5LE-63HFB系列剩余电流动作断路器,NB5LE,19,35,0, -59452,系列,Ex9C系列交流接触器(船岸专用),Ex9C,18,207,0, -59453,系列,Ex9R系列热过载继电器(船岸专用),Ex9R,4,15,0, -59455,系列,Ex9B125小型断路器(船岸专用),Ex9B,14,33,0, -59456,系列,Ex9BD125小型断路器(船岸专用),Ex9BD125,14,42,0, -59457,系列,Ex9BP直流小型断路器(船岸专用),Ex9BP,15,34,0, -59459,系列,Ex9BG/Ex9BHG交流小型断路器(船岸专用),Ex9B,16,34,0, -59462,系列,Ex9A系列空气断路器(船岸专用),Ex9A,69,89,0, -59464,系列,Ex9M系列塑料外壳式断路器(船岸专用),Ex9M,72,807,0, -59466,系列,Ex9MD系列直流塑料外壳式断路器(船岸专用),Ex9MD,6,12,0, -59468,系列,NM5NE高电压(HV)系列塑壳断路器,NM5NE,29,71,0, -59469,系列,Ex9MHV高电压系列塑料外壳式断路器(船岸专用),Ex9M,18,34,0, -59621,系列,NJBK8系列电动机保护器,NJBK8,3,4,0, -59622,系列,NJXB1系列低压线路保护器,NJXB1,3,4,0, -59624,系列,NXB-63G系列塑料外壳式断路器,NXB,13,32,0, -59645,系列,DTSYU666系列三相导轨安装式电能表(昆仑),DTSYU666,5,6,0, -59705,系列,OUVR-2G系列自恢复式过欠压保护器,OUVR,5,11,0, -59849,系列,FQK浮球液位开关,FQK,3,0,0, -59905,系列,NCZ2NE系列直流接触器,NCZ2NE,5,9,0, -59906,系列,EPEC300系列电力环境控制器,EPEC300,2,4,0, -59907,系列,EPEC400系列电力环境控制器,EPEC400,1,0,0, -59988,系列,L1H系列UL1053剩余电流动作断路器(UL认证),L1,4,2,0, -60020,系列,NM5NEDC高电压(HV)系列直流塑壳断路器,NM5NEDC,29,47,0, -60021,系列,NH5NE(DC)-HV系列新能源专供隔离开关,NH5NE,13,20,0, -60022,系列,NHB5NE-40GX系列旋转隔离开关,NHB5NE,6,12,0, -60023,系列,NHB5NE-50X系列旋转式隔离开关,NHB5NE,7,3,0, -60024,系列,NHB5NE-S50X系列旋转式隔离开关,NHB5NE-S,8,3,0, -60025,系列,NB5NEDC-80HU系列塑料外壳式断路器,NB5NEDC,14,48,0, -60026,系列,NB5NEDC-125HU系列塑料外壳式断路器,NB5NEDC,14,26,0, -60027,系列,NC1NE系列交流接触器,NC1NE,20,59,0, -60028,系列,NR2NE系列热过载继电器,NR2NE,3,9,0, -60042,系列,BH-0.66系列低压电流互感器(0.5S级实心),BH,4,0,0, -60059,系列,ExATSNV系列自动转换开关电器(PC级),ExATSNV,4,5,0, -60060,系列,NJBK5系列电动机保护器,NJBK5,2,4,0, -60061,系列,NJR5-D系列软起动器,NJR5,3,0,0, -60062,系列,NXLH-1系列III型立式电流互感器,NXLH,5,38,0, -60063,系列,NJXB5系列低压线路保护器,NJXB5,2,4,0, -60064,系列,Ex9JX系列电磁继电器,Ex9JX,4,6,0, -60066,系列,NRZNE系列直流熔断器,NRZNE,6,2,0, -60068,系列,NXQ系列电磁起动器,NXQ,5,9,0, -60069,系列,NAFD2000型故障电弧探测器,NAFD2000,1,0,0, -60070,系列,WHR/G100系列智能温湿度控制器,WH,5,16,0, -60071,系列,NTD500/NTD300型测温主机,NTD,2,2,0, -60072,系列,NS1000系列无线测温传感器,NS1000,3,3,0, -60157,系列,NKY2G系列开关电源,NKY2G,2,4,0, -60216,系列,NXC-CS系列交流接触器,NXC,24,130,0, -60226,系列,NXBLE-63GYH系列剩余电流动作断路器,NXBLE,15,44,0, -60227,系列,NXBLE-63YHE系列剩余电流动作断路器,NXBLE,16,41,0, -60228,系列,NXTCW系列防水连接器,NXTCW,4,5,0, -60229,系列,NP2(XM)系列高防护型按钮,NP2,6,8,0, -60330,系列,NA1P系列万能式断路器,NA1P,7,25,0, -60398,系列,NXJYB系列电压保护继电器,NXJYB,1,9,0, -60399,系列,NXTCP系列电源连接器,NXTCP,4,0,0, -60400,系列,PD666高可靠系列数显多功能表,P,8,0,0, -60402,系列,WH系列温湿度控制器,WH,6,8,0, -60451,系列,NXC-XMG系列交流接触器,NXC,5,0,0, -60463,系列,NWC8系列自愈式低电压并联电容器(干式),NWC8,3,12,0, diff --git a/yjktool/系列数据表_含价格.csv b/yjktool/系列数据表_含价格.csv deleted file mode 100644 index 2062ecc..0000000 --- a/yjktool/系列数据表_含价格.csv +++ /dev/null @@ -1,1545 +0,0 @@ -编号,类型,名称,型号代码,规格组数,级联映射条数,真实价格条数,价格明细(型号=价格元) -1,树,(正泰厂家树·1859条),,,, -2,系列,NH1系列隔离开关,NH1,7,186,0, -4,系列,NA8系列智能型万能式断路器(按项目报价),NA8,53,242,0, -5,系列,NA1-2000X~6300X系列万能式断路器(带欠压),NA1,48,383,0, -6,系列,NA1-1000X系列万能式断路器,NA1,44,299,0, -7,系列,DW17系列万能式断路器,DW17,13,294,0, -8,系列,DW16系列万能式断路器(已停产,被DW15替代),DW16,5,30,0, -9,系列,DW15系列万能式断路器,DW15,19,314,0, -10,系列,DZ15LE系列漏电断路器,DZ15LE,12,29,0, -11,系列,NL18系列剩余电流动作断路器(已停产,建议选用NXBLE),NL18,3,4,0, -12,系列,NM8L、NM8SL系列塑壳漏电断路器(已停产,建议选用NM8NL),NM8,10,39,0, -13,系列,DZ267-32系列小型断路器(已停产,建议选用NXB-40),DZ267,4,0,0, -14,系列,DZ47-60系列型小型断路器(已停产,被NXB-63替代),DZ47,4,34,0, -15,系列,NBH8-40系列家用小型断路器,NBH8,11,12,0, -16,系列,NB1-63H系列高分断小型断路器(双汇流排),NB1,9,2,0, -17,系列,DZ267LE-32系列剩余电流动作断路器(已停产,建议选用NXBLE-40),DZ267LE,6,0,0, -19,系列,DZ47LE-63系列剩余电流动作断路器(已停产,被NXBLE-63替代),DZ47LE,5,23,0, -20,系列,NL1E-63系列剩余电流动作断路器,NL1E,4,2,0, -21,系列,NL1-63系列剩余电流动作断路器,NL1,6,2,0, -22,系列,NBH8LE-40系列剩余电流动作断路器,NBH8LE,5,2,0, -23,系列,NB47LE-63系列剩余电流动作断路器(已停产,建议选用NXBLE-63),NB47LE,4,18,0, -24,系列,NB1LE-63系列电子式剩余电流动作断路器,NB1LE,7,17,0, -25,系列,NB1LE-40系列电子式剩余电流动作断路器,NB1LE,7,11,0, -26,系列,NB1L-63系列电磁式剩余电流动作断路器,NB1L,5,6,0, -27,系列,NB1L-40系列电磁式剩余电流动作断路器,NB1L,8,339,0, -28,系列,NH3-63系列隔离开关,NH3,2,3,0, -29,系列,NH9-32系列隔离开关,NH9,3,4,0, -30,系列,NH4-125系列隔离开关,NH4,3,4,0, -31,系列,NH2-125系列隔离开关,NH2,3,4,0, -32,系列,DZ158S-100IC系列卡表专用断路器(已停产,建议选用NBP-100S),DZ158S,2,0,0, -33,系列,NB7S-100系列带分励脱扣断路器(已停产,建议选用NBP-100S),NB7S,3,0,0, -34,系列,NB7S-63系列带分励脱扣断路器(已停产,建议选用NBP-63S),NB7S,4,0,0, -36,系列,NU6-Ⅲ系列电涌保护器,NU6-Ⅲ,4,2,0, -37,系列,NU6-Ⅱ系列电涌保护器(已停产,建议选用NU6-ⅡG),NU6-Ⅱ,4,3,0, -38,系列,NX8系列配电箱(已停产),NX8,8,12,0, -39,系列,NX2系列配电箱(已停产,建议选用NX30),NX2,1,0,0, -40,系列,JR36系列热过载继电器,JR36,2,24,1,JR36-20 0.25-0.35A = 44.439998626709 元 -41,系列,JRS1系列热过载继电器(已停产,被NR2替代),JRS1,5,12,0, -42,系列,NR4系列热过载继电器(已停产,被NR4-G代替),NR4,3,28,0, -44,系列,NR2系列热过载继电器,NR2,4,39,0, -45,系列,CZ0系列直流接触器(已停产,建议选用NCZ2),CZ0,4,65,0, -46,系列,NJX-13FW系列无氧化零飞弧电磁继电器,NJX-13FW,5,101,0, -47,系列,NJB1-S系列时间继电器(已停产,建议选用NTE8),NJB1,2,0,0, -48,系列,NJB1-Y系列单相电压继电器,NJB1,2,9,0, -49,系列,NJB1-X/X1系列继电器,NJB1,2,2,0, -50,系列,NJB1-YW系列液位继电器,NJB1-YW,1,0,0, -51,系列,NJS1系列时间继电器(已停产,建议选用JSS48A),NJS1,4,31,0, -53,系列,DJ1系列电流时间转换装置(已停产),DJ1,4,9,0, -54,系列,KG316T系列时控开关,KG316T,4,6,0, -55,系列,KG10M系列时控开关,KG10M,2,2,0, -56,系列,KG10D系列时控开关,KG10D,2,0,0, -57,系列,NKG1系列时控开关,NKG1,1,0,0, -59,系列,JYB-714系列液位继电器,JYB-714,2,0,0, -60,系列,NJYW1系列液位继电器,NJYW1,3,6,0, -61,系列,JZF系列正反转控制继电器,JZF,2,16,0, -63,系列,XJ3系列断相与相序保护继电器,XJ3,3,9,0, -64,系列,JZC4系列接触器式继电器,JZC4,10,5,0, -65,系列,JZC1系列接触器式继电器,JZC1,3,30,0, -66,系列,JZ7系列中间继电器,JZ7,2,5,0, -68,系列,NRE8系列电子式过载继电器(按项目报价),NRE8,3,49,0, -70,系列,NB1-63系列小型断路器,NB1,14,27,0, -71,系列,CJX2系列交流接触器,CJX2,37,530,1,CJX2-0910 24V = 117.62999725342 元 -72,系列,CJX2系列机械联锁交流接触器,CJX2,19,14,0, -73,系列,CJ19系列电容交流接触器,CJ19,3,16,0, -74,系列,"CJT1系列交流接触器(已停产,被NXC代替)",CJT1,29,125,0, -75,系列,CJ20系列交流接触器,CJ20,34,354,0, -76,系列,NC3(CJ46)系列交流接触器(已停产,建议选用NXC),NC3(CJ46),21,109,0, -77,系列,CJ12系列交流接触器(已停产,建议选用NC2、NC7、NC8),CJ12,3,13,0, -79,系列,CJ40系列交流接触器,CJ40,19,124,0, -80,系列,NC2系列交流接触器,NC2,32,240,0, -81,系列,NC5系列交流接触器,NC5,19,181,0, -82,系列,NC6系列交流接触器(已停产,建议选用NXC-M),NC6,8,17,0, -83,系列,NC9系列真空交流接触器(已停产,建议选用CJX1-K),NC9,8,40,0, -84,系列,NCK3系列空调用交流接触器,NCK3,5,11,0, -85,系列,NCH8系列家用交流接触器,NCH8,3,12,0, -86,系列,CKJ5系列真空交流接触器(已停产),CKJ5,6,15,0, -87,系列,CJX1系列交流接触器,CJX1,18,170,0, -88,系列,CJX1-N系列交流接触器,CJX1,4,51,0, -89,系列,NCX1系列交流接触器(已停产,建议选用NCX1防尘型),NCX1,6,4,0, -90,系列,NC7系列交流接触器(已停产,建议选用NXC),NC7,24,220,0, -92,系列,DZ15系列塑壳断路器,DZ15,6,22,0, -93,系列,"NM10系列塑壳断路器(已停产,被NXM替换)",NM10,26,85,0, -95,系列,NJS2系列时间继电器(已停产,建议选用NJS1-M),NJS2,1,0,0, -97,系列,NTE8系列时间继电器,NTE8,3,14,0, -98,系列,JSS48A系列时间继电器(部分产品已停销),JSS48A,8,208,0, -99,系列,JSS48B系列时间继电器(已停产,建议选用JSS48A),JSS48B,1,0,0, -100,系列,JSZ3系列时间继电器,JSZ3,7,48,0, -104,系列,JS14A系列时间继电器,JS14A,5,25,0, -105,系列,JS14P系列时间继电器,JS14P,3,48,0, -106,系列,JS14S系列时间继电器(部分产品已停销),JS14S,3,37,0, -107,系列,LMZ1-0.66系列低压电流互感器(0.2级)(已停产,建议选用BH-0.66),LMZ1,2,22,0, -108,系列,JSS1系列时间继电器(已停产,建议选用JSS48A),JSS1,4,20,0, -109,系列,NDK系列控制变压器,NDK,3,258,0, -110,系列,NDKS系列控制变压器,NDKS,3,22,0, -111,系列,NDKG系列控制变压器,NDKG,3,35,0, -112,系列,NDKR系列控制变压器,NDKR,3,22,0, -113,系列,BKC系列控制变压器(已停产,建议选用NDK),BKC,2,10,0, -114,系列,JS11S系列时间继电器(部分产品已停销),JS11S,3,30,0, -115,系列,JBK1系列机床控制变压器(已停产,建议选用JBK4),JBK1,1,0,0, -116,系列,JBK3系列机床控制变压器,JBK3,3,98,0, -117,系列,JBK5系列机床控制变压器,JBK5,3,91,0, -118,系列,JBK6系列机床控制变压器,JBK6,3,11,0, -119,系列,JMB系列照明变压器,JMB,4,138,0, -120,系列,SG系列三相开启式干式变压器,SG,1,0,0, -121,系列,BKZ系列整流变压器,BKZ,3,6,0, -122,系列,LMZJ1-0.5系列低压电流互感器(0.2级),LMZJ1,5,68,0, -123,系列,JS11系列时间继电器(已停产,建议选用JS11S),JS11,3,22,0, -124,系列,LMZ1-0.66系列低压电流互感器(0.5级)(已停产,建议选用BH-0.66),LMZ1,3,42,0, -125,系列,JZX-22F系列小型中功率电磁继电器,JZX-22F,7,117,0, -126,系列,LMZ1-0.66系列低压电流互感器(0.5S级)(已停产,建议选用BH-0.66),LMZ1,2,19,0, -127,系列,JQX-10F系列通用型小型大功率电磁继电器,JQX-10F,4,8,0, -128,系列,LMZJ1-0.5系列低压电流互感器(0.5级),LMZJ1,5,167,0, -129,系列,JTX系列通用型小型大功率电磁继电器,JTX,4,6,0, -130,系列,JQX-13F系列小型电磁继电器,JQX-13F,5,36,0, -131,系列,QZB-J系列起动用自耦减压变压器,QZB-J,1,22,0, -132,系列,JMK系列通用型小型大功率电磁继电器,JMK,4,6,0, -133,系列,LMZJ1-0.5系列低压电流互感器(0.5S级),LMZJ1,5,75,0, -134,系列,BP8R1系列频敏变阻器(已停产,建议选用BP8Y),BP8R1,3,17,0, -136,系列,LMZJ1-0.66系列低压电流互感器(0.2级),LMZJ1,4,59,0, -137,系列,BP8R2系列频敏变阻器(已停产,建议选用BP8Y),BP8R2,3,4,0, -138,系列,BP8R3系列频敏变阻器(已停产,建议选用BP8Y),BP8R3,3,13,0, -142,系列,LMZJ1-0.66系列低压电流互感器(0.5级),LMZJ1,4,78,0, -144,系列,LMZJ1-0.66系列低压电流互感器(0.5S级),LMZJ1,4,59,0, -145,系列,BP8Y系列频敏变阻器,BP8Y,3,16,0, -146,系列,LQG-0.66系列低压电流互感器(0.2级),LQG,3,22,0, -148,系列,NJJ3系列计数继电器,NJJ3,1,0,0, -149,系列,NJJ5-J系列电子式计数器,NJJ5,4,0,0, -150,系列,JDM1-14系列计数继电器(已退市,建议选用JDM1-48),JDM1-14,3,0,0, -151,系列,JJ1系列自耦减压起动控制柜,JJ1,1,18,0, -152,系列,JDM1-48系列计数继电器,JDM1-48,4,0,0, -153,系列,JDM1-9系列计数继电器,JDM1-9,2,0,0, -154,系列,JDM15G系列计数继电器(已退市,建议选用NJJ3),JDM15G,1,0,0, -155,系列,JDM1-6系列计数继电器(已停产,建议选用NJJ5-J),JDM1-6,2,0,0, -156,系列,LQG-0.66系列低压电流互感器(0.5级),LQG,3,22,0, -157,系列,TDR系列电源变压器(已停产,建议选用NDK),TDR,1,12,0, -158,系列,JDM3系列超小型电子式计数器,JDM3,3,3,0, -159,系列,LQG-0.66系列低压电流互感器(0.5S级),LQG,3,22,0, -160,系列,HB系列环型电源变压器(已停产,建议选用NDK),HB,1,9,0, -161,系列,NJJ5-L系列电子式累时器,NJJ5,4,0,0, -163,系列,SC3L系列超小型电子式累时器,SC3L,3,6,0, -164,系列,TDGC2系列单相接触调压器,TDGC2,3,24,0, -165,系列,JD-5系列电动机综合保护器,JD-5,5,27,0, -166,系列,TSGC2系列三相接触调压器,TSGC2,2,11,0, -168,系列,NKY1系列开关电源,NKY1,3,34,0, -169,系列,JD-8系列电动机综合保护器,JD-8,1,5,0, -170,系列,JD-9系列电动机综合保护器(已停产,被JD-8代替),JD-9,1,0,0, -171,系列,NJBK2系列电动机保护继电器,NJBK2,6,16,0, -172,系列,NJBK5系列电动机控制器(已停产),NJBK5,4,0,0, -173,系列,NJBK6系列电动机保护继电器,NJBK6,3,0,0, -174,系列,LMZ3-0.66系列低压电流互感器(0.5级实芯)(已停产),LMZ3,4,0,0, -175,系列,LMZ3-0.66系列低压电流互感器(0.5级)(已停产,替换产品为LMZJ1),LMZ3,5,75,0, -176,系列,LMZW1-0.5系列户外低压电流互感器(0.5级),LMZW1,5,50,0, -177,系列,LMZW1-0.5系列户外低压电流互感器(0.5S级),LMZW1,4,18,0, -179,系列,NKG2系列时控开关(已停产,被NKG3-M代替),NKG2,1,0,0, -180,系列,NLH1-0.66系列电流互感器(0.2级)(已停产,被BH-I代替),NLH1,4,43,0, -181,系列,NLH1-0.66系列电流互感器(0.5级)(已停产,被BH-I代替),NLH1,4,46,0, -182,系列,NLH1-0.66系列电流互感器(0.5S级)(已停产,被BH-I代替),NLH1,4,43,0, -183,系列,JDG4-0.5系列电压互感器,JDG,3,0,0, -184,系列,JDZ-1系列电压互感器(即将停销,被JDZ6-1产品替代),JDZ,3,4,0, -185,系列,XD1系列限流电抗器,XD,3,10,0, -186,系列,TNSZ(SBW)系列三相大功率补偿型稳压器,TNSZ(SBW),1,18,0, -187,系列,RCT系列低压电流互感器(0.5级)(已停产,替换产品为BH-0.66),RCT,3,30,0, -188,系列,TNDZ(DBW)系列单相大功率补偿式稳压器,TNDZ(DBW),1,0,0, -190,系列,NPS系列交流精密稳压电源,NPS,2,2,0, -193,系列,TNS1(SVC)系列高精度全自动三相交流稳压电源,TNS1(SVC),2,10,0, -194,系列,TND1(SVC)系列高精度全自动单相交流稳压电源,TND1(SVC),4,32,0, -195,系列,TND3(TSD)系列挂壁式单相交流稳压电源,TND3(TSD),1,0,0, -196,系列,BH-0.66Ⅰ系列低压电流互感器(0.2级),BH,7,429,0, -199,系列,"LM-0.5系列低压电流互感器(即将停销,被NXLH-1产品替代)",LM,3,82,0, -200,系列,HD11系列开启式刀开关,HD,6,104,0, -201,系列,BH-0.66Ⅰ系列低压电流互感器(0.5级),BH,7,508,0, -202,系列,HD12系列开启式刀开关,HD,11,86,0, -203,系列,HD13系列开启式刀开关(HD其他各系列派生新型号),HD13,6,14,0, -204,系列,HD13/HD13BX系列开启式刀开关,HD,17,478,0, -205,系列,HD14系列开启式刀开关,HD,7,20,0, -206,系列,BH-0.66Ⅰ系列低压电流互感器(0.5S级),BH,7,433,0, -207,系列,HS11系列双投转换式刀开关,HS,9,143,0, -208,系列,HS13系列双投转换式刀开关(HS其他各系列派生新型号),HS13,5,13,0, -209,系列,HS13系列双投转换式刀开关,HS,14,287,0, -210,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.2级),BH,5,250,0, -211,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5级),BH,6,459,0, -212,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5S级),BH,5,198,0, -213,系列,BH-0.66Ⅲ系列低压电流互感器(0.2级),BH,5,113,0, -214,系列,BH-0.66Ⅲ系列低压电流互感器(0.5级),BH,5,138,0, -215,系列,BH-0.66Ⅲ系列低压电流互感器(0.5S级),BH,5,115,0, -216,系列,BH-0.66系列低压电流互感器(0.5级实心),BH,4,0,0, -217,系列,LMZW2-0.5系列电流互感器(0.5级),LMZW2,4,15,0, -218,系列,LQZJ1-0.66系列低压电流互感器(0.2级),LQZJ1,3,0,0, -219,系列,LQZJ1-0.66系列低压电流互感器(0.5级),LQZJ1,3,11,0, -220,系列,LQZJ1-0.66系列低压电流互感器(0.5S级),LQZJ1,3,0,0, -221,系列,HD13系列大电流开启式刀开关,HD13,6,32,0, -223,系列,BZMJ系列自愈式低压并联电容器,BZMJ,3,444,0, -224,系列,HF40系列防护式刀形隔离器,HF40,5,65,0, -225,系列,HR3系列熔断器式隔离开关,HR3,20,69,0, -226,系列,HR5系列熔断器式隔离开关,HR5,4,5,0, -227,系列,HR6系列熔断器式隔离开关,HR6,5,38,0, -228,系列,NHR17系列熔断器式隔离开关,NHR17,4,27,0, -230,系列,HH15(QSA)系列隔离开关熔断器组,HH15,4,8,0, -231,系列,HH15(QP)系列隔离开关,HH15,4,0,0, -232,系列,HH15(QA)系列隔离开关,HH15,4,2,0, -233,系列,HH15(QSS)系列隔离开关,HH15(QSS),2,12,0, -234,系列,GW9系列户外高压隔离开关,GW9,3,3,0, -235,系列,NH40SZ系列自动转换开关(PC级),NH40,11,1776,0, -236,系列,NHR40系列隔离开关熔断器组,NHR40,11,156,0, -237,系列,NH40系列隔离开关,NH40,11,230,0, -238,系列,NH40-F系列防护罩式隔离开关,NH40,6,2,0, -239,系列,NH50系列隔离开关长胶板,NH,6,0,0, -240,系列,HK18系列隔离开关,HK18,3,14,0, -245,系列,NWC1系列自愈式低压并联电容器,NWC1,4,217,0, -248,系列,NWC5系列自愈式低压并联电容器,NWC5,4,69,0, -249,系列,NWKL1系列智能型无功补偿控制器(无功电流型),NWKL1,2,0,0, -254,系列,JKF8系列智能型低压无功补偿控制器(复合控制型),JKF8,1,0,0, -257,系列,NWK1-G系列智能型低压无功补偿控制器,NWK1-G,1,0,0, -259,系列,LAY3系列按钮(已停产,建议选用NP2),LAY3,6,60,0, -260,系列,TBBX系列低压无功就地补偿装置(已停产,建议选用NWC6、BAGB450),TBBX,5,84,0, -265,系列,LA2系列按钮(已停产,建议选用NP2),LA,2,2,0, -266,系列,YBLX-K1系列行程开关,YBLX-K1,3,5,0, -269,系列,RT29系列圆筒形帽熔断器体,RT29,3,4,0, -270,系列,RT28系列熔断器体,RT28,4,26,0, -271,系列,RT36系列有填料封闭管式刀型触头熔断器体,RT36,2,16,0, -273,系列,YBLX-3系列行程开关,YBLX-3,2,0,0, -277,系列,HDLRT0系列有填料封闭管式熔断器体,HDLRT0,2,10,0, -278,系列,BZMJ-YN系列自愈式低压并联电容器,BZMJ,4,35,0, -279,系列,RS71(NGT)系列快速熔断器体,RS71,4,30,0, -280,系列,RT14系列熔断器底座,底座RT14,1,0,0, -281,系列,NH50系列隔离开关,NH,6,114,0, -283,系列,HDLRS3系列半导体设备保护用熔断体,HDLRS3,2,10,0, -284,系列,YBLX-12系列行程开关,YBLX-12,2,0,0, -285,系列,YBLX-19系列行程开关,YBLX-19,5,18,0, -286,系列,YBLX-22系列行程开关,YBLX-22,1,0,0, -287,系列,YBLX-33系列行程开关,YBLX-33,2,0,0, -288,系列,NRT36系列熔断体,NRT36,2,2,0, -290,系列,YBLXW-6系列微动开关,YBLXW,3,0,0, -291,系列,YBLXW-5系列微动开关,YBLXW,4,0,0, -292,系列,YBLX-JW2系列行程开关,YBLX-JW2,5,11,0, -293,系列,YBLX-K3系列行程开关,YBLX-K3,3,0,0, -294,系列,YBLX-P1系列行程开关,YBLX-P1,2,5,0, -295,系列,RT28(R)系列熔断器底座,底座RT28,4,0,0, -296,系列,RT28系列熔断体底座,底座RT28,3,0,0, -297,系列,RT29系列熔断体底座,底座RT29,1,0,0, -298,系列,YBLX-WL系列行程开关,YBLX-WL,1,0,0, -299,系列,NRT28系列熔断体底座,底座NRT28,3,6,0, -300,系列,YBLX-HL系列行程开关,YBLX-HL,1,6,0, -301,系列,NRT36系列熔断器底座,底座NRT36,2,0,0, -302,系列,HY23系列倒顺开关,HY23,4,8,0, -303,系列,HDLRT0系列有填料封闭管式熔断器底座,底座HDLRT0,1,5,0, -304,系列,HZ5系列组合开关,HZ5,4,5,0, -306,系列,HZ10系列组合开关,HZ10,7,129,0, -311,系列,HZ12系列组合开关,HZ12,2,2,0, -313,系列,LW5D系列万能转换开关,LW5D,4,29,0, -314,系列,LW6系列万能转换开关(已停产,被LW112替代),LW6,3,29,0, -316,系列,LW112系列万能转换开关,LW112,9,736,0, -321,系列,LW32系列万能转换开关,LW32,5,131,0, -330,系列,TB系列接线端子,TB,2,5,0, -338,系列,JCUK系列接线端子,JCUK,10,66,0, -340,系列,JCUK系列熔断器端子,JCUK,2,0,0, -344,系列,LA18系列按钮(已停产,建议选用NP2/NP4),LA18,3,8,0, -345,系列,LA19系列按钮(已停产,建议选用NP2),LA19,5,25,0, -351,系列,NP2系列塑料信号灯,NP2,16,16,0, -352,系列,HGW9系列户外高压隔离开关,HGW9,1,0,0, -358,系列,YBLT系列脚踏开关,YBLT,1,0,0, -359,系列,YBLT-EKW系列脚踏开关,YBLT-EKW,3,0,0, -360,系列,YBLT-YDT1系列脚踏开关,YBLT-YDT1,2,0,0, -361,系列,YBLT-JDK系列脚踏开关,YBLT-JDK,1,0,0, -378,系列,QJX2系列“星三角”减压起动器,QJX2,2,10,0, -379,系列,NQ2系列电磁起动器,NQ,6,64,0, -380,系列,QC36系列电磁起动器,QC36,4,18,0, -381,系列,NVF2G系列变频器,NVF2G,12,288,0, -382,系列,NZ7系列自动转换开关(CB级)(已停产,被NXZM替代),NZ7,8,48,0, -383,系列,NJR2-G系列软起动器控制柜,NJR,2,0,0, -387,系列,NA8G系列智能型万能式断路器(已停产,被NA8代替),NA8G,24,973,0, -388,系列,LAY3系列蘑菇头式按钮(已停产,建议选用NP2),LAY3,4,11,0, -389,系列,LAY3系列自锁式按钮(已停产,建议选用NP2),LAY3,4,12,0, -390,系列,LAY3系列旋柄开关(已停产,建议选用NP2),LAY3,4,31,0, -391,系列,LAY3系列钥匙式开关(已停产,建议选用NP2),LAY3,3,5,0, -392,系列,LA4系列按钮(已停产,建议选用NP2),LA,2,0,0, -393,系列,NP2系列平头式按钮,NP2,18,107,0, -394,系列,NP2系列蘑菇头式金属按钮,NP2,17,15,0, -395,系列,NP2系列旋钮(金属),NP2,17,34,0, -396,系列,NP2系列钥匙式按钮,NP2,16,12,0, -397,系列,NP2系列金属信号灯,NP2,16,9,0, -398,系列,NP2系列金属带灯平钮,NP2,19,25,0, -399,系列,NP2系列蘑菇头式塑料按钮,NP2,18,51,0, -400,系列,NP2系列旋钮(塑料),NP2,16,12,0, -402,系列,NP2系列塑料带灯平钮,NP2,19,23,0, -403,系列,NP2系列塑料双头带灯按钮,NP2,19,0,0, -404,系列,ND16系列信号灯,ND16,5,37,0, -405,系列,NP3系列控制按钮,NP3,2,4,0, -406,系列,NP4系列高、平钮,NP4,3,20,0, -407,系列,NP4系列蘑菇头式按钮,NP4,4,12,0, -408,系列,NP4系列旋钮,NP4,4,7,0, -409,系列,NP4系列带灯按钮,NP4,5,29,0, -410,系列,NP6系列平钮,NP6,4,0,0, -411,系列,NP6系列蘑菇头式按钮,NP6,3,0,0, -412,系列,NP6系列旋钮式按钮,NP6,4,2,0, -413,系列,NP6系列指示灯,NP6,5,6,0, -414,系列,NP8系列平钮,NP8,3,0,0, -415,系列,NP8系列蘑菇头式按钮,NP8,4,12,0, -416,系列,NP8系列双头钮,NP8,4,6,0, -417,系列,NP6系列钥匙钮,NP6,4,2,0, -418,系列,NP8系列旋钮,NP8,5,11,0, -419,系列,NP8系列钥匙钮,NP8,3,5,0, -420,系列,NP8系列指示灯,NP8,3,0,0, -421,系列,NP9系列按钮,NP9,5,22,0, -422,系列,ND9系列信号灯,ND9,5,40,0, -424,系列,HD11系列开启式长板刀开关,HD,5,0,0, -425,系列,HD11系列开启式保护型刀开关,HD,7,48,0, -426,系列,NHRT40系列熔断器式隔离开关,NHRT40,5,27,0, -428,系列,JBK2系列机床控制变压器(已停产,建议选用JBK4),JBK2,1,0,0, -429,系列,JBK4系列机床控制变压器,JBK4,3,22,0, -431,系列,YBLX-X2系列行程开关,YBLX,2,0,0, -432,系列,YBLX-ME系列行程开关,YBLX-ME,1,0,0, -433,系列,HY2系列倒顺开关,HY2,3,0,0, -436,系列,HS11系列保护型刀开关,HS,6,17,0, -445,系列,ND16系列超短型信号灯,ND16,6,42,0, -446,系列,ND16系列用于电容柜型信号灯,ND16,6,4,0, -447,系列,ND16系列双色灯信号灯,ND16,5,6,0, -448,系列,ND16系列快速接线型信号灯,ND16,5,2,0, -452,系列,RT36(NT)系列有填料封闭管式刀型触头熔断器底座,底座RT36,1,12,0, -453,系列,RT36(R)系列有填料封闭管式刀型触头熔断器底座,底座RT36,2,6,0, -454,系列,RT36(R)系列有填料封闭管式刀型触头熔断器体,RT36,4,16,0, -455,系列,RT36(NT00)系列底座,底座RT36-00(NT00),2,0,0, -458,系列,SG系列三相防护式干式变压器,SG,2,0,0, -459,系列,XJZ1系列自耦减压起动控制箱,XJZ1,1,15,0, -460,系列,NJL1系列漏电保护继电器,NJL1,1,0,0, -461,系列,NJL2系列漏电保护继电器,NJL2,4,4,0, -462,系列,LAY39系列平钮,LAY39,5,8,0, -463,系列,LAY39系列蘑菇头按钮,LAY39,4,6,0, -464,系列,LAY39系列瞬动型带灯钮,LAY39,6,0,0, -465,系列,LAY39系列瞬动型带灯蘑菇头钮,LAY39,6,0,0, -466,系列,LAY39系列旋钮,LAY39,5,8,0, -467,系列,LAY39系列钥匙钮,LAY39,5,0,0, -468,系列,NP4系列蘑菇头带灯按钮,NP4,5,3,0, -469,系列,NP4系列旋柄钮,NP4,4,18,0, -470,系列,NP4系列带灯旋钮,NP4,6,4,0, -471,系列,NP4系列钥匙钮,NP4,3,5,0, -472,系列,NP6系列带灯平钮,NP6,6,6,0, -473,系列,NP8系列高钮,NP8,3,0,0, -474,系列,NP8系列带灯平钮,NP8,4,0,0, -475,系列,NP8系列带灯高钮,NP8,4,0,0, -476,系列,NP8系列带灯蘑菇钮,NP8,5,0,0, -477,系列,NP2系列金属双头带灯按钮,NP2,19,0,0, -480,系列,YBLX-8系列行程开关,YBLX-8,1,0,0, -481,系列,YBLX-44系列行程开关,YBLX-44,1,3,0, -483,系列,YBLX-10系列行程开关,YBLX-10,3,7,0, -486,系列,DZ47LG系列带过压剩余动作电流断路器(已停产,建议选用NXBLG),DZ47LG,6,22,0, -488,系列,RT14(R)系列熔断器底座,底座RT14,2,0,0, -489,系列,RT28(N)系列熔断器底座,底座RT28N,3,0,0, -490,系列,NC8系列交流接触器(按项目报价),NC8,27,490,0, -492,系列,NC8系列可逆交流接触器(按项目报价),NC8,27,219,0, -493,系列,NC8系列小型交流接触器(按项目报价),NC8,13,24,0, -494,系列,NC8系列小型直流接触器(按项目报价),NC8,13,30,0, -495,系列,NC8系列小型交流可逆接触器(按项目报价),NC8,14,24,0, -496,系列,NC8系列小型直流可逆接触器(按项目报价),NC8,14,18,0, -497,系列,NC1系列交流接触器,NC1,25,83,0, -498,系列,NC1系列可逆交流接触器,NC1,25,60,0, -499,系列,NC1系列直流接触器,NC1,25,51,0, -500,系列,DZ20Y系列塑壳断路器,DZ20,13,494,0, -501,系列,DZ20J系列塑壳断路器(已停产,被DZ20Y改进型代替),DZ20,12,175,0, -502,系列,NM1LE系列漏电断路器(漏电报警不跳闸),NM1LE,15,115,0, -503,系列,NA1-2000X~6300X系列万能式断路器(不带欠压),NA1,43,156,0, -504,系列,NM1系列二极塑料外壳式断路器,NM1,11,40,0, -505,系列,NM1系列四极塑料外壳式断路器,NM1,31,389,0, -506,系列,NM1系列三极塑料外壳式断路器,NM1,50,852,0, -507,系列,DZ20L-4P系列塑壳漏电断路器,DZ20L,12,140,0, -508,系列,DZ20L-3N系列塑壳漏电断路器,DZ20L,13,87,0, -514,系列,ND16系列蜂鸣器式信号灯,ND16,4,28,0, -515,系列,NM8-630系列三极塑壳断路器(已停产,建议选用NM8N),NM8,10,52,0, -517,系列,NM8-630系列四极塑壳断路器(已停产,建议选用NM8N),NM8,10,134,0, -518,系列,NM8S系列智能型塑壳断路器(已停产,建议选用NM8N),NM8S,12,658,0, -519,系列,DZ108系列塑壳断路器,DZ108,4,25,0, -520,系列,NS2系列交流电动机起动器,NS2,20,86,0, -521,系列,"DZ158-100(R)系列小型断路器(已停产,被NXB-125G替代)",DZ158,7,2,0, -522,系列,"DZ158-125(R)系列小型断路器(已停产,被NXB-125替代)",DZ158,10,11,0, -523,系列,DZ158LE-100系列剩余电流动作断路器(已停产,建议选用DZ158LE-125),DZ158LE,4,2,0, -524,系列,"DZ47-60系列型小型断路器(透明外壳)(已停产,建议选用NXB-63T)",DZ47,5,34,0, -525,系列,DZ47-60(R)系列小型断路器(已停产),DZ47,4,23,0, -526,系列,NBH8-40H系列家用小型断路器,NBH8,11,12,0, -527,系列,DZ47LE-32系列剩余动作电流断路器(已停产,被NXBLE-32替代),DZ47LE,5,62,0, -528,系列,NB1Z-63系列交直流用小型断路器,NB1Z,8,4,0, -529,系列,NB7系列小型断路器,NB7,5,67,0, -530,系列,NB7LE-32系列微型漏电断路器,NB7LE,5,7,0, -531,系列,NB7LE-63系列微型漏电断路器,NB7LE,5,28,0, -532,系列,DZ20L系列透明型漏电断路器(部分型号已被NXMLE代替),DZ20L,14,186,0, -533,系列,LQG-0.66系列低压电流互感器(0.2S级),LQG,3,22,0, -534,系列,NJR2-D系列软起动器,NJR,6,23,0, -536,系列,NJBK7系列电动机保护继电器,NJBK7,6,6,0, -537,系列,NJBK10系列电动机保护继电器,NJBK10,3,3,0, -538,系列,NZ7B-63系列自动转换开关(CB级)(已停产,被NXZB替代),NZ7B,7,6,0, -539,系列,DZ20C系列塑壳断路器(已停产,被DZ20C改进型代替),DZ20,9,16,0, -540,系列,42L6系列模拟指示电流表(已停产),42,5,24,0, -541,系列,42L6系列模拟指示电压表,42,4,2,0, -542,系列,42L6系列模拟指示功率表(已停产),42,4,1,0, -543,系列,42L6系列模拟指示频率表,42,5,3,0, -544,系列,42L6系列模拟指示功率因数表(已停产),42,4,2,0, -545,系列,44L1系列模拟指示电流表,44,5,19,0, -546,系列,44L1系列模拟指示电压表,44,4,3,0, -551,系列,51T666系列模拟电测量仪表,51,4,4,0, -552,系列,59L1系列模拟指示电流表,59,4,1,0, -553,系列,59L1系列模拟指示电压表,59,3,1,0, -556,系列,62T51系列模拟指示电流表,62,4,2,0, -559,系列,65T666系列模拟指示电流表,65,4,2,0, -560,系列,65T666系列模拟指示电压表,65,4,1,0, -563,系列,69L9系列模拟指示电流表,69,5,10,0, -564,系列,69L9系列模拟指示电压表,69,5,11,0, -565,系列,69L9系列模拟指示频率表,69,6,6,0, -566,系列,6L2系列模拟指示电流表(已停产),6,4,2,0, -567,系列,6L2系列模拟指示电压表(已停产),6,4,2,0, -568,系列,6L2系列模拟指示功率表(已停产),6,4,0,0, -569,系列,6L2系列模拟指示频率表(已停产),6,3,0,0, -570,系列,6L2系列模拟指示功率因数表(已停产),6,3,3,0, -571,系列,85C1系列模拟指示电流表,85,4,0,0, -572,系列,85C1系列模拟指示电压表,85,4,0,0, -574,系列,85L1系列模拟指示电流表,85,4,2,0, -575,系列,85L1系列模拟指示电压表,85,4,0,0, -577,系列,99T666系列模拟指示电流表,99,4,3,0, -578,系列,99T666系列模拟指示电压表,99,4,2,0, -579,系列,PA666系列数显电流表(已停产),P,2,10,0, -580,系列,PZ666系列数显电压表(已停产),P,5,16,0, -581,系列,PD666系列数显多功能仪表(已停产),P,6,0,0, -592,系列,DD862系列单相电能表,DD862-4,4,7,0, -593,系列,DDS666系列单相电子式电能表(已停产),DDS666,3,20,0, -594,系列,DDS7777系列单相电子式电能表,DDS7777,3,5,0, -595,系列,DDSY666系列单相电子预付费电能表(已停产),DDSY666,3,4,0, -596,系列,DDM702系列单相亚长寿脉冲电能表,DDM702,2,12,0, -600,系列,DTSF666系列三相电子式多费率电能表(已停产),DTSF666,4,5,0, -601,系列,DSSD666系列三相电子式多功能电能表,DSSD666,5,6,0, -602,系列,DTSD666系列三相电子式多功能电能表,DTSD666,5,15,0, -603,系列,DSS633系列三相电子式有功电能表(已停产),DSS633,4,6,0, -604,系列,DTS634系列三相电子式有功电能表(已停产),DTS634,4,26,2,"DTS634 220/380V 1.5(6)A 1级 计度器 = 520.59997558594 元 -DTS634 220/380V 1.5(6)A 1级 LCD 红外/485 = 745.55999755859 元" -605,系列,DTSY666系列三相电子式预付费电能表(已停产),DTSY666,4,5,0, -608,系列,DS862系列三相三线有功电能表,DS862-4,4,8,0, -610,系列,DT666系列三相四线有功电能表(已停产),DT666,2,0,0, -611,系列,DT862系列三相四线有功电能表,DT862-4,2,10,0, -619,系列,XMT系列数字温度指示调节仪,XMT,9,81,0, -620,系列,TD、TE系列电子式温度指示调节仪,T,9,45,0, -621,系列,NM8-100系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,29,107,0, -622,系列,NM8-250系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,11,412,0, -623,系列,NM8-1250系列热磁型塑壳断路器(已停产,建议选用NM8N),NM8,10,62,0, -624,系列,RT36(CR)系列有填料封闭管式刀型触头熔断器体,RT36,4,14,0, -625,系列,NM7LE系列塑壳漏电断路器(已停产,建议选用NXMLE),NM7LE,9,16,0, -628,系列,RT36N系列熔断器底座,底座RT36N,2,5,0, -629,系列,NB1-63DC系列微型直流断路器,NB1,10,6,0, -632,系列,NM1系列塑料外壳式断路器(透明),NM1,13,61,0, -633,系列,NH20-2500系列万能式隔离开关(已停产,被NH1代替),NH20,5,28,0, -634,系列,PZ30系列配电箱,PZ30,6,52,0, -635,系列,PZ30系列配电箱(不锈钢)(已停产,建议选用PZ30),PZ30,2,10,0, -637,系列,PZ25系列配电箱(已停产,建议选用PZ30),PZ25,2,2,0, -638,系列,AC30系列插座,AC30,1,20,0, -641,系列,NH42系列隔离开关,NH42,2,0,0, -642,系列,NH42SZ系列自动转换开关(PC级),NH42,9,693,0, -643,系列,CRT36系列直流熔断器,CRT36,6,29,0, -647,系列,CJ20系列交流接触器(无磁系统),CJ20,2,16,0, -648,系列,"DZ158LE-125系列剩余电流动作断路器(已停产,被NXBLE-125替代)",DZ158LE,5,10,0, -650,系列,BZMJ2系列自愈式低压并联电容器,BZMJ,4,123,0, -651,系列,NJR2-ZX系列软起动器(已停产,被NJR5-ZX代替),NJR,3,0,0, -652,系列,NRZ36系列熔断体,NRZ36,3,6,0, -653,系列,NRZ28系列熔断体,NRZ28,2,0,0, -654,系列,NRZ28系列熔断器底座,底座NRZ28,3,0,0, -655,系列,RS71(NGT)系列快速熔断器体(直流),RS71,2,0,0, -656,系列,NC8系列直流接触器(按项目报价),NC8,19,97,0, -658,系列,NU210系列浪涌保护器,NU210,5,0,0, -661,系列,NQ3系列电磁起动器,NQ3,4,2,0, -662,系列,NQB1系列保护式起动器,NQB1,4,0,0, -677,系列,AZMJ系列低压交流滤波电容器,AZMJ,3,6,0, -678,系列,NWC6系列干式低电压并联电容器,NWC6,4,50,0, -679,系列,NB1L(2)系列剩余动作断路器,NB1L(2),5,0,0, -680,系列,LMZ□D系列电流互感器,LMZ,4,41,0, -682,系列,LFZ1D系列电流互感器(已停产,被LMZ1D代替),LFZ1D,3,9,0, -684,系列,NH43系列隔离开关,NH43,2,0,0, -685,系列,JDZ6-1系列电压互感器,JDZ6-1,2,0,0, -686,系列,NH41SZ系列自动转换开关(PC级),NH41,7,471,0, -687,系列,LQZJ4-0.66系列低压电流互感器(0.2S级),LQZJ4,3,0,0, -688,系列,LMZW2-0.5系列电流互感器(0.2级),LMZW2,4,15,0, -690,系列,LMZW2-0.5系列电流互感器(0.5S级),LMZW2,4,15,0, -691,系列,LMZW1-0.5系列户外低压电流互感器(0.2级),LMZW1,5,22,0, -692,系列,LMZS1系列电流互感器,LMZS1,3,10,0, -693,系列,HR20系列户外熔断器式隔离开关,HR20,2,0,0, -694,系列,HS12系列双投转换式刀开关,HS12,4,14,0, -695,系列,HS13D系列电动大电流刀开关,HS13D,2,0,0, -696,系列,NPH1系列按钮,NPH1,3,24,0, -698,系列,LAY39B系列平钮,LAY39,4,12,0, -699,系列,LAY39B系列带灯平钮,LAY39,5,10,0, -700,系列,LAY39B系列高钮,LAY39,4,5,0, -701,系列,LAY39B系列带灯高钮,LAY39,5,5,0, -702,系列,LAY39B系列蘑菇头钮,LAY39,5,16,0, -703,系列,LAY39B系列带灯蘑菇头钮,LAY39,6,10,0, -704,系列,LAY39B系列旋钮,LAY39,5,26,0, -705,系列,LAY39B系列带灯旋钮,LAY39,6,31,0, -706,系列,LAY39B系列钥匙钮,LAY39,4,3,0, -707,系列,LAY39B系列双头钮,LAY39,5,4,0, -709,系列,JDW2系列低压户外熔断器式隔离开关,JDW2,4,17,0, -710,系列,NH40-II/III系列隔离开关,NH40,3,7,0, -711,系列,NM1LE系列透明型漏电断路器(125S/250S已停产,建议选用NM1LE-G),NM1LE,11,10,0, -712,系列,NVF3系列变频器,NVF3,7,81,0, -713,系列,NVF3M系列变频器,NVF3M,5,2,0, -714,系列,NSK-BH系列低压非晶合金变压器,NSK,4,0,0, -715,系列,NSK-SG系列太阳能单晶硅炉配套专用变压器,NSK(SG),3,0,0, -716,系列,电磁继电器插座,,1,6,0, -717,系列,NJS5-M2系列时间继电器(已停产,建议选用NTE8),NJS5,2,0,0, -718,系列,JSZ6系列时间继电器,JSZ6,5,23,0, -719,系列,时间继电器插座,,1,14,0, -720,系列,挂钩,,1,0,0, -721,系列,NM1LE系列漏电断路器(漏电跳闸/可调),NM1LE,15,243,0, -722,系列,LW5D系列万能转换开关(特殊),LW5D,6,392,0, -723,系列,NH7系列隔离开关(已停产,建议选用NXHB),NH7,2,0,0, -725,系列,NXM系列塑壳断路器,NXM,61,4399,36,"NXM-400S/3300 400A = 1453 元 -NXM-630S/3300 400A = 2234 元 -NXM-63S/3300 63A = 322 元 -NXM-125S/3300 10A = 406 元 -NXM-400S/3300 250A = 1453 元 -NXM-250S/3300 200A = 659 元 -NXM-W800S/3300 630A(R) = 3200 元 -NXM-63S/2300 10A = 266 元 -NXM-125S/3300 100A = 406 元 -NXM-63S/33082 25A = 363 元 -NXM-W125S/2300 25A(R) = 376 元 -NXM-160S/2300 25A = 427 元 -NXM-63S/3308 25A = 363 元 -NXM-250S/3300 160A = 659 元 -NXM-63S/3300 10A = 322 元 -NXM-125S/2300 10A = 355 元 -NXM-W630S/3300 400A(R) = 2449 元 -NXM-250S/3300 125A = 659 元 -NXM-63S/23002 10A = 266 元 -NXM-125S/2300 25A = 355 元 -NXM-125S/3300 25A = 406 元 -NXM-63S/3300 25A = 322 元 -NXM-63S/2300 25A = 266 元 -NXM-250S/2300 125A = 508 元 -NXM-400S/33002 250A = 1453 元 -NXM-400S/33002 400A = 1453 元 -NXM-125S/33002 100A = 406 元 -NXM-125S/3300 125A = 406 元 -NXM-63S/2300 63A = 266 元 -NXM-63S/33002 10A = 322 元 -NXM-160S/3300 125A = 600 元 -NXM-160S/3300 160A = 600 元 -NXM-63S/33002 63A = 322 元 -NXM-125S/3300 63A = 406 元 -NXM-250S/2300 200A = 508 元 -NXM-W125S/3300 25A(R) = 437 元" -726,系列,NXB-40系列小型断路器,NXB,13,39,0, -727,系列,NXB-63系列小型断路器,NXB,15,51,0, -728,系列,NXB-125系列小型断路器,NXB,14,43,0, -729,系列,NXBLE-40系列剩余电流动作断路器,NXBLE,14,39,0, -730,系列,NXBLE-63YH系列剩余电流动作断路器,NXBLE,14,66,0, -731,系列,NXBLE-32系列剩余电流动作断路器,NXBLE,14,49,0, -732,系列,NXBLE-125系列剩余电流动作断路器,NXBLE,14,46,0, -733,系列,NXC系列交流接触器,NXC,28,405,1,NXC-06 24V = 92.540000915527 元 -734,系列,NXJ系列小型电磁继电器,NXJ,13,23,0, -735,系列,NXA系列万能式断路器,NXA,82,426,1,NXA16N04-MF3-AC220/230/240 = 16877 元 -736,系列,NXB-80系列小型断路器,NXB,15,61,0, -737,系列,NXB-63H系列高分断小型断路器,NXB,16,45,0, -738,系列,NXHB-125系列隔离开关,NXHB,3,4,0, -739,系列,NXU-Ⅱ系列电涌保护器(被NXU-ⅡG代替),NXU-Ⅱ,4,4,0, -740,系列,NXU-Ⅲ系列电涌保护器,NXU-Ⅲ,4,2,0, -741,系列,NXR系列热过载继电器,NXR,4,32,0, -742,系列,NXBLE-32H系列剩余电流动作断路器,NXBLE,15,39,0, -743,系列,NXBLG-32系列剩余电流动作断路器(带过压),NXBLG-32,6,0,0, -744,系列,NXBLE-63H系列剩余电流动作断路器,NXBLE,16,45,0, -745,系列,NXBLG-63系列剩余电流动作断路器(带过压),NXBLG-63,6,0,0, -746,系列,NXBLG-125系列剩余电流动作断路器,NXBLG,5,0,0, -747,系列,NXC系列迷你型3极交流接触器,NXC,12,7,0, -748,系列,NXC系列迷你型4极交流接触器,NXC,12,11,0, -749,系列,ZT-830系列智能低压无功功率自动补偿控制器,ZT,6,0,0, -750,系列,ZCK系列智能复合开关,ZCK,4,5,0, -751,系列,NR8系列热过载继电器(按项目报价),NR8,2,15,0, -752,系列,JXF系列户外终端箱,JXF,2,25,0, -753,系列,NX10系列配电箱箱体,NX10,1,0,0, -754,系列,JFF1系列户外终端箱,JFF1,2,26,0, -755,系列,JD1A系列电磁调速电动机控制装置,JD1A,3,3,0, -756,系列,JD2A系列电磁调速电动机控制装置,JD2A,2,0,0, -757,系列,NXMLE系列剩余电流动作断路器,NXMLE,32,870,1,NXMLE-125S/3300 10A A = 809 元 -758,系列,NXMS系列电子式塑壳断路器,NXMS,21,841,0, -759,系列,NXHM系列隔离开关,NXHM,3,16,0, -23303,系列,LMZ1-0.5系列低压电流互感器(已停产,建议选用BH-0.66),LMZ1,5,100,0, -23352,系列,NXU-Ⅰ+Ⅱ系列电涌保护器,NXU-Ⅰ+Ⅱ,4,2,0, -23353,系列,NXBLE-63Y系列剩余电流动作断路器,NXBLE,14,39,0, -23354,系列,DZ47-63系列小型断路器(已停产,建议选用NXB-63),DZ47,4,22,0, -23655,系列,NXB-125G系列小型断路器,NXB-125G,11,47,0, -25078,系列,NXB-63Z系列小型断路器(已停产,被NXB-63代替),NXB,5,6,0, -25359,系列,OUVR-1系列自恢复式过欠压保护器(专供),OUVR,6,2,0, -25402,系列,DZ267LG-32系列剩余电流动作断路器(已停产,建议选用NXBLG-40),DZ267,6,0,0, -25440,系列,NB1LG-40系列剩余电流动作断路器,NB1,6,0,0, -25547,系列,NP2系列带罩按钮,NP2,16,0,0, -25548,系列,NP2系列双头按钮,NP2,17,2,0, -25549,系列,NP2系列按钮盒,NP2,1,0,0, -25550,系列,ND16-16系列信号灯,ND16,5,6,0, -26159,系列,NH3-100系列隔离开关,NH3,3,3,0, -26164,系列,LMZJ1-0.5系列低压电流互感器(0.2S级),LMZJ1,4,29,0, -26185,系列,BH-0.66Ⅰ系列低压电流互感器(0.2S级),BH,7,433,0, -26394,系列,NXBLE-125G系列剩余电流动作断路器,NXBLE,9,34,0, -26395,系列,NXB-63系列小型断路器(煤改电),NXB,5,0,0, -26397,系列,NXBELG-32系列剩余电流动作断路器(带过压)电商(已停产),NXBELG,6,0,0, -26398,系列,NXBELG-63系列剩余电流动作断路器(带过压)电商(已停产),NXBELG,6,1,0, -26542,系列,DZ47-60M系列单磁式小型断路器(已停产,被NXB-63M替代),DZ47,5,36,0, -26544,系列,NB1G-80系列小型断路器,NB1G,5,2,0, -26550,系列,CJX1-K系列交流真空接触器,CJX1,10,19,0, -26572,系列,CJX1F系列交流接触器(已停产,被NCX1替代),CJX1,4,0,0, -26606,系列,TD系列接线端子,TD,4,7,0, -26621,系列,SR2系列浪涌抑制器,SR2,3,3,0, -26632,系列,DW16系列万能式断路器(整定值)(已停产,被DW15替代),DW16,6,19,0, -26637,系列,DW15系列万能式断路器(整定值),DW15,7,172,0, -26638,系列,DW17系列万能式断路器(整定值),DW17,6,195,0, -26793,系列,TC系列接线端子,TC,3,14,0, -26794,系列,JF5系列接线端子,JF5,5,5,0, -26800,系列,NPH1系列空盒,NPH1,2,2,0, -26803,系列,WRKT系列控制类仪表热电阻,WRKT,2,3,0, -26954,系列,NM1LE系列漏电断路器(漏电跳闸/不可调),NM1LE,15,245,0, -26956,系列,DZ47LE-63H系列剩余电流动作断路器(已停产,建议选用NXBLE-63H),DZ47LE,7,0,0, -26960,系列,YH系列避雷器(已停产,建议选用YH复合避雷器),YH,5,15,0, -26964,系列,TM系列超低压全自动交流稳压器,TM,1,8,0, -26965,系列,SAK系列接线端子,SAK,3,7,0, -26967,系列,NJBK1系列电动机保护继电器,NJBK1,3,2,0, -26968,系列,BAM系列高压电容器,BAM,4,123,0, -26991,系列,NJMC1系列脉冲继电器,NJMC1,4,16,0, -27093,系列,YJVR系列软导体电线电缆,YJVR,1,0,0, -27094,系列,YJV系列电力电缆,,5,10,0, -27096,系列,VVR系列软导体电线电缆,VVR,1,0,0, -27098,系列,YJV22系列电力电缆,,7,10,0, -27099,系列,PV1-F系列光伏电缆,PV1-F,2,0,0, -27100,系列,VV系列电力电缆,,4,2,0, -27101,系列,VV22系列电力电缆,,6,2,0, -27102,系列,Z-YJV系列电力电缆,,5,2,0, -27103,系列,Z-YJV22系列电力电缆,,7,2,0, -27104,系列,Z-VV系列电力电缆,,5,2,0, -27105,系列,Z-VV22系列电力电缆,,7,2,0, -27109,系列,BVN系列尼龙电线,BVN,1,0,0, -27111,系列,JK系列架空电缆,,5,113,0, -27115,系列,DJYVP-A系列计算机电缆,DJYVP-A,1,0,0, -27117,系列,KVV系列控制电缆,KVV,2,20,0, -27120,系列,N-YJV系列耐火电力电缆,,5,0,0, -27121,系列,N-YJV22系列耐火电力电缆,,7,0,0, -27122,系列,N-VV系列耐火电力电缆,,5,0,0, -27123,系列,N-VV22系列耐火电力电缆,,7,0,0, -27124,系列,ZN-YJV系列耐火电力电缆,,6,3,0, -27125,系列,ZN-YJV22系列耐火电力电缆,,8,3,0, -27126,系列,ZN-VV系列耐火电力电缆,,6,3,0, -27127,系列,ZN-VV22系列耐火电力电缆,,8,3,0, -27129,系列,KVVP系列控制电缆,KVVP,2,20,0, -27130,系列,KVV22系列控制电缆,KVV22,2,20,0, -27131,系列,KVVP2系列控制电缆,KVVP2,2,20,0, -27132,系列,KVVR系列控制电缆,KVVR,2,20,0, -27133,系列,KVVRP系列控制电缆,KVVRP,2,20,0, -27134,系列,KVVP2-22系列控制电缆,KVVP2-22,2,20,0, -27135,系列,KYJV系列控制电缆,KYJV,2,20,0, -27136,系列,KYJVP系列控制电缆,KYJVP,2,20,0, -27137,系列,KYJV22系列控制电缆,KYJV22,2,20,0, -27138,系列,KYJVP2系列控制电缆,KYJVP2,2,20,0, -27139,系列,KYJVP2-22系列控制电缆,KYJVP2-22,2,20,0, -27143,系列,BV系列聚氯乙烯绝缘电线,B,3,2,0, -27144,系列,BVR系列铜芯聚氯乙烯绝缘软电缆,BVR,1,0,0, -27145,系列,RV系列铜芯聚氯乙烯绝缘软电线,RV,1,0,0, -27146,系列,RVV系列铜芯聚氯乙烯绝缘护套软线,RVV,1,0,0, -27147,系列,N-KVV系列控制电缆,N-KVV,2,19,0, -27148,系列,N-KVVP系列控制电缆,N-KVVP,2,19,0, -27149,系列,N-KVVP2系列控制电缆,N-KVVP2,2,19,0, -27150,系列,N-KVV22系列控制电缆,N-KVV22,2,19,0, -27151,系列,N-KYJV系列控制电缆,N-KYJV,2,19,0, -27152,系列,N-KYJV22系列控制电缆,N-KYJV22,2,19,0, -27153,系列,N-KYJVP系列控制电缆,N-KYJVP,2,19,0, -27154,系列,N-KYJVP2系列控制电缆,N-KYJVP2,2,19,0, -27156,系列,N-BV系列聚氯乙烯绝缘耐火电线,N-BV,1,0,0, -27157,系列,N-BVR系列铜芯聚氯乙烯绝缘耐火软电缆,N-BVR,1,0,0, -27158,系列,RVVP系列铜芯聚氯乙烯绝缘护套屏蔽电线,RVVP,1,0,0, -27159,系列,RVS系列铜芯聚氯乙烯绝缘绞型连接用软电线,RVS,1,0,0, -27160,系列,BVVB系列铜芯聚氯乙烯绝缘护套扁型电缆,BVVB,1,0,0, -27161,系列,BVV系列铜芯聚氯乙烯绝缘护套电线,BVV,1,0,0, -27162,系列,N-RVS系列铜芯聚氯乙烯绝缘绞型连接用耐火软电线,N-RVS,1,0,0, -27163,系列,WDZ系列低压无卤电线,WDZ,4,2,0, -27164,系列,DJYPVP-A系列计算机电缆,DJYPVP-A,1,0,0, -27165,系列,DJYPV-A系列计算机电缆,DJYPV-A,1,0,0, -27166,系列,DJYVP2-A系列计算机电缆,DJYVP2-A,1,0,0, -27167,系列,DJYP2VP2-A系列计算机电缆,DJYP2VP2-A,1,0,0, -27168,系列,DJYP2V-A系列计算机电缆,DJYP2V-A,1,0,0, -27169,系列,DJYVP22-A系列计算机电缆,DJYVP22-A,1,0,0, -27170,系列,DJYPVP22-A系列计算机电缆,DJYPVP22-A,1,0,0, -27171,系列,DJYPV22-A系列计算机电缆,DJYPV22-A,1,0,0, -27172,系列,DJYVP2-22-A系列计算机电缆,DJYVP2-22-A,1,0,0, -27173,系列,DJYP2VP2-22-A系列计算机电缆,DJYP2VP2-22-A,1,0,0, -27175,系列,WDZ系列低烟无卤阻燃电缆,WDZ,6,4,0, -27176,系列,YC系列橡套电缆,YC,1,0,0, -27177,系列,YZ系列橡套电缆,YZ,1,0,0, -27178,系列,YH系列橡套电缆,YH,1,0,0, -27179,系列,BTRY系列柔性矿物绝缘电缆,BTRY,2,2,0, -27180,系列,WDZN系列低烟无卤阻燃耐火电缆,WDZ,7,4,0, -27181,系列,MC系列采煤机橡套软电缆,MC,2,0,0, -27182,系列,DT系列金具,DT,1,0,0, -27183,系列,OT系列金具,OT,1,0,0, -27184,系列,JG系列金具,JG,1,0,0, -27185,系列,MCP系列采煤机屏蔽橡套软电缆,MCP,2,3,0, -27186,系列,MY系列煤矿用移动橡套软电缆,MY,2,0,0, -27187,系列,MYP系列煤矿用移动屏蔽橡套软电缆,MYP,2,2,0, -27188,系列,MZ系列煤矿用电钻橡套软电缆,MZ,1,0,0, -27189,系列,MZP系列煤矿用电钻屏蔽橡套软电缆,MZP,1,0,0, -27190,系列,MYQ系列煤矿用移动轻型橡套软电缆,MYQ,1,0,0, -27191,系列,MCPT系列采煤机金属屏蔽橡套软电缆,MCPT,3,4,0, -27192,系列,MYPTJ系列煤矿用移动金属屏蔽监视型橡套软电缆,MYPTJ,2,3,0, -27194,系列,MYPT系列煤矿用移动金属屏蔽橡套软电缆,MYPT,2,0,0, -27195,系列,SC(JGK)系列金具,SC(JGK),2,12,0, -27196,系列,GT系列金具,GT,2,0,0, -27204,系列,YJHLV系列铝合金电缆,YJHLV,2,2,0, -27206,系列,YJHLV22系列铝合金电缆,YJHLV22,2,2,0, -27209,系列,YJHLV8系列铝合金电缆,YJHLV8,1,0,0, -27210,系列,YJHLV82系列铝合金电缆,YJHLV82,1,0,0, -27399,系列,DRDL系列地热电缆,DRDL,2,0,0, -27534,系列,YJV系列电力电缆(完整版),,8,154,0, -27845,系列,CKSG系列三相干式串联电抗器,CKSG,3,137,0, -27980,系列,BH-0.66系列低压电流互感器(0.2级实心),,5,20,0, -28208,系列,NXRC系列接触器式继电器,NXRC,7,12,0, -28265,系列,NJG2系列固态继电器,NJG2,8,39,0, -28269,系列,NJJ7-M系列计数继电器,NJJ7,2,0,0, -28270,系列,NJJ7-H系列计数继电器,NJJ7,2,0,0, -28271,系列,NJG1系列固态继电器,NJG1,8,3,0, -28272,系列,NJYB1系列电压保护继电器(已停产,被NJYB3代替),NJYB1,1,0,0, -28273,系列,NJYB3系列继电器,NJYB3,3,36,0, -28274,系列,NB1L(2H)系列剩余动作断路器,NB1L(2H),6,0,0, -28278,系列,NJS5系列时间继电器(已停产,建议选用NTE8),NJS5,3,12,0, -28279,系列,NJS3系列时间继电器(已停产,建议选用NTE8),NJS3,3,3,0, -28280,系列,NJS3-D系列时间继电器(已停产,建议选用NTE8),NJS3,2,0,0, -28281,系列,NJDC-12系列带测试按钮小型电磁继电器,NJDC-12,2,0,0, -28282,系列,NJDC-17系列带测试按钮小型电磁继电器,NJDC-17,7,22,0, -28294,系列,NCK5系列空调用交流接触器,NCK5,4,12,0, -28300,系列,NCZ1系列直流接触器(已停产,建议选用NCZ2),NCZ1,2,0,0, -28303,系列,NC11系列交流接触器,NC11,3,0,0, -28326,系列,NWK1-GR系列中文液晶低压无功补偿控制器,NWK1,5,7,0, -28344,系列,LMZJ1-0.5系列低压电流互感器(0.5级实芯),LMZJ1,4,0,0, -28461,系列,NKG3系列时控开关,NKG3,3,4,0, -28627,系列,DDS666系列单相电子式电能表(昆仑),DDS666,5,16,0, -28749,系列,NVF5系列通用型变频器,NVF5,13,42,0, -28756,系列,NXZ系列自动转换开关(PC级),NXZ,5,3,0, -28757,系列,NXZB-63系列自动转换开关(CB级)(即将停销,被NXZBN替代),NXZB,7,0,0, -28758,系列,NXZM系列自动转换开关(CB级)(即将停销,被NXZMN替代),NXZM,6,126,0, -28759,系列,NXZHB系列自动转换开关(PC级)(即将停销,被NXZHBN替代),NXZHB,6,2,0, -28760,系列,NXZHM系列自动转换开关(PC级)(即将停销,被NXZHMN替代),NXZHM,5,7,0, -29498,系列,OUVR-2系列自恢复式过欠压保护器,OUVR,5,9,0, -30302,系列,DDSY666系列单相电子预付费电能表(昆仑),DDSY666,5,19,0, -30310,系列,DSSF666系列三相电子式多费率电能表(昆仑),DSSF666,5,4,0, -30311,系列,DTSF666系列三相电子式多费率电能表(昆仑),DTSF666,5,8,0, -30312,系列,DSS633系列三相电子式有功电能表(昆仑),DSS633,5,39,0, -30313,系列,DTS634系列三相电子式有功电能表(昆仑),DTS634,5,65,0, -30314,系列,DTSY666系列三相电子式预付费电能表(昆仑),DTSY666,5,19,0, -30337,系列,DSS(X)666系列三相有功、无功电能表(昆仑),DSS(X)666,5,4,0, -30338,系列,DTS(X)666系列三相有功、无功电能表(昆仑),DTS(X)666,5,20,0, -30339,系列,NB1G-63系列小型断路器,NB1G,6,0,0, -31337,系列,NB1-63系列小型断路器(双汇流排),NB1,7,22,0, -32370,系列,ZCT系列零序电流互感器,ZCT,2,2,0, -32371,系列,TND6系列交流稳压器,TND6,2,2,0, -32372,系列,NSDK系列三相干式电抗器,NSDK,2,3,0, -32373,系列,BAGB(BAFB)系列智能组合低电压并联电容器,BA,6,169,0, -32374,系列,BKMJ系列干式低电压并联电容器,BKMJ,4,81,0, -32375,系列,TH35-7.5系列导轨,TH35,2,0,0, -32377,系列,JXB系列接线端子,JXB,3,16,0, -32394,系列,NPM8-12A系列高钮,NPM8,5,0,0, -32395,系列,NPM8-12A系列环形灯高钮,NPM8,7,0,0, -32396,系列,NPM8-12Z系列指示灯,NPM8,4,0,0, -32397,系列,NPM8-16A系列平钮,NPM8,5,0,0, -32398,系列,NPM8-16A系列单点灯平钮,NPM8,7,0,0, -32399,系列,NPM8-16A系列单点灯高钮(已停产),NPM8,7,0,0, -32400,系列,NPM8-16A系列环形灯平钮,NPM8,7,0,0, -32401,系列,NPM8-16A系列环形灯高钮,NPM8,7,0,0, -32402,系列,NPM8-16A系列电源标识平钮,NPM8,7,0,0, -32403,系列,NPM8-16Z系列指示灯,NPM8,4,0,0, -32404,系列,NPM8-19A系列平钮,NPM8,5,0,0, -32405,系列,NPM8-19A系列单点灯平钮,NPM8,7,0,0, -32406,系列,NPM8-19A系列环形灯平钮,NPM8,7,0,0, -32407,系列,NPM8-19A系列电源标识平钮,NPM8,7,0,0, -32408,系列,NPM8-19J系列急停钮,NPM8,4,0,0, -32409,系列,NPM8-19Y系列钥匙钮,NPM8,3,0,0, -32410,系列,NPM8-19X系列旋钮,NPM8,3,0,0, -32411,系列,NPM8-19Z系列指示灯,NPM8,4,0,0, -32412,系列,NPM8-22A系列平钮,NPM8,5,0,0, -32413,系列,NPM8-22A系列单点灯平钮,NPM8,7,0,0, -32414,系列,NPM8-22A系列环形灯平钮,NPM8,7,0,0, -32415,系列,NPM8-22A系列电源标识平钮,NPM8,7,0,0, -32416,系列,NPM8-22J系列急停钮,NPM8,4,0,0, -32417,系列,NPM8-22Z系列指示灯,NPM8,4,0,0, -32418,系列,NPM8-22Y系列钥匙钮,NPM8,3,0,0, -32419,系列,NPM8-22X系列旋钮,NPM8,3,0,0, -32554,系列,NM1B系列塑壳断路器(表箱专用),NM1B,22,137,0, -32606,系列,NKB1系列控制与保护开关,NKB1,12,105,0, -32608,系列,NKX2系列行程开关,NKX2,1,0,0, -32615,系列,NB3LE-63M系列剩余电流动作断路器,NB3LE,9,162,0, -32639,系列,NKB300系列控制与保护开关(已停产,建议选用NKB1或NKB8),NKB300,4,5,0, -32640,系列,NH45系列隔离开关,NH45,4,41,0, -32641,系列,NH51系列隔离开关,NH51,3,0,0, -33017,系列,DZ47-60系列型小型断路器(煤改电专供)(已停产,建议选用NXB-63煤改电),DZ47,5,9,0, -33018,系列,NXBLE-32系列剩余电流动作断路器(煤改电专供),NXBLE,6,0,0, -33019,系列,NXBLE-32H系列剩余电流动作断路器(煤改电专供),NXBLE,7,0,0, -33020,系列,NXBLE-63系列剩余电流动作断路器(煤改电专供),NXBLE,6,0,0, -33021,系列,NXBLG-32系列剩余电流动作断路器(带过压)(煤改电专供),NXBLG-32,5,0,0, -33022,系列,NXBLG-63系列剩余电流动作断路器(带过压)(煤改电专供),NXBLG-63,5,0,0, -33023,系列,NXBLE-63H系列剩余电流动作断路器(煤改电专供),NXBLE,7,0,0, -33024,系列,TND5(SVC)系列交流稳压器(已停产,建议选用TND1(SVC)),TND5(SVC),2,6,0, -33025,系列,TD系列接线端子(组合型),TD,4,38,0, -33026,系列,LW32系列万能转换开关(电机用),LW32,4,3,0, -33027,系列,TNS5系列稳压器(已停产,建议选用TNS1(SVC)),TNS5,1,0,0, -33028,系列,OCLSG系列三相干式出线电抗器,OCLSG,2,0,0, -33029,系列,ACLSG系列三相干式进线电抗器,ACLSG,2,0,0, -33030,系列,BH-1.0Ⅰ系列低压电流互感器(0.5级),,6,137,0, -33441,系列,QSA系列隔离开关熔断器组,QSA,16,55,0, -33442,系列,QP系列隔离开关,QP,6,17,0, -33443,系列,QA系列隔离开关,QA,4,6,0, -33444,系列,HH15D系列电动式隔离开关熔断器组,HH15D,3,0,0, -35543,系列,JD6A系列电磁调速电动机控制装置(已停产,建议选用JD2A),JD6A,2,0,0, -35546,系列,NCC2系列磁保持继电器,NCC2,6,7,0, -35548,系列,NZ7HB系列自动转换开关(已停产,被NXZHB替代),NZ7HB,4,0,0, -35552,系列,DK系列接线端子,DK,3,0,0, -35553,系列,AP系列接线端子挡板,AP,2,0,0, -35556,系列,NF1系列负荷开关,NF1,6,19,0, -35572,系列,PC-UPS系列不间断电源(已停销),PC-UPS,1,6,0, -35575,系列,GP-UPS系列在线式不间断电源(已停销),GP-UPS,4,98,0, -35586,系列,HP-UPS系列在线式不间断电源(已停销),HP-UPS,2,0,0, -42887,系列,JN15-12系列户内高压交流接地开关,JN15,5,4,0, -42894,系列,ZN85-40.5系列户内高压交流真空断路器,ZN85,5,31,0, -42896,系列,ZN63A-12系列户内高压交流真空断路器,ZN63A,4,25,0, -45189,系列,ND2系列警示灯,ND2,7,0,0, -45190,系列,NTF2系列轴流风扇,NTF2,11,104,0, -45296,系列,LKB1-0.66系列电流互感器,LKB1,5,38,0, -45888,系列,JCUK系列接地端子,JCUK,2,0,0, -45890,系列,SAK系列熔断器端子,SAK,4,0,0, -45891,系列,JF5系列熔断器端子,JF5,3,0,0, -45892,系列,JF5系列试验端子,JF5,4,0,0, -45901,系列,RT28系列圆筒形帽熔断器,RT28,9,10,0, -45962,系列,NTP1系列工业触摸屏,NTP1,1,18,0, -45964,系列,NSC1系列运动控制器,NSC1,1,0,0, -45965,系列,NKB8-12、32系列控制与保护开关电器(按项目报价),NKB8,19,10,0, -45971,系列,NKB8-63系列控制与保护开关电器(按项目报价),NKB8,5,0,0, -46309,系列,NSD1系列伺服驱动器,NSD1,4,2,0, -46311,系列,NTC1系列工业插头、插座及耦合器,NTC1,6,11,0, -46312,系列,NM8N系列交流塑壳断路器(按项目报价),NM8N,123,1572,0, -46314,系列,NKZ1系列万能转换开关,NKZ1,7,18,0, -46317,系列,NJX2系列小型电磁继电器(已停产,建议选用JMK、JTX、JQX-10F),NJX2,6,4,0, -46321,系列,NJA1-KG系列继电器,NJA1,2,0,0, -46322,系列,NJA1-L系列继电器,NJA1,4,0,0, -46329,系列,NM8NL系列剩余电流保护断路器(按项目报价),NM8NL,115,461,0, -46519,系列,NTY1系列移动电缆盘,NTY1,2,3,0, -46595,系列,65L666系列电测量仪表,65L666,3,0,0, -46596,系列,DDSU666系列单相电子式电能表(导轨)(已停产),DDSU666,3,0,0, -46600,系列,DDSU666系列单相导轨电能表(昆仑),DDSU666,4,6,0, -46601,系列,DTSU666系列三相四线导轨电能表(昆仑),DTSU666,4,12,0, -46602,系列,CC系列转换连接器,CC,2,2,0, -46721,系列,NRZ28系列太阳能光伏系统保护用熔断器,底座NRZ28,6,3,0, -46748,系列,ND16系列信号灯(抗干扰),ND16,6,2,0, -46788,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.2S级),BH,5,166,0, -46789,系列,BH-0.66Ⅰ系列低压电流互感器(1级),,7,15,0, -46790,系列,BH-0.66Ⅲ系列低压电流互感器(1级),,7,1,0, -46791,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(1级),BH,6,6,0, -46792,系列,BH-0.66Ⅰ系列低压电流互感器(3级),,8,0,0, -46793,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(3级),BH,6,0,0, -46995,系列,NM8NDC系列直流塑壳断路器(按项目报价),NM8N,107,767,0, -46996,系列,NM8NSD系列隔离开关(按项目报价),NM8N,28,93,0, -47041,系列,NCZ2系列直流接触器,NCZ2,9,47,0, -47055,系列,NXBLE-63ZB系列自诊断剩余电流动作断路器,NXBLE,8,0,0, -47095,系列,NM2系列塑料外壳式断路器(已停产,建议选用NM3),NM2,9,4,0, -47111,系列,NKX3系列行程开关,NKX3,2,17,0, -47149,系列,LMZJ1-0.5系列低压电流互感器(1级),LMZJ1,5,4,0, -47150,系列,LMZJ1-0.5系列低压电流互感器(3级),LMZJ1,5,0,0, -47247,系列,DTM系列铜接线端子(堵油型)(已停产),DTM,4,40,0, -47249,系列,DTL系列铜铝接线端子(已停产),DTL,1,0,0, -47252,系列,DLM系列铝接线端子(堵油型)(已停产),DLM,1,10,0, -47262,系列,OT系列开口型端子(已停产),OT,4,30,0, -47264,系列,GL系列铝连接管(已停产),GL,1,12,0, -47265,系列,GTM系列铜连接管(已停产),GTM,1,0,0, -47266,系列,GTLM系列铜、铝连接管(已停产),GTLM,1,0,0, -47267,系列,GLM系列铝连接管(已停产),GLM,1,12,0, -47268,系列,GT系列铜连接管(已停产),GT,1,0,0, -47269,系列,C45插针(已停产),C45,1,0,0, -47344,系列,NX30系列明/暗装式配电箱,NX30,2,36,0, -47385,系列,NM1系列塑料外壳式断路器(升级型),NM1,46,538,0, -47545,系列,DZ20C系列塑壳断路器(改进型),DZ20,10,16,0, -47546,系列,DZ20Y系列塑壳断路器(改进型),DZ20,12,54,0, -47557,系列,NM2LC系列剩余电流保护断路器,NM2LC,5,60,0, -47638,系列,HD11-F系列防误操作型开启式刀开关,HD11,5,7,0, -47738,系列,NCH8-M系列家用接触器,NCH8,7,7,0, -47919,系列,NB8-40系列小型断路器(环保),NB8,15,26,0, -47928,系列,NB8-40J系列小型断路器,NB8,15,29,0, -47929,系列,NB8-63系列小型断路器(环保),NB8,15,26,0, -47930,系列,NB8-63H系列小型断路器(环保),NB8,16,26,0, -47931,系列,NB8-63M系列单磁式断路器(环保),NB8,16,26,0, -47932,系列,NH8-125系列隔离开关,NH8,4,0,0, -47933,系列,NB8LE-40系列剩余电流动作断路器,NB8LE,16,26,0, -47934,系列,NB8LE-63系列剩余电流动作断路器(环保),NB8LE,18,30,0, -47954,系列,NM1LE系列漏电断路器(升级型),NM1LE,17,435,0, -47964,系列,NRT28系列熔断器,NRT28,9,21,0, -47965,系列,NVF5-GS系列供水专用变频器(已停产),NVF5,8,24,0, -47968,系列,NVF3G-QZ系列起重专用变频器,NVF3G,2,17,0, -48088,系列,NCX1系列防尘交流接触器,NCX1,6,14,0, -48090,系列,NBHLE-32系列剩余电流动作断路器(H系列专供),NBHLE,15,65,0, -48093,系列,NBHLE-40系列剩余电流动作断路器(H系列专供),NBHLE,7,2,0, -48094,系列,NBHLE-40Y系列剩余电流动作断路器(H系列专供),NBHLE,16,26,0, -48095,系列,NBHLE-63系列剩余电流动作断路器(H系列专供),NBHLE,15,65,0, -48097,系列,NBHLE-63Y系列剩余电流动作断路器(H系列专供),NBHLE,16,28,0, -48206,系列,SV系列叉型预绝缘端头(已停产),SV,3,8,0, -48207,系列,RV系列圆型预绝缘端头(已停产),RV,3,8,0, -48208,系列,FDD系列母预绝缘端头(已停产),FDD,3,6,0, -48209,系列,PTV系列针型预绝缘端头(已停产),PTV,3,6,0, -48297,系列,NB8LE-63M系列剩余电流动作断路器,NB8LE,19,39,0, -48306,系列,NBH-40系列小型断路器(H系列专供),NBH,6,0,0, -48307,系列,NBH-63系列小型断路器(H系列专供),NBH,13,41,0, -48308,系列,NBH-63H系列小型断路器(H系列专供),NBH,14,34,0, -48310,系列,NBH-80系列小型断路器(H系列专供),NBH,12,28,0, -48311,系列,NBH-80H系列小型断路器(H系列专供),NBH,14,28,0, -48312,系列,NBH-80GQ系列小型断路器(H系列专供),NBH,6,0,0, -48314,系列,NA1H系列万能式断路器(H系列专供),NA1H,36,105,0, -48317,系列,SBW-JW系列工业级无触点智能稳压器,SBW,2,0,0, -48318,系列,NVF3G-LS系列拉丝专用变频器,NVF3G,2,0,0, -48319,系列,NDKQ系列控制变压器,NDKQ,3,0,0, -48329,系列,HD18系列隔离开关,HD18,2,3,0, -48330,系列,HS18系列隔离开关,HS18,2,8,0, -48344,系列,DZ20L系列塑壳漏电断路器(升级型),DZ20L,19,162,0, -48380,系列,NHH-125系列隔离开关(H系列专供),NHH,4,4,0, -48381,系列,NXZB-63系列自动转换开关(CB级)(H系列专供,已停产,被NZ1HB代替),NXZB,8,0,0, -48382,系列,NXZHB系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZHB,5,0,0, -48383,系列,NXZHM系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZHM,6,119,0, -48384,系列,NXZM系列自动转换开关(CB级)(H系列专供,已停产,被NZ1HM代替),NXZM,7,126,0, -48385,系列,NXZ系列自动转换开关(PC级)(H系列专供,已停产,被NZ1HP代替),NXZ,5,3,0, -48387,系列,WRET系列热电阻,WRET,2,3,0, -48388,系列,NL210系列剩余电流动作断路器(新能源专供),NL210,6,2,0, -48391,系列,NDDK1系列光伏逆变电抗器,NDDK1,1,0,0, -48412,系列,LMZJ1-0.66系列低压电流互感器(0.2S级),LMZJ1,4,57,0, -48450,系列,NXMH系列塑壳断路器(H系列专供),NXMH,38,259,0, -48567,系列,BH-0.66系列电流互感器(实芯 H系列专供),BH,6,0,0, -48587,系列,NPC系列气动接头,NPC,2,5,0, -48588,系列,NPCF系列气动接头,NPCF,2,5,0, -48589,系列,NPL系列气动接头,NPL,2,5,0, -48590,系列,NPLF系列气动接头,NPLF,2,5,0, -48593,系列,NPB系列气动接头,NPB,2,5,0, -48594,系列,NPX系列气动接头,NPX,2,5,0, -48595,系列,NPH系列气动接头,NPH,2,5,0, -48596,系列,BH(SDH)-0.66Ⅱ系列低压电流互感器(0.5级 H系列专供),BH,7,7,0, -48614,系列,NUH-40B系列电涌保护器(H系列专供),NUH,7,0,0, -48628,系列,OUVR-3系列自恢复式过欠压保护器(专供),OUVR,5,0,0, -48630,系列,NBH-125系列塑料外壳式断路器(H系列专供),NBH,12,32,0, -48631,系列,NBH-100系列小型断路器(H系列专供),NBH,7,24,0, -48632,系列,NBO-63系列小型断路器(专供),NBO,5,0,0, -48663,系列,NB1-63H系列小型断路器(通讯专供),NB1,8,7,0, -48664,系列,NB1-63DC系列直流小型断路器(通讯专供),NB1,9,4,0, -48667,系列,CB-60A系列小型断路器(通讯专供),CB,7,0,0, -48668,系列,CB-60A系列小型断路器(交直流通讯专供),CB,7,0,0, -48669,系列,CB-60A(R)系列小型断路器(通讯专供),CB,8,0,0, -48670,系列,CB-60B系列小型断路器(通讯专供),CB,8,6,0, -48671,系列,CB-60G系列小型断路器(通讯专供),CB,7,0,0, -48672,系列,CB-60G系列小型断路器(交直流 通讯专供),CB,8,2,0, -48673,系列,CB-60Z系列小型断路器(交直流通讯专供),CB,7,0,0, -48674,系列,CB-125A系列小型断路器(交直流通讯专供),CB,7,0,0, -48675,系列,CB-63H系列小型断路器(通讯专供),CB,7,0,0, -48676,系列,CB-63HZ系列小型断路器(通讯专供),CB,7,2,0, -48677,系列,CB-60DC系列直流小型断路器(通讯专供),CB,7,2,0, -48678,系列,CB-125A系列小型断路器(通讯专供),CB,7,0,0, -48682,系列,CB-125G系列小型断路器(通讯专供),CB,6,4,0, -48685,系列,NXMHLE系列剩余电流动作断路器(H系列专供),NXMHLE,51,152,0, -48757,系列,NKC1系列直线导轨,NKC1,17,30,0, -48778,系列,NKC1系列滑块,NKC1,8,109,0, -49164,系列,LMZ-0.66系列电流互感器,LMZ,4,45,0, -49165,系列,BH(SDH)-1.0Ⅱ系列低压电流互感器(0.5级),,6,143,0, -49169,系列,NBP-100NGV系列带过失压保护断路器,NBP,5,4,0, -49170,系列,NBP-63R系列小型断路器,NBP,4,0,0, -49171,系列,CJX2e系列交流接触器,CJX2e,4,10,0, -49173,系列,NPM8-16A系列高钮,NPM8,5,0,0, -49174,系列,NXBF-40系列小型断路器,NXBF,18,26,0, -49176,系列,NXBF-63系列小型断路器,NXBF,17,32,0, -49177,系列,NXBF-125系列小型断路器,NXBF,17,30,0, -49178,系列,NXBFLE-32系列剩余电流动作断路器,NXBFLE,19,31,0, -49179,系列,NXBFLE-63系列剩余电流动作断路器,NXBFLE,19,31,0, -49182,系列,NXMF系列塑壳断路器,NXMF,41,284,0, -49200,系列,NSM1系列伺服电机,NSM1,1,0,0, -49201,系列,DJZ666系列直流智能电能表,DJZ666,4,28,0, -49231,系列,NXMFLE系列剩余电流动作断路器,NXMFLE,50,116,0, -49238,系列,NTK1系列温控器,NTK1,4,0,0, -49239,系列,NTR1系列加热器,NTR1,1,0,0, -49240,系列,热缩套管,热缩管,3,58,0, -49241,系列,行线槽,线槽,1,14,0, -49243,系列,FJ6G系列开关端子,FJ6G,4,14,0, -49730,系列,42L6系列模拟指示功率因数表(改进型),42,5,0,0, -49732,系列,42L6系列模拟指示电流表(改进型),42,6,25,0, -49733,系列,42L6系列模拟指示电压表(改进型),42,6,2,0, -49734,系列,42L6系列模拟指示功率表(改进型),42,6,0,0, -49735,系列,42L6系列模拟指示频率表(改进型),42,6,0,0, -49745,系列,6L2系列模拟指示电流表(改进型),6,6,2,0, -49746,系列,6L2系列模拟指示电压表(改进型),6,6,2,0, -49747,系列,6L2系列模拟指示频率表(改进型),6,6,2,0, -49748,系列,6L2系列模拟指示功率因数表(改进型),6,5,0,0, -49757,系列,NXW系列电能质量治理装置(已停产),NXW,4,12,0, -49758,系列,NM1系列塑壳断路器(消防专供),NM1,11,28,0, -49759,系列,NC1系列交流接触器(畜牧专用),NC1,5,0,0, -49760,系列,NP2系列带灯旋钮,NP2,20,17,0, -49761,系列,AC系列交流阀用电磁铁(已停产),AC,3,24,0, -49764,系列,NFV系列交流阀用电磁铁,NFV,1,0,0, -49767,系列,ACL系列交流输入电抗器,ACL,4,54,0, -49772,系列,DCL系列直流输入电抗器,DCL,4,42,0, -49794,系列,发光器,,3,0,0, -49795,系列,NEW系列电子组件板,,2,47,0, -50013,系列,YH系列复合避雷器,YH,7,21,0, -50276,系列,2V系列电磁阀,2V,3,0,0, -50277,系列,3V系列电磁阀,3V,5,12,0, -50278,系列,4V系列电磁阀,4V,5,58,0, -50279,系列,4M系列电磁阀,4M,4,2,0, -50291,系列,NJR5-ZX系列软起动器,NJR5,6,23,0, -50346,系列,AC30系列强电插座,,3,23,0, -50804,系列,NXU-ⅡG系列直流电涌保护器(通信专供)(按项目报价),NXU-ⅡG,5,0,0, -50860,系列,NZ1HP系列自动转换开关(PC级)(H系列专供),NZ1HP,6,14,0, -50864,系列,NZ1HM系列自动转换开关(塑壳型 CB级)(H系列专供,即将停销,被NXZMN替代),NZ1HM,7,12,0, -50865,系列,NZ1HB系列自动转换开关(微断 CB级)(H系列专供,即将停销,被NXZBN替代),NZ1HB,6,0,0, -50905,系列,NXAF系列万能式断路器,NXAF,24,49,0, -51149,系列,NKY2系列开关电源,NKY2,2,10,0, -51150,系列,NKY3系列薄型开关电源,NKY3,2,7,0, -51275,系列,TNSZ3系列柱式交流自动稳压器,TNSZ3,1,4,0, -51367,系列,NZ5-H系列自动转换开关(PC级),NZ5,8,15,0, -51453,系列,NB5-63系列小型断路器,NB5,16,34,0, -51456,系列,NB5LE-40系列剩余电流动作断路器,NB5LE,18,34,0, -51457,系列,NB5-40系列小型断路器,NB5,16,32,0, -51459,系列,NB5-63G系列塑料外壳式断路器,NB5,17,76,0, -51460,系列,NB5LE-40Y系列剩余电流动作断路器,NB5LE,18,28,0, -51461,系列,NB5LE-63系列剩余电流动作断路器,NB5LE,17,33,0, -51462,系列,NB5LG-63系列剩余电流动作断路器,NB5LG,16,28,0, -51463,系列,NB5LE-63Y系列剩余电流动作断路器,NB5LE,18,30,0, -51464,系列,NB5LE-63ZB系列自诊断剩余电流动作断路器,NB5LE,18,28,0, -51465,系列,NB5L-40Y系列电磁式剩余电流动作断路器,NB5L,18,28,0, -51466,系列,NB5L-40M系列电磁式剩余电流动作断路器,NB5L,18,28,0, -51468,系列,NH5-125系列隔离开关,NH5,4,4,0, -51469,系列,NU5-Ⅱ系列电涌保护器,NU5,6,28,0, -51470,系列,OUVR-5系列自恢复式过欠压保护器,OUVR-5,4,2,0, -51573,系列,NB2-40ZT/ZW系列智慧小型断路器,NB2,7,0,0, -51574,系列,NB2-80ZT/ZW系列智慧小型断路器(环保),NB2,7,2,0, -51575,系列,NB2LE系列剩余电流动作断路器,NB2LE,6,0,0, -51576,系列,NB2LE-80ZT系列智慧剩余电流动作断路器(环保),NB2LE,9,2,0, -51578,系列,NB2LE-40ZT系列智慧剩余电流动作断路器,NB2LE,7,0,0, -51579,系列,RX系列信号熔断器,RX,1,0,0, -51673,系列,NX50系列暗装式配电箱(箱体),NX50,6,274,0, -51698,系列,NR5系列热过载继电器,NR5,4,31,0, -51699,系列,NS5系列电动机起动器,NS5,12,14,0, -51712,系列,NB8-125系列小型断路器,NB8,14,26,0, -51719,系列,NB8LE-63H系列剩余电流动作断路器,NB8LE,18,26,0, -51720,系列,NB8LE-63YH系列剩余电流动作断路器,NB8LE,18,26,0, -51721,系列,NB8LG-63YH系列剩余电流动作断路器,NB8LG,8,0,0, -51931,系列,NDT1系列警示灯,NDT1,8,6,0, -51933,系列,NU6-ⅡG系列电涌保护器,NU6-ⅡG,4,0,0, -51934,系列,NXU-ⅡG系列电涌保护器,NXU-ⅡG,4,6,0, -52215,系列,NA5系列万能式断路器,NA5,114,182,0, -52245,系列,NBP-125GVS系列小型断路器,NBP,7,2,0, -52259,系列,NM5系列塑壳断路器,NM5,64,329,0, -52273,系列,JQX-13FA系列小型电磁继电器,JQX-13FA,6,4,0, -52447,系列,NB5L-40J系列电磁式剩余电流动作断路器,NB5L,18,28,0, -52495,系列,NB5-125G系列塑料外壳式断路器,NB5,16,32,0, -52496,系列,NB5LE/LG-125G系列剩余电流动作断路器,NB5,19,47,0, -52497,系列,NU5-Ⅰ+Ⅱ系列电涌保护器,NU5,6,0,0, -52498,系列,NSCB5系列电涌保护器专用保护装置,NSCB5,6,6,0, -52623,系列,FLN36-12D系列户内高压负荷开关,FLN36,5,0,0, -52624,系列,NFW1-12(F)系列户外分界交流负荷开关,NFW1,4,0,0, -52625,系列,NFW2-12系列户外高压交流真空负荷开关,NFW2,4,0,0, -52626,系列,NFW2-12(F)系列户外高压交流分界负荷开关,NFW2,5,0,0, -52627,系列,NFW2-12(Z)系列户外高压交流智能真空负荷开关,NFW2,5,0,0, -52628,系列,NFZ77-40.5D系列风电专用负荷开关,NFZ77,5,0,0, -52629,系列,NV1-24/T系列户内高压交流真空断路器,NV1,5,0,0, -52630,系列,NV1-24/T(P)系列户内固封极柱真空断路器,NV1,6,7,0, -52631,系列,NV2-12/T(P)系列户内固封极柱真空断路器,NV2,6,8,0, -52632,系列,NV3-40.5/T(P)系列户内固封极柱真空断路器,NV3,6,6,0, -52633,系列,NV6-12/T(P)系列环保型户内高压交流真空断路器,NV6,6,0,0, -52636,系列,ZN63S-12/T系列户内高压交流真空断路器,ZN63S,5,7,0, -52638,系列,ZW7-40.5系列户外高压交流真空断路器,ZW7,4,4,0, -52639,系列,ZW20A-12(F)系列户外分界高压交流真空断路器,ZW20A,5,0,0, -52643,系列,6L2系列模拟指示功率表(改进型),6,6,0,0, -52645,系列,BH-0.66Ⅲ系列低压电流互感器(0.2S级),BH,5,51,0, -52673,系列,NM2LC系列剩余电流保护断路器(光伏专用),NM2LC,5,10,0, -52674,系列,NJX3系列小型电磁继电器,NJX3,2,0,0, -52680,系列,RT29-16系列圆筒形帽熔断器,RT29,5,1,0, -52688,系列,RT36(R)系列熔断器,RT36,6,19,0, -52689,系列,RT36(NT00)系列熔断器,RT36-00(NT00),6,3,0, -52694,系列,RT36系列刀型触头熔断器,RT36,4,19,0, -52697,系列,NRT36系列刀型触头熔断器,NRT36,5,3,0, -52698,系列,HDLRT0系列刀型触头熔断器,HDLRT0,4,11,0, -52754,系列,NXB-63T系列透明壳小型断路器,NXB,13,61,0, -52755,系列,NXBLE-40T系列透明壳漏电断路器,NXBLE,14,46,0, -52756,系列,NXBLE-63T系列透明壳漏电断路器,NXBLE,14,44,0, -52757,系列,OUVR-2N系列自恢复式过欠压保护器,OUVR,4,2,0, -52758,系列,NB5NE-40S系列小型断路器,NB5NE,6,0,0, -52759,系列,"NM10系列塑壳断路器(升级型)(已停产,被NXM替换)",NM10,9,0,0, -52760,系列,NB5NE-63N系列小型断路器,NB5NE,6,6,0, -52761,系列,NB5NELE-40S系列剩余电流动作断路器,NB5NELE,8,0,0, -52762,系列,NB5NELE-63Y系列剩余电流动作断路器,NB5NELE,8,0,0, -52763,系列,NB5NELE-63系列剩余电流动作断路器,NB5NELE,7,4,0, -52764,系列,OUVR-1N系列自恢复式过欠压保护器(专供),OUVR,4,2,0, -52765,系列,NXBFLE-40系列剩余电流动作断路器,NXBFLE,19,26,0, -52766,系列,NXHBF-125系列小型隔离开关,NXHBF,3,4,0, -52767,系列,NU5NE-Ⅰ+Ⅱ系列电涌保护器,NU5NE,5,0,0, -52816,系列,ExASD E直流隔离开关,ExASD E,5,8,0, -52817,系列,ExBP E系列塑壳断路器,ExBP E,4,4,0, -52818,系列,ExBD125 E直流小型断路器,ExBD125 E,3,4,0, -52819,系列,ExlR50 E旋转隔离开关,ExlR50 E,2,8,0, -52821,系列,HD11-□E系列刀开关,HD11,6,0,0, -52822,系列,HK18-□E系列隔离开关,HK18,3,0,0, -52823,系列,HD18-□E系列光伏专供刀开关,HD18,3,0,0, -52824,系列,NA5PD系列万能式断路器,NA5PD,4,6,0, -53003,系列,NC5NE系列交流接触器,NC5NE,3,42,0, -53110,系列,NXB-63E系列小型断路器,NXB,13,39,0, -53111,系列,NXB-80E系列小型断路器,NXB,13,39,0, -53112,系列,NXB-125E系列小型断路器,NXB,12,39,0, -53135,系列,ExJPV E系列新能源专供板载继电器,ExJPV,2,8,0, -53213,系列,NBP-80NZSY系列电能表外置断路器,NBP,6,0,0, -54236,系列,NJX12系列小型电磁继电器,NJX12,6,0,0, -54237,系列,NXLH-1系列电流互感器,NXLH-1,5,284,0, -54245,系列,CKDG系列单相干式串联电抗器,CKDG,3,0,0, -54267,系列,NJYB2系列电压保护继电器,NJYB2,3,0,0, -54268,系列,JSZ3P系列时间继电器,JSZ3P,3,3,0, -54355,系列,NXCF系列交流接触器,NXCF,11,37,0, -54356,系列,NXRF系列热继电器,NXRF,4,10,0, -54428,系列,HR6系列熔断器式隔离开关(蓝色),HR6,5,12,0, -54429,系列,CB-63HB系列塑料外壳式断路器,CB,4,0,0, -54457,系列,NHM5系列隔离开关,NHM5,54,195,0, -54458,系列,NM5S系列电子式塑壳断路器,NM5S,60,196,0, -54459,系列,NM5LE系列剩余电流动作断路器,NM5LE,59,224,0, -54460,系列,NA5NE系列万能式断路器,NA5NE,9,15,0, -54463,系列,NB5LE-63□/B系列剩余电流动作断路器,NB5LE,18,31,0, -54465,系列,NWFBA系列智能组合式低压并联电容器,NWFBA,2,2,0, -54468,系列,KG316T-S系列时控开关,KG316T-S,1,0,0, -54469,系列,HD11G-□E系列光伏专用刀开关,HD11G,3,0,0, -54476,系列,NXCQ系列交流接触器应急启动装置(已停销,被NQ1替代),NXCQ,4,15,0, -54498,系列,NKB8G系列控制与保护开关电器,NKB8G,4,2,0, -54541,系列,HK18G系列刀开关,HK18G,3,0,0, -54542,系列,PES系列便携式储能电源(已停产),PES,1,4,0, -54567,系列,NB5-63M系列塑料外壳式断路器,NB5,17,32,0, -54569,系列,NU5-I系列电涌保护器,NU5,5,0,0, -54625,系列,NXMSF系列电子式塑壳断路器,NXMSF,44,120,0, -54832,系列,NA5T系列5G&通信专供万能断路器,NA5T,8,22,0, -54844,系列,NDK2系列控制变压器,NDK2,3,3,0, -54895,系列,NCH8G系列家用交流接触器,NCH8G,3,12,0, -54909,系列,NXTC系列工业插头插座和耦合器,NXTC,6,23,0, -54993,系列,TFD110系列简易矢量型变频器,TFD110,5,23,0, -54994,系列,TFD120系列变频器,TFD120,5,26,0, -54995,系列,TFD130系列变频器,TFD130,5,26,0, -54996,系列,TR150-ZX系列软起动器,TR150,3,0,0, -54997,系列,TR120-D系列软起动器,TR120,2,0,0, -54998,系列,DTSH666系列三相四线电子式多用户电能表,DTSH666,5,5,0, -55007,系列,NH3-125系列隔离开关,NH3,3,3,0, -55011,系列,NVFP5系列变频器,NVFP5,5,83,0, -55014,系列,NJRP5系列软起动器,NJRP5,3,0,0, -55019,系列,EV-TN系列绝缘护套双线管形冷压端子(已停产),EV-TN,3,33,0, -55021,系列,CKJ11系列真空交流接触器,CKJ11,3,6,0, -55027,系列,NXBLE-63系列剩余电流动作断路器,NXBLE,15,55,0, -55028,系列,NXBLE-63YHF系列剩余电流动作断路器(下进线),NXBLE,17,39,0, -55029,系列,NXBLG-63YH系列剩余电流动作断路器(带过压),NXBLG-63YH,6,0,0, -55167,系列,DDSYU666-B系列单相导轨电子式预付费电能表(昆仑),DDSYU666-B,4,0,0, -55168,系列,DJZU666X系列直流智能导轨电能表(昆仑),DJZU666X,4,0,0, -55169,系列,PA666系列电流数显表(昆仑),PA666,6,177,0, -55170,系列,PD666系列多功能数显表(昆仑),PD666,6,54,0, -55171,系列,PH666系列功率因数表(昆仑),PH666,6,11,0, -55172,系列,PP666系列频率数显表(昆仑),PP666,6,21,0, -55173,系列,PS666系列数显功率表(昆仑),PS666,5,6,0, -55174,系列,PZ666系列电压数显表(昆仑),PZ666,6,172,0, -55175,系列,NXMP系列塑壳断路器,NXMP,37,861,0, -55181,系列,RT36J系列低功耗熔断器体,RT36J,2,2,0, -55329,系列,NLH2-0.8系列电流互感器,NLH2,4,61,0, -55470,系列,NXSCB系列电涌保护器专用保护装置,NXSCB,5,6,0, -55645,系列,CKSG2系列三相干式串联电抗器,CKSG2,3,22,0, -55646,系列,ExMYHV E系列高电压系列塑料外壳式断路器,ExMY,7,8,0, -55647,系列,NJX5系列小型电磁继电器,NJX5,4,6,0, -55652,系列,NR4-G系列热过载继电器,NR4,3,18,0, -55655,系列,NH40DC系列直流隔离开关,NH40DC,3,0,0, -55750,系列,NBH-40J系列小型断路器,NBH,5,4,0, -55751,系列,NBHLU-63系列剩余电流动作断路器,NBHLU,5,0,0, -55752,系列,NX30H系列安装配电箱,NX30H,3,10,0, -55753,系列,NXMSH系列电子式塑壳断路器(H系列专供),NXMSH,43,86,0, -55754,系列,NBP-63S系列小型断路器,NBP,7,2,0, -55755,系列,HPD2000GH配网三相不平衡综合治理装置,HPD2000GH,4,2,0, -55756,系列,NBP-63系列微型断路器,NBP,6,0,0, -55757,系列,NBP-80RG系列小型断路器,NBP,5,7,0, -55758,系列,NBP-80系列小型断路器,NBP,6,2,0, -55759,系列,NBP-100HS系列小型断路器,NBP,7,2,0, -55760,系列,NBP-100NZS/L系列电能表外置断路器,NBP,8,7,0, -55761,系列,NBP-125NZS系列电能表外置断路器,NBP,7,4,0, -55762,系列,NBP-125系列塑料外壳式断路器,NBP,5,4,0, -55763,系列,NBPLE/LG-63系列剩余电流动作断路器,NBP,8,9,0, -55764,系列,NBPLE/LG-125系列剩余电流动作断路器,NBP,9,14,0, -55765,系列,NBPLE-63YH系列剩余电流动作断路器,NBP,9,0,0, -55766,系列,NBPLE-63系列剩余电流漏电断路器(FJ专供),NBPLE,8,0,0, -55767,系列,NHP-125G系列隔离开关,NHP,4,0,0, -55768,系列,NHP-125系列隔离开关,NHP,4,4,0, -55769,系列,ZCKP系列智能复合开关,ZCKP,3,0,0, -55781,系列,NM5NELE系列新能源专供塑壳漏电断路器,NM5NELE,97,296,0, -55782,系列,NM5NE系列新能源专供塑壳断路器,NM5NE,93,472,0, -55783,系列,NM3DC系列高电压直流塑壳断路器,NM3DC,13,16,0, -55784,系列,NM3FC系列费控塑壳断路器,NM3FC,10,25,0, -55785,系列,NM3LC系列剩余电流保护器断路器,NM3LC,14,25,0, -55787,系列,XMT-5000改进型系列数字温度指示控制仪,,8,50,0, -55788,系列,NM3系列塑壳断路器,NM3,19,20,0, -55789,系列,BWD系列干式变压器温度控制器,BWD,5,2,0, -55790,系列,EPEC100系列电力环境控制器(已停销),EPEC100,3,0,0, -55791,系列,EPEC200系列电力环境控制器(已停销),EPEC200,3,2,0, -55792,系列,NPR300-FV/H微机防孤岛保护装置,,3,2,0, -55793,系列,NPR300-M系列电动机保护器,,1,0,0, -55794,系列,NPR300系列微机保护装置,,3,12,0, -55795,系列,NPR500系列微机保护装置,,3,12,0, -55796,系列,NPR530系列微机保护装置,,3,18,0, -55797,系列,NPR550-FB系列微机保护装置,,1,0,0, -55798,系列,NPR550系列微机保护装置,,4,60,0, -55799,系列,NSC100系列智能操控装置,NSC,9,99,0, -55800,系列,WSG系列温湿度控制器,,6,53,0, -55801,系列,NDH50智能除湿器,,4,9,0, -55802,系列,NTD50/70系列无线测温装置,,3,12,0, -55803,系列,NS100-W系列无线测温传感器,,3,0,0, -55804,系列,DSN10系列户内电磁锁,,4,0,0, -55805,系列,DXN20系列高压带电显示器,,3,24,0, -55806,系列,EKL30系列故障指示器,,1,12,0, -55807,系列,HT系列加热器(板),,6,16,0, -55813,系列,NXCC系列切换电容器接触器,NXCC,3,8,0, -55962,系列,OCL系列交流输出电抗器(已停产),OCL,4,54,0, -55965,系列,NP2系列自锁按钮,NP2,7,4,0, -56061,系列,NXMN系列透明壳塑壳断路器,NXMN,10,60,0, -56149,系列,NXMNLE系列透明壳剩余电流动作断路器,NXMNLE,11,40,0, -56175,系列,CG系列电缆接头,CG,5,46,0, -56177,系列,NXTC2系列电缆接头,NXTC2,3,29,0, -56178,系列,NXTC2系列接插体,NXTC2,11,71,0, -56179,系列,NXTC2系列外壳底座,NXTC2,5,302,0, -56183,系列,NB2DC-100ZT系列直流小型断路器,NB2DC,6,0,0, -56184,系列,NXZF系列自动转换开关(PC级),NXZF,3,0,0, -56186,系列,NJR5-G系列在线式软起动控制柜,NJR5,2,0,0, -56189,系列,EV系列管形冷压端子(已停产),EV,2,14,0, -56191,系列,EV-N系列冷压端子(已停产),EV-N,3,28,0, -56195,系列,NB5NE-125G系列小型断路器,NB5NE,6,4,0, -56196,系列,NB5NELE-125G系列剩余电流动作断路器,NB5NELE,8,3,0, -56214,系列,NQ1系列智能型一体式星三角起动器,NQ1,6,9,0, -56404,系列,DSSU666系列三相电子式导轨电能表(昆仑),DSSU666,5,6,0, -56420,系列,HD13/E系列刀开关(已停产),HD13,6,5,0, -56422,系列,NRT30系列熔断体底座,底座NRT30,3,0,0, -56424,系列,RT28N系列熔断器底座,底座RT28N,4,6,0, -56426,系列,C型、G型导轨,,2,0,0, -56623,系列,NXBLE-125E系列小型漏电断路器,NXBLE,14,41,0, -56624,系列,NXB-125E系列小型直流断路器,NXB,13,41,0, -56627,系列,NXBLE-63E系列小型漏电断路器,NXBLE,15,43,0, -56698,系列,JXFG系列配电箱(箱体),JXFG,3,56,0, -56699,系列,NJX6系列配套插座,NJX6,2,0,0, -56700,系列,NJX6系列小型电磁继电器,NJX6,3,0,0, -56701,系列,NJX6系列整机,NJX6,3,0,0, -56702,系列,NJRM5-ZX系列通用型软起动器(15A-220A),NJRM5,3,0,0, -56703,系列,PZ30G系列配电箱,PZ30G,3,36,0, -56711,系列,NJRM5-D-SZ数智型软起动器(180A-1000A),NJRM5,4,0,0, -56714,系列,WPanel智慧终端箱,WPanel,5,47,0, -56715,系列,BP8R4系列频敏变阻器(已停产),特 BP8R4,2,10,0, -56716,系列,2W系列电磁阀,2W,4,41,0, -56717,系列,PU系列气管,PU,5,81,0, -56739,系列,NDKH系列控制变压器,NDKH,3,24,0, -56741,系列,NXKY系列开关电源,NXKY,2,0,0, -56774,系列,NCC2NE-90系列磁保持继电器,NCC2NE,4,0,0, -56976,系列,NXC-XM系列交流接触器,NXC,4,11,0, -56990,系列,NXR-XM系列热过载继电器,NXR,3,3,0, -57023,系列,NXC-R系列交流接触器,NXC,3,0,0, -57134,系列,NKY6系列开关电源,NKY6,2,23,0, -57135,系列,NXW系列模块化电能质量功率单元,NXW,7,24,0, -57136,系列,LMZ□G-ZTN1系列电流互感器,LMZ,5,10,0, -57137,系列,NKY2S系列开关电源,NKY2S,2,4,0, -57138,系列,NXW N系列模块化电能质量功率单元,NXW,6,2,0, -57142,系列,NXA-NE系列万能式断路器,NXA,82,112,0, -57147,系列,NZ5系列自动转换开关电器(PC级),NZ5,7,18,0, -57322,系列,TND2系列自动交流稳压器,TND2,2,11,0, -57324,系列,MA系列迷你气缸,MA,3,0,0, -57325,系列,HRQ系列回转气缸,HRQ,2,8,0, -57326,系列,MD系列多位置固定型气缸,MD,3,6,0, -57327,系列,RMS系列磁耦合无杆气缸,RMS,5,32,0, -57328,系列,MK系列多位置固定型气缸,MK,3,12,0, -57329,系列,QTR系列双轴气缸,QTR,3,12,0, -57330,系列,TN系列双轴气缸,TN,3,10,0, -57336,系列,SDA系列薄型气缸,SDA,4,547,0, -57337,系列,PB系列笔形气缸,PB,4,68,0, -57419,系列,NXZN系列自动转换开关(PC级),NXZN,5,21,0, -57457,系列,ExIZ HV E系列新能源专供隔离开关,ExIZ,14,52,0, -57461,系列,NXU-IIG E 电涌保护器,NXU-IIG,5,0,0, -57462,系列,NM8N高电压(HV)系列塑壳断路器,NM8N,16,90,0, -57463,系列,NM5T系列塑料外壳式断路器,NM5T,48,189,0, -57464,系列,CB-63DC系列直流断路器,CB,5,0,0, -57465,系列,NM8N系列高电压塑壳断路器(按项目报价),NM8N,24,38,0, -57466,系列,NBP-100NGV E光伏并网专用断路器,NBP,9,2,0, -57471,系列,NBP-125NGV E光伏并网专用断路器,NBP,8,2,0, -57477,系列,NGC5系列低压品牌柜,NGC5,3,0,0, -57478,系列,NGC8系列智能型成套开关柜,NGC8,2,0,0, -57487,系列,NXMSP系列电子式塑壳断路器,NXMSP,41,111,0, -57488,系列,RT36-T系列刀型触头熔断器,底座RT36,7,16,0, -57489,系列,NM3LFC系列剩余电流保护器断路器,NM3LFC,17,34,0, -57491,系列,SDH-0.66 T系列电流互感器,SDH,4,0,0, -57494,系列,NM3SD系列隔离开关,NM3SD,26,75,0, -57495,系列,NXMSPD系列塑壳断路器,NXMSPD,38,59,0, -57496,系列,NTCE系列储能连接器(插头),NTCE,4,5,0, -57497,系列,NTCE系列储能连接器(插座),NTCE,5,5,0, -57502,系列,NWP系列模块化电能质量功率单元,NWP,5,6,0, -57522,系列,NBP-100□ZW系列电能表外置断路器,NBP,5,4,0, -57523,系列,NBP-80ZSW系列电能表外置断路器,NBP,5,0,0, -57526,系列,NM5TS系列塑料外壳式断路器,NM5TS,48,189,0, -57529,系列,NM3N系列智能量测开关,NM3N,27,123,0, -57530,系列,LMZ□K-ZTN1系列抗直流偏磁低压电流互感器,LMZ,5,15,0, -57707,系列,NCZ5NE-F系列直流接触器,NCZ5NE,6,28,0, -57708,系列,NXMNS系列电子式塑壳断路器,NXMNS,97,919,0, -57709,系列,NXMN-1250、1600系列塑壳断路器,NXMN,13,75,0, -57896,系列,NXD-16系列信号灯,NXD,5,0,0, -57897,系列,NXD-22系列信号灯,NXD,7,136,0, -57898,系列,NXD-22系列蜂鸣器式信号灯,NXD,5,4,0, -57907,系列,NM2FC系列塑料外壳式断路器,NM2FC,5,4,0, -58062,系列,Ex9A-DC系列直流空气断路器,Ex9A,71,100,0, -58063,系列,Ex9A系列空气断路器,Ex9A,96,217,0, -58064,系列,Ex9MD3HV直流塑料外壳式断路器,Ex9M,34,216,0, -58065,系列,Ex9MDYHV系列高电压直流塑壳断路器,Ex9MDY,15,33,0, -58066,系列,Ex9MD系列直流塑料外壳式断路器,Ex9MD,5,28,0, -58067,系列,Ex9MHV高电压系列塑料外壳式断路器,Ex9M,17,34,0, -58068,系列,Ex9ML系列剩余电流保护模块,Ex9ML,6,6,0, -58069,系列,Ex9MV2S-PV/DC 1500V光伏专用直流塑料外壳式断路器,Ex9MV,11,21,0, -58070,系列,Ex9MV2S-PV10光伏专用直流塑料外壳式断路器,Ex9MV,10,8,0, -58071,系列,Ex9MYHV系列塑料外壳式断路器,Ex9MY,15,32,0, -58072,系列,Ex9M系列交流塑料外壳式断路器,Ex9M,78,1324,0, -58073,系列,ATSA自动电源转换系统组件,,4,51,0, -58074,系列,ExATS9B系列自动转换开关电器,ExATS9B,5,127,0, -58075,系列,ExATS9M系列自动转换开关电器(CB级),ExATS9M,4,5,0, -58076,系列,ExATSNH系列自动转换开关电器(PC级),ExATS,12,42,0, -58077,系列,ExATSN系列自动转换开关电器(PC级),ExATSN,4,4,0, -58078,系列,Ex9I(Z)HV系列隔离开关,Ex9I,14,52,0, -58079,系列,Ex9IRTZ隔离开关熔断器组,Ex9IRTZ,9,34,0, -58080,系列,Ex9IR隔离开关,Ex9I,12,6,0, -58081,系列,Ex9I隔离开关,Ex9I,9,17,0, -58082,系列,Ex9MSD系列隔离开关,Ex9M,7,25,0, -58083,系列,Ex9CF系列宽电压交流接触器,Ex9C,7,50,0, -58084,系列,Ex9CM系列模数化交流接触器,Ex9C,6,0,0, -58085,系列,Ex9CN系列交流接触器,Ex9CN,4,10,0, -58086,系列,Ex9C系列交流接触器,Ex9C,18,867,0, -58087,系列,Ex9RC系列中间继电器,Ex9RC,7,2,0, -58088,系列,Ex9RN系列热过载继电器,Ex9RN,3,6,0, -58089,系列,Ex9R系列热过载继电器,Ex9R,4,15,0, -58090,系列,Ex9S电动机保护用断路器,Ex9S,26,40,0, -58091,系列,Ex9IRZ系列隔离开关,Ex9IRZ,6,0,0, -58092,系列,Ex9JM系列小型电磁继电器,Ex9JM,7,6,0, -58093,系列,Ex9JPV系列光伏继电器,Ex9JPV,2,0,0, -58094,系列,Ex9JP系列电压保护继电器,Ex9JP,3,44,0, -58095,系列,Ex9P2系列按钮,Ex9P2,18,102,0, -58096,系列,Ex9PL系列信号灯及蜂鸣器,Ex9PL,3,12,0, -58097,系列,Ex9ZA系列万能转换开关,Ex9ZA,5,64,0, -58098,系列,Ex9VF3系列变频器,Ex9VF3,13,26,0, -58099,系列,Ex9VF6系列变频器,Ex9VF6,13,25,0, -58100,系列,Ex9QR系列软起动器,Ex9QR,5,26,0, -58101,系列,Ex9B40J小型断路器,Ex9B40J,13,33,0, -58102,系列,Ex9B125小型断路器,Ex9B,13,38,0, -58103,系列,Ex9BD125小型断路器,Ex9BD125,13,106,0, -58104,系列,Ex9BG小型断路器,Ex9B,18,42,0, -58105,系列,Ex9BH125小型断路器,Ex9B,4,0,0, -58106,系列,Ex9BM电动机保护小型断路器,Ex9BM,17,38,0, -58107,系列,Ex9BP-JX直流小型断路器,Ex9BP,16,37,0, -58108,系列,Ex9B小型断路器,Ex9B,24,120,0, -58109,系列,Ex9PN小型断路器(相线+中性线),Ex9PN,13,26,0, -58110,系列,Ex9BP直流小型断路器,Ex9BP,21,208,0, -58111,系列,Ex9B100+GQ自愈式过欠压保护断路器,Ex9B,5,0,0, -58112,系列,Ex9B100+GV光伏并网专用小型断路器,Ex9B,5,0,0, -58113,系列,Ex9B100+ZS电能表外置断路器,Ex9B,5,0,0, -58115,系列,Ex9BL40电磁式剩余电流动作断路器,Ex9BL40,5,4,0, -58116,系列,Ex9CBL电磁式剩余电流动作断路器,Ex9CBL,6,0,0, -58117,系列,Ex9NLE EL剩余电流动作断路器,Ex9NLE,6,0,0, -58118,系列,Ex9PLE电子式剩余电流动作保护断路器,Ex9PLE,4,2,0, -58119,系列,Ex9BI系列交流隔离开关,Ex9BI,2,0,0, -58120,系列,Ex9I40系列隔离开关,Ex9I,3,0,0, -58121,系列,Ex9I125系列隔离开关,Ex9I,3,0,0, -58122,系列,Ex9IP系列光伏专用隔离开关,Ex9IP,2,0,0, -58123,系列,Ex9IR50系列旋转式隔离开关,Ex9IR,5,6,0, -58124,系列,Ex9BT2框缘式双极开关,Ex9BT2,2,0,0, -58125,系列,Ex9UE1+2 12.5电涌保护器,Ex9UE,5,0,0, -58126,系列,Ex9UE1+2 25电涌保护器,Ex9UE,9,2,0, -58127,系列,Ex9UE2电涌保护器,Ex9UE,9,4,0, -58128,系列,Ex9UE3电涌保护器,Ex9UE,9,0,0, -58129,系列,Ex9UEP电涌保护器,Ex9UE,9,6,0, -58130,系列,Ex9FP30H系列熔断器式隔离器,Ex9FP,2,0,0, -58131,系列,Ex9FP30系列光伏直流熔断器,Ex9FP30,2,0,0, -58132,系列,Ex9XE终端箱,Ex9X,5,14,0, -58133,系列,AL31/AXL31报警触头,,2,2,0, -58134,系列,AX31辅助触头,,2,0,0, -58136,系列,Ex9LE电子式剩余电流动作附件,Ex9LE,6,82,0, -58137,系列,LK-I锁扣装置,,1,0,0, -58138,系列,OVT31过压脱扣器,,2,0,0, -58139,系列,SHT31分励脱扣器,,3,0,0, -58140,系列,UVT31欠压脱扣器,,3,0,0, -58141,系列,ExMVB-T01-12系列户内真空断路器(固封),ExMVB,23,46,0, -58142,系列,ExMPD系列微机保护装置,ExMPD,2,0,0, -58143,系列,PMA600系列三相数显多功能表,PMA600,3,0,0, -58144,系列,PMA710系列在线式电能质量检测仪,PMA710,2,0,0, -58145,系列,PMR700系列智能电动机保护器,PMR700,7,0,0, -58146,系列,PMR710系列智能电动机保护器,PMR710,10,0,0, -58147,系列,ExMCM-AI01-12系列中压开关柜,ExMCM,4,0,0, -58148,系列,InModule智能型低压开关柜,InModule,1,0,0, -58149,系列,Ex9TC快速连接器,Ex9TC,4,12,0, -58150,系列,ExMRM SF6充气式环网柜,ExMRM SF6I01,4,0,0, -58154,系列,ASD16 DC直流框架隔离开关,ASD16,37,26,0, -58155,系列,ASD25 DC直流框架隔离开关,ASD,35,28,0, -58159,系列,M1PVS壳架15~100A塑壳断路器(光伏专用),M,70,74,0, -58160,系列,M1壳架15~150A塑壳断路器,M,94,320,0, -58161,系列,M2G壳架100~250A塑壳断路器(接地保护),M2G,16,3,0, -58162,系列,M2HV壳架60~250A塑壳断路器(800Vac),M2HV,39,33,0, -58163,系列,M2壳架100~250A塑壳断路器,M,94,238,0, -58164,系列,M3HV壳架250~400A塑壳断路器(800Vac),M3HV,38,31,0, -58165,系列,M3壳架225~400A塑壳断路器,M,75,227,0, -58166,系列,M4壳架400~600A塑壳断路器,M,85,141,0, -58167,系列,M5壳架600~800A塑壳断路器,M,77,168,0, -58168,系列,M6壳架800~1200A塑壳断路器,M,76,158,0, -58169,系列,MD3HV壳架200~400A塑壳断路器(1500Vdc),MD3HV,36,29,0, -58170,系列,9FP系列熔断器组(UL认证),9FP,4,1,0, -58171,系列,B1B系列UL489 SC小型断路器(UL认证),B1B,14,22,0, -58172,系列,B1E系列UL1077小型断路器(UL认证),B1E,9,45,0, -58173,系列,B1系列UL489小型断路器(UL认证),B1,17,135,0, -58174,系列,B2系列UL489小型断路器(UL认证),B2,3,2,0, -58175,系列,B4系列UL489&UL1077液压式断路器(UL认证),B4,6,50,0, -58176,系列,CBA系列汇流排(UL认证),CBA,12,3,0, -58177,系列,Ex9BP系列UL1077小型断路器(UL认证),Ex9BP,13,24,0, -58179,系列,F30系列熔断器座(UL认证),F,4,0,0, -58181,系列,U4系列浪涌保护器(UL认证),U4,4,59,0, -58182,系列,UL489附件(UL认证),,4,8,0, -58183,系列,UL1077附件(UL认证),UL1077,4,8,0, -58184,系列,Ex9CA系列安全接触器,Ex9CA,5,2,0, -58185,系列,Ex9CKT系列专用接触器,Ex9CKT,7,35,0, -58186,系列,Ex9C系列交流接触器(UL认证),Ex9C,48,752,0, -58187,系列,Ex9QR5系列软起动器,Ex9QR,4,0,0, -58188,系列,Ex9RCA系列安全继电器,Ex9RCA,4,13,0, -58189,系列,Ex9RE系列电子式过载继电器,Ex9RE,4,0,0, -58190,系列,Ex9R系列热过载继电器(UL认证),Ex9R,5,15,0, -58191,系列,Ex9S电动机保护用断路器(UL认证),Ex9S,23,18,0, -58213,系列,Ex9MV2口-PV/DC 1200V光伏专用直流塑料外壳式断路器,Ex9MV,16,23,0, -58245,系列,NXZBN-63系列自动转换开关(CB级),NXZBN,7,11,0, -58246,系列,NXZHBN-63系列自动转换开关(PC级),NXZHBN,5,3,0, -58247,系列,NXZHBN-125系列自动转换开关(PC级),NXZHBN,5,3,0, -58483,系列,VF-3000(VF-5000) 系列电磁阀,VF,5,2,0, -58484,系列,4H系列手动阀,4H,3,2,0, -58485,系列,CV系列真空发生器,CV,3,0,0, -58486,系列,AF系列空气过滤器,AF,3,20,0, -58492,系列,LKS系列电子排水器,LKS,2,0,0, -58493,系列,4R系列手动阀,4R,3,8,0, -58494,系列,FV系列脚踏阀,FV,1,0,0, -58495,系列,HV系列手转阀,HV,1,0,0, -58498,系列,QE系列快速排气阀,QE,1,0,0, -58499,系列,RE系列单向节流阀,RE,1,0,0, -58507,系列,HFK系列起动手指,,3,36,0, -58508,系列,HLS、HLSL系列双轴型精密滑台气缸(滚柱型),,10,38,0, -58509,系列,MGP系列三杆带导杆气缸,,3,10,0, -58510,系列,MI系列不锈钢迷你气缸,,8,212,0, -58511,系列,MU系列小型自由安装气缸,,6,42,0, -58512,系列,SC系列标准复动型气缸,SC,4,12,0, -58515,系列,CS1系列感应开关,CS1,1,4,0, -58516,系列,200M系列阀座,200M,1,0,0, -58517,系列,TCL、TCM系列三轴气缸,TC,7,52,0, -58527,系列,YB系列油雾器,YB,2,20,0, -58528,系列,YB/BL系列油雾器,,2,2,0, -58529,系列,AC/BC系列三联件,,3,4,0, -58530,系列,AF/BF系列过滤器,,3,4,0, -58531,系列,AFC/BFC系列二联件,,3,4,0, -58532,系列,AFR/BFR系列调压过滤器,,3,4,0, -58533,系列,AR/BR系列调压阀,,3,2,0, -58534,系列,AR系列调压阀,AR,2,28,0, -58535,系列,AW系列过滤带调压阀,AW,3,18,0, -58662,系列,RDSD HV系列旋转式直流隔离开关,RDS,14,44,0, -58665,系列,RDS1系列UL98交流隔离开关(UL认证),RDS,16,30,0, -58672,系列,Ex9IR50N系列UL旋转式隔离开关,Ex9IR,4,1,0, -58752,系列,TNSC系列接触稳压器,TNSC,1,0,0, -58808,系列,ExMRM-AIRI01-12系列环保气体环网柜,ExMRM-AIRI01,9,0,0, -58810,系列,Ex9IL系列信号灯,Ex9IL,3,2,0, -58811,系列,Ex9PB系列按钮,Ex9PB,14,184,0, -58813,系列,B1HC系列UL489小型断路器(UL认证),B1HC,15,32,0, -58827,系列,NXB-63M系列单磁式断路器,NXB,14,43,0, -58845,系列,Ex9ASD-DC系列直流隔离开关,Ex9ASD,71,50,0, -58854,系列,Ex9ASD系列交流隔离开关,Ex9ASD,63,76,0, -59128,系列,M1C系列塑壳断路器,M,37,25,0, -59133,系列,M2C系列塑壳断路器,M,37,25,0, -59149,系列,PMA901系列智能电力参数测量仪,PMA901,5,4,0, -59150,系列,Ex9TJ系列低压智能接插件,Ex9TJ,4,3,0, -59152,系列,Ex9TJV系列智能接插件,Ex9TJV,4,2,0, -59155,系列,Ex9TF11L系列智能配电终端,,1,0,0, -59158,系列,WTS-1系列无线温度传感器,,2,0,0, -59162,系列,NXZMN系列自动转换开关电器(CB级),NXZMN,8,27,0, -59163,系列,NXZHMN系列自动转换开关电器(PC级),NXZHMN,6,12,5,"NXZHMN-63/3A 10 = 2064 元 -NXZHMN-63/3DTK 63 = 2652 元 -NXZHMN-63/3DTK 10 = 2652 元 -NXZHMN-63/3DK 63 = 2428 元 -NXZHMN-63/3A 63 = 2064 元" -59241,系列,A系列框架断路器(UL认证),A,65,242,0, -59244,系列,A系列框架隔离开关(UL认证),ASD,65,223,0, -59255,系列,Ex9L电磁式剩余动作电流断路器,Ex9L,6,6,0, -59256,系列,Ex9IR-250隔离开关,Ex9IR,5,4,0, -59287,系列,Ex9MY系列塑料外壳式断路器,Ex9MY,28,139,0, -59288,系列,Ex9MLY系列剩余电流动作断路器,Ex9MLY,31,99,0, -59292,系列,Ex9CH系列家用接触器,Ex9CH,4,4,0, -59298,系列,Ex9BP80直流小型断路器,Ex9BP,18,32,0, -59299,系列,Ex9IR40系列旋转隔离开关,Ex9IR40,3,2,0, -59300,系列,Ex9IR40G系列旋转隔离开关,Ex9IR40G,3,4,0, -59301,系列,Ex9IRS50系列旋转隔离开关,Ex9IRS50,5,0,0, -59391,系列,NB5-63NFB系列小型断路器,NB5,17,34,0, -59393,系列,NKY2K系列开关电源,NKY2K,2,4,0, -59394,系列,NB5LE-63HFB系列剩余电流动作断路器,NB5LE,19,35,0, -59452,系列,Ex9C系列交流接触器(船岸专用),Ex9C,18,207,0, -59453,系列,Ex9R系列热过载继电器(船岸专用),Ex9R,4,15,0, -59455,系列,Ex9B125小型断路器(船岸专用),Ex9B,14,33,0, -59456,系列,Ex9BD125小型断路器(船岸专用),Ex9BD125,14,42,0, -59457,系列,Ex9BP直流小型断路器(船岸专用),Ex9BP,15,34,0, -59459,系列,Ex9BG/Ex9BHG交流小型断路器(船岸专用),Ex9B,16,34,0, -59462,系列,Ex9A系列空气断路器(船岸专用),Ex9A,69,89,0, -59464,系列,Ex9M系列塑料外壳式断路器(船岸专用),Ex9M,72,807,0, -59466,系列,Ex9MD系列直流塑料外壳式断路器(船岸专用),Ex9MD,6,12,0, -59468,系列,NM5NE高电压(HV)系列塑壳断路器,NM5NE,29,71,0, -59469,系列,Ex9MHV高电压系列塑料外壳式断路器(船岸专用),Ex9M,18,34,0, -59621,系列,NJBK8系列电动机保护器,NJBK8,3,4,0, -59622,系列,NJXB1系列低压线路保护器,NJXB1,3,4,0, -59624,系列,NXB-63G系列塑料外壳式断路器,NXB,13,32,0, -59645,系列,DTSYU666系列三相导轨安装式电能表(昆仑),DTSYU666,5,6,0, -59705,系列,OUVR-2G系列自恢复式过欠压保护器,OUVR,5,11,0, -59849,系列,FQK浮球液位开关,FQK,3,0,0, -59905,系列,NCZ2NE系列直流接触器,NCZ2NE,5,9,0, -59906,系列,EPEC300系列电力环境控制器,EPEC300,2,4,0, -59907,系列,EPEC400系列电力环境控制器,EPEC400,1,0,0, -59988,系列,L1H系列UL1053剩余电流动作断路器(UL认证),L1,4,2,0, -60020,系列,NM5NEDC高电压(HV)系列直流塑壳断路器,NM5NEDC,29,47,0, -60021,系列,NH5NE(DC)-HV系列新能源专供隔离开关,NH5NE,13,20,0, -60022,系列,NHB5NE-40GX系列旋转隔离开关,NHB5NE,6,12,0, -60023,系列,NHB5NE-50X系列旋转式隔离开关,NHB5NE,7,3,0, -60024,系列,NHB5NE-S50X系列旋转式隔离开关,NHB5NE-S,8,3,0, -60025,系列,NB5NEDC-80HU系列塑料外壳式断路器,NB5NEDC,14,48,0, -60026,系列,NB5NEDC-125HU系列塑料外壳式断路器,NB5NEDC,14,26,0, -60027,系列,NC1NE系列交流接触器,NC1NE,20,59,0, -60028,系列,NR2NE系列热过载继电器,NR2NE,3,9,0, -60042,系列,BH-0.66系列低压电流互感器(0.5S级实心),BH,4,0,0, -60059,系列,ExATSNV系列自动转换开关电器(PC级),ExATSNV,4,5,0, -60060,系列,NJBK5系列电动机保护器,NJBK5,2,4,0, -60061,系列,NJR5-D系列软起动器,NJR5,3,0,0, -60062,系列,NXLH-1系列III型立式电流互感器,NXLH,5,38,0, -60063,系列,NJXB5系列低压线路保护器,NJXB5,2,4,0, -60064,系列,Ex9JX系列电磁继电器,Ex9JX,4,6,0, -60066,系列,NRZNE系列直流熔断器,NRZNE,6,2,0, -60068,系列,NXQ系列电磁起动器,NXQ,5,9,0, -60069,系列,NAFD2000型故障电弧探测器,NAFD2000,1,0,0, -60070,系列,WHR/G100系列智能温湿度控制器,WH,5,16,0, -60071,系列,NTD500/NTD300型测温主机,NTD,2,2,0, -60072,系列,NS1000系列无线测温传感器,NS1000,3,3,0, -60157,系列,NKY2G系列开关电源,NKY2G,2,4,0, -60216,系列,NXC-CS系列交流接触器,NXC,24,130,0, -60226,系列,NXBLE-63GYH系列剩余电流动作断路器,NXBLE,15,44,0, -60227,系列,NXBLE-63YHE系列剩余电流动作断路器,NXBLE,16,41,0, -60228,系列,NXTCW系列防水连接器,NXTCW,4,5,0, -60229,系列,NP2(XM)系列高防护型按钮,NP2,6,8,0, -60330,系列,NA1P系列万能式断路器,NA1P,7,25,0, -60398,系列,NXJYB系列电压保护继电器,NXJYB,1,9,0, -60399,系列,NXTCP系列电源连接器,NXTCP,4,0,0, -60400,系列,PD666高可靠系列数显多功能表,P,8,0,0, -60402,系列,WH系列温湿度控制器,WH,6,8,0, -60451,系列,NXC-XMG系列交流接触器,NXC,5,0,0, -60463,系列,NWC8系列自愈式低电压并联电容器(干式),NWC8,3,12,0,