338 lines
12 KiB
C#
338 lines
12 KiB
C#
|
namespace HK.Editor
|
|||
|
{
|
|||
|
using UnityEngine;
|
|||
|
using UnityEditor;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System;
|
|||
|
// 移除了System.Windows.Forms引用
|
|||
|
|
|||
|
public class DevLoggerWindow : EditorWindow
|
|||
|
{
|
|||
|
// 日志分类选项
|
|||
|
public enum LogCategory
|
|||
|
{
|
|||
|
功能开发,
|
|||
|
BUG修复,
|
|||
|
优化改进,
|
|||
|
文档编写,
|
|||
|
测试验证,
|
|||
|
会议讨论,
|
|||
|
自定义
|
|||
|
}
|
|||
|
|
|||
|
// 日志数据类
|
|||
|
[Serializable]
|
|||
|
public class DevLogEntry
|
|||
|
{
|
|||
|
public string timestamp; // 时间戳
|
|||
|
public string content; // 开发内容
|
|||
|
public bool isCompleted; // 是否完成
|
|||
|
public string date; // 日期(用于分组)
|
|||
|
public string category; // 分类标签
|
|||
|
}
|
|||
|
|
|||
|
// 日志列表
|
|||
|
private List<DevLogEntry> logEntries = new List<DevLogEntry>();
|
|||
|
|
|||
|
// 窗口状态
|
|||
|
private string newLogContent = "";
|
|||
|
private bool newLogCompleted = false;
|
|||
|
private LogCategory selectedCategory = LogCategory.功能开发;
|
|||
|
private string customCategory = "";
|
|||
|
private Vector2 scrollPosition;
|
|||
|
private string savePath;
|
|||
|
private string copyFeedback = ""; // 复制成功提示
|
|||
|
private float feedbackTimer = 0; // 提示信息计时器
|
|||
|
|
|||
|
// 菜单栏打开窗口
|
|||
|
[MenuItem("Tool/开发日志")]
|
|||
|
public static void ShowWindow()
|
|||
|
{
|
|||
|
GetWindow<DevLoggerWindow>("开发日志", true);
|
|||
|
GetWindow<DevLoggerWindow>().minSize = new Vector2(600, 400);
|
|||
|
}
|
|||
|
|
|||
|
private void OnEnable()
|
|||
|
{
|
|||
|
// 初始化保存路径(项目根目录/DevLogs.json)
|
|||
|
savePath = Path.Combine(Application.dataPath, "../DevLogs.json");
|
|||
|
LoadLogs();
|
|||
|
}
|
|||
|
|
|||
|
private void Update()
|
|||
|
{
|
|||
|
// 处理复制成功提示的显示时间
|
|||
|
if (feedbackTimer > 0)
|
|||
|
{
|
|||
|
feedbackTimer -= Time.deltaTime;
|
|||
|
if (feedbackTimer <= 0)
|
|||
|
{
|
|||
|
copyFeedback = "";
|
|||
|
Repaint();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnGUI()
|
|||
|
{
|
|||
|
// 显示复制成功提示
|
|||
|
if (!string.IsNullOrEmpty(copyFeedback))
|
|||
|
{
|
|||
|
GUIStyle feedbackStyle = new GUIStyle(EditorStyles.helpBox);
|
|||
|
feedbackStyle.normal.textColor = Color.green;
|
|||
|
EditorGUILayout.LabelField(copyFeedback, feedbackStyle);
|
|||
|
}
|
|||
|
|
|||
|
GUILayout.Label("添加新日志", EditorStyles.boldLabel);
|
|||
|
|
|||
|
// 分类选择
|
|||
|
EditorGUILayout.BeginHorizontal();
|
|||
|
GUILayout.Label("日志分类:", GUILayout.Width(80));
|
|||
|
selectedCategory = (LogCategory)EditorGUILayout.EnumPopup(selectedCategory);
|
|||
|
|
|||
|
// 自定义分类输入框
|
|||
|
if (selectedCategory == LogCategory.自定义)
|
|||
|
{
|
|||
|
customCategory = EditorGUILayout.TextField(customCategory);
|
|||
|
}
|
|||
|
|
|||
|
EditorGUILayout.EndHorizontal();
|
|||
|
|
|||
|
// 输入新日志内容
|
|||
|
newLogContent = EditorGUILayout.TextArea(newLogContent, GUILayout.Height(80));
|
|||
|
|
|||
|
// 完成状态选择
|
|||
|
newLogCompleted = EditorGUILayout.Toggle("是否完成", newLogCompleted);
|
|||
|
|
|||
|
// 添加按钮
|
|||
|
if (GUILayout.Button("添加日志"))
|
|||
|
{
|
|||
|
if (!string.IsNullOrEmpty(newLogContent.Trim()))
|
|||
|
{
|
|||
|
// 验证自定义分类
|
|||
|
if (selectedCategory == LogCategory.自定义 && string.IsNullOrEmpty(customCategory.Trim()))
|
|||
|
{
|
|||
|
EditorUtility.DisplayDialog("提示", "请输入自定义分类名称", "确定");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
AddNewLogEntry();
|
|||
|
newLogContent = ""; // 清空输入框
|
|||
|
newLogCompleted = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
EditorUtility.DisplayDialog("提示", "日志内容不能为空", "确定");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GUILayout.Space(20);
|
|||
|
GUILayout.Label("历史日志", EditorStyles.boldLabel);
|
|||
|
|
|||
|
// 显示日志列表
|
|||
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
|||
|
|
|||
|
// 按日期分组显示
|
|||
|
string currentDate = "";
|
|||
|
for (int i = logEntries.Count - 1; i >= 0; i--)
|
|||
|
{
|
|||
|
var entry = logEntries[i];
|
|||
|
|
|||
|
// 显示日期分组标题
|
|||
|
if (entry.date != currentDate)
|
|||
|
{
|
|||
|
currentDate = entry.date;
|
|||
|
GUILayout.Space(10);
|
|||
|
GUILayout.Label(currentDate, EditorStyles.centeredGreyMiniLabel);
|
|||
|
GUILayout.Space(5);
|
|||
|
}
|
|||
|
|
|||
|
// 日志条目样式
|
|||
|
EditorGUILayout.BeginHorizontal();
|
|||
|
|
|||
|
// 分类标签
|
|||
|
GUIStyle categoryStyle = new GUIStyle(EditorStyles.miniButton)
|
|||
|
{
|
|||
|
fontSize = 10,
|
|||
|
fixedWidth = 80,
|
|||
|
alignment = TextAnchor.MiddleCenter
|
|||
|
};
|
|||
|
SetCategoryStyleColors(categoryStyle, entry.category);
|
|||
|
GUILayout.Label(entry.category, categoryStyle);
|
|||
|
|
|||
|
// 完成状态标记
|
|||
|
string statusLabel = entry.isCompleted ? "✓ 已完成" : "○ 进行中";
|
|||
|
GUIStyle statusStyle = entry.isCompleted
|
|||
|
? new GUIStyle(EditorStyles.label) { normal = { textColor = Color.green } }
|
|||
|
: new GUIStyle(EditorStyles.label) { normal = { textColor = Color.yellow } };
|
|||
|
|
|||
|
EditorGUILayout.LabelField(statusLabel, statusStyle, GUILayout.Width(80));
|
|||
|
|
|||
|
// 日志内容
|
|||
|
EditorGUILayout.LabelField(entry.content, GUILayout.ExpandWidth(true));
|
|||
|
|
|||
|
// 时间戳
|
|||
|
EditorGUILayout.LabelField(entry.timestamp, EditorStyles.miniLabel, GUILayout.Width(80));
|
|||
|
|
|||
|
// 复制按钮
|
|||
|
if (GUILayout.Button("复制", EditorStyles.miniButtonLeft, GUILayout.Width(50)))
|
|||
|
{
|
|||
|
CopyLogToClipboard(entry);
|
|||
|
}
|
|||
|
|
|||
|
// 删除按钮
|
|||
|
if (GUILayout.Button("删除", EditorStyles.miniButtonRight, GUILayout.Width(50)))
|
|||
|
{
|
|||
|
if (EditorUtility.DisplayDialog("确认", "确定要删除这条日志吗?", "是", "否"))
|
|||
|
{
|
|||
|
logEntries.RemoveAt(i);
|
|||
|
SaveLogs();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EditorGUILayout.EndHorizontal();
|
|||
|
GUILayout.Space(2);
|
|||
|
}
|
|||
|
|
|||
|
EditorGUILayout.EndScrollView();
|
|||
|
}
|
|||
|
|
|||
|
// 将日志内容复制到剪贴板(使用Unity内置方法)
|
|||
|
private void CopyLogToClipboard(DevLogEntry entry)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
// 格式化复制内容,包含完整信息
|
|||
|
string formattedLog = $"{entry.date} {entry.timestamp} [{entry.category}] {entry.content} ({(entry.isCompleted ? "已完成" : "进行中")})";
|
|||
|
|
|||
|
// 使用Unity编辑器的剪贴板功能
|
|||
|
EditorGUIUtility.systemCopyBuffer = formattedLog;
|
|||
|
|
|||
|
// 显示复制成功提示
|
|||
|
copyFeedback = "日志内容已复制到剪贴板!";
|
|||
|
feedbackTimer = 2f; // 显示2秒
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
Debug.LogError("复制日志失败: " + e.Message);
|
|||
|
copyFeedback = "复制失败: " + e.Message;
|
|||
|
feedbackTimer = 3f;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 设置分类标签的样式颜色
|
|||
|
private void SetCategoryStyleColors(GUIStyle style, string category)
|
|||
|
{
|
|||
|
switch (category)
|
|||
|
{
|
|||
|
case "功能开发":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.2f, 0.4f, 0.8f, 0.8f));
|
|||
|
break;
|
|||
|
case "BUG修复":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.8f, 0.3f, 0.3f, 0.8f));
|
|||
|
break;
|
|||
|
case "优化改进":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.3f, 0.7f, 0.3f, 0.8f));
|
|||
|
break;
|
|||
|
case "文档编写":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.7f, 0.7f, 0.3f, 0.8f));
|
|||
|
break;
|
|||
|
case "测试验证":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.6f, 0.3f, 0.8f, 0.8f));
|
|||
|
break;
|
|||
|
case "会议讨论":
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.8f, 0.5f, 0.2f, 0.8f));
|
|||
|
break;
|
|||
|
default: // 自定义分类
|
|||
|
style.normal.textColor = Color.white;
|
|||
|
style.normal.background = MakeTex(2, 2, new Color(0.6f, 0.6f, 0.6f, 0.8f));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 创建简单的纹理用于GUI样式
|
|||
|
private Texture2D MakeTex(int width, int height, Color col)
|
|||
|
{
|
|||
|
Color[] pix = new Color[width * height];
|
|||
|
for (int i = 0; i < pix.Length; i++)
|
|||
|
pix[i] = col;
|
|||
|
Texture2D result = new Texture2D(width, height);
|
|||
|
result.SetPixels(pix);
|
|||
|
result.Apply();
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
// 添加新日志条目
|
|||
|
private void AddNewLogEntry()
|
|||
|
{
|
|||
|
string category = selectedCategory.ToString();
|
|||
|
if (selectedCategory == LogCategory.自定义)
|
|||
|
{
|
|||
|
category = customCategory.Trim();
|
|||
|
}
|
|||
|
|
|||
|
var newEntry = new DevLogEntry
|
|||
|
{
|
|||
|
timestamp = DateTime.Now.ToString("HH:mm:ss"),
|
|||
|
date = DateTime.Now.ToString("yyyy-MM-dd"),
|
|||
|
content = newLogContent,
|
|||
|
isCompleted = newLogCompleted,
|
|||
|
category = category
|
|||
|
};
|
|||
|
|
|||
|
logEntries.Add(newEntry);
|
|||
|
SaveLogs();
|
|||
|
}
|
|||
|
|
|||
|
// 保存日志到文件
|
|||
|
private void SaveLogs()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string json = JsonUtility.ToJson(new LogWrapper { entries = logEntries }, true);
|
|||
|
File.WriteAllText(savePath, json);
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
Debug.LogError("保存日志失败: " + e.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 从文件加载日志
|
|||
|
private void LoadLogs()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (File.Exists(savePath))
|
|||
|
{
|
|||
|
string json = File.ReadAllText(savePath);
|
|||
|
LogWrapper wrapper = JsonUtility.FromJson<LogWrapper>(json);
|
|||
|
if (wrapper != null && wrapper.entries != null)
|
|||
|
{
|
|||
|
logEntries = wrapper.entries;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
Debug.LogError("加载日志失败: " + e.Message);
|
|||
|
logEntries = new List<DevLogEntry>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 用于JSON序列化的包装类
|
|||
|
[Serializable]
|
|||
|
private class LogWrapper
|
|||
|
{
|
|||
|
public List<DevLogEntry> entries;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|