using System; using System.Collections.Generic; using System.Linq; using Logic.CrashSight; using Logic.Multilingual; using TH1_Core.Events; using TH1_Logic.Oss; using TH1_Logic.Questionnaire; using TH1Resource; using TMPro; using UnityEngine; using UnityEngine.UI; #if STEAM_CHANNEL || STEAMWORKS_NET using Steamworks; #endif namespace TH1_UI.View.Outside { public class UIOutsideQuestionnaireView : Base.View { private const string DataAssetPath = "DataAssets/QuestionnaireDataAssets"; private const string QuestionPrefabPath = "Prefab/UI/Outside/UIOutsideQuestionnaireQuestion"; private const string OptionPrefabPath = "Prefab/UI/Outside/UIOutsideQuestionnaireOption"; public Button CloseButton; public Button SubmitButton; public Button RefillButton; public TextMeshProUGUI TitleText; public TextMeshProUGUI DescriptionText; public TextMeshProUGUI StatusText; public TextMeshProUGUI SubmitButtonText; public TextMeshProUGUI RefillButtonText; public TextMeshProUGUI CloseButtonText; public Transform QuestionListContent; public GameObject QuestionPrefab; public GameObject OptionPrefab; public ViDelegateAssisstant.Dele OnBtnCloseClick; private readonly List _questionItems = new List(); private readonly List _listItems = new List(); private QuestionnaireDataAssets _dataAssets; private QuestionnaireInfo _questionnaireInfo; private QuestionnaireAnswerSheet _currentSheet; private bool _isUploading; private bool _layoutBuilt; private bool _showExpired; private Transform _sidebarContent; private Transform _rightBody; private Transform _rightFooter; private TextMeshProUGUI _expiredToggleText; private TextMeshProUGUI _rightHeaderTitle; private TextMeshProUGUI _rightHeaderSubtitle; private Button _recordsButton; private Button _startButton; private TextMeshProUGUI _recordsButtonText; private TextMeshProUGUI _startButtonText; protected override void OnInit() { base.OnInit(); EnsureLayout(); } public void SetContent(ShowUIOutsideQuestionnaire evt) { EnsureLayout(); LoadAssetsIfNeeded(); CloseButton.onClick.RemoveAllListeners(); CloseButton.onClick.AddListener(OnCloseClicked); SetUploading(false); var selected = ResolveInitialQuestionnaire(evt); if (selected != null && selected.GetEffectiveStatus(DateTime.UtcNow) == QuestionnaireStatus.Expired) { _showExpired = true; } BuildQuestionnaireList(); if (selected == null) { ShowEmptyState("暂无可填写问卷"); return; } SelectQuestionnaire(selected); } public void OnCloseView() { } public static string ResolveText(string raw) { if (string.IsNullOrEmpty(raw)) return string.Empty; if (uint.TryParse(raw, out var id)) { return MultilingualManager.Instance.GetMultilingualText(id); } return raw; } public static TextMeshProUGUI CreateText(Transform parent, string objectName, string text, float fontSize, Color color, TextAlignmentOptions alignment) { var go = new GameObject(objectName, typeof(RectTransform), typeof(TextMeshProUGUI)); go.transform.SetParent(parent, false); var label = go.GetComponent(); label.text = text; label.fontSize = fontSize; label.color = color; label.alignment = alignment; label.enableWordWrapping = false; label.raycastTarget = false; return label; } private void LoadAssetsIfNeeded() { if (_dataAssets == null) { _dataAssets = ResourceLoader.Load(DataAssetPath); } if (QuestionPrefab == null) { QuestionPrefab = ResourceLoader.Load(QuestionPrefabPath); } if (OptionPrefab == null) { OptionPrefab = ResourceLoader.Load(OptionPrefabPath); } } private QuestionnaireInfo ResolveInitialQuestionnaire(ShowUIOutsideQuestionnaire evt) { if (_dataAssets == null) { Debug.LogError("[UIOutsideQuestionnaireView] QuestionnaireDataAssets is missing."); return null; } QuestionnaireInfo selected = null; if (!string.IsNullOrEmpty(evt.QuestionnaireId)) { _dataAssets.GetQuestionnaireInfo(evt.QuestionnaireId, out selected); } selected ??= _dataAssets.GetDefaultQuestionnaire(); if (selected != null && selected.IsVisibleAt(DateTime.UtcNow)) return selected; return GetVisibleQuestionnaires().FirstOrDefault(); } private List GetVisibleQuestionnaires() { return _dataAssets != null ? _dataAssets.GetVisibleQuestionnaires(DateTime.UtcNow) : new List(); } private void SelectQuestionnaire(QuestionnaireInfo info) { if (info == null) { ShowEmptyState("暂无可填写问卷"); return; } _questionnaireInfo = info; _currentSheet = QuestionnaireAnswerStore.Instance.GetLatestAnswerSheet(info.QuestionnaireId); if (info.GetEffectiveStatus(DateTime.UtcNow) == QuestionnaireStatus.Expired && !_showExpired) { _showExpired = true; BuildQuestionnaireList(); } UpdateListSelection(); ShowDetail(); } private void BuildQuestionnaireList() { if (_sidebarContent == null) return; DestroyChildren(_sidebarContent); _listItems.Clear(); var items = GetVisibleQuestionnaires(); var featured = items.Where(item => item.GetEffectiveStatus(DateTime.UtcNow) == QuestionnaireStatus.Featured).ToList(); var longTerm = items.Where(item => item.GetEffectiveStatus(DateTime.UtcNow) == QuestionnaireStatus.LongTerm).ToList(); var expired = items.Where(item => item.GetEffectiveStatus(DateTime.UtcNow) == QuestionnaireStatus.Expired).ToList(); CreateSectionHeader(_sidebarContent, "当期问卷"); CreateQuestionnaireListItems(featured, "暂无当期问卷"); CreateDivider(_sidebarContent); CreateSectionHeader(_sidebarContent, "长期问卷"); CreateQuestionnaireListItems(longTerm, "暂无长期问卷"); CreateDivider(_sidebarContent); CreateExpiredHeader(expired.Count); if (_showExpired) { CreateQuestionnaireListItems(expired, "暂无往期问卷"); } else if (expired.Count > 0) { var hint = CreateText(_sidebarContent, "ExpiredHiddenHint", $"{expired.Count} 份往期问卷已收起", 17f, new Color(0.62f, 0.66f, 0.64f, 1f), TextAlignmentOptions.Left); hint.enableWordWrapping = true; } if (items.Count == 0) { var empty = CreateText(_sidebarContent, "EmptyList", "暂无可显示问卷", 18f, new Color(0.74f, 0.76f, 0.72f, 1f), TextAlignmentOptions.Left); empty.enableWordWrapping = true; } } private void CreateQuestionnaireListItems(List infos, string emptyText) { if (infos == null || infos.Count == 0) { var empty = CreateText(_sidebarContent, "Empty", emptyText, 17f, new Color(0.62f, 0.66f, 0.64f, 1f), TextAlignmentOptions.Left); empty.enableWordWrapping = true; return; } foreach (var info in infos) { CreateQuestionnaireListItem(info); } } private void CreateQuestionnaireListItem(QuestionnaireInfo info) { var row = new GameObject("QuestionnaireItem", typeof(RectTransform), typeof(Image), typeof(Button), typeof(VerticalLayoutGroup), typeof(LayoutElement)); row.transform.SetParent(_sidebarContent, false); var image = row.GetComponent(); image.color = new Color(1f, 1f, 1f, 0.055f); var layout = row.GetComponent(); layout.padding = new RectOffset(12, 12, 10, 10); layout.spacing = 4f; layout.childControlWidth = true; layout.childControlHeight = true; layout.childForceExpandWidth = true; layout.childForceExpandHeight = false; var layoutElement = row.GetComponent(); layoutElement.minHeight = 76f; layoutElement.preferredHeight = 82f; var button = row.GetComponent