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

139 lines
5.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class_name PayPanel
extends PanelModule
# 充值/充值入口面板:
# - 负责充值、金豆购买等配置展示和模拟购买流程。
# - 海外 H5 首版不接真实支付 SDK本面板只保留 UI 和后端接口入口。
# - 商品卡片不保存全局状态,支付结果通过 callbacks 更新玩家资源。
const NumberFormatterScript := preload("res://scripts/core/number_formatter.gd")
var _pay_api
var _tab_index := 0
var _content: Control
func setup(options: Dictionary) -> void:
super.setup(options)
_pay_api = options.get("pay_api")
func open() -> void:
_close_modal(false)
_tab_index = 0
var common_path: String = _texture_provider.atlas_path("common")
var panel: Control = _ui.create_common_panel_shell("PayPanel", Vector2(600.0, 790.0), "panel_icon_pay", common_path, "panel_title_pay", common_path)
_ui.add_content_panel_background(panel, "PayInner", Vector2(78.0, 238.0), Vector2(484.0, 550.0))
_create_tab_bar(panel, "PayTabs", ["金豆充值"], Vector2(93.0, 189.0), _tab_index, Callable(self, "_on_tab_pressed"))
_content = Control.new()
_content.name = "PayContent"
_content.position = Vector2(83.0, 242.0)
_content.size = Vector2(476.0, 540.0)
panel.add_child(_content)
_open_modal(panel)
render()
func _on_tab_pressed(index: int) -> void:
_tab_index = 0
var panel := _content.get_parent() as Control if _content != null else null
var tabs := panel.get_node_or_null("PayTabs") as Control if panel != null else null
_update_tab_bar(tabs, _tab_index)
render()
func render() -> void:
if _content == null:
return
_clear_children(_content)
var rows := _filter_rows(_tab_index)
if rows.is_empty():
_ui.add_panel_label(_content, "Empty", "暂无充值配置", Vector2(6.0, 196.0), Vector2(464.0, 52.0), 26, Color.html("#753f24"), 0, Color.TRANSPARENT)
return
for index in range(mini(rows.size(), 6)):
var row := rows[index]
var col := index % 3
var row_index := index / 3
var card_position := Vector2(10.0 + float(col) * 145.0, 10.0 + float(row_index) * 262.0)
_add_card(_content, row, index, card_position)
func _filter_rows(tab_index: int) -> Array[Dictionary]:
var result: Array[Dictionary] = []
for raw_row in _game_config.get_pay_config_list():
if not raw_row is Dictionary:
continue
var row: Dictionary = raw_row.duplicate(true)
var id := int(row.get("id", 0))
var is_gold := int(row.get("gold", 0)) > 0 or id > 6
if is_gold:
result.append(row)
result.sort_custom(func(left: Dictionary, right: Dictionary) -> bool:
return int(left.get("id", 0)) < int(right.get("id", 0))
)
return result
func _add_card(parent: Control, row: Dictionary, index: int, position: Vector2) -> void:
var holder := Control.new()
holder.name = "PayItem%s" % index
holder.position = position
holder.size = Vector2(134.0, 255.0)
holder.pivot_offset = holder.size * 0.5
holder.mouse_filter = Control.MOUSE_FILTER_STOP
parent.add_child(holder)
_ui.add_texture(holder, "Bg", _texture_provider.standalone("res://assets/egret/assets/game/pay/pay_item_bg.png"), Vector2.ZERO, Vector2(134.0, 224.0), TextureRect.STRETCH_SCALE)
var icon_prefix := "pay_g"
var icon_path := "res://assets/egret/assets/game/pay/%s%s.png" % [icon_prefix, index + 1]
_ui.add_texture(holder, "PayIcon", _texture_provider.standalone(icon_path, _texture_provider.standalone("res://assets/egret/assets/game/pay/pay_d1.png")), Vector2(25.0, 31.0), Vector2(85.0, 75.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
_ui.add_texture(holder, "ValueBar", _texture_provider.standalone("res://assets/egret/assets/game/pay/pay_bar.png"), Vector2(0.0, 126.0), Vector2(134.0, 36.0), TextureRect.STRETCH_SCALE)
var currency_icon: Texture2D = _texture_provider.common("sicon_gold")
_ui.add_texture(holder, "Currency", currency_icon, Vector2(12.0, 132.0), Vector2(32.0, 31.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
_ui.add_panel_label(holder, "Value", NumberFormatterScript.compact(_pay_value(row)), Vector2(43.0, 133.0), Vector2(88.0, 31.0), 22, Color.html("#f7b607"), 2, Color.html("#7d4b21"), HORIZONTAL_ALIGNMENT_LEFT)
_ui.add_texture_button(holder, "Buy", _texture_provider.common("c_btn2"), Vector2(26.0, 179.0), Vector2(88.0, 44.0), "购买", Callable(self, "_buy_item").bind(row.duplicate(true)), 22)
_ui.add_panel_label(holder, "Price", "%s" % int(row.get("rmb", 0)), Vector2(3.0, 228.0), Vector2(132.0, 27.0), 22, Color.html("#ff9b73"), 2, Color.WHITE)
func _pay_value(row: Dictionary) -> int:
return int(row.get("gold", 0))
func _buy_item(row: Dictionary) -> void:
if _is_busy():
return
var token := _token()
var pay_id := int(row.get("id", 0))
if token.is_empty() or pay_id <= 0:
_show_toast("登录信息失效")
return
_set_busy(true)
var result: Dictionary = await _pay_api.buy(token, pay_id)
_set_busy(false)
if not result.get("ok", false):
_show_toast(_response_status_text(result, "充值下单失败"))
return
var url := _payment_url(result)
if url.is_empty():
_show_toast("充值下单成功")
return
_show_toast("正在打开支付")
_open_payment_url(url)
func _payment_url(result: Dictionary) -> String:
var data = _response_data(result, {})
if data is Dictionary:
return str(data.get("url", data.get("pay_url", "")))
return ""
func _open_payment_url(url: String) -> void:
if url.strip_edges().is_empty():
return
if Engine.has_singleton("JavaScriptBridge"):
var bridge := Engine.get_singleton("JavaScriptBridge")
if bridge != null:
bridge.call("eval", "window.location.href = %s;" % JSON.stringify(url), true)
return
OS.shell_open(url)