refactor: 更新 README 和代码以支持默认模板导出功能

- README.md: 修改数据源描述,明确默认模板随程序发布,并更新操作流程中的按钮名称。
- ExcelService.cs: 重命名模板生成方法为 CopyTemplate,简化模板导出逻辑。
- MainForm.cs: 更新按钮文本和事件处理,改为导出默认模板。
- Config.cs 和 config.json: 添加 OriginalEstimateRef 字段以支持新功能。
- 删除不再使用的 build_template.ps1 脚本及相关模板部件。
This commit is contained in:
chenshoulin
2026-11-01 12:14:10 +08:00
parent 49d29133cc
commit c2d121d185
14 changed files with 74 additions and 292 deletions
+21 -31
View File
@@ -144,10 +144,10 @@ namespace TfsExcelImporter
_btnBrowse.Click += (s, e) => BrowseExcel();
grpImport.Controls.Add(_btnBrowse);
_btnTemplate.Text = "生成Excel模板";
_btnTemplate.Text = "导出Excel模板";
_btnTemplate.Location = new Point(760, 58); _btnTemplate.Size = new Size(110, 29);
_btnTemplate.Anchor = AnchorStyles.Top | AnchorStyles.Right;
_btnTemplate.Click += (s, e) => GenerateTemplate();
_btnTemplate.Click += (s, e) => ExportTemplate();
grpImport.Controls.Add(_btnTemplate);
_chkSkip.Text = "跳过已存在标题";
@@ -155,7 +155,7 @@ namespace TfsExcelImporter
_chkSkip.Anchor = AnchorStyles.Top | AnchorStyles.Right;
grpImport.Controls.Add(_chkSkip);
_chkBypass.Text = "bypassRules(可写系统日期)";
_chkBypass.Text = "bypassRules(绕过字段规则)";
_chkBypass.Location = new Point(886, 60); _chkBypass.Size = new Size(150, 24);
_chkBypass.Anchor = AnchorStyles.Top | AnchorStyles.Right;
grpImport.Controls.Add(_chkBypass);
@@ -357,25 +357,25 @@ namespace TfsExcelImporter
}
}
private void GenerateTemplate()
private void ExportTemplate()
{
using (var dlg = new SaveFileDialog())
{
dlg.Filter = "Excel 文件 (*.xlsx)|*.xlsx";
dlg.FileName = "TFS导入模板.xlsx";
dlg.Title = "保存 Excel 模板";
dlg.FileName = ExcelService.TemplateFileName;
dlg.Title = "导出默认模板";
if (dlg.ShowDialog(this) != DialogResult.OK) return;
try
{
ExcelService.GenerateTemplate(dlg.FileName);
Log("模板已生成: " + dlg.FileName);
MessageBox.Show(this, "模板已生成:\n" + dlg.FileName, "完成",
ExcelService.CopyTemplate(dlg.FileName);
Log("模板已导出: " + dlg.FileName);
MessageBox.Show(this, "模板已导出:\n" + dlg.FileName, "完成",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
Log("生成模板失败: " + ex.Message);
MessageBox.Show(this, "生成模板失败:\n" + ex.Message, "错误",
Log("导出模板失败: " + ex.Message);
MessageBox.Show(this, "导出模板失败:\n" + ex.Message, "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
@@ -402,9 +402,8 @@ namespace TfsExcelImporter
财务项目 = r.FinancialProject,
r.Completed,
LogDate = r.LogDate,
Created = r.CreatedDate,
Closed = r.ClosedDate,
r.Notes
r.PbiId,
r.Description
}).ToList();
_lblStatus.Text = $"已读取 {_rows.Count} 行";
Log($"读取 {path} 共 {_rows.Count} 行");
@@ -563,13 +562,12 @@ namespace TfsExcelImporter
var assignedRef = "System.AssignedTo";
var iterationRef = "System.IterationPath";
var areaRef = "System.AreaPath";
var createdRef = "System.CreatedDate";
var closedRef = "Microsoft.VSTS.Common.ClosedDate";
var finRef = TfsClient.ResolveRef(fieldMap, "FinancialProject", _cfg.FinancialProjectRef);
var compRef = TfsClient.ResolveRef(fieldMap, "Completed", _cfg.CompletedRef);
var logRef = TfsClient.ResolveRef(fieldMap, "LogDate", _cfg.LogDateRef);
Log($"字段: FinancialProject->{finRef ?? "(未找到)"} Completed->{compRef ?? "(未找到)"} LogDate->{logRef ?? "(未找到)"}");
var origEstRef = TfsClient.ResolveRef(fieldMap, "Original Estimate", _cfg.OriginalEstimateRef);
Log($"字段: FinancialProject->{finRef ?? "(未找到)"} Completed->{compRef ?? "(未找到)"} LogDate->{logRef ?? "(未找到)"} OriginalEstimate->{origEstRef ?? "(未找到)"}");
Log($"父PBI: '{(string.IsNullOrWhiteSpace(_cfg.ParentPbiId) ? "(未填)" : _cfg.ParentPbiId)}'——Excel 每行可用 PBI Id 列覆盖");
HashSet<string> existing = null;
@@ -612,25 +610,17 @@ namespace TfsExcelImporter
if (completed != null && compRef != null)
fields.Add(new KeyValuePair<string, object>(compRef, completed));
// Notes -> Description(该 Task 模板必填)
if (!string.IsNullOrWhiteSpace(row.Notes))
fields.Add(new KeyValuePair<string, object>("System.Description", row.Notes.Trim()));
// Original Estimate 默认取 Completed 的值
if (completed != null && origEstRef != null)
fields.Add(new KeyValuePair<string, object>(origEstRef, completed));
if (!string.IsNullOrWhiteSpace(row.Description))
fields.Add(new KeyValuePair<string, object>("System.Description", row.Description.Trim()));
var logDate = ExcelService.ToIsoDateTime(row.LogDate);
if (logDate != null && logRef != null)
fields.Add(new KeyValuePair<string, object>(logRef, logDate));
// 系统日期字段:bypassRules 时尝试写入
if (_chkBypass.Checked)
{
var created = ExcelService.ToIsoDateTime(row.CreatedDate);
if (created != null)
fields.Add(new KeyValuePair<string, object>(createdRef, created));
var closed = ExcelService.ToIsoDateTime(row.ClosedDate);
if (closed != null)
fields.Add(new KeyValuePair<string, object>(closedRef, closed));
}
// 父 PBI:行级 PBI Id 列优先,其次界面默认值
var pbiText = !string.IsNullOrWhiteSpace(row.PbiId) ? row.PbiId.Trim() : _cfg.ParentPbiId;
int? parentPbi = int.TryParse(pbiText, out var pbiNum) ? pbiNum : (int?)null;