退役独立扒图程序与试验工具,消除重复源码:删 pdfbt 项目/cadbt C#部分(保留 node+CAD-Viewer 网页引擎,主程序扒图依赖)/ghj/yjktool;打包链同步(make_package 去独立exe/setup.iss 删pdfbt/更新包不再带pdfbt.exe);护栏扩到全部4对双胞胎文件;README 结构更新;编译+组装验证通过

This commit is contained in:
dqb-dev
2026-10-02 02:10:32 +08:00
parent e7f25a8ceb
commit 193035acfb
74 changed files with 34 additions and 26829 deletions
-20
View File
@@ -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
-213
View File
@@ -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();
/// <summary>网页 CAD 是否已挂载(WebView2 已附加)。</summary>
public static bool IsViewerReady
{
get { return _wv != null && _wv.CoreWebView2 != null; }
}
/// <summary>网页 CAD 中实体被删除(句柄十六进制字符串)。</summary>
public static event Action<string> EntityErased;
/// <summary>网页 CAD 扒图完成一批(图号/箱号/元件)。</summary>
public static event Action<MyApp.PaMode, List<MyApp.PaTextResult>> PaPicked;
/// <summary>用户按 ESC 退出网页扒图连续模式。</summary>
public static event Action PaExited;
/// <summary>用户按 F1(焦点在网页或宿主时都触发)——元件两两合并。</summary>
public static event Action F1Requested;
/// <summary>用户按 F2——元件三个一组合并。</summary>
public static event Action F2Requested;
/// <summary>用户按 F3——元件四个一组合并。</summary>
public static event Action F3Requested;
/// <summary>触发 F1 请求(消息过滤器等宿主侧来源调用)。</summary>
public static void RaiseF1()
{
if (F1Requested != null) F1Requested();
}
/// <summary>触发 F2 请求(消息过滤器等宿主侧来源调用)。</summary>
public static void RaiseF2()
{
if (F2Requested != null) F2Requested();
}
/// <summary>触发 F3 请求(消息过滤器等宿主侧来源调用)。</summary>
public static void RaiseF3()
{
if (F3Requested != null) F3Requested();
}
/// <summary>把 WebView2 挂到桥上(在控件初始化完成后调用一次)。</summary>
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<Dictionary<string, object>>(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<MyApp.PaTextResult>();
var arr = msg["results"] as System.Collections.ArrayList;
if (arr != null)
{
foreach (Dictionary<string, object> 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 { }
}
/// <summary>
/// 发送扒图命令。接受原 CAD 命令名(CADPATU/CADPAXH/CADPAYJ/CADPACL)
/// 或网页命令名(patu/paxh/payj)。
/// </summary>
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 });
}
/// <summary>缩放居中到指定 Handle 的实体并高亮(点击表格行定位框)。</summary>
public static void ZoomToFrameHandle(string handle)
{
if (string.IsNullOrWhiteSpace(handle)) return;
Post(new { type = "zoomToHandle", handle = handle });
}
/// <summary>批量删除指定 Handle 的实体(删表格行联动删框)。</summary>
public static void DeleteFramesByHandles(IEnumerable<string> handles)
{
if (handles == null) return;
var list = new List<string>();
foreach (string h in handles)
if (!string.IsNullOrWhiteSpace(h)) list.Add(h);
if (list.Count == 0) return;
Post(new { type = "deleteHandles", handles = list });
}
/// <summary>
/// 合并蒙版:保留 keep 句柄的蒙版并扩大到所有 removes 蒙版的并集,
/// 被合并行的蒙版从网页 CAD 移除(元件合并时蒙版同步合并)。
/// </summary>
public static void MergeMasks(string keep, System.Collections.Generic.IEnumerable<string> removes)
{
if (string.IsNullOrWhiteSpace(keep)) return;
var list = new List<string>();
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 });
}
/// <summary>清除网页 CAD 中的所有高亮。</summary>
public static void ClearHighlight()
{
Post(new { type = "clearHighlight" });
}
}
}
-27
View File
@@ -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
}
}
-187
View File
@@ -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
{
/// <summary>停靠窗口:网页 CAD 查看器(DockState.Document)。</summary>
public partial class CadViewerWindow : WeifenLuo.WinFormsUI.Docking.DockContent
{
private WebView2 _webView;
private Label _hint;
/// <summary>静态服务进程句柄(退出时杀进程树)。</summary>
private static Process _serverProcess;
public CadViewerWindow()
{
InitializeComponent();
Text = "CAD 查看器";
TabText = "CAD 查看器";
FormClosed += (s, e) => 停止网页服务();
LoadViewer();
}
/// <summary>CAD 网页服务端口(与 server.cjs 一致)。</summary>
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 运行时。");
}
}
/// <summary>启动 CAD 网页静态服务(端口已通=复用;不通=node server.cjs 后台拉起)。</summary>
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); }
}
/// <summary>快速探测本机端口。</summary>
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;
}
/// <summary>退出清理:杀 node 静态服务进程树(taskkill /T 覆盖可能的子进程)。</summary>
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); }
}
/// <summary>简单诊断日志(logs\cad服务.log)。</summary>
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();
}
}
}
-27
View File
@@ -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
}
}
-26
View File
@@ -1,26 +0,0 @@
// ============================================================
// 停靠窗口:报价插件工具栏(左侧)
// 把 cadcj 的 Form3 报价界面作为子控件嵌入(TopLevel=false)。
// ============================================================
using System.Windows.Forms;
namespace cadbt.DockWindows
{
/// <summary>停靠窗口:报价插件工具栏(DockState.DockLeft)。</summary>
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();
}
}
}
-69
View File
@@ -1,69 +0,0 @@
namespace cadbt
{
partial class MainForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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;
}
}
-28
View File
@@ -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);
}
}
}
-59
View File
@@ -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
{
/// <summary>
/// Description of MainForm.
/// </summary>
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();
/// <summary>把 F1 按键(0x70)转成 CadBridge.F1Requested,不拦截按键本身。</summary>
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;
}
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-29
View File
@@ -1,29 +0,0 @@
// ============================================================
// 扒图数据类型(与原 cadcj 插件 / 网页端 cadbridge.ts 保持一致)
// ============================================================
using System.Collections.Generic;
namespace MyApp
{
/// <summary>
/// 扒数据模式:图号/箱号/元件
/// </summary>
public enum PaMode
{
Tuhao, // 扒图号
Xianghao, // 扒箱号
Yuanjian // 扒元件
}
/// <summary>
/// 扒图结果:一条文本 + 它对应的彩色框的 Handle(句柄字符串)
/// 用于关联表格数据行与网页 CAD 框实体,实现点击行定位、删除行删框。
/// ★ TextHandle:源文本实体自身的 Handle,用于判断"是否同一个文本"。
/// </summary>
public class PaTextResult
{
public string Text;
public string FrameHandle;
public string TextHandle = "";
}
}
-132
View File
@@ -1,132 +0,0 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace MyApp
{
/// <summary>
/// 新建项目 窗口(简化版,不依赖企业信息)。
/// UI 布局见 新建项目.ui.cs,本文件只含交互逻辑。
/// </summary>
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) { }
/// <summary>带数据库路径的构造函数(用于自动生成项目编号)。</summary>
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();
}
/// <summary>自动填充项目日期(当天)和项目编号(yyyyMMdd+3位序号)。</summary>
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;
}
/// <summary>查数据库当天最大序号+1,失败返回1。</summary>
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; }
}
/// <summary>收集对话框字段,以列名为键返回(供 Form3 写入数据库)。</summary>
public Dictionary<string, string> GetInputValues()
{
var values = new Dictionary<string, string>();
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<string, string> dict, string key, string value)
{
if (!string.IsNullOrWhiteSpace(value)) dict[key] = value.Trim();
}
}
}
File diff suppressed because it is too large Load Diff
-43
View File
@@ -1,43 +0,0 @@
/*
* 由SharpDevelop创建。
* 用户: 099978
* 日期: 2026-09-04
* 时间: 12:24
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
using System.Windows.Forms;
namespace cadbt
{
/// <summary>
/// Class with program entry point.
/// </summary>
internal sealed class Program
{
/// <summary>
/// Program entry point.
/// </summary>
[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);
}
}
}
}
-31
View File
@@ -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.*")]
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>
-147
View File
@@ -1,147 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{0A91D57B-B279-4672-9440-78088D022EB1}</ProjectGuid>
<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>WinExe</OutputType>
<RootNamespace>cadbt</RootNamespace>
<AssemblyName>cadbt</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<PlatformTarget>x86</PlatformTarget>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<Prefer32Bit>True</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="Smart.CustomComponents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba044a4aa43e0dc4">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\Smart.CustomComponents.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="WeifenLuo.WinFormsUI.Docking">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SQLite">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Data.SQLite.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="log4net">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Resources.Extensions">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Resources.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Memory">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Memory.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Numerics.Vectors">
<HintPath>C:\Program Files (x86)\SharpDevelop\5.2\bin\System.Numerics.Vectors.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AdvancedDataGridView">
<HintPath>libs\AdvancedDataGridView.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.WebView2.Core">
<HintPath>libs\webview2\Microsoft.Web.WebView2.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.WebView2.WinForms">
<HintPath>libs\webview2\Microsoft.Web.WebView2.WinForms.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MainForm.cs" />
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="MainForm.DockWindows.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="CadBridge.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Plugin\Form3.cs" />
<Compile Include="Plugin\Form3.ui.cs">
<DependentUpon>Form3.cs</DependentUpon>
</Compile>
<Compile Include="Plugin\PaTypes.cs" />
<Compile Include="Plugin\新建项目.cs" />
<Compile Include="Plugin\新建项目.ui.cs">
<DependentUpon>新建项目.cs</DependentUpon>
</Compile>
<Compile Include="DockWindows\CadViewerWindow.cs" />
<Compile Include="DockWindows\CadViewerWindow.Designer.cs">
<DependentUpon>CadViewerWindow.cs</DependentUpon>
</Compile>
<Compile Include="DockWindows\QuoteWindow.cs" />
<Compile Include="DockWindows\QuoteWindow.Designer.cs">
<DependentUpon>QuoteWindow.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="app.manifest" />
</ItemGroup>
<ItemGroup>
<Content Include="libs\webview2\WebView2Loader.dll">
<Link>WebView2Loader.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Binary file not shown.
Binary file not shown.
Binary file not shown.