233 lines
11 KiB
C#
233 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Forms;
|
|
|
|
namespace 成套报价软件
|
|
{
|
|
/// <summary>
|
|
/// 新建项目 的交互逻辑(事件处理)。
|
|
/// UI 布局定义见 新建项目.ui.cs。
|
|
/// 本窗体作为 MainForm 的对话框使用,故不含独立的 Main 入口点。
|
|
/// </summary>
|
|
public partial class 新建项目 : Form
|
|
{
|
|
/// <summary>项目数据库文件相对路径(与 MainForm 保持一致)。</summary>
|
|
private readonly string _dbPath;
|
|
|
|
/// <summary>项目数据库表名。</summary>
|
|
private readonly string _tableName;
|
|
|
|
/// <summary>构造函数:初始化 UI 并绑定事件。</summary>
|
|
public 新建项目()
|
|
: this(null, null)
|
|
{
|
|
// 无参构造保留,以便独立测试时仍可创建。
|
|
}
|
|
|
|
/// <summary>
|
|
/// 带数据库路径的构造函数(主窗口调用此版本)。
|
|
/// 传入数据库后,对话框会在打开时自动填入“项目日期”和“项目编号”。
|
|
/// </summary>
|
|
/// <param name="dbPath">SQLite 数据库绝对路径;为 null/不存在则不自动生成编号。</param>
|
|
/// <param name="tableName">项目数据表名。</param>
|
|
public 新建项目(string dbPath, string tableName)
|
|
{
|
|
InitializeComponent();
|
|
|
|
_dbPath = dbPath;
|
|
_tableName = tableName;
|
|
|
|
// 预置价格格式化下拉框选项(小数位 + 取整方式)
|
|
InitPriceFormatCombos();
|
|
|
|
// 加载完成后(已显示)自动填充编号和日期。
|
|
// 用 Load 事件确保控件都已创建好。
|
|
this.Load += 新建项目_Load;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 预置“单台价格/项目总价/单台取整/项目取整”4 个下拉框的“候选选项列表”。
|
|
/// 注意:只填充 Items,不改动 SelectedIndex/Text —— 默认选中项由设计器 XML 里的
|
|
/// Text 属性决定,不要在代码里覆盖。
|
|
///
|
|
/// 控件布局对应(UI 里 label 文字决定语义):
|
|
/// 单台价格行 → cmb单台价格(单台层小数位)
|
|
/// 项目总价行 → cmb项目总价(项目层小数位)
|
|
/// 单台取整行 → comboBox1 (单台层取整方式)
|
|
/// 项目取整行 → comboBox2 (项目层取整方式)
|
|
/// </summary>
|
|
private void InitPriceFormatCombos()
|
|
{
|
|
// 小数位选项:cmb单台价格(单台层) + cmb项目总价(项目层)
|
|
this.cmb单台价格.Items.Clear();
|
|
this.cmb单台价格.Items.AddRange(价格格式化.小数位选项);
|
|
|
|
this.cmb项目总价.Items.Clear();
|
|
this.cmb项目总价.Items.AddRange(价格格式化.小数位选项);
|
|
|
|
// 取整方式选项:comboBox1(单台层) + comboBox2(项目层)
|
|
this.comboBox1.Items.Clear();
|
|
this.comboBox1.Items.AddRange(价格格式化.取整方式选项);
|
|
|
|
this.comboBox2.Items.Clear();
|
|
this.comboBox2.Items.AddRange(价格格式化.取整方式选项);
|
|
}
|
|
|
|
/// <summary>对话框首次加载:自动填项目日期 + 项目编号。</summary>
|
|
private void 新建项目_Load(object sender, EventArgs e)
|
|
{
|
|
FillAutoFields();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 自动填充“项目日期”为当天,并按 yyyyMMdd+3位序号
|
|
/// 规则生成“项目编号”(序号=数据库当天最大序号+1)。
|
|
/// 同时把 txt项目编号 设为只读,用户不能修改。
|
|
/// </summary>
|
|
private void FillAutoFields()
|
|
{
|
|
// 1) 项目日期 = 当天 yyyy-MM-dd
|
|
DateTime today = DateTime.Today;
|
|
this.txt项目日期.Text = today.ToString("yyyy-MM-dd");
|
|
|
|
// 2) 项目编号 = yyyyMMdd + 3 位序号(001 起,查库取当天最大序号 +1)
|
|
string datePart = today.ToString("yyyyMMdd");
|
|
int seq = GetNextSeqForDate(datePart); // 找不到就返回 1
|
|
this.txt项目编号.Text = datePart + seq.ToString("000");
|
|
|
|
// 3) 项目编号只读,用户不能改
|
|
this.txt项目编号.ReadOnly = true;
|
|
this.txt项目编号.TabStop = false;
|
|
// 给只读框一个浅灰背景,视觉上提示“不可编辑”
|
|
this.txt项目编号.BackColor = System.Drawing.SystemColors.Control;
|
|
|
|
// 4) 成套厂信息(名称/地址/联系人/联系电话)从「企业信息」配置自动带入,
|
|
// 用户可在对话框中临时改写;改写后的值随项目一起保存到项目库。
|
|
// 若企业信息未配置,则留空由用户手填。
|
|
try
|
|
{
|
|
var qiye = 企业信息.LoadSettings();
|
|
if (qiye != null)
|
|
{
|
|
// 仅在文本框为空时填入,避免覆盖已有内容(理论上 Load 阶段都是空)
|
|
if (string.IsNullOrEmpty(this.txt成套厂名称.Text))
|
|
this.txt成套厂名称.Text = qiye["企业名称"];
|
|
if (string.IsNullOrEmpty(this.txt成套厂地址.Text))
|
|
this.txt成套厂地址.Text = qiye["地址"];
|
|
if (string.IsNullOrEmpty(this.txt成套厂联系人.Text))
|
|
this.txt成套厂联系人.Text = qiye["联系人"];
|
|
if (string.IsNullOrEmpty(this.txt成套厂联系电话.Text))
|
|
this.txt成套厂联系电话.Text = qiye["电话"];
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 读不到企业信息不阻断新建项目流程
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 在数据库中查找“指定日期前缀(yyyyMMdd)”的最大序号,
|
|
/// 返回“最大序号 + 1”;若无数据或出错则返回 1。
|
|
/// 例:库中已有 20260721001、20260721005,返回 6。
|
|
/// </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();
|
|
|
|
// 取“项目编号”这一列中、前 8 位等于 datePart 的最大值。
|
|
// SUBSTR 兼容 SQLite,从 1 开始计数,截取前 8 位。
|
|
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;
|
|
// ExecuteScalar 返回的可能是 long/int
|
|
if (int.TryParse(result.ToString(), out maxSeq))
|
|
{
|
|
return maxSeq + 1;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 查询失败时不阻断流程,退化为从 001 开始
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 收集对话框中已填写的字段,以“去掉 txt 前缀的字段名”为键返回。
|
|
/// 仅包含实际存在文本框且文本非空的字段。
|
|
/// 调用方只需按列名(Name/DataPropertyName)匹配,匹配不上的字段自动忽略。
|
|
/// </summary>
|
|
public Dictionary<string, string> GetInputValues()
|
|
{
|
|
var values = new Dictionary<string, string>();
|
|
|
|
// (字段名, 对应文本框)。字段名与MainForm advancedDataGridView6 列名一致。
|
|
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);
|
|
|
|
// 成套厂信息(4 个字段):新建项目时从企业信息带入,用户可改写;
|
|
// 写入项目库,供项目窗口后续调用。
|
|
AddIfNotEmpty(values, "成套厂名称", txt成套厂名称.Text);
|
|
AddIfNotEmpty(values, "成套厂地址", txt成套厂地址.Text);
|
|
AddIfNotEmpty(values, "成套厂联系人", txt成套厂联系人.Text);
|
|
AddIfNotEmpty(values, "成套厂联系电话", txt成套厂联系电话.Text);
|
|
|
|
// 价格显示格式化(4 个字段):控制报价页价格单元格的“小数位 + 取整方式”。
|
|
// 仅影响显示,不改变原始计算值;随项目一起保存到「项目信息」表。
|
|
// 控件对应:cmb单台价格=单台小数位 / cmb项目总价=项目小数位 /
|
|
// comboBox1=单台取整方式 / comboBox2=项目取整方式
|
|
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();
|
|
}
|
|
}
|
|
|
|
// 提示:在设计器的属性窗口(事件页)双击事件名,
|
|
// 会自动在此生成事件处理方法骨架。
|
|
|
|
}
|
|
}
|