2026-05-29 19:54:56 +08:00

207 lines
6.5 KiB
GDScript

class_name LogPanel
extends PanelModule
# 日志面板:
# - 展示农场事件、系统记录等只读列表。
# - 列表数据只在打开时拉取,不常驻轮询,减少 H5 Web 端网络和节点压力。
# - 行背景/文本使用 UiBuilder 统一创建,保持和其它活动面板同一风格。
var _log_item_bg: Texture2D
var _tab_index := 0
var _page_index := 1
var _page_max := 1
var _list: VBoxContainer
var _page_label: Label
var _panel: Control
func setup(options: Dictionary) -> void:
super.setup(options)
_log_item_bg = options.get("log_item_bg_texture") as Texture2D
func open() -> void:
_close_modal(false)
_tab_index = 0
_page_index = 1
_page_max = 1
_panel = _ui.create_common_panel_shell("LogPanel", Vector2(600.0, 790.0), "panel_icon_log", _texture_provider.atlas_path("common"), "panel_title_log", _texture_provider.atlas_path("common"))
_ui.add_content_panel_background(_panel, "InnerPage", Vector2(77.0, 239.0), Vector2(487.0, 520.0))
_ui.create_tab_bar(_panel, "LogTabs", ["玩家日志", "系统日志"], Vector2(77.0, 192.0), _tab_index, Callable(self, "_on_tab_pressed"))
var scroll := ScrollContainer.new()
scroll.name = "LogScroll"
scroll.position = Vector2(80.0, 248.0)
scroll.size = Vector2(482.0, 500.0)
scroll.clip_contents = true
_ui.configure_vertical_scroll(scroll)
_panel.add_child(scroll)
_list = VBoxContainer.new()
_list.name = "LogList"
_list.custom_minimum_size = Vector2(482.0, 0.0)
_list.add_theme_constant_override("separation", 3)
scroll.add_child(_list)
_ui.add_texture_button(_panel, "LogPrev", _texture_provider.common("btn_page_prev"), Vector2(241.0, 789.0), Vector2(46.0, 41.0), "", Callable(self, "_on_prev_pressed"), 20)
_ui.add_texture_button(_panel, "LogNext", _texture_provider.common("btn_page_next"), Vector2(369.0, 789.0), Vector2(46.0, 41.0), "", Callable(self, "_on_next_pressed"), 20)
_page_label = _ui.add_panel_label(_panel, "LogPage", "1/1", Vector2(289.0, 796.0), Vector2(72.0, 28.0), 24, Color.html("#753f24"), 0, Color.TRANSPARENT)
_ui.add_texture_button(_panel, "LogClear", _texture_provider.common("c_btn2"), Vector2(463.0, 784.0), Vector2(88.0, 44.0), "清空", Callable(self, "_on_clear_pressed"), 22)
_open_modal(_panel)
await render()
func render() -> void:
var list := _list
if not _clear_children_if_live(list):
return
_ui.add_panel_label(list, "Loading", "读取日志中...", Vector2.ZERO, Vector2(462.0, 44.0), 22, Color.html("#753f24"), 0, Color.TRANSPARENT)
var token := _token()
if token.is_empty():
return
var offset := (_page_index - 1) * 10
var result: Dictionary
if _tab_index == 0:
result = await _activity_api.fetch_user_logs(token, offset, 10)
else:
result = await _activity_api.fetch_system_logs(token, offset, 10)
if not _is_current_node(list, _list):
return
_clear_children(list)
if not result.get("ok", false):
_ui.add_panel_label(list, "Error", _response_status_text(result, "日志读取失败"), Vector2.ZERO, Vector2(462.0, 48.0), 22, Color.html("#ce5f5f"), 0, Color.TRANSPARENT)
return
var data = _response_data(result, {})
var rows: Array = []
if data is Dictionary:
rows = data.get("list", [])
_page_max = clampi(int(ceil(float(int(data.get("total_count", rows.size()))) / 10.0)), 1, 10)
else:
_page_max = 1
if _is_live_node(_page_label):
_page_label.text = "%s/%s" % [_page_index, _page_max]
if rows.is_empty():
_ui.add_panel_label(list, "Empty", "暂无日志", Vector2.ZERO, Vector2(462.0, 48.0), 24, Color.html("#753f24"), 0, Color.TRANSPARENT)
return
for index in range(rows.size()):
if rows[index] is Dictionary:
_add_row(list, rows[index], index)
func _on_tab_pressed(index: int) -> void:
_tab_index = index
_page_index = 1
var tab_bar := _panel.get_node_or_null("LogTabs") if _panel != null else null
_ui.update_tab_bar(tab_bar as Control, index)
await render()
func _on_prev_pressed() -> void:
if _page_index <= 1:
return
_page_index -= 1
await render()
func _on_next_pressed() -> void:
if _page_index >= _page_max:
return
_page_index += 1
await render()
func _on_clear_pressed() -> void:
if _is_busy():
return
var token := _token()
if token.is_empty():
_show_toast("登录信息失效")
return
_set_busy(true)
var result: Dictionary = await _activity_api.clean_user_logs(token)
_set_busy(false)
if not result.get("ok", false):
_show_toast(_response_status_text(result, "清空失败"))
return
_page_index = 1
await render()
func _add_row(parent: Control, row: Dictionary, index: int) -> void:
var holder := Control.new()
holder.name = "LogRow%s" % index
holder.custom_minimum_size = Vector2(462.0, 56.0)
holder.size = Vector2(462.0, 56.0)
parent.add_child(holder)
_ui.add_nine_patch(holder, "Bg", _log_item_bg, Vector2.ZERO, holder.size, Vector4(25.0, 25.0, 1.0, 1.0))
_ui.add_panel_label(holder, "Text", _format_row(row), Vector2(16.0, 3.0), Vector2(430.0, 50.0), 20, Color.html("#753f24"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
func _format_row(row: Dictionary) -> String:
if _tab_index == 1:
return "%s %s" % [_format_timestamp(int(row.get("created_at", row.get("time", 0)))), str(row.get("message", row.get("content", "")))]
var type_text := _player_log_action(int(row.get("type", -1)))
var player := _player_data()
var actor := "" if int(row.get("user_id", row.get("uid", 0))) == int(player.get("user_id", player.get("id", 0))) else str(row.get("be_user_nickname", row.get("name", "玩家")))
var item_id := int(row.get("item_id", 0))
var item_text := ""
if item_id > 0:
item_text = _game_config.get_item_name(item_id)
var num := int(row.get("num", 0))
if num > 0:
item_text += "x%s" % num
return "%s %s %s %s" % [_format_timestamp(int(row.get("time", row.get("created_at", 0)))), actor, type_text, item_text]
func _player_log_action(type: int) -> String:
match type:
0:
return "购买"
1:
return "卖出"
2:
return "种植"
3:
return "收获"
4:
return "偷取了"
5:
return "对植物进行了施肥"
6:
return "进行了锄地"
7:
return "进行了土地升级"
8:
return "切换了农场风格"
9:
return "喂了狗狗"
10:
return "使坏放虫"
11:
return "使坏种草"
12:
return "对土地浇水"
13:
return "对植物除虫"
14:
return "对植物除草"
15:
return "扩建了1块土地"
16:
return "进行了房屋升级"
17:
return "被偷了"
18:
return "狗狗抓住"
19:
return "被狗狗抓住"
20:
return "给你放虫"
21:
return "给你种草"
22, 24:
return "帮你浇水"
23:
return "帮你放虫"
_:
return "操作"