253 lines
12 KiB
C#
253 lines
12 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>当前要修改的项目编号(主键)。</summary>
|
|
private readonly string _projectId;
|
|
|
|
/// <summary>
|
|
/// 默认构造函数(无参保留,以便独立测试时仍可创建)。
|
|
/// 不做任何自动填充。
|
|
/// </summary>
|
|
public 修改项目()
|
|
{
|
|
InitializeComponent();
|
|
InitPriceFormatCombos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 带数据库路径与现有项目数据的构造函数(主窗口调用此版本)。
|
|
/// 传入后对话框在 Load 时会把现有字段值填到各输入框里。
|
|
/// </summary>
|
|
/// <param name="dbPath">SQLite 数据库绝对路径。</param>
|
|
/// <param name="tableName">项目数据表名。</param>
|
|
/// <param name="projectId">要修改的项目编号(用于 WHERE 条件)。</param>
|
|
/// <param name="existing">现有字段值(键=列名,值=字符串);为空则从数据库读取。</param>
|
|
public 修改项目(string dbPath, string tableName,
|
|
string projectId, Dictionary<string, string> existing)
|
|
{
|
|
InitializeComponent();
|
|
InitPriceFormatCombos();
|
|
|
|
_dbPath = dbPath;
|
|
_tableName = tableName;
|
|
_projectId = projectId;
|
|
_existingValues = existing;
|
|
|
|
// 加载完成后(已显示)填充已有字段。
|
|
this.Load += 修改项目_Load;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 预置“单台价格/项目总价/单台取整/项目取整”4 个下拉框的“候选选项列表”。
|
|
/// 注意:只填充 Items,不改动 SelectedIndex/Text —— 默认值由设计器 XML 决定,
|
|
/// 加载已有项目时由 FillFields 根据数据库内容覆盖。
|
|
///
|
|
/// 控件布局对应(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(价格格式化.取整方式选项);
|
|
}
|
|
|
|
private readonly Dictionary<string, string> _existingValues;
|
|
|
|
/// <summary>对话框首次加载:把已有项目数据填入各输入框。</summary>
|
|
private void 修改项目_Load(object sender, EventArgs e)
|
|
{
|
|
// 若未传入 existing,则按 projectId 从数据库读取
|
|
Dictionary<string, string> data = _existingValues;
|
|
if (data == null || data.Count == 0)
|
|
{
|
|
data = LoadProjectFromDatabase();
|
|
}
|
|
|
|
FillFields(data);
|
|
|
|
// 项目编号为主键,不允许修改
|
|
this.txt项目编号.ReadOnly = true;
|
|
this.txt项目编号.TabStop = false;
|
|
this.txt项目编号.BackColor = System.Drawing.SystemColors.Control;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从数据库读取当前 projectId 的项目记录(单行)。
|
|
/// 找不到则返回空字典。
|
|
/// </summary>
|
|
private Dictionary<string, string> LoadProjectFromDatabase()
|
|
{
|
|
var dict = new Dictionary<string, string>();
|
|
if (string.IsNullOrEmpty(_dbPath) ||
|
|
string.IsNullOrEmpty(_tableName) ||
|
|
string.IsNullOrEmpty(_projectId) ||
|
|
!System.IO.File.Exists(_dbPath))
|
|
{
|
|
return dict;
|
|
}
|
|
|
|
try
|
|
{
|
|
string connStr = "Data Source=" + _dbPath + ";Version=3;";
|
|
using (var conn = new System.Data.SQLite.SQLiteConnection(connStr))
|
|
{
|
|
conn.Open();
|
|
string sql = "SELECT * FROM " + _tableName +
|
|
" 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())
|
|
{
|
|
for (int i = 0; i < reader.FieldCount; i++)
|
|
{
|
|
string col = reader.GetName(i);
|
|
object v = reader.IsDBNull(i) ? "" : reader.GetValue(i);
|
|
dict[col] = v == null ? "" : v.ToString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 读取失败不阻断 UI,只是字段为空
|
|
}
|
|
return dict;
|
|
}
|
|
|
|
/// <summary>把字段字典按列名填到对应的输入框。</summary>
|
|
private void FillFields(Dictionary<string, string> data)
|
|
{
|
|
if (data == null || data.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
this.txt项目编号.Text = GetOrNull(data, "项目编号");
|
|
this.txt项目日期.Text = GetOrNull(data, "项目日期");
|
|
this.txt项目名称.Text = GetOrNull(data, "项目名称");
|
|
this.txt客户名称.Text = GetOrNull(data, "客户名称");
|
|
this.txt客户地址.Text = GetOrNull(data, "客户地址");
|
|
this.txt联系人.Text = GetOrNull(data, "联系人");
|
|
this.txt联系电话.Text = GetOrNull(data, "联系电话");
|
|
this.txt成套厂名称.Text = GetOrNull(data, "成套厂名称");
|
|
this.txt成套厂地址.Text = GetOrNull(data, "成套厂地址");
|
|
this.txt成套厂联系人.Text = GetOrNull(data, "成套厂联系人");
|
|
this.txt成套厂联系电话.Text = GetOrNull(data, "成套厂联系电话");
|
|
this.txt备注.Text = GetOrNull(data, "备注");
|
|
|
|
// 下拉框:只有在数据库里有值时才覆盖,避免清空设计器默认项
|
|
string v;
|
|
if ((v = GetOrNull(data, "报出方式")) != null) this.cmb报出方式.Text = v;
|
|
if ((v = GetOrNull(data, "箱柜模板")) != null) this.cmb箱柜模板.Text = v;
|
|
|
|
// 价格显示格式化(4 个字段):从「项目信息」表读出后回填到对应控件
|
|
// 控件对应:cmb单台价格=单台小数位 / cmb项目总价=项目小数位 /
|
|
// comboBox1=单台取整方式 / comboBox2=项目取整方式
|
|
if ((v = GetOrNull(data, "单台小数位")) != null)
|
|
{
|
|
this.cmb单台价格.Text = v; // 单台层小数位
|
|
if (this.cmb单台价格.SelectedIndex < 0) this.cmb单台价格.Text = "保留整数";
|
|
}
|
|
if ((v = GetOrNull(data, "项目小数位")) != null)
|
|
{
|
|
this.cmb项目总价.Text = v; // 项目层小数位
|
|
if (this.cmb项目总价.SelectedIndex < 0) this.cmb项目总价.Text = "保留整数";
|
|
}
|
|
if ((v = GetOrNull(data, "单台取整方式")) != null)
|
|
{
|
|
this.comboBox1.Text = v; // 单台层取整方式
|
|
if (this.comboBox1.SelectedIndex < 0) this.comboBox1.Text = "四舍五入";
|
|
}
|
|
if ((v = GetOrNull(data, "项目取整方式")) != null)
|
|
{
|
|
this.comboBox2.Text = v; // 项目层取整方式
|
|
if (this.comboBox2.SelectedIndex < 0) this.comboBox2.Text = "四舍五入";
|
|
}
|
|
}
|
|
|
|
private static string GetOrNull(Dictionary<string, string> dict, string key)
|
|
{
|
|
string v;
|
|
return dict.TryGetValue(key, out v) ? v : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 收集对话框中已填写的字段,以"字段名"为键返回。
|
|
/// 返回的字典包含所有可能存在的字段(含空值,供 UPDATE 用)。
|
|
/// 调用方按列名匹配。
|
|
/// </summary>
|
|
public Dictionary<string, string> GetInputValues()
|
|
{
|
|
var values = new Dictionary<string, string>();
|
|
|
|
// 以下字段会进入数据库 UPDATE;字段名与MainForm advancedDataGridView6 列名一致。
|
|
values["项目名称"] = Safe(this.txt项目名称.Text);
|
|
values["客户名称"] = Safe(this.txt客户名称.Text);
|
|
values["客户地址"] = Safe(this.txt客户地址.Text);
|
|
values["联系人"] = Safe(this.txt联系人.Text);
|
|
values["联系电话"] = Safe(this.txt联系电话.Text);
|
|
values["项目日期"] = Safe(this.txt项目日期.Text);
|
|
values["备注"] = Safe(this.txt备注.Text);
|
|
|
|
// 成套厂信息(4 个字段):新建项目时从企业信息带入,这里随项目一起 UPDATE 回写
|
|
values["成套厂名称"] = Safe(this.txt成套厂名称.Text);
|
|
values["成套厂地址"] = Safe(this.txt成套厂地址.Text);
|
|
values["成套厂联系人"] = Safe(this.txt成套厂联系人.Text);
|
|
values["成套厂联系电话"] = Safe(this.txt成套厂联系电话.Text);
|
|
|
|
// 价格显示格式化(4 个字段):控制报价页价格单元格的“小数位 + 取整方式”
|
|
// 控件对应:cmb单台价格=单台小数位 / cmb项目总价=项目小数位 /
|
|
// comboBox1=单台取整方式 / comboBox2=项目取整方式
|
|
values["单台小数位"] = (this.cmb单台价格.SelectedItem ?? this.cmb单台价格.Text ?? "保留整数").ToString();
|
|
values["项目小数位"] = (this.cmb项目总价.SelectedItem ?? this.cmb项目总价.Text ?? "保留整数").ToString();
|
|
values["单台取整方式"] = (this.comboBox1.SelectedItem ?? this.comboBox1.Text ?? "四舍五入").ToString();
|
|
values["项目取整方式"] = (this.comboBox2.SelectedItem ?? this.comboBox2.Text ?? "四舍五入").ToString();
|
|
|
|
return values;
|
|
}
|
|
|
|
private static string Safe(string s)
|
|
{
|
|
return s == null ? "" : s.Trim();
|
|
}
|
|
|
|
// 提示:在设计器的属性窗口(事件页)双击事件名,
|
|
// 会自动在此生成事件处理方法骨架。
|
|
|
|
}
|
|
}
|