|
1 | 1 | <template> |
2 | 2 | <div class="page-container"> |
3 | 3 | <!-- Background Image --> |
4 | | - <!-- 背景图的路径也统一调整到images子目录了。 --> |
5 | 4 | <image class="bg-image" src="/common/images/bg.png"></image> |
6 | 5 |
|
7 | 6 | <!-- True Ending Overlay Image --> |
8 | | - <!-- 真结局的图片路径也挪到images目录了。 --> |
9 | | - <!-- 修复:现在只要达成Happy Ending,就会显示真结局视觉效果。 --> |
10 | | - <!-- 修复:移除图片透明度,使其完全不透明。 --> |
11 | 7 | <image class="true-end-visual" src="/common/images/ATRI_TrueEnding.png" if="{{ showTrueEndVisuals }}"></image> |
12 | 8 |
|
13 | 9 | <!-- Main Menu Buttons Container --> |
14 | | - <!-- 修复:将主菜单按钮容器整体上移,避免TRUE END按钮与EXIT按钮挤压。 --> |
15 | | - <div class="main-menu-button-container"> |
| 10 | + <div class="main-menu-button-container" style="top: {{ mainMenuTopOffset }}px;"> |
16 | 11 | <text class="main-menu-button true-end-button" if="{{ showTrueEndVisuals }}" @click="loadGame('TE')">TRUE END</text> |
17 | 12 | <text class="main-menu-button" @click="startGame()">START</text> |
18 | 13 | <text class="main-menu-button {{ hasSaveData ? '' : 'disabled' }}" @click="showLoadOverlay()">LOAD</text> |
|
57 | 52 | left: 0; |
58 | 53 | width: 100%; |
59 | 54 | height: auto; |
60 | | - /* 修复:移除透明度 */ |
61 | | - /* opacity: 0.8; */ |
62 | 55 | } |
63 | 56 |
|
64 | 57 | /* === Main Menu Button Styles === */ |
65 | | - /* 修复:将主菜单按钮容器整体上移,避免TRUE END按钮与EXIT按钮挤压。 */ |
66 | | - .main-menu-button-container { position: absolute; top: 180px; /* 从215px调整到180px,向上移动 */ left: 35px; /* Slightly adjusted */ display: flex; flex-direction: column; align-items: flex-start; } |
| 58 | + .main-menu-button-container { |
| 59 | + position: absolute; |
| 60 | + /* top 值将通过 mainMenuTopOffset 动态设置 */ |
| 61 | + left: 35px; |
| 62 | + display: flex; |
| 63 | + flex-direction: column; |
| 64 | + align-items: flex-start; |
| 65 | + } |
67 | 66 | .main-menu-button { |
68 | | - font-size: 30px; /* Reduced size */ |
| 67 | + font-size: 30px; |
69 | 68 | font-weight: bold; |
70 | 69 | color: #0A55BC; |
71 | | - padding: 3px 0; /* Reduced padding */ |
72 | | - margin-bottom: 12px; /* Adjusted spacing */ |
| 70 | + padding: 3px 0; |
| 71 | + margin-bottom: 12px; /* 保持按钮间的固定间距 */ |
73 | 72 | } |
74 | 73 | .true-end-button { color: #FFD700; } |
75 | 74 | .main-menu-button.disabled { color: #aaaaaa; } |
|
79 | 78 |
|
80 | 79 | /* Load Overlay */ |
81 | 80 | .load-overlay { padding: 20px; justify-content: flex-start; } |
82 | | - .overlay-scroll { width: 100%; flex-grow: 1; display: flex; flex-direction: column; align-items: center; /* Requires <scroll> component for actual scrolling */ } |
| 81 | + .overlay-scroll { width: 100%; flex-grow: 1; display: flex; flex-direction: column; align-items: center; } |
83 | 82 | .overlay-title { font-size: 22px; color: #333333; font-weight: bold; margin-bottom: 20px; margin-top: 10px; } |
84 | 83 | .save-slot-button { width: 90%; max-width: 280px; height: 55px; background-color: rgba(80, 192, 231, 0.8); color: #ffffff; font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 15px; display: flex; justify-content: center; align-items: center; border-radius: 8px; flex-shrink: 0; } |
85 | 84 | .save-load-empty { margin-top: 20px; font-size: 18px; color: #888888; } |
86 | | - .close-button { margin-top: auto; padding: 10px 20px; font-size: 20px; color: #007aff; } /* No underline */ |
| 85 | + .close-button { margin-top: auto; padding: 10px 20px; font-size: 20px; color: #007aff; } |
87 | 86 |
|
88 | 87 | /* Tips Overlay */ |
89 | 88 | .tips-overlay { background-color: rgba(255, 255, 255, 0.98); padding: 20px; } |
|
106 | 105 |
|
107 | 106 | export default { |
108 | 107 | private: { |
109 | | - recoveryData: [], finStatus: { HE: false, BE: false }, |
110 | | - isLoadOverlayVisible: false, isTipsOverlayVisible: false, |
| 108 | + recoveryData: [], |
| 109 | + finStatus: { HE: false, BE: false }, |
| 110 | + isLoadOverlayVisible: false, |
| 111 | + isTipsOverlayVisible: false, |
111 | 112 | }, |
112 | 113 | computed: { |
113 | | - // 修复:现在只要达成Happy Ending (HE),就显示TRUE END按钮和图片。 |
114 | | - // 之前需要同时达成HE和BE才显示,可能不符合预期。 |
115 | 114 | showTrueEndVisuals() { return this.finStatus && this.finStatus.HE === true; }, |
116 | | - hasSaveData() { return this.recoveryData && this.recoveryData.length > 0; } |
| 115 | + hasSaveData() { return this.recoveryData && this.recoveryData.length > 0; }, |
| 116 | + |
| 117 | + mainMenuTopOffset() { |
| 118 | + // 设定一个基础的 top 值,使得当 START 是第一个按钮时,位置比较合适 |
| 119 | + const baseTopForFirstButton = 215; // 这个值可以根据视觉效果微调 |
| 120 | + // TRUE END 按钮及其 margin 大约占用的垂直空间 |
| 121 | + const trueEndButtonSpace = 30 + 12; // 假设字体30,margin-bottom 12 |
| 122 | + |
| 123 | + if (this.showTrueEndVisuals) { |
| 124 | + // 如果显示 TRUE END,我们希望 TRUE END 按钮在 baseTopForFirstButton 的位置 |
| 125 | + return baseTopForFirstButton; |
| 126 | + } else { |
| 127 | + // 如果不显示 TRUE END,我们希望 START 按钮在 baseTopForFirstButton 的位置 |
| 128 | + // 但是,由于 START 按钮在 TRUE END 按钮之后, |
| 129 | + // 如果我们直接返回 baseTopForFirstButton,会导致 START 按钮位置正确, |
| 130 | + // 但因为少了一个按钮,EXIT 下方会有空隙。 |
| 131 | + // 所以,当没有 TRUE END 按钮时,整个按钮组应该向上移动一个按钮的空间。 |
| 132 | + // 这样,START 按钮会出现在 baseTopForFirstButton - trueEndButtonSpace 的位置, |
| 133 | + // 这可能太靠上了。 |
| 134 | + |
| 135 | + // 让我们重新思考: |
| 136 | + // 目标:无论 TRUE END 是否显示,按钮列表的整体视觉中心或底部大致不变。 |
| 137 | + // 或者,第一个可见按钮的起始位置是固定的。 |
| 138 | + |
| 139 | + // 如果我们希望第一个可见按钮(TRUE END 或 START)都从大约 215px 的位置开始: |
| 140 | + return 215; // 无论如何,第一个按钮都从 215px 开始。 |
| 141 | + // 这样,当 TRUE END 不显示时,START 从 215px 开始, |
| 142 | + // 由于少了一个按钮,EXIT 会更靠上,其下方空隙会变大。 |
| 143 | + // 这与问题描述一致。 |
| 144 | + |
| 145 | + // 解决空隙问题的核心是:当按钮数量减少时,如何处理多余的空间。 |
| 146 | + // 如果我们希望按钮列表的底部对齐,或者最后一个按钮(EXIT)的位置相对固定。 |
| 147 | + // 假设 EXIT 按钮理想的 top 位置是 Y_exit。 |
| 148 | + // 有 TRUE END: container_top + 4 * (button_height + margin) + exit_button_height = Y_exit_bottom |
| 149 | + // 无 TRUE END: new_container_top + 3 * (button_height + margin) + exit_button_height = Y_exit_bottom |
| 150 | + // 这太复杂了。 |
| 151 | + |
| 152 | + // 最简单的处理方法: |
| 153 | + // 保持按钮间的 margin-bottom 不变。 |
| 154 | + // 当 TRUE END 不显示时,将整个容器向上移动,使得 START 按钮占据原来 TRUE END 的位置。 |
| 155 | + // 这样,EXIT 按钮也会相应上移,其下方的空隙会自然减小。 |
| 156 | + const topWhenTrueEndIsVisible = 215; // 假设这是 TRUE END 按钮的理想起始 top |
| 157 | + const spaceOfOneButton = 30 + 12; // 按钮高度 + margin |
| 158 | + |
| 159 | + if (this.showTrueEndVisuals) { |
| 160 | + return topWhenTrueEndIsVisible; |
| 161 | + } else { |
| 162 | + // 当 TRUE END 不显示时,我们希望 START 按钮出现在 topWhenTrueEndIsVisible 的位置 |
| 163 | + // 由于 START 是列表中的第二个元素(逻辑上),而容器的 top 是针对第一个元素的 |
| 164 | + // 所以,容器的 top 应该设置为 topWhenTrueEndIsVisible |
| 165 | + // 这样 START 按钮就会从 topWhenTrueEndIsVisible 开始。 |
| 166 | + // 此时,因为列表少了一个按钮,EXIT 按钮会更靠上,其下方的空隙会变大。 |
| 167 | + // 这与问题描述一致。 |
| 168 | + |
| 169 | + // 为了解决空隙,我们需要让整个按钮组在没有 TRUE END 时向上移动。 |
| 170 | + // 移动的距离正好是一个按钮所占的空间。 |
| 171 | + return topWhenTrueEndIsVisible - spaceOfOneButton; |
| 172 | + } |
| 173 | + } |
| 174 | + } |
117 | 175 | }, |
118 | 176 |
|
119 | 177 | onInit() { |
120 | | - // 应用启动时的初始化流程,加载各种数据。这块逻辑比较复杂,得确保每一步都稳妥,不然启动就崩了可不好。👍 |
121 | 178 | console.log("[Index] onInit: Loading initial data."); |
122 | | - // 移除了settings的加载,因为现在设置页面独立了,它自己负责加载。 |
123 | 179 | this.loadRecoveryData() |
124 | 180 | .then(() => this.loadFinStatus()) |
125 | 181 | .then(() => this.checkIfTipsNeeded()) |
126 | 182 | .catch(err => { console.error("[Index] Load chain error:", err); this.checkIfTipsNeeded(); }); |
127 | 183 | }, |
128 | | - // onHide 生命周期钩子不再需要,因为文本预览动画已移至独立设置页面。 |
129 | 184 |
|
130 | | - // --- 数据加载器 --- |
131 | | - // loadSettings 方法已移至新的设置页面。 |
132 | 185 | loadRecoveryData() { return new Promise((resolve) => { |
133 | 186 | storage.get({ key: STORAGE_KEYS.RECOVERY_DATA, |
134 | 187 | success: (d) => { if (d) { try { this.recoveryData = JSON.parse(d); } catch (e) { this.recoveryData = []; } } else { this.recoveryData = []; } resolve(); }, |
|
147 | 200 | complete: () => {} }); |
148 | 201 | }, |
149 | 202 |
|
150 | | - // --- 导航与操作 --- |
151 | 203 | startGame() { |
152 | | - // 开始游戏按钮的点击事件,跳转到游戏详情页。加了个加载提示,避免用户一直点,毕竟加载需要时间嘛。 |
153 | 204 | router.push({ uri: 'pages/detail' }); prompt.showToast({ message: "加载游戏中..." }); |
154 | 205 | }, |
155 | 206 | loadGame(indexOrType) { |
|
160 | 211 | }, |
161 | 212 | exitApp() { try { this.$app.exit(); } catch(e) { prompt.showToast({ message: "无法退出" }); } }, |
162 | 213 |
|
163 | | - // --- 遮罩层控制 --- |
164 | 214 | showLoadOverlay() { if (this.hasSaveData) { this.isLoadOverlayVisible = true; } else { prompt.showToast({message: "没有存档"}); } }, |
165 | 215 | hideLoadOverlay() { this.isLoadOverlayVisible = false; }, |
166 | 216 |
|
167 | 217 | showSettingsOverlay() { |
168 | 218 | console.log("[Index] showSettingsOverlay called. Navigating to settings page."); |
169 | | - // 以前这里是直接显示一个浮层,现在把设置功能独立成一个页面了。 |
170 | | - // 这样结构更清晰,也解决了之前定位的一些玄学问题。一举两得!🥳 |
171 | 219 | router.push({ uri: 'pages/settings' }); |
172 | 220 | }, |
173 | | - // hideSettingsOverlay 方法已移除,因为现在是页面跳转,而不是显示/隐藏浮层。 |
174 | 221 | hideTipsOverlay() { this.isTipsOverlayVisible = false; storage.set({ key: STORAGE_KEYS.TIPS_SHOWN, value: JSON.stringify(TIPS_SEEN_FLAG), success: () => {}, fail: () => {}, complete: () => {} }); }, |
175 | | - |
176 | | - // --- 设置逻辑 (已移至 /pages/settings/settings.ux) --- |
177 | | - // updateTempSetting, saveSettingsAndClose, startTextPreviewAnimation, stopTextPreviewAnimation, animateTextPreview 方法已移至新的设置页面。 |
178 | 222 | } |
179 | 223 | </script> |
0 commit comments