Design_SubModule/Scripts/Editor/Design_Tools/MigrateResFormatTool.cs
2026-04-14 17:30:13 +08:00

156 lines
5.5 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using OfficeOpenXml;
using ArtResource;
namespace DesignTools
{
/// <summary>
/// 一次性工具:将 Item.xlsx 的 Res 字段从 "TableId,ItemId" 迁移为 "TableName,ItemName"
/// 使用完毕后可删除此文件
/// </summary>
public static class MigrateResFormatTool
{
private const string ART_SO_PATH = "Assets/Art_SubModule/Art_SO";
private const string ITEM_SHEET_NAME = "Item";
[MenuItem("策划工具/一次性迁移/Res格式 ID→Name")]
public static void Execute()
{
// 1. 选择 Item.xlsx
string excelPath = EditorUtility.OpenFilePanel("选择 Item.xlsx", "", "xlsx");
if (string.IsNullOrEmpty(excelPath)) return;
if (!File.Exists(excelPath))
{
EditorUtility.DisplayDialog("错误", "文件不存在", "确定");
return;
}
// 2. 备份
string backupPath = excelPath + ".bak";
File.Copy(excelPath, backupPath, true);
Debug.Log($"已备份到: {backupPath}");
// 3. 加载所有 ArtTableSO
var allArtTables = new List<ArtTableSO>();
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO", new[] { ART_SO_PATH });
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var so = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (so != null) allArtTables.Add(so);
}
if (allArtTables.Count == 0)
{
EditorUtility.DisplayDialog("错误", "未找到任何 ArtTableSO 资源", "确定");
return;
}
// 4. 读取并修改 Excel
int migratedCount = 0;
int skippedCount = 0;
int errorCount = 0;
var errors = new List<string>();
using (var package = new ExcelPackage(new FileInfo(excelPath)))
{
var ws = package.Workbook.Worksheets[ITEM_SHEET_NAME];
if (ws == null)
{
EditorUtility.DisplayDialog("错误", $"未找到 Sheet: {ITEM_SHEET_NAME}", "确定");
return;
}
// 找 Res 列
int resCol = -1;
int idCol = -1;
int nameCol = -1;
int colCount = ws.Dimension?.Columns ?? 0;
for (int c = 1; c <= colCount; c++)
{
string h = ws.Cells[1, c].Text;
if (h == "Res") resCol = c;
else if (h == "Id") idCol = c;
else if (h == "Name") nameCol = c;
}
if (resCol < 0)
{
EditorUtility.DisplayDialog("错误", "未找到 Res 列", "确定");
return;
}
int rowCount = ws.Dimension?.Rows ?? 0;
for (int row = 3; row <= rowCount; row++)
{
string res = ws.Cells[row, resCol].Text.Trim();
if (string.IsNullOrEmpty(res)) continue;
string[] parts = res.Split(',');
if (parts.Length < 2) continue;
// 判断是否是旧格式(首段为数字)
if (!int.TryParse(parts[0], out int tableId))
{
skippedCount++;
continue;
}
int.TryParse(parts[1], out int artItemId);
string rowId = idCol > 0 ? ws.Cells[row, idCol].Text : row.ToString();
string rowName = nameCol > 0 ? ws.Cells[row, nameCol].Text : "";
var table = allArtTables.FirstOrDefault(x => x.TableId == tableId);
if (table == null)
{
errorCount++;
errors.Add($"Row {row} Id={rowId}({rowName}): TableId={tableId} 不存在");
continue;
}
if (artItemId < 0)
{
ws.Cells[row, resCol].Value = $"{table.TableName},";
migratedCount++;
continue;
}
var artItem = table.Items.FirstOrDefault(x => x.Id == artItemId);
if (artItem == null)
{
errorCount++;
errors.Add($"Row {row} Id={rowId}({rowName}): Table={table.TableName} 中无 ItemId={artItemId}");
continue;
}
ws.Cells[row, resCol].Value = $"{table.TableName},{artItem.Name}";
migratedCount++;
}
package.Save();
}
// 5. 报告结果
string msg = $"迁移完成!\n\n" +
$"成功: {migratedCount} 条\n" +
$"已是新格式(跳过): {skippedCount} 条\n" +
$"错误: {errorCount} 条\n\n" +
$"备份文件: {backupPath}";
if (errorCount > 0)
{
msg += $"\n\n错误详情:\n{string.Join("\n", errors)}";
}
EditorUtility.DisplayDialog("Res迁移结果", msg, "确定");
Debug.Log(msg);
}
}
}