更新插件功能
This commit is contained in:
@@ -12,6 +12,7 @@ public class ConfigTableInfo
|
|||||||
public string description;
|
public string description;
|
||||||
public List<FieldRelation> relations = new List<FieldRelation>();
|
public List<FieldRelation> relations = new List<FieldRelation>();
|
||||||
public bool isExistInProject;
|
public bool isExistInProject;
|
||||||
|
public string fileExtension = ".xlsx";
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -24,13 +25,70 @@ public class FieldRelation
|
|||||||
public string description;
|
public string description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ReverseRelation
|
||||||
|
{
|
||||||
|
public string sourceTable;
|
||||||
|
public string sourceDisplayName;
|
||||||
|
public string fieldName;
|
||||||
|
public string description;
|
||||||
|
public string relationFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class FieldRelationBackup
|
||||||
|
{
|
||||||
|
public string fieldName;
|
||||||
|
public string targetTable;
|
||||||
|
public string targetField;
|
||||||
|
public string relationFormat;
|
||||||
|
public string description;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ConfigLinkDatabase
|
public static class ConfigLinkDatabase
|
||||||
{
|
{
|
||||||
private static List<ConfigTableInfo> _cachedData;
|
private static List<ConfigTableInfo> _cachedData;
|
||||||
private static HashSet<string> _existingTableNames;
|
private static HashSet<string> _existingTableNames;
|
||||||
|
private static string _excelFolderPath;
|
||||||
|
|
||||||
private const string CONFIG_PATH = "Resources/Resources_moved/config";
|
private const string CONFIG_PATH = "Resources/Resources_moved/config";
|
||||||
|
|
||||||
|
public static void SetExcelFolderPath(string path)
|
||||||
|
{
|
||||||
|
_excelFolderPath = path;
|
||||||
|
PlayerPrefs.SetString("ConfigLinkExcelFolderPath", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetExcelFolderPath()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_excelFolderPath))
|
||||||
|
{
|
||||||
|
_excelFolderPath = PlayerPrefs.GetString("ConfigLinkExcelFolderPath", "");
|
||||||
|
}
|
||||||
|
return _excelFolderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetExcelFilePath(string tableName)
|
||||||
|
{
|
||||||
|
string folderPath = GetExcelFolderPath();
|
||||||
|
if (string.IsNullOrEmpty(folderPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var tableInfo = GetTableInfo(tableName);
|
||||||
|
string extension = tableInfo?.fileExtension ?? ".xlsx";
|
||||||
|
string excelPath = Path.Combine(folderPath, $"{tableName}{extension}");
|
||||||
|
return File.Exists(excelPath) ? excelPath : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsExcelFolderSet()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(GetExcelFolderPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsExcelFileExists(string tableName)
|
||||||
|
{
|
||||||
|
return GetExcelFilePath(tableName) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<ConfigTableInfo> GetAllTableInfo()
|
public static List<ConfigTableInfo> GetAllTableInfo()
|
||||||
{
|
{
|
||||||
if (_cachedData != null)
|
if (_cachedData != null)
|
||||||
@@ -319,7 +377,9 @@ public static class ConfigLinkDatabase
|
|||||||
}},
|
}},
|
||||||
new ConfigTableInfo { tableName = "fishingreward", displayName = "钓鱼奖励表", description = "钓鱼游戏奖励", relations = new List<FieldRelation> {
|
new ConfigTableInfo { tableName = "fishingreward", displayName = "钓鱼奖励表", description = "钓鱼游戏奖励", relations = new List<FieldRelation> {
|
||||||
new FieldRelation { fieldName = "rewards", targetTable = "prop", targetField = "id", relationFormat = "type_id_num", description = "奖励" }
|
new FieldRelation { fieldName = "rewards", targetTable = "prop", targetField = "id", relationFormat = "type_id_num", description = "奖励" }
|
||||||
}}
|
}},
|
||||||
|
new ConfigTableInfo { tableName = "dirty_words", displayName = "敏感词表", description = "敏感词过滤配置(TXT文件)", fileExtension = ".txt" },
|
||||||
|
new ConfigTableInfo { tableName = "奖励格式说明", displayName = "奖励格式说明", description = "奖励数据格式说明文档(TXT文件)", fileExtension = ".txt" }
|
||||||
};
|
};
|
||||||
|
|
||||||
MarkExistingTables();
|
MarkExistingTables();
|
||||||
@@ -341,12 +401,62 @@ public static class ConfigLinkDatabase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string configPathAlt = Path.Combine(Application.dataPath, "../Resources/Resources_moved/config");
|
||||||
|
if (Directory.Exists(configPathAlt))
|
||||||
|
{
|
||||||
|
string[] jsonFilesAlt = Directory.GetFiles(configPathAlt, "*.json");
|
||||||
|
foreach (string file in jsonFilesAlt)
|
||||||
|
{
|
||||||
|
string tableName = Path.GetFileNameWithoutExtension(file);
|
||||||
|
_existingTableNames.Add(tableName.ToLower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var table in _cachedData)
|
foreach (var table in _cachedData)
|
||||||
{
|
{
|
||||||
table.isExistInProject = _existingTableNames.Contains(table.tableName.ToLower());
|
bool existInConfig = _existingTableNames.Contains(table.tableName.ToLower());
|
||||||
|
|
||||||
|
if (!existInConfig && table.fileExtension == ".txt")
|
||||||
|
{
|
||||||
|
string excelFolderPath = GetExcelFolderPath();
|
||||||
|
if (!string.IsNullOrEmpty(excelFolderPath))
|
||||||
|
{
|
||||||
|
string txtPath = Path.Combine(excelFolderPath, $"{table.tableName}{table.fileExtension}");
|
||||||
|
existInConfig = File.Exists(txtPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.isExistInProject = existInConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTableExistInConfigFolder(string tableName)
|
||||||
|
{
|
||||||
|
string configPath = Path.Combine(Application.dataPath, CONFIG_PATH);
|
||||||
|
if (!Directory.Exists(configPath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var tableInfo = GetTableInfo(tableName);
|
||||||
|
string extension = tableInfo?.fileExtension ?? ".xlsx";
|
||||||
|
|
||||||
|
string jsonPath = Path.Combine(configPath, $"{tableName}.json");
|
||||||
|
string configPathAlt = Path.Combine(Application.dataPath, "../Resources/Resources_moved/config");
|
||||||
|
string jsonPathAlt = Path.Combine(configPathAlt, $"{tableName}.json");
|
||||||
|
|
||||||
|
if (extension == ".txt")
|
||||||
|
{
|
||||||
|
string excelFolderPath = GetExcelFolderPath();
|
||||||
|
if (!string.IsNullOrEmpty(excelFolderPath))
|
||||||
|
{
|
||||||
|
string txtPath = Path.Combine(excelFolderPath, $"{tableName}{extension}");
|
||||||
|
if (File.Exists(txtPath))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.Exists(jsonPath) || File.Exists(jsonPathAlt);
|
||||||
|
}
|
||||||
|
|
||||||
public static ConfigTableInfo GetTableInfo(string tableName)
|
public static ConfigTableInfo GetTableInfo(string tableName)
|
||||||
{
|
{
|
||||||
return GetAllTableInfo().Find(x => x.tableName.Equals(tableName, StringComparison.OrdinalIgnoreCase));
|
return GetAllTableInfo().Find(x => x.tableName.Equals(tableName, StringComparison.OrdinalIgnoreCase));
|
||||||
@@ -357,6 +467,90 @@ public static class ConfigLinkDatabase
|
|||||||
return GetAllTableInfo().ConvertAll(x => x.tableName);
|
return GetAllTableInfo().ConvertAll(x => x.tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<ReverseRelation> GetReverseRelations(string targetTableName)
|
||||||
|
{
|
||||||
|
List<ReverseRelation> result = new List<ReverseRelation>();
|
||||||
|
|
||||||
|
foreach (var table in GetAllTableInfo())
|
||||||
|
{
|
||||||
|
foreach (var relation in table.relations)
|
||||||
|
{
|
||||||
|
if (relation.targetTable.Equals(targetTableName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
result.Add(new ReverseRelation
|
||||||
|
{
|
||||||
|
sourceTable = table.tableName,
|
||||||
|
sourceDisplayName = table.displayName,
|
||||||
|
fieldName = relation.fieldName,
|
||||||
|
description = relation.description,
|
||||||
|
relationFormat = relation.relationFormat
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatRelationValue(string format, string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(format) || string.IsNullOrEmpty(value))
|
||||||
|
return value;
|
||||||
|
|
||||||
|
string[] parts = value.Split('_');
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
switch (format.ToLower())
|
||||||
|
{
|
||||||
|
case "item_id_num":
|
||||||
|
if (parts.Length >= 3)
|
||||||
|
result = $"类型:{parts[0]}, ID:{parts[1]}, 数量:{parts[2]}";
|
||||||
|
break;
|
||||||
|
case "type_id_num":
|
||||||
|
if (parts.Length >= 3)
|
||||||
|
result = $"类型:{parts[0]}, ID:{parts[1]}, 数量:{parts[2]}";
|
||||||
|
break;
|
||||||
|
case "id_pos_lv":
|
||||||
|
if (parts.Length >= 3)
|
||||||
|
result = $"ID:{parts[0]}, 位置:{parts[1]}, 等级:{parts[2]}";
|
||||||
|
break;
|
||||||
|
case "id_lv_num":
|
||||||
|
if (parts.Length >= 3)
|
||||||
|
result = $"ID:{parts[0]}, 等级:{parts[1]}, 数量:{parts[2]}";
|
||||||
|
break;
|
||||||
|
case "id_lv_num_time":
|
||||||
|
if (parts.Length >= 4)
|
||||||
|
result = $"ID:{parts[0]}, 等级:{parts[1]}, 数量:{parts[2]}, 时间:{parts[3]}";
|
||||||
|
break;
|
||||||
|
case "buffid_lv":
|
||||||
|
if (parts.Length >= 2)
|
||||||
|
result = $"BuffID:{parts[0]}, 等级:{parts[1]}";
|
||||||
|
break;
|
||||||
|
case "rune_id_num":
|
||||||
|
if (parts.Length >= 2)
|
||||||
|
result = $"符文ID:{parts[0]}, 数量:{parts[1]}";
|
||||||
|
break;
|
||||||
|
case "equip_id_num":
|
||||||
|
if (parts.Length >= 2)
|
||||||
|
result = $"装备ID:{parts[0]}, 数量:{parts[1]}";
|
||||||
|
break;
|
||||||
|
case "表名":
|
||||||
|
result = $"表名: {value}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrEmpty(result) ? value : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> GetRelatedTableNames(string tableName)
|
||||||
|
{
|
||||||
|
var tableInfo = GetTableInfo(tableName);
|
||||||
|
if (tableInfo == null)
|
||||||
|
return new List<string>();
|
||||||
|
|
||||||
|
return tableInfo.relations.Select(r => r.targetTable).Distinct().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public static List<string> GetAllDisplayNames()
|
public static List<string> GetAllDisplayNames()
|
||||||
{
|
{
|
||||||
return GetAllTableInfo().ConvertAll(x => $"{x.displayName} ({x.tableName})");
|
return GetAllTableInfo().ConvertAll(x => $"{x.displayName} ({x.tableName})");
|
||||||
|
|||||||
@@ -2,33 +2,33 @@ using UnityEngine;
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
public class ConfigLinkViewerWindow : EditorWindow
|
public class ConfigLinkViewerWindow : EditorWindow
|
||||||
{
|
{
|
||||||
private string selectedTableName;
|
private string selectedTableName;
|
||||||
private Vector2 scrollPos;
|
|
||||||
private Dictionary<string, bool> expandedRelations = new Dictionary<string, bool>();
|
private Dictionary<string, bool> expandedRelations = new Dictionary<string, bool>();
|
||||||
private Vector2 relationScrollPos;
|
private Vector2 relationScrollPos;
|
||||||
private string searchFilter = "";
|
private string searchFilter = "";
|
||||||
private bool showOnlyExisting = true;
|
private bool showOnlyExisting = true;
|
||||||
|
private bool showReverseRelations = false;
|
||||||
|
|
||||||
[MenuItem("Tools/配置表联动查看器")]
|
[MenuItem("Tools/配置表联动查看器")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<ConfigLinkViewerWindow>("配置表联动");
|
var window = GetWindow<ConfigLinkViewerWindow>("配置表联动");
|
||||||
|
window.minSize = new Vector2(900, 600);
|
||||||
|
window.position = new Rect(100, 100, 900, 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGUI()
|
private void OnGUI()
|
||||||
{
|
{
|
||||||
|
float windowWidth = position.width;
|
||||||
|
float windowHeight = position.height;
|
||||||
|
|
||||||
DrawHeader();
|
DrawHeader();
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
DrawTableSelector();
|
DrawTableSelector(windowWidth, windowHeight);
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(selectedTableName))
|
|
||||||
{
|
|
||||||
DrawTableInfo();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawHeader()
|
private void DrawHeader()
|
||||||
@@ -39,7 +39,7 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTableSelector()
|
private void DrawTableSelector(float windowWidth, float windowHeight)
|
||||||
{
|
{
|
||||||
EditorGUILayout.BeginVertical("box");
|
EditorGUILayout.BeginVertical("box");
|
||||||
|
|
||||||
@@ -47,9 +47,12 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
searchFilter = EditorGUILayout.TextField("搜索:", searchFilter, EditorStyles.toolbarSearchField);
|
searchFilter = EditorGUILayout.TextField("搜索:", searchFilter, EditorStyles.toolbarSearchField);
|
||||||
showOnlyExisting = EditorGUILayout.ToggleLeft("只显示当前项目存在的表", showOnlyExisting, GUILayout.Width(160));
|
showOnlyExisting = EditorGUILayout.ToggleLeft("只显示当前项目存在的表", showOnlyExisting);
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
DrawExcelPathSettings(windowWidth);
|
||||||
|
|
||||||
var allTables = showOnlyExisting ? ConfigLinkDatabase.GetExistingTables() : ConfigLinkDatabase.GetAllTableInfo();
|
var allTables = showOnlyExisting ? ConfigLinkDatabase.GetExistingTables() : ConfigLinkDatabase.GetAllTableInfo();
|
||||||
var filteredTables = string.IsNullOrEmpty(searchFilter)
|
var filteredTables = string.IsNullOrEmpty(searchFilter)
|
||||||
? allTables
|
? allTables
|
||||||
@@ -65,20 +68,24 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
|
|
||||||
var tableKeys = filteredTables.Select(x => x.tableName).ToArray();
|
var tableKeys = filteredTables.Select(x => x.tableName).ToArray();
|
||||||
|
|
||||||
int selectedIndex = selectedTableName != null ? System.Array.IndexOf(tableKeys, selectedTableName) : 0;
|
|
||||||
selectedIndex = Mathf.Clamp(selectedIndex, 0, Mathf.Max(0, displayNames.Length - 1));
|
|
||||||
|
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.BeginVertical(GUILayout.Width(200));
|
|
||||||
|
float leftPanelWidth = Mathf.Clamp(windowWidth * 0.3f, 180f, 300f);
|
||||||
|
float rightPanelWidth = windowWidth - leftPanelWidth - 20f;
|
||||||
|
float panelHeight = windowHeight - 150f;
|
||||||
|
|
||||||
|
EditorGUILayout.BeginVertical(GUILayout.Width(leftPanelWidth), GUILayout.Height(panelHeight));
|
||||||
EditorGUILayout.LabelField($"配置表列表 ({filteredTables.Count}):", EditorStyles.miniBoldLabel);
|
EditorGUILayout.LabelField($"配置表列表 ({filteredTables.Count}):", EditorStyles.miniBoldLabel);
|
||||||
relationScrollPos = EditorGUILayout.BeginScrollView(relationScrollPos, GUILayout.Height(300));
|
relationScrollPos = EditorGUILayout.BeginScrollView(relationScrollPos, false, true, GUILayout.ExpandHeight(true));
|
||||||
|
|
||||||
|
GUIStyle listButtonStyle = new GUIStyle(EditorStyles.label) { wordWrap = false, stretchWidth = true };
|
||||||
|
|
||||||
for (int i = 0; i < displayNames.Length; i++)
|
for (int i = 0; i < displayNames.Length; i++)
|
||||||
{
|
{
|
||||||
bool isSelected = tableKeys[i] == selectedTableName;
|
bool isSelected = tableKeys[i] == selectedTableName;
|
||||||
GUIStyle buttonStyle = isSelected ? "Button" : "Label";
|
GUIStyle buttonStyle = isSelected ? "Button" : listButtonStyle;
|
||||||
|
|
||||||
if (GUILayout.Button(displayNames[i], buttonStyle))
|
if (GUILayout.Button(displayNames[i], buttonStyle))
|
||||||
{
|
{
|
||||||
@@ -90,19 +97,22 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
EditorGUILayout.EndScrollView();
|
EditorGUILayout.EndScrollView();
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical("box", GUILayout.MinWidth(400));
|
EditorGUILayout.BeginVertical("box", GUILayout.Width(rightPanelWidth), GUILayout.Height(panelHeight));
|
||||||
DrawCurrentTableInfo();
|
DrawCurrentTableInfo(rightPanelWidth);
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawCurrentTableInfo()
|
private void DrawCurrentTableInfo(float panelWidth)
|
||||||
{
|
{
|
||||||
|
EditorGUILayout.BeginScrollView(Vector2.zero, false, true, GUILayout.ExpandHeight(true));
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(selectedTableName))
|
if (string.IsNullOrEmpty(selectedTableName))
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("请从左侧选择一个配置表", EditorStyles.centeredGreyMiniLabel);
|
EditorGUILayout.LabelField("请从左侧选择一个配置表", EditorStyles.centeredGreyMiniLabel);
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +120,7 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
if (tableInfo == null)
|
if (tableInfo == null)
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("未找到该表的配置信息", EditorStyles.helpBox);
|
EditorGUILayout.LabelField("未找到该表的配置信息", EditorStyles.helpBox);
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +132,20 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
|
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
DrawOpenExcelButtons(panelWidth);
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
showReverseRelations = EditorGUILayout.ToggleLeft("显示反向引用", showReverseRelations);
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
if (showReverseRelations)
|
||||||
|
{
|
||||||
|
DrawReverseRelations(panelWidth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (tableInfo.relations.Count == 0)
|
if (tableInfo.relations.Count == 0)
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("该表暂无联动关系", EditorStyles.miniLabel);
|
EditorGUILayout.LabelField("该表暂无联动关系", EditorStyles.miniLabel);
|
||||||
@@ -128,18 +153,122 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField($"联动关系 ({tableInfo.relations.Count}):", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField($"联动关系 ({tableInfo.relations.Count}):", EditorStyles.boldLabel);
|
||||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));
|
|
||||||
|
|
||||||
foreach (var relation in tableInfo.relations)
|
foreach (var relation in tableInfo.relations)
|
||||||
{
|
{
|
||||||
DrawRelation(relation);
|
DrawRelation(relation, panelWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
EditorGUILayout.EndScrollView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawOpenExcelButtons(float panelWidth)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
string excelPath = ConfigLinkDatabase.GetExcelFilePath(selectedTableName);
|
||||||
|
bool canOpen = !string.IsNullOrEmpty(excelPath);
|
||||||
|
|
||||||
|
if (canOpen)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("打开表格", GUILayout.Height(30), GUILayout.Width(panelWidth / 2 - 5)))
|
||||||
|
{
|
||||||
|
OpenExcelFile(selectedTableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("未找到Excel文件", EditorStyles.helpBox, GUILayout.Height(30), GUILayout.Width(panelWidth / 2 - 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawRelation(FieldRelation relation)
|
if (GUILayout.Button("批量打开关联表", GUILayout.Height(30), GUILayout.Width(panelWidth / 2 - 5)))
|
||||||
|
{
|
||||||
|
OpenRelatedTables(selectedTableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenExcelFile(string tableName)
|
||||||
|
{
|
||||||
|
string excelPath = ConfigLinkDatabase.GetExcelFilePath(tableName);
|
||||||
|
if (!string.IsNullOrEmpty(excelPath) && File.Exists(excelPath))
|
||||||
|
{
|
||||||
|
System.Diagnostics.Process.Start(excelPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenRelatedTables(string tableName)
|
||||||
|
{
|
||||||
|
var relatedTables = ConfigLinkDatabase.GetRelatedTableNames(tableName);
|
||||||
|
foreach (var relatedTable in relatedTables)
|
||||||
|
{
|
||||||
|
OpenExcelFile(relatedTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawReverseRelations(float panelWidth)
|
||||||
|
{
|
||||||
|
var reverseRels = ConfigLinkDatabase.GetReverseRelations(selectedTableName);
|
||||||
|
if (reverseRels.Count == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("暂无其他表引用该表", EditorStyles.miniLabel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField($"反向引用 ({reverseRels.Count}):", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
foreach (var rel in reverseRels)
|
||||||
|
{
|
||||||
|
bool sourceExist = ConfigLinkDatabase.IsTableExist(rel.sourceTable);
|
||||||
|
EditorGUILayout.BeginVertical("frameBox", GUILayout.Width(panelWidth - 10));
|
||||||
|
|
||||||
|
GUIStyle headerStyle = new GUIStyle(sourceExist ? EditorStyles.boldLabel : EditorStyles.helpBox) { wordWrap = false };
|
||||||
|
EditorGUILayout.LabelField($"{rel.sourceDisplayName} ({rel.sourceTable}) → {rel.fieldName}", headerStyle);
|
||||||
|
|
||||||
|
GUIStyle labelStyle = new GUIStyle(EditorStyles.miniLabel) { wordWrap = false };
|
||||||
|
EditorGUILayout.LabelField($"说明: {rel.description}", labelStyle);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(rel.relationFormat))
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField($"格式: {rel.relationFormat}", labelStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceExist && GUILayout.Button($"查看 {rel.sourceTable} 表", EditorStyles.miniButton))
|
||||||
|
{
|
||||||
|
selectedTableName = rel.sourceTable;
|
||||||
|
expandedRelations.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.Space(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawExcelPathSettings(float windowWidth)
|
||||||
|
{
|
||||||
|
string currentPath = ConfigLinkDatabase.GetExcelFolderPath();
|
||||||
|
string displayPath = string.IsNullOrEmpty(currentPath) ? "未设置" : currentPath;
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("Excel文件夹:", GUILayout.Width(70));
|
||||||
|
EditorGUILayout.LabelField(displayPath, EditorStyles.textField, GUILayout.ExpandWidth(true));
|
||||||
|
|
||||||
|
if (GUILayout.Button("选择文件夹", GUILayout.Width(80)))
|
||||||
|
{
|
||||||
|
string selectedPath = EditorUtility.OpenFolderPanel("选择Excel文件夹", "", "");
|
||||||
|
if (!string.IsNullOrEmpty(selectedPath))
|
||||||
|
{
|
||||||
|
ConfigLinkDatabase.SetExcelFolderPath(selectedPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawRelation(FieldRelation relation, float panelWidth)
|
||||||
{
|
{
|
||||||
string key = $"{selectedTableName}_{relation.fieldName}_{relation.targetTable}";
|
string key = $"{selectedTableName}_{relation.fieldName}_{relation.targetTable}";
|
||||||
if (!expandedRelations.ContainsKey(key))
|
if (!expandedRelations.ContainsKey(key))
|
||||||
@@ -150,29 +279,33 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
bool targetExist = ConfigLinkDatabase.IsTableExist(relation.targetTable);
|
bool targetExist = ConfigLinkDatabase.IsTableExist(relation.targetTable);
|
||||||
string existMark = targetExist ? "" : "[目标表缺失]";
|
string existMark = targetExist ? "" : "[目标表缺失]";
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical("frameBox");
|
EditorGUILayout.BeginVertical("frameBox", GUILayout.Width(panelWidth - 10));
|
||||||
|
|
||||||
|
GUIStyle foldoutStyle = new GUIStyle(EditorStyles.foldout) { wordWrap = false, richText = true };
|
||||||
expandedRelations[key] = EditorGUILayout.Foldout(expandedRelations[key],
|
expandedRelations[key] = EditorGUILayout.Foldout(expandedRelations[key],
|
||||||
$"{relation.fieldName} → {relation.targetTable}.{relation.targetField} {existMark}",
|
$"{relation.fieldName} → {relation.targetTable}.{relation.targetField} {existMark}",
|
||||||
true);
|
true, foldoutStyle);
|
||||||
|
|
||||||
if (expandedRelations[key])
|
if (expandedRelations[key])
|
||||||
{
|
{
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
EditorGUILayout.BeginVertical("helpBox");
|
EditorGUILayout.BeginVertical("helpBox", GUILayout.Width(panelWidth - 30));
|
||||||
|
|
||||||
EditorGUILayout.LabelField($"目标表: {relation.targetTable} {(targetExist ? "" : "(当前项目不存在)")}",
|
GUIStyle labelStyle = new GUIStyle(EditorStyles.miniLabel) { wordWrap = false, richText = true };
|
||||||
targetExist ? EditorStyles.miniLabel : EditorStyles.helpBox);
|
|
||||||
EditorGUILayout.LabelField($"目标字段: {relation.targetField}", EditorStyles.miniLabel);
|
EditorGUILayout.LabelField($"目标表: {relation.targetTable} {(targetExist ? "" : "(当前项目不存在)")}", labelStyle);
|
||||||
|
EditorGUILayout.LabelField($"目标字段: {relation.targetField}", labelStyle);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(relation.relationFormat))
|
if (!string.IsNullOrEmpty(relation.relationFormat))
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField($"格式: {relation.relationFormat}", EditorStyles.miniLabel);
|
EditorGUILayout.LabelField($"格式: {relation.relationFormat}", labelStyle);
|
||||||
|
DrawFormatExample(relation.relationFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.LabelField($"说明: {relation.description}", EditorStyles.miniLabel);
|
EditorGUILayout.LabelField($"说明: {relation.description}", labelStyle);
|
||||||
|
|
||||||
if (targetExist && GUILayout.Button($"查看 {relation.targetTable} 表", EditorStyles.miniButton, GUILayout.Width(120)))
|
if (targetExist && GUILayout.Button($"查看 {relation.targetTable} 表", EditorStyles.miniButton))
|
||||||
{
|
{
|
||||||
selectedTableName = relation.targetTable;
|
selectedTableName = relation.targetTable;
|
||||||
expandedRelations.Clear();
|
expandedRelations.Clear();
|
||||||
@@ -186,76 +319,48 @@ public class ConfigLinkViewerWindow : EditorWindow
|
|||||||
EditorGUILayout.Space(2);
|
EditorGUILayout.Space(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTableInfo()
|
private void DrawFormatExample(string format)
|
||||||
{
|
{
|
||||||
var tableInfo = ConfigLinkDatabase.GetTableInfo(selectedTableName);
|
string example = "";
|
||||||
if (tableInfo == null) return;
|
string formatted = "";
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical("box");
|
switch (format.ToLower())
|
||||||
|
|
||||||
EditorGUILayout.LabelField($"当前表: {tableInfo.displayName} ({tableInfo.tableName})", EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.LabelField($"描述: {tableInfo.description}", EditorStyles.miniLabel);
|
|
||||||
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
if (tableInfo.relations.Count == 0)
|
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("暂无联动关系", EditorStyles.miniLabel);
|
case "item_id_num":
|
||||||
}
|
case "type_id_num":
|
||||||
else
|
example = "1001_10_5";
|
||||||
{
|
formatted = "类型:1001, ID:10, 数量:5";
|
||||||
EditorGUILayout.LabelField("联动关系:", EditorStyles.boldLabel);
|
break;
|
||||||
|
case "id_pos_lv":
|
||||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(300));
|
example = "100_1_30";
|
||||||
|
formatted = "ID:100, 位置:1, 等级:30";
|
||||||
foreach (var relation in tableInfo.relations)
|
break;
|
||||||
{
|
case "id_lv_num":
|
||||||
DrawRelationItem(relation);
|
example = "100_30_5";
|
||||||
|
formatted = "ID:100, 等级:30, 数量:5";
|
||||||
|
break;
|
||||||
|
case "id_lv_num_time":
|
||||||
|
example = "100_30_5_120";
|
||||||
|
formatted = "ID:100, 等级:30, 数量:5, 时间:120秒";
|
||||||
|
break;
|
||||||
|
case "buffid_lv":
|
||||||
|
example = "5_3";
|
||||||
|
formatted = "BuffID:5, 等级:3";
|
||||||
|
break;
|
||||||
|
case "rune_id_num":
|
||||||
|
example = "10_2";
|
||||||
|
formatted = "符文ID:10, 数量:2";
|
||||||
|
break;
|
||||||
|
case "equip_id_num":
|
||||||
|
example = "20_1";
|
||||||
|
formatted = "装备ID:20, 数量:1";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
if (!string.IsNullOrEmpty(example))
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawRelationItem(FieldRelation relation)
|
|
||||||
{
|
{
|
||||||
string key = $"{selectedTableName}_{relation.fieldName}";
|
GUIStyle labelStyle = new GUIStyle(EditorStyles.miniLabel) { wordWrap = false, richText = true };
|
||||||
if (!expandedRelations.ContainsKey(key))
|
EditorGUILayout.LabelField($"示例: {example} → {formatted}", labelStyle);
|
||||||
{
|
|
||||||
expandedRelations[key] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool targetExist = ConfigLinkDatabase.IsTableExist(relation.targetTable);
|
|
||||||
|
|
||||||
expandedRelations[key] = EditorGUILayout.Foldout(expandedRelations[key],
|
|
||||||
$"字段: {relation.fieldName} → {relation.targetTable} {(targetExist ? "" : "(缺失)")}");
|
|
||||||
|
|
||||||
if (expandedRelations[key])
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical();
|
|
||||||
EditorGUILayout.LabelField($"目标字段: {relation.targetField}", EditorStyles.miniLabel);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(relation.relationFormat))
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField($"数据格式: {relation.relationFormat}", EditorStyles.miniLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField($"说明: {relation.description}", EditorStyles.miniLabel);
|
|
||||||
|
|
||||||
if (targetExist && GUILayout.Button($"跳转到 {relation.targetTable}", EditorStyles.miniButton))
|
|
||||||
{
|
|
||||||
selectedTableName = relation.targetTable;
|
|
||||||
Repaint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,144 +1,159 @@
|
|||||||
# 配置表联动查看器
|
# 配置表联动关系查看器
|
||||||
|
|
||||||
一个用于 Unity 项目的配置表联动关系可视化工具,支持跨项目复用。
|
一个用于查看 Unity 项目中配置表联动关系的编辑器工具,支持跨项目复用。
|
||||||
|
|
||||||
## 功能特性
|
## 功能特性
|
||||||
|
|
||||||
- ✅ 支持 76+ 配置表的联动关系查看
|
### 1. 配置表列表
|
||||||
- ✅ 自动检测项目中实际存在的配置表
|
- 支持搜索过滤配置表
|
||||||
- ✅ 智能搜索功能
|
- 显示表是否存在于当前项目
|
||||||
- ✅ 快速跳转到关联表
|
- 支持 TXT 文件(如敏感词表)
|
||||||
- ✅ 显示数据格式说明
|
|
||||||
- ✅ 跨项目自动适配
|
### 2. 联动关系查看
|
||||||
|
- 查看当前表关联哪些其他表
|
||||||
|
- 显示字段联动关系详情
|
||||||
|
- 支持跳转到关联表
|
||||||
|
|
||||||
|
### 3. 反向查询
|
||||||
|
- 查看哪些表引用了当前表
|
||||||
|
- 快速定位依赖关系
|
||||||
|
|
||||||
|
### 4. 数据格式可视化
|
||||||
|
- 自动解析数据格式
|
||||||
|
- 显示格式示例和说明
|
||||||
|
- 支持多种格式:item_id_num, id_pos_lv, id_lv_num 等
|
||||||
|
|
||||||
|
### 5. Excel 操作
|
||||||
|
- 一键打开配置表 Excel 文件
|
||||||
|
- 批量打开所有关联表
|
||||||
|
|
||||||
|
### 6. 跨项目适配
|
||||||
|
- 自动检测项目中存在的配置表
|
||||||
|
- 支持不同项目配置不同路径
|
||||||
|
|
||||||
## 安装指南
|
## 安装指南
|
||||||
|
|
||||||
### 方法一:复制文件
|
### 方法一:复制文件
|
||||||
|
1. 复制 `ConfigLinkViewer` 文件夹到目标项目
|
||||||
|
2. 路径:`Assets/Editor/ConfigLinkViewer/`
|
||||||
|
|
||||||
1. 找到本项目中的 `ConfigLinkViewer` 文件夹:
|
### 方法二:Git 子模块
|
||||||
```
|
|
||||||
Assets/Scripts/mgame/tools/ConfigLinkViewer/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 复制整个文件夹到目标项目的任意位置(建议保持相同路径):
|
|
||||||
```
|
|
||||||
目标项目/Assets/Scripts/mgame/tools/ConfigLinkViewer/
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 打开 Unity,等待脚本编译完成。
|
|
||||||
|
|
||||||
### 方法二:Git 子模块(推荐)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd 你的项目目录
|
git submodule add <repository-url> Assets/Editor/ConfigLinkViewer
|
||||||
git submodule add <本工具仓库地址> Assets/Scripts/mgame/tools/ConfigLinkViewer
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
### 打开工具
|
### 打开工具
|
||||||
|
在 Unity 编辑器菜单中点击:`Tools → 配置表联动查看器`
|
||||||
|
|
||||||
在 Unity 编辑器菜单中点击:
|
### 设置 Excel 路径
|
||||||
```
|
1. 点击"选择文件夹"按钮
|
||||||
Tools → 配置表联动查看器
|
2. 选择包含配置表 Excel 文件的文件夹
|
||||||
```
|
3. 路径会自动保存
|
||||||
|
|
||||||
### 界面说明
|
### 基本操作
|
||||||
|
| 操作 | 说明 |
|
||||||
| 区域 | 说明 |
|
|
||||||
|------|------|
|
|------|------|
|
||||||
| 搜索框 | 按表名、显示名、描述搜索配置表 |
|
| 单击列表项 | 选中配置表,查看详情 |
|
||||||
| 过滤选项 | 可选择只显示当前项目存在的表 |
|
| 点击"打开表格" | 打开当前表的 Excel 文件 |
|
||||||
| 左侧列表 | 配置表列表,显示状态标记 |
|
| 点击"批量打开关联表" | 打开所有关联的配置表 |
|
||||||
| 右侧详情 | 显示选中表的联动关系 |
|
| 勾选"显示反向引用" | 查看哪些表引用了当前表 |
|
||||||
|
|
||||||
### 操作指南
|
### 数据格式说明
|
||||||
|
|
||||||
1. **选择配置表**:从左侧列表点击任意配置表
|
|
||||||
2. **查看联动关系**:右侧显示该表的所有字段关联
|
|
||||||
3. **展开详情**:点击折叠箭头查看详细信息
|
|
||||||
4. **跳转到关联表**:点击"查看 xxx 表"按钮跳转
|
|
||||||
5. **搜索过滤**:在搜索框输入关键词快速定位
|
|
||||||
|
|
||||||
### 状态标识说明
|
|
||||||
|
|
||||||
| 标记 | 含义 |
|
|
||||||
|------|------|
|
|
||||||
| [存在] | 该表存在于当前项目 |
|
|
||||||
| [缺失] | 该表不存在于当前项目 |
|
|
||||||
| [目标表缺失] | 联动目标表不存在于当前项目 |
|
|
||||||
|
|
||||||
## 跨项目适配
|
|
||||||
|
|
||||||
工具会自动检测目标项目中的配置表:
|
|
||||||
|
|
||||||
1. 扫描路径:`Resources/Resources_moved/config/*.json`
|
|
||||||
2. 自动标记哪些表存在/缺失
|
|
||||||
3. 缺失的表不会影响工具正常运行
|
|
||||||
4. 联动到缺失表的跳转按钮会自动禁用
|
|
||||||
|
|
||||||
## 配置表联动关系示例
|
|
||||||
|
|
||||||
### 敌人表 (enemy)
|
|
||||||
- reward_id → checkpointreward.id - 掉落奖励
|
|
||||||
- skills → skill.id - 技能列表
|
|
||||||
|
|
||||||
### 商店表 (mall)
|
|
||||||
- productId → prop.id - 商品道具ID
|
|
||||||
- consumes → prop.id (格式: item_id_num) - 购买消耗
|
|
||||||
- rewards → prop.id (格式: item_id_num) - 购买获得奖励
|
|
||||||
|
|
||||||
### 英雄表 (hero)
|
|
||||||
- skills → skill.id - 技能列表
|
|
||||||
- equips → equip.id - 装备列表
|
|
||||||
- buffs → buff.id - 升阶解锁buff
|
|
||||||
|
|
||||||
## 数据格式说明
|
|
||||||
|
|
||||||
| 格式 | 示例 | 说明 |
|
| 格式 | 示例 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| item_id_num | 1001_5 | 道具ID_数量 |
|
| item_id_num | 1001_10_5 | 类型:1001, ID:10, 数量:5 |
|
||||||
| type_id_num | item_1001_5 | 类型_道具ID_数量 |
|
| type_id_num | 1001_10_5 | 类型:1001, ID:10, 数量:5 |
|
||||||
| id_pos_lv | 101_2_5 | ID_位置_等级 |
|
| id_pos_lv | 100_1_30 | ID:100, 位置:1, 等级:30 |
|
||||||
| id_lv_num | 101_5_3 | ID_等级_数量 |
|
| id_lv_num | 100_30_5 | ID:100, 等级:30, 数量:5 |
|
||||||
| id_lv_num_time | 101_5_3_30 | ID_等级_数量_时间 |
|
| id_lv_num_time | 100_30_5_120 | ID:100, 等级:30, 数量:5, 时间:120秒 |
|
||||||
|
| buffid_lv | 5_3 | BuffID:5, 等级:3 |
|
||||||
|
| rune_id_num | 10_2 | 符文ID:10, 数量:2 |
|
||||||
|
| equip_id_num | 20_1 | 装备ID:20, 数量:1 |
|
||||||
|
|
||||||
## 维护指南
|
## 跨项目复用
|
||||||
|
|
||||||
### 添加新表联动关系
|
### 自动检测
|
||||||
|
工具会自动检测目标项目中的配置表:
|
||||||
|
- 检查 `Resources/Resources_moved/config/` 目录
|
||||||
|
- 检查 `Resources/config/` 目录
|
||||||
|
- TXT 文件检查 Excel 文件夹
|
||||||
|
|
||||||
编辑 `ConfigLinkDatabase.cs`,在 `GetAllTableInfo()` 方法中添加:
|
### 添加新配置表
|
||||||
|
编辑 `ConfigLinkDatabase.cs`,在 `GetAllTableInfo()` 方法中添加新表:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
new ConfigTableInfo {
|
new ConfigTableInfo {
|
||||||
tableName = "新表名",
|
tableName = "new_table",
|
||||||
displayName = "显示名称",
|
displayName = "新表",
|
||||||
description = "表描述",
|
description = "新表描述",
|
||||||
relations = new List<FieldRelation> {
|
relations = new List<FieldRelation> {
|
||||||
new FieldRelation {
|
new FieldRelation {
|
||||||
fieldName = "字段名",
|
fieldName = "field1",
|
||||||
targetTable = "目标表名",
|
targetTable = "target_table",
|
||||||
targetField = "目标字段",
|
targetField = "id",
|
||||||
relationFormat = "数据格式(可选)",
|
description = "关联说明"
|
||||||
description = "说明文字"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 清理缓存
|
## 文件结构
|
||||||
|
|
||||||
如果配置表有变动,可以调用:
|
```
|
||||||
|
Assets/Editor/ConfigLinkViewer/
|
||||||
```csharp
|
├── ConfigLinkDatabase.cs # 配置表数据和联动关系存储
|
||||||
ConfigLinkDatabase.ClearCache();
|
├── ConfigLinkViewerWindow.cs # Unity编辑器窗口界面
|
||||||
|
└── README.md # 使用文档
|
||||||
```
|
```
|
||||||
|
|
||||||
## 技术支持
|
## 支持的配置表
|
||||||
|
|
||||||
如有问题或建议,请联系开发者。
|
工具包含以下类型的配置表支持:
|
||||||
|
- 活动系统:activity, activityreward
|
||||||
|
- 成就系统:achievement
|
||||||
|
- 战斗系统:fight_fb1~4, fight_arena, fight_sample
|
||||||
|
- 英雄系统:hero, herolevel, herostage
|
||||||
|
- 道具系统:prop, mall
|
||||||
|
- 装备系统:equip, equiplevel, equipstage
|
||||||
|
- 技能系统:skill, skilllevel
|
||||||
|
- 符文系统:rune, runelevel
|
||||||
|
- 任务系统:quest
|
||||||
|
- VIP系统:vip, recharge
|
||||||
|
- 服务端文件:dirty_words.txt, 奖励格式说明.txt
|
||||||
|
|
||||||
---
|
## 注意事项
|
||||||
|
|
||||||
*版本: 1.0*
|
1. Excel 文件命名必须与配置表名一致(如 `enemy.xlsx`)
|
||||||
*最后更新: 2026年5月*
|
2. 路径设置后会自动保存到 PlayerPrefs
|
||||||
|
3. 建议将 Excel 文件夹设置为版本控制忽略
|
||||||
|
4. TXT 文件需要放置在 Excel 文件夹中
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.0.0
|
||||||
|
- 初始版本
|
||||||
|
- 支持配置表列表和联动关系查看
|
||||||
|
|
||||||
|
### v1.1.0
|
||||||
|
- 添加反向查询功能
|
||||||
|
- 添加数据格式可视化
|
||||||
|
- 添加批量打开关联表功能
|
||||||
|
|
||||||
|
### v1.2.0
|
||||||
|
- 支持 TXT 文件识别
|
||||||
|
- 优化跨项目适配
|
||||||
|
- 更新使用文档
|
||||||
|
|
||||||
|
### v1.3.0
|
||||||
|
- 移除所有水平滚动条
|
||||||
|
- 左右面板自适应布局
|
||||||
|
- Excel文件夹路径与搜索框对齐
|
||||||
|
- 文本保持单行显示不换行
|
||||||
|
- 窗口默认大小优化为 900×600
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|||||||
Reference in New Issue
Block a user