killapp/Assets/Scripts/UI/Components/SelectCountry.cs
“虞渠成” c62ae623e8 feat: 新增国家选择跳过功能,首页可跳过国家选择
新增数据管理器中关联用户账号的跳过标记存储方法,修改首页逻辑,当用户未设置国家且未跳过时弹出国家选择界面,新增选择国家界面的跳过按钮,跳过后本地保存标记不再弹出。
2026-09-23 10:51:38 +08:00

271 lines
8.4 KiB
C#
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.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Kill.Managers;
using Kill.Network;
using Kill.UI;
using Kill.UI.Components;
public class SelectCountry : MonoBehaviour
{
public GameObject countryPrefab;
public Transform countryParent;
public Button submitButton;
public Button backButton;
public Button skipButton;
public InputField searchInput;
public ScrollRect scrollRect;
LanguageManager.Country selectCountry;
private bool _hasSelection;
private string _originalCode;
/// <summary>
/// 未选中 选中
/// </summary>
public Color[] textColors;
private List<SelectCountryItem> _items = new List<SelectCountryItem>();
private bool _showSkipButton;
/// <summary>
/// 确认回调code 为选中的国家代码null 表示返回/取消
/// </summary>
public System.Action<string> onConfirm;
/// <summary>
/// 初始化
/// </summary>
/// <param name="code">当前选中的国家代码</param>
/// <param name="showBackButton">是否显示返回按钮(个人信息页显示,首页不显示)</param>
/// <param name="showSkipButton">是否显示跳过按钮(首页显示,个人信息页不显示)</param>
public void Init(string code, bool showBackButton = true, bool showSkipButton = false)
{
_originalCode = code;
_showSkipButton = showSkipButton;
countryPrefab.SetActive(false);
// 清理旧 item
foreach (var item in _items)
Destroy(item.gameObject);
_items.Clear();
_hasSelection = false;
// 返回按钮
if (backButton != null)
{
backButton.gameObject.SetActive(showBackButton);
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(OnBack);
if (showBackButton)
UIManager.Instance.RegisterBackAction(OnBack);
}
// 跳过按钮不选择国家直接关闭onConfirm(null),不更新国家)
if (skipButton != null)
{
skipButton.gameObject.SetActive(showSkipButton);
skipButton.onClick.RemoveAllListeners();
skipButton.onClick.AddListener(OnBack);
}
if (LanguageManager.Instance == null || LanguageManager.Instance.countryList == null)
return;
foreach (var country in LanguageManager.Instance.countryList)
{
var go = Instantiate(countryPrefab, countryParent);
var item = go.AddComponent<SelectCountryItem>();
item.Init(this, country);
_items.Add(item);
item.gameObject.SetActive(true);
}
// 绑定搜索
if (searchInput != null)
{
searchInput.onValueChanged.RemoveAllListeners();
searchInput.onValueChanged.AddListener(OnSearchChanged);
}
// 设置默认选中code 为空时不选中)
if (!string.IsNullOrEmpty(code))
SelectCountryByCode(code);
// 自动滚动到选中项
ScrollToSelected();
UpdateSubmitButton();
}
/// <summary>
/// 返回按钮点击
/// </summary>
private void OnBack()
{
onConfirm?.Invoke(null);
}
/// <summary>
/// 滚动到当前选中的国家项(居中显示)
/// </summary>
private void ScrollToSelected()
{
if (scrollRect == null || !_hasSelection) return;
int index = _items.FindIndex(i => i.Country.code == selectCountry.code);
if (index < 0) return;
Canvas.ForceUpdateCanvases();
var itemRect = _items[index].GetComponent<RectTransform>();
float contentHeight = scrollRect.content.rect.height;
float viewportHeight = scrollRect.viewport.rect.height;
if (contentHeight <= viewportHeight) return;
// 计算目标滚动位置:使选中项居中
float maxScrollY = contentHeight - viewportHeight;
float itemCenterY = Mathf.Abs(itemRect.anchoredPosition.y) + itemRect.rect.height / 2;
float targetScrollY = itemCenterY - viewportHeight / 2;
targetScrollY = Mathf.Clamp(targetScrollY, 0, maxScrollY);
scrollRect.verticalNormalizedPosition = 1f - targetScrollY / maxScrollY;
}
private void OnSearchChanged(string keyword)
{
foreach (var item in _items)
{
item.gameObject.SetActive(item.MatchKeyword(keyword));
}
}
public void SelectCountryByCode(string code)
{
_hasSelection = !string.IsNullOrEmpty(code);
foreach (var item in _items)
{
bool isSelected = _hasSelection && item.Country.code == code;
item.SetSelected(isSelected);
if (isSelected)
selectCountry = item.Country;
}
UpdateSubmitButton();
}
public string GetSelectedCode()
{
return _hasSelection ? selectCountry.code : null;
}
private void UpdateSubmitButton()
{
// 确认与跳过共用位置:选中显示确认、隐藏跳过;未选中显示跳过(仅首页场景)
if (submitButton != null)
{
submitButton.gameObject.SetActive(_hasSelection);
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (skipButton != null)
{
skipButton.gameObject.SetActive(_showSkipButton && !_hasSelection);
}
}
private async void OnSubmit()
{
if (!_hasSelection) return;
await UpdateCountryCodeAsync(selectCountry.code);
}
/// <summary>
/// 更新用户国家代码
/// </summary>
private async System.Threading.Tasks.Task UpdateCountryCodeAsync(string code)
{
LoadingUI.Show();
try
{
var requestData = new CountryCodeRequest
{
country_code = code
};
var response = await NetworkCtrl.Instance.Put<NoDataResponse>("/api/v1/user/country-code", requestData);
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
if (DataManager.Instance.userInfo != null)
DataManager.Instance.userInfo.country_code = code;
onConfirm?.Invoke(code);
},
onError: null
);
}
catch (Exception ex)
{
Debug.LogError($"更新国家代码失败: {ex.Message}");
}
LoadingUI.Hide();
}
}
internal class SelectCountryItem : MonoBehaviour
{
public LanguageManager.Country Country { get; private set; }
private SelectCountry _parent;
private Text _nameText;
private GameObject _selectGo;
private Color _selectedColor;
private Color _unselectedColor;
public void Init(SelectCountry parent, LanguageManager.Country country)
{
_parent = parent;
Country = country;
_nameText = transform.Find("name")?.GetComponent<Text>();
_selectGo = transform.Find("选中")?.gameObject;
_selectedColor = parent.textColors.Length > 0 ? parent.textColors[0] : Color.white;
_unselectedColor = parent.textColors.Length > 1 ? parent.textColors[1] : Color.gray;
// 显示国家名称(根据当前语言)
bool isChinese = LanguageManager.Instance != null && LanguageManager.Instance.languageType == LanguageManager.LanguageType.Chinese;
if (_nameText != null)
_nameText.text = isChinese ? country.name_zh : country.name_en;
// 点击事件
var btn = GetComponent<Button>();
if (btn == null)
btn = gameObject.AddComponent<Button>();
btn.onClick.AddListener(OnClick);
}
public void SetSelected(bool selected)
{
if (_nameText != null)
_nameText.color = selected ? _selectedColor : _unselectedColor;
if (_selectGo != null)
_selectGo.SetActive(selected);
}
public bool MatchKeyword(string keyword)
{
if (string.IsNullOrEmpty(keyword))
return true;
var k = keyword.ToLower();
return Country.name_zh.ToLower().Contains(k)
|| Country.name_en.ToLower().Contains(k)
|| Country.code.ToLower().Contains(k);
}
private void OnClick()
{
_parent.SelectCountryByCode(Country.code);
}
}