433 lines
13 KiB
C#
433 lines
13 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
/// <summary>
|
||
/// 用户使用日志面板
|
||
/// 显示和管理用户操作日志记录
|
||
/// </summary>
|
||
public class UseLogPanel : BasePanel
|
||
{
|
||
[Header("滚动列表")]
|
||
public ScrollableListView UseLogListView;
|
||
|
||
[Header("操作按钮")]
|
||
public Button HomeButton;
|
||
public Button BackButton;
|
||
public Button RefreshButton; // 刷新按钮
|
||
public Button ClearButton; // 清空记录按钮
|
||
public Button ExportButton; // 导出按钮
|
||
|
||
[Header("状态显示")]
|
||
public TextMeshProUGUI StatusText; // 状态文本
|
||
public TextMeshProUGUI RecordCountText; // 记录数量文本
|
||
|
||
[Header("筛选选项")]
|
||
public TMP_Dropdown LogTypeDropdown; // 日志类型筛选
|
||
public TMP_InputField UserFilterInput; // 用户筛选
|
||
public Button FilterButton; // 筛选按钮
|
||
|
||
private UserLogService _userLogService;
|
||
private IAuthenticationService _authService;
|
||
private List<UseLogEvent> _currentLogs = new List<UseLogEvent>();
|
||
|
||
// 自动刷新相关
|
||
private const int MAX_DISPLAY_RECORDS = 500; // 最多显示500条记录
|
||
private const float AUTO_REFRESH_INTERVAL = 15f; // 自动刷新间隔(秒)
|
||
private Coroutine _autoRefreshCoroutine;
|
||
|
||
public override void Init()
|
||
{
|
||
_userLogService = ServiceLocator.Get<UserLogService>();
|
||
_authService = ServiceLocator.Get<IAuthenticationService>();
|
||
if (_userLogService == null)
|
||
{
|
||
_userLogService = new UserLogService();
|
||
ServiceLocator.Register(_userLogService);
|
||
}
|
||
|
||
InitializeUI();
|
||
Populate();
|
||
|
||
// 启动自动刷新
|
||
_autoRefreshCoroutine = StartCoroutine(AutoRefreshCoroutine());
|
||
}
|
||
|
||
private void InitializeUI()
|
||
{
|
||
if (HomeButton != null)
|
||
HomeButton.onClick.AddListener(() =>
|
||
{
|
||
ConfirmDialog.Show("确认", "是否返回主界面?", () =>
|
||
{
|
||
ReturnToHome();
|
||
});
|
||
});
|
||
|
||
if (BackButton != null)
|
||
BackButton.onClick.AddListener(() =>
|
||
ConfirmDialog.Show("确认", "是否返回设置界面?", () =>
|
||
{
|
||
ClosePanel();
|
||
ClosePanel();
|
||
})
|
||
);
|
||
|
||
// 刷新按钮已取消,改为自动刷新
|
||
if (RefreshButton != null)
|
||
RefreshButton.gameObject.SetActive(false);
|
||
|
||
if (ClearButton != null)
|
||
ClearButton.onClick.AddListener(OnClearClicked);
|
||
|
||
if (ExportButton != null)
|
||
ExportButton.onClick.AddListener(OnExportClicked);
|
||
|
||
if (FilterButton != null)
|
||
FilterButton.onClick.AddListener(OnFilterClicked);
|
||
|
||
// 设置用户筛选输入框的自定义键盘
|
||
if (UserFilterInput != null)
|
||
{
|
||
CustomKeyboardManager.SetupInputField(UserFilterInput, KeyboardLayout.Default,
|
||
(newValue) =>
|
||
{
|
||
UserFilterInput.text = newValue;
|
||
},
|
||
clearOnFirstInput: false); // 筛选输入不需要清空
|
||
}
|
||
|
||
// 初始化筛选下拉框
|
||
if (LogTypeDropdown != null)
|
||
{
|
||
LogTypeDropdown.ClearOptions();
|
||
LogTypeDropdown.AddOptions(new List<string>
|
||
{
|
||
"全部日志", "用户日志", "系统日志", "登录日志", "操作日志"
|
||
});
|
||
LogTypeDropdown.value = 0;
|
||
}
|
||
|
||
SetStatus("正在加载用户操作日志...", true);
|
||
}
|
||
|
||
|
||
|
||
private void SetStatus(string message, bool isSuccess)
|
||
{
|
||
if (StatusText != null)
|
||
{
|
||
StatusText.text = message;
|
||
StatusText.color = isSuccess ? Color.green : Color.red;
|
||
}
|
||
}
|
||
|
||
private void UpdateRecordCount(int count)
|
||
{
|
||
if (RecordCountText != null)
|
||
{
|
||
RecordCountText.text = $"共 {count} 条记录";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动刷新协程
|
||
/// </summary>
|
||
private IEnumerator AutoRefreshCoroutine()
|
||
{
|
||
while (true)
|
||
{
|
||
yield return new WaitForSeconds(AUTO_REFRESH_INTERVAL);
|
||
|
||
// 只有在面板激活时才刷新
|
||
if (gameObject.activeInHierarchy)
|
||
{
|
||
Populate();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnClearClicked()
|
||
{
|
||
// 显示确认对话框
|
||
ConfirmDialog.ShowDeleteConfirm(
|
||
"所有用户操作日志",
|
||
() => ClearAllRecords(),
|
||
() => Debug.Log("取消清空记录")
|
||
);
|
||
}
|
||
|
||
private void ClearAllRecords()
|
||
{
|
||
if (_userLogService != null)
|
||
{
|
||
// 根据当前筛选类型清空不同的日志
|
||
if (LogTypeDropdown != null)
|
||
{
|
||
switch (LogTypeDropdown.value)
|
||
{
|
||
case 1: // 用户日志
|
||
_userLogService.ClearUserLogs();
|
||
break;
|
||
case 2: // 系统日志
|
||
_userLogService.ClearSystemLogs();
|
||
break;
|
||
default: // 全部日志
|
||
_userLogService.ClearAllLogs();
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_userLogService.ClearAllLogs();
|
||
}
|
||
}
|
||
|
||
// 清空UI显示
|
||
if (UseLogListView != null)
|
||
{
|
||
UseLogListView.ClearItems();
|
||
}
|
||
|
||
_currentLogs.Clear();
|
||
UpdateRecordCount(0);
|
||
SetStatus("记录已清空", true);
|
||
}
|
||
|
||
private void Populate()
|
||
{
|
||
if (_userLogService == null)
|
||
{
|
||
SetStatus("日志服务不可用", false);
|
||
return;
|
||
}
|
||
|
||
// 获取系统日志(保持向后兼容)
|
||
var systemLogs = _userLogService.GetAllSystemLogs();
|
||
|
||
// 也可以将用户日志转换为系统日志格式显示
|
||
var userLogs = _userLogService.GetAllUserLogs();
|
||
foreach (var userLog in userLogs)
|
||
{
|
||
var systemLog = new UseLogEvent
|
||
{
|
||
Id = userLog.Id,
|
||
Account = userLog.Username,
|
||
OperationContentText = $"{userLog.Operation}: {userLog.OperationDetails ?? ""}",
|
||
Time = userLog.Timestamp
|
||
};
|
||
systemLogs.Add(systemLog);
|
||
}
|
||
|
||
// 按时间排序,最新的在后面
|
||
systemLogs.Sort((a, b) => a.Time.CompareTo(b.Time));
|
||
|
||
// 限制最多显示500条记录
|
||
if (systemLogs.Count > MAX_DISPLAY_RECORDS)
|
||
{
|
||
systemLogs = systemLogs.Take(MAX_DISPLAY_RECORDS).ToList();
|
||
}
|
||
|
||
_currentLogs = systemLogs;
|
||
|
||
// 优先使用新的ScrollableListView
|
||
if (UseLogListView != null)
|
||
{
|
||
PopulateWithScrollableList(_currentLogs);
|
||
}
|
||
|
||
UpdateRecordCount(_currentLogs.Count);
|
||
SetStatus($"成功加载 {_currentLogs.Count} 条记录", true);
|
||
}
|
||
|
||
private void PopulateWithScrollableList(IReadOnlyList<UseLogEvent> records)
|
||
{
|
||
UseLogListView.ClearItems();
|
||
|
||
for (int i = 0; i < records.Count; i++)
|
||
{
|
||
var evt = records[i];
|
||
var listItem = UseLogListView.AddItem(evt);
|
||
if (listItem != null)
|
||
{
|
||
var uselogItem = listItem.gameObject.GetComponent<UseLogItem>();
|
||
if (uselogItem != null)
|
||
{
|
||
uselogItem.Initialize(evt, i + 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 滚动到底部显示最新记录
|
||
UseLogListView.ScrollToBottom();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出日志按钮点击事件
|
||
/// </summary>
|
||
private void OnExportClicked(){
|
||
InputDialog.Show("验证身份",
|
||
$"请输入管理者密码:",
|
||
"",
|
||
(password) => {
|
||
if (_authService.ValidCurrentPassword(password)){
|
||
ExportUseLogs();
|
||
}else{
|
||
SetStatus("密码错误", false);
|
||
// ClosePanel();
|
||
}
|
||
},
|
||
ClosePanel, true); // 密码模式
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 导出日志
|
||
/// </summary>
|
||
private void ExportUseLogs()
|
||
{
|
||
if (_userLogService == null)
|
||
{
|
||
SetStatus("日志服务不可用", false);
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
string exportPath = _userLogService.GetLogFilePath();
|
||
SetStatus($"日志文件路径: {exportPath}", true);
|
||
|
||
// 可以在这里添加更多导出功能,比如复制到剪贴板或生成CSV等
|
||
Debug.Log($"日志文件导出路径: {exportPath}");
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
SetStatus($"导出失败: {ex.Message}", false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 筛选按钮点击事件
|
||
/// </summary>
|
||
private void OnFilterClicked()
|
||
{
|
||
ApplyFilter();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用筛选条件
|
||
/// </summary>
|
||
private void ApplyFilter()
|
||
{
|
||
if (_userLogService == null)
|
||
{
|
||
SetStatus("日志服务不可用", false);
|
||
return;
|
||
}
|
||
|
||
var filteredLogs = new List<UseLogEvent>();
|
||
|
||
// 根据日志类型筛选
|
||
if (LogTypeDropdown != null)
|
||
{
|
||
switch (LogTypeDropdown.value)
|
||
{
|
||
case 1: // 用户日志
|
||
var userLogs = _userLogService.GetAllUserLogs();
|
||
foreach (var userLog in userLogs)
|
||
{
|
||
filteredLogs.Add(new UseLogEvent
|
||
{
|
||
Id = userLog.Id,
|
||
Account = userLog.Username,
|
||
OperationContentText = $"{userLog.Operation}: {userLog.OperationDetails ?? ""}",
|
||
Time = userLog.Timestamp
|
||
});
|
||
}
|
||
break;
|
||
case 2: // 系统日志
|
||
filteredLogs.AddRange(_userLogService.GetAllSystemLogs());
|
||
break;
|
||
case 3: // 登录日志
|
||
var loginLogs = _userLogService.GetLogsByOperation("登录");
|
||
foreach (var loginLog in loginLogs)
|
||
{
|
||
filteredLogs.Add(new UseLogEvent
|
||
{
|
||
Id = loginLog.Id,
|
||
Account = loginLog.Username,
|
||
OperationContentText = $"{loginLog.Operation}: {loginLog.OperationDetails ?? ""}",
|
||
Time = loginLog.Timestamp
|
||
});
|
||
}
|
||
break;
|
||
case 4: // 操作日志(排除登录登出)
|
||
var operationLogs = _userLogService.GetAllUserLogs()
|
||
.Where(log => !log.Operation.Contains("登录") && !log.Operation.Contains("登出"))
|
||
.ToList();
|
||
foreach (var opLog in operationLogs)
|
||
{
|
||
filteredLogs.Add(new UseLogEvent
|
||
{
|
||
Id = opLog.Id,
|
||
Account = opLog.Username,
|
||
OperationContentText = $"{opLog.Operation}: {opLog.OperationDetails ?? ""}",
|
||
Time = opLog.Timestamp
|
||
});
|
||
}
|
||
break;
|
||
default: // 全部日志
|
||
Populate();
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 根据用户名筛选
|
||
if (UserFilterInput != null && !string.IsNullOrEmpty(UserFilterInput.text))
|
||
{
|
||
string userFilter = UserFilterInput.text.ToLower();
|
||
filteredLogs = filteredLogs.Where(log =>
|
||
log.Account.ToLower().Contains(userFilter)).ToList();
|
||
}
|
||
|
||
// 按时间排序,最新的在后面
|
||
filteredLogs.Sort((a, b) => a.Time.CompareTo(b.Time));
|
||
|
||
// 限制最多显示500条记录
|
||
if (filteredLogs.Count > MAX_DISPLAY_RECORDS)
|
||
{
|
||
filteredLogs = filteredLogs.Take(MAX_DISPLAY_RECORDS).ToList();
|
||
}
|
||
|
||
_currentLogs = filteredLogs;
|
||
|
||
// 更新UI显示
|
||
if (UseLogListView != null)
|
||
{
|
||
PopulateWithScrollableList(_currentLogs);
|
||
}
|
||
|
||
UpdateRecordCount(_currentLogs.Count);
|
||
SetStatus($"筛选完成,显示 {_currentLogs.Count} 条记录", true);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
// 停止自动刷新协程
|
||
if (_autoRefreshCoroutine != null)
|
||
{
|
||
StopCoroutine(_autoRefreshCoroutine);
|
||
}
|
||
// 关闭自定义键盘(如果正在显示)
|
||
if (CustomKeyboardManager.Instance != null && CustomKeyboardManager.Instance.IsKeyboardShowing())
|
||
{
|
||
CustomKeyboardManager.Instance.HideKeyboard();
|
||
}
|
||
}
|
||
|
||
}
|
||
|