2026-07-10 17:04:54 +08:00
|
|
|
|
using System;
|
2026-07-10 16:11:09 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEngine;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
using UnityEngine.UI;
|
2026-07-10 16:11:09 +08:00
|
|
|
|
using Kill.Managers;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
using Kill.Network;
|
2026-07-13 14:17:12 +08:00
|
|
|
|
using Kill.UI;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
|
2026-07-10 16:11:09 +08:00
|
|
|
|
public class SelectCountry : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public GameObject countryPrefab;
|
|
|
|
|
|
public Transform countryParent;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
public Button submitButton;
|
2026-07-13 14:17:12 +08:00
|
|
|
|
public Button backButton;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
public InputField searchInput;
|
2026-07-13 14:17:12 +08:00
|
|
|
|
public ScrollRect scrollRect;
|
2026-07-10 16:11:09 +08:00
|
|
|
|
LanguageManager.Country selectCountry;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
private bool _hasSelection;
|
2026-07-13 14:17:12 +08:00
|
|
|
|
private string _originalCode;
|
2026-07-10 17:04:54 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 未选中 选中
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Color[] textColors;
|
|
|
|
|
|
|
|
|
|
|
|
private List<SelectCountryItem> _items = new List<SelectCountryItem>();
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 确认回调:code 为选中的国家代码,null 表示返回/取消
|
|
|
|
|
|
/// </summary>
|
2026-07-10 17:04:54 +08:00
|
|
|
|
public System.Action<string> onConfirm;
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="code">当前选中的国家代码</param>
|
|
|
|
|
|
/// <param name="showBackButton">是否显示返回按钮(主页不显示)</param>
|
|
|
|
|
|
public void Init(string code, bool showBackButton = true)
|
2026-07-10 16:11:09 +08:00
|
|
|
|
{
|
2026-07-13 14:17:12 +08:00
|
|
|
|
_originalCode = code;
|
|
|
|
|
|
|
2026-07-10 17:04:54 +08:00
|
|
|
|
countryPrefab.SetActive(false);
|
|
|
|
|
|
// 清理旧 item
|
|
|
|
|
|
foreach (var item in _items)
|
|
|
|
|
|
Destroy(item.gameObject);
|
|
|
|
|
|
_items.Clear();
|
|
|
|
|
|
_hasSelection = false;
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
// 返回按钮
|
|
|
|
|
|
if (backButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
backButton.gameObject.SetActive(showBackButton);
|
|
|
|
|
|
backButton.onClick.RemoveAllListeners();
|
|
|
|
|
|
backButton.onClick.AddListener(OnBack);
|
|
|
|
|
|
if (showBackButton)
|
|
|
|
|
|
UIManager.Instance.RegisterBackAction(OnBack);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 17:04:54 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
// 自动滚动到选中项
|
|
|
|
|
|
ScrollToSelected();
|
|
|
|
|
|
|
2026-07-10 17:04:54 +08:00
|
|
|
|
UpdateSubmitButton();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
/// <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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 17:04:54 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async void OnSubmit()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_hasSelection) return;
|
|
|
|
|
|
await UpdateCountryCodeAsync(selectCountry.code);
|
2026-07-10 16:11:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 17:04:54 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新用户国家代码
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async System.Threading.Tasks.Task UpdateCountryCodeAsync(string code)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var requestData = new CountryCodeRequest
|
|
|
|
|
|
{
|
|
|
|
|
|
country_code = code
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-13 14:17:12 +08:00
|
|
|
|
var response = await NetworkCtrl.Instance.Put<NoDataResponse>("/api/v1/user/country-code", requestData);
|
2026-07-10 17:04:54 +08:00
|
|
|
|
|
|
|
|
|
|
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}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2026-07-10 16:11:09 +08:00
|
|
|
|
}
|