show_product.html 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. {include file="header" /}
  2. {if $m_style==1}
  3. <link rel="stylesheet" href="/assets/xtu/show-product.css?v=202608304-mobilefix6">
  4. {else}
  5. <link rel="stylesheet" href="/assets/xtu/show-product-bai.css?v=202620804-mobilefix6">
  6. {/if}
  7. <main class="show-product-page">
  8. <section class="show-product-hero">
  9. <div class="show-product-hero-media">
  10. <img src="{$thumb3}" alt="{$title}">
  11. </div>
  12. <div class="show-product-hero-overlay"></div>
  13. <div class="show-product-hero-content">
  14. <div class="show-product-hero-copy">
  15. {if !empty($title1)}
  16. <div class="show-product-hero-subtitle">{$title1}</div>
  17. {/if}
  18. <h1>{$title}</h1>
  19. {if !empty($title2)}
  20. <div class="show-product-hero-tagline">{$title2}</div>
  21. {/if}
  22. <div class="show-product-hero-actions">
  23. {if !empty($shopurl)}
  24. <a class="show-product-hero-btn show-product-hero-btn-light" href="{$shopurl}" target="_blank">{:cms_t('buy_now','立即购买')}</a>
  25. {/if}
  26. {if !empty($video)}
  27. <button class="show-product-hero-btn show-product-hero-btn-dark js-product-video-open" type="button" data-video="{$video}">
  28. {:cms_t('watch_video','观看视频')}
  29. <i class="bi bi-play-fill"></i>
  30. </button>
  31. {/if}
  32. </div>
  33. </div>
  34. </div>
  35. </section>
  36. <div class="show-product-video-modal" id="showProductVideoModal" hidden>
  37. <div class="show-product-video-modal__backdrop" data-product-modal-close></div>
  38. <div class="show-product-video-modal__dialog" role="dialog" aria-modal="true" aria-label="{:cms_t('watch_video','观看视频')}">
  39. <button class="show-product-video-modal__close" type="button" aria-label="{:cms_t('close','关闭')}" data-product-modal-close>×</button>
  40. <div class="show-product-video-modal__body">
  41. <video class="show-product-video-modal__player" controls playsinline preload="metadata"></video>
  42. </div>
  43. </div>
  44. </div>
  45. <?php $where = "project_id=".$id; ?>
  46. {yzn module="cms" action="lists" catid="9" where="$where" order="listorder asc,id desc" num="1" return="productBlocks" moreinfo="1"}
  47. {volist name="productBlocks" id="block"}
  48. <section class="show-product-story-section">
  49. <div class="content-1300-wrap">
  50. <div class="show-product-story-copy text-center">
  51. {if !empty($block.title_2_1)}
  52. <h2 class="spx-reveal">{$block.title_2_1}</h2>
  53. {/if}
  54. </div>
  55. <div class="show-product-story-media">
  56. {if !empty($block.thumb_2_pc)}
  57. <img class="show-product-story-image is-pc" src="{$block.thumb_2_pc}" alt="{$title}">
  58. {/if}
  59. {if !empty($block.thumb_2_wap)}
  60. <img class="show-product-story-image is-wap" src="{$block.thumb_2_wap}" alt="{$title}">
  61. {/if}
  62. </div>
  63. <div class="show-product-story-copy show-product-story-copy-bottom text-center">
  64. {if !empty($block.title_2_2)}
  65. <p class="spx-reveal spx-reveal--delay-1">{$block.title_2_2}</p>
  66. {/if}
  67. {if !empty($shopurl)}
  68. <div class="show-product-story-action">
  69. <a href="{$shopurl}" target="_blank" class="show-product-story-link">{:cms_t('learn_more','了解更多')}</a>
  70. </div>
  71. {/if}
  72. </div>
  73. </div>
  74. </section>
  75. <section class="spx-stage-three js-spx-stage-three">
  76. <div class="content-1300-wrap">
  77. <div class="spx-stage-three-copy">
  78. <div class="spx-stage-three-copy-switch">
  79. {if !empty($block.title_3_1)}
  80. <div class="spx-stage-three-title-layer js-spx-stage-three-title-layer">
  81. <h2 class="spx-stage-three-title">{$block.title_3_1|nl2br=###|raw}</h2>
  82. </div>
  83. {/if}
  84. <div class="spx-stage-three-texts js-spx-stage-three-texts">
  85. {if !empty($block.title_3_2)}
  86. <h3 class="spx-stage-three-subtitle">{$block.title_3_2|nl2br=###|raw}</h3>
  87. {/if}
  88. {if !empty($block.title_3_3)}
  89. <p class="spx-stage-three-text">{$block.title_3_3|nl2br=###|raw}</p>
  90. {/if}
  91. </div>
  92. </div>
  93. {if !empty($block.thumb_3_pc)}
  94. <div class="spx-stage-three-media">
  95. <img class="spx-stage-three-image" src="{$block.thumb_3_pc}" alt="{$title}">
  96. </div>
  97. {/if}
  98. </div>
  99. </div>
  100. </section>
  101. <section class="spx-stage-four js-spx-stage-four">
  102. <div class="content-1300-wrap">
  103. <div class="spx-stage-four-head">
  104. <div class="spx-stage-four-head-left">
  105. {if !empty($block.title_4_3)}
  106. <div class="spx-stage-kicker spx-reveal">{$block.title_4_3|nl2br=###|raw}</div>
  107. {/if}
  108. {if !empty($block.title_4_1)}
  109. <h2 class="spx-stage-four-title spx-reveal spx-reveal--delay-1">{$block.title_4_1|nl2br=###|raw}</h2>
  110. {/if}
  111. </div>
  112. <div class="spx-stage-four-head-right">
  113. {if !empty($block.title_4_2)}
  114. <div class="spx-stage-four-desc spx-reveal spx-reveal--delay-2">{$block.title_4_2|nl2br=###|raw}</div>
  115. {/if}
  116. </div>
  117. </div>
  118. <?php
  119. $stageFourMedia = !empty($block['thumb_4']) ? $block['thumb_4'] : (!empty($block['video_4']) ? $block['video_4'] : (!empty($block['thumb_4_wap']) ? $block['thumb_4_wap'] : (!empty($block['thumb_4_pc']) ? $block['thumb_4_pc'] : '')));
  120. $stageFourMediaExt = $stageFourMedia ? strtolower(pathinfo(parse_url($stageFourMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  121. $stageFourMediaIsVideo = in_array($stageFourMediaExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  122. ?>
  123. <div class="spx-stage-four-compare spx-stage-four-compare-single">
  124. <div class="spx-stage-four-card spx-stage-four-card-single">
  125. <div class="spx-stage-four-card-media">
  126. {if !empty($stageFourMedia)}
  127. {if $stageFourMediaIsVideo}
  128. <video class="spx-stage-four-video" src="<?php echo $stageFourMedia; ?>" autoplay muted loop playsinline preload="metadata"></video>
  129. {else /}
  130. <img class="spx-stage-four-image" src="<?php echo $stageFourMedia; ?>" alt="{$title}">
  131. {/if}
  132. {/if}
  133. </div>
  134. </div>
  135. </div>
  136. </div>
  137. </section>
  138. <?php
  139. $stageFiveMedia = !empty($block['thumb_5']) ? $block['thumb_5'] : '';
  140. $stageFiveMediaExt = $stageFiveMedia ? strtolower(pathinfo(parse_url($stageFiveMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  141. $stageFiveMediaIsVideo = in_array($stageFiveMediaExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  142. ?>
  143. <section class="spx-stage-five js-spx-stage-five">
  144. <div class="content-1300-wrap">
  145. <div class="spx-stage-five-copy text-center">
  146. {if !empty($block.title_5_3)}
  147. <div class="spx-stage-kicker spx-stage-five-kicker spx-reveal">{$block.title_5_3|nl2br=###|raw}</div>
  148. {/if}
  149. {if !empty($block.title_5_1)}
  150. <h2 class="spx-stage-five-title spx-reveal spx-reveal--delay-1">{$block.title_5_1|nl2br=###|raw}</h2>
  151. {/if}
  152. {if !empty($block.title_5_2)}
  153. <div class="spx-stage-five-desc spx-reveal spx-reveal--delay-2">{$block.title_5_2|nl2br=###|raw}</div>
  154. {/if}
  155. </div>
  156. {if !empty($stageFiveMedia)}
  157. <div class="spx-stage-five-media">
  158. {if $stageFiveMediaIsVideo}
  159. <video class="spx-stage-five-video" src="<?php echo $stageFiveMedia; ?>" autoplay muted loop playsinline preload="metadata"></video>
  160. {else /}
  161. <img class="spx-stage-five-image" src="<?php echo $stageFiveMedia; ?>" alt="{$title}">
  162. {/if}
  163. </div>
  164. {/if}
  165. </div>
  166. </section>
  167. <?php
  168. $stageSixRaw = $block['thumb_6'] ?? [];
  169. $stageSixSlides = [];
  170. if (is_array($stageSixRaw)) {
  171. $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($stageSixRaw));
  172. foreach ($iterator as $item) {
  173. if (is_string($item)) {
  174. $item = trim($item);
  175. if ($item !== '') {
  176. $stageSixSlides[] = $item;
  177. }
  178. }
  179. }
  180. } else {
  181. $stageSixRaw = trim((string)$stageSixRaw);
  182. if ($stageSixRaw !== '') {
  183. $stageSixSlides = preg_split('/[\r\n,|]+/', $stageSixRaw);
  184. $stageSixSlides = array_values(array_filter(array_map('trim', $stageSixSlides)));
  185. }
  186. }
  187. ?>
  188. <section class="spx-stage-six js-spx-stage-six">
  189. <div class="content-1300-wrap">
  190. <div class="spx-stage-six-head">
  191. <div class="spx-stage-six-head-left">
  192. {if !empty($block.title_6_1)}
  193. <h2 class="spx-stage-six-title spx-reveal">{$block.title_6_1|nl2br=###|raw}</h2>
  194. {/if}
  195. </div>
  196. <div class="spx-stage-six-head-right">
  197. {if !empty($block.title_6_2)}
  198. <div class="spx-stage-six-desc spx-reveal spx-reveal--delay-1">{$block.title_6_2|nl2br=###|raw}</div>
  199. {/if}
  200. </div>
  201. </div>
  202. {if !empty($stageSixSlides)}
  203. <div class="spx-stage-six-slider js-stage-six-slider">
  204. <div class="spx-stage-six-track">
  205. {volist name="stageSixSlides" id="slide" key="slideIndex"}
  206. <div class="spx-stage-six-slide{if $slideIndex == 1} is-active{/if}">
  207. <img class="spx-stage-six-image" src="{$slide}" alt="{$title}">
  208. </div>
  209. {/volist}
  210. {if count($stageSixSlides) > 1}
  211. <button class="spx-stage-six-arrow spx-stage-six-arrow-prev" type="button" data-stage-six-prev aria-label="上一张">
  212. <i class="bi bi-chevron-left" aria-hidden="true"></i>
  213. </button>
  214. <button class="spx-stage-six-arrow spx-stage-six-arrow-next" type="button" data-stage-six-next aria-label="下一张">
  215. <i class="bi bi-chevron-right" aria-hidden="true"></i>
  216. </button>
  217. <div class="spx-stage-six-dots spx-stage-six-dots-inside">
  218. {volist name="stageSixSlides" id="slide" key="slideIndex"}
  219. <button class="spx-stage-six-dot{if $slideIndex == 1} is-active{/if}" type="button" data-stage-six-dot="{$slideIndex - 1}" aria-label="Slide {$slideIndex}"></button>
  220. {/volist}
  221. </div>
  222. {/if}
  223. </div>
  224. </div>
  225. {/if}
  226. </div>
  227. </section>
  228. <?php
  229. $stageSevenMedia = !empty($block['thumb_7']) ? $block['thumb_7'] : '';
  230. $stageSevenMediaExt = $stageSevenMedia ? strtolower(pathinfo(parse_url($stageSevenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  231. $stageSevenMediaIsVideo = in_array($stageSevenMediaExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  232. ?>
  233. <section class="spx-stage-seven js-spx-stage-seven">
  234. <div class="content-1300-wrap">
  235. <div class="spx-stage-seven-copy text-center">
  236. {if !empty($block.title_7_1)}
  237. <h2 class="spx-stage-seven-title spx-reveal">{$block.title_7_1|nl2br=###|raw}</h2>
  238. {/if}
  239. {if !empty($block.title_7_2)}
  240. <div class="spx-stage-seven-desc spx-reveal spx-reveal--delay-1">{$block.title_7_2|nl2br=###|raw}</div>
  241. {/if}
  242. </div>
  243. {if !empty($stageSevenMedia)}
  244. <div class="spx-stage-seven-media">
  245. {if $stageSevenMediaIsVideo}
  246. <video class="spx-stage-seven-video" src="<?php echo $stageSevenMedia; ?>" autoplay muted loop playsinline preload="metadata"></video>
  247. {else /}
  248. <img class="spx-stage-seven-image" src="<?php echo $stageSevenMedia; ?>" alt="{$title}">
  249. {/if}
  250. </div>
  251. {/if}
  252. </div>
  253. </section>
  254. <?php
  255. $stageEightMediaRaw = $block['thumb_8'] ?? [];
  256. $stageEightLabelRaw = $block['tag_8'] ?? [];
  257. $stageEightContentRaw = $block['title_8_2'] ?? [];
  258. $spxFlatten = function ($value) {
  259. $result = [];
  260. if (is_array($value)) {
  261. $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($value));
  262. foreach ($iterator as $item) {
  263. if (is_string($item)) {
  264. $item = trim($item);
  265. if ($item !== '') {
  266. $result[] = $item;
  267. }
  268. }
  269. }
  270. } else {
  271. $value = trim((string)$value);
  272. if ($value !== '') {
  273. $result = preg_split('/[\r\n|]+/', $value);
  274. $result = array_values(array_filter(array_map('trim', $result)));
  275. }
  276. }
  277. return $result;
  278. };
  279. $stageEightMediaList = $spxFlatten($stageEightMediaRaw);
  280. $stageEightLabelList = $spxFlatten($stageEightLabelRaw);
  281. $stageEightContentList = $spxFlatten($stageEightContentRaw);
  282. $stageEightItems = [];
  283. $stageEightCount = max(count($stageEightMediaList), count($stageEightLabelList), count($stageEightContentList));
  284. for ($i = 0; $i < $stageEightCount; $i++) {
  285. $media = $stageEightMediaList[$i] ?? '';
  286. $label = $stageEightLabelList[$i] ?? '';
  287. $content = $stageEightContentList[$i] ?? '';
  288. if ($media === '' && $label === '' && $content === '') {
  289. continue;
  290. }
  291. $ext = $media ? strtolower(pathinfo(parse_url($media, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  292. $stageEightItems[] = [
  293. 'media' => $media,
  294. 'label' => $label,
  295. 'content' => $content,
  296. 'is_video' => in_array($ext, ['mp4', 'webm', 'ogg', 'mov', 'm4v']),
  297. ];
  298. }
  299. ?>
  300. <section class="spx-stage-eight js-stage-eight">
  301. <div class="content-1300-wrap">
  302. <div class="spx-stage-eight-copy text-center">
  303. {if !empty($block.title_8_1)}
  304. <h2 class="spx-stage-eight-title spx-reveal">{$block.title_8_1|nl2br=###|raw}</h2>
  305. {/if}
  306. </div>
  307. {if !empty($stageEightItems)}
  308. <div class="spx-stage-eight-tabs js-stage-eight-tabs">
  309. <div class="spx-stage-eight-media-wrap">
  310. {volist name="stageEightItems" id="item" key="itemIndex"}
  311. <div class="spx-stage-eight-panel{if $itemIndex == 1} is-active{/if}" data-stage-eight-panel="{$itemIndex - 1}">
  312. {if !empty($item.media)}
  313. {if $item.is_video}
  314. <video class="spx-stage-eight-video" src="{$item.media}" autoplay muted loop playsinline preload="metadata"></video>
  315. {else /}
  316. <img class="spx-stage-eight-image" src="{$item.media}" alt="{$title}">
  317. {/if}
  318. {/if}
  319. </div>
  320. {/volist}
  321. </div>
  322. <div class="spx-stage-eight-nav" role="tablist" aria-label="第八屏切换标签">
  323. {volist name="stageEightItems" id="item" key="itemIndex"}
  324. <button class="spx-stage-eight-tab{if $itemIndex == 1} is-active{/if}" type="button" data-stage-eight-tab="{$itemIndex - 1}" role="tab" aria-selected="{if $itemIndex == 1}true{else /}false{/if}">
  325. {$item.label|default='标签'}
  326. </button>
  327. {/volist}
  328. </div>
  329. <div class="spx-stage-eight-content-wrap">
  330. {volist name="stageEightItems" id="item" key="itemIndex"}
  331. <div class="spx-stage-eight-content{if $itemIndex == 1} is-active{/if}" data-stage-eight-content="{$itemIndex - 1}">
  332. {$item.content|default=''}
  333. </div>
  334. {/volist}
  335. </div>
  336. </div>
  337. {/if}
  338. </div>
  339. </section>
  340. <?php
  341. $stageNineMedia = !empty($block['thumb_9']) ? (is_string($block['thumb_9']) ? $block['thumb_9'] : '') : '';
  342. $stageNineMediaExt = $stageNineMedia ? strtolower(pathinfo(parse_url($stageNineMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  343. $stageNineMediaIsVideo = in_array($stageNineMediaExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  344. ?>
  345. <section class="spx-stage-nine js-stage-nine">
  346. <div class="spx-stage-nine-sticky">
  347. <div class="content-1300-wrap">
  348. <div class="spx-stage-nine-title-layer">
  349. {if !empty($block.title_9)}
  350. <h2 class="spx-stage-nine-title spx-reveal">{$block.title_9|nl2br=###|raw}</h2>
  351. {/if}
  352. </div>
  353. {if !empty($stageNineMedia)}
  354. <div class="spx-stage-nine-media">
  355. {if $stageNineMediaIsVideo}
  356. <video class="spx-stage-nine-video" src="<?php echo $stageNineMedia; ?>" preload="metadata" muted></video>
  357. {else /}
  358. <img class="spx-stage-nine-image" src="<?php echo $stageNineMedia; ?>" alt="{$title}">
  359. {/if}
  360. </div>
  361. {/if}
  362. <div class="spx-stage-nine-overlay-copy">
  363. {if !empty($block.title_10_1)}
  364. <h3 class="spx-stage-nine-subtitle spx-reveal spx-reveal--delay-1">{$block.title_10_1|nl2br=###|raw}</h3>
  365. {/if}
  366. {if !empty($block.title_10_2)}
  367. <div class="spx-stage-nine-desc spx-reveal spx-reveal--delay-2">{$block.title_10_2|nl2br=###|raw}</div>
  368. {/if}
  369. {if !empty($block.thumb_10)}
  370. <div class="spx-stage-nine-media">
  371. <img class="spx-stage-nine-image" src="{$block.thumb_10}">
  372. </div>
  373. {/if}
  374. </div>
  375. </div>
  376. </div>
  377. </section>
  378. <?php
  379. $stageTenMediaRaw = $block['thumb_11'] ?? [];
  380. $stageTenTitle = !empty($block['title_11_1']) ? $block['title_11_1'] : '';
  381. $stageTenLabelsRaw = $block['title_11_2'] ?? [];
  382. $stageTenMediaList = $spxFlatten($stageTenMediaRaw);
  383. $stageTenLabelList = $spxFlatten($stageTenLabelsRaw);
  384. $stageTenItems = [];
  385. $stageTenCount = max(count($stageTenMediaList), count($stageTenLabelList));
  386. for ($i = 0; $i < $stageTenCount; $i++) {
  387. $media = $stageTenMediaList[$i] ?? '';
  388. $label = $stageTenLabelList[$i] ?? '';
  389. if ($media === '' && $label === '') {
  390. continue;
  391. }
  392. $ext = $media ? strtolower(pathinfo(parse_url($media, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  393. $stageTenItems[] = [
  394. 'media' => $media,
  395. 'label' => $label,
  396. 'is_video' => in_array($ext, ['mp4', 'webm', 'ogg', 'mov', 'm4v']),
  397. ];
  398. }
  399. ?>
  400. {if !empty($stageTenItems) || !empty($stageTenTitle)}
  401. <section class="spx-stage-ten js-stage-ten">
  402. <div class="content-1300-wrap">
  403. <div class="spx-stage-ten-container">
  404. <div class="spx-stage-ten-media">
  405. <div class="spx-stage-ten-media-container">
  406. {volist name="stageTenItems" id="item" key="itemIndex"}
  407. <div class="spx-stage-ten-panel{if $itemIndex == 1} is-active{/if}" data-stage-ten-panel="{$itemIndex - 1}">
  408. {if !empty($item.media)}
  409. {if $item.is_video}
  410. <video class="spx-stage-ten-video" src="{$item.media}" muted playsinline preload="metadata" loop></video>
  411. <button class="spx-stage-ten-sound-toggle" type="button" data-stage-ten-sound aria-label="切换声音">
  412. <i class="bi bi-volume-mute-fill" aria-hidden="true"></i>
  413. </button>
  414. {else /}
  415. <img class="spx-stage-ten-image" src="{$item.media}" alt="{$title}">
  416. {/if}
  417. {/if}
  418. </div>
  419. {/volist}
  420. </div>
  421. </div>
  422. <div class="spx-stage-ten-content">
  423. {if !empty($stageTenTitle)}
  424. <h2 class="spx-stage-ten-title spx-reveal">{$stageTenTitle|nl2br=###|raw}</h2>
  425. {/if}
  426. {if !empty($stageTenItems)}
  427. <div class="spx-stage-ten-tabs" role="tablist" aria-label="第十屏切换标签">
  428. {volist name="stageTenItems" id="item" key="itemIndex"}
  429. <button class="spx-stage-ten-tab{if $itemIndex == 1} is-active{/if}" type="button" data-stage-ten-tab="{$itemIndex - 1}" role="tab" aria-selected="{if $itemIndex == 1}true{else /}false{/if}">
  430. {$item.label|default='选项'|trim}
  431. </button>
  432. {/volist}
  433. </div>
  434. {/if}
  435. </div>
  436. </div>
  437. </div>
  438. </section>
  439. {/if}
  440. <?php
  441. $stageElevenItems = [];
  442. $stageElevenSourceMap = [
  443. [
  444. 'title' => trim((string)($block['title_12_1'] ?? '')),
  445. 'content' => trim((string)($block['title_12_2'] ?? '')),
  446. 'media' => trim((string)($block['thumb_12_1'] ?? '')),
  447. ],
  448. [
  449. 'title' => trim((string)($block['title_12_3'] ?? '')),
  450. 'content' => trim((string)($block['title_12_4'] ?? '')),
  451. 'media' => trim((string)($block['thumb_12_2'] ?? '')),
  452. ],
  453. ];
  454. foreach ($stageElevenSourceMap as $stageElevenItem) {
  455. if ($stageElevenItem['title'] === '' && $stageElevenItem['content'] === '' && $stageElevenItem['media'] === '') {
  456. continue;
  457. }
  458. $ext = $stageElevenItem['media'] ? strtolower(pathinfo(parse_url($stageElevenItem['media'], PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  459. $stageElevenItem['is_video'] = in_array($ext, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  460. $stageElevenItems[] = $stageElevenItem;
  461. }
  462. ?>
  463. {if !empty($stageElevenItems)}
  464. <section class="spx-stage-eleven js-stage-eleven">
  465. <div class="spx-stage-eleven-media-shell">
  466. {volist name="stageElevenItems" id="item" key="itemIndex"}
  467. <div class="spx-stage-eleven-panel{if $itemIndex == 1} is-active{/if}" data-stage-eleven-panel="{$itemIndex - 1}">
  468. {if !empty($item.media)}
  469. {if $item.is_video}
  470. <video class="spx-stage-eleven-video" src="{$item.media}" muted playsinline preload="metadata" loop></video>
  471. {else /}
  472. <img class="spx-stage-eleven-image" src="{$item.media}" alt="{$item.title|default=$title}">
  473. {/if}
  474. {/if}
  475. </div>
  476. {/volist}
  477. <div class="spx-stage-eleven-overlay"></div>
  478. </div>
  479. <div class="spx-stage-eleven-content-wrap">
  480. <div class="spx-stage-eleven-content">
  481. <div class="spx-stage-eleven-tabs" role="tablist" aria-label="第十一屏切换选项">
  482. {volist name="stageElevenItems" id="item" key="itemIndex"}
  483. <button class="spx-stage-eleven-tab{if $itemIndex == 1} is-active{/if}" type="button" data-stage-eleven-tab="{$itemIndex - 1}" role="tab" aria-selected="{if $itemIndex == 1}true{else /}false{/if}">
  484. <span class="spx-stage-eleven-tab-line" aria-hidden="true"></span>
  485. <span class="spx-stage-eleven-tab-body">
  486. <span class="spx-stage-eleven-tab-title spx-reveal">{$item.title|default='选项'|trim}</span>
  487. <span class="spx-stage-eleven-tab-content spx-reveal spx-reveal--delay-1">{$item.content|trim|nl2br=###|raw}</span>
  488. </span>
  489. </button>
  490. {/volist}
  491. </div>
  492. </div>
  493. </div>
  494. </section>
  495. {/if}
  496. <?php
  497. $stageTwelveTitle = trim((string)($block['title_13_1'] ?? ''));
  498. $stageTwelveDesc = trim((string)($block['title_13_2'] ?? ''));
  499. $stageTwelveMedia = trim((string)($block['thumb_13'] ?? ''));
  500. $stageTwelveExt = $stageTwelveMedia ? strtolower(pathinfo(parse_url($stageTwelveMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  501. $stageTwelveIsVideo = in_array($stageTwelveExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  502. ?>
  503. {if $stageTwelveTitle !== '' || $stageTwelveDesc !== '' || $stageTwelveMedia !== ''}
  504. <section class="spx-stage-twelve">
  505. <div class="content-1300-wrap spx-stage-twelve-wrap">
  506. <div class="spx-stage-twelve-copy">
  507. {if $stageTwelveTitle !== ''}
  508. <h2 class="spx-stage-twelve-title spx-reveal">{$stageTwelveTitle|trim}</h2>
  509. {/if}
  510. {if $stageTwelveDesc !== ''}
  511. <div class="spx-stage-twelve-desc spx-reveal spx-reveal--delay-1">{$stageTwelveDesc|trim|nl2br=###|raw}</div>
  512. {/if}
  513. </div>
  514. {if $stageTwelveMedia !== ''}
  515. <div class="spx-stage-twelve-media">
  516. <div class="spx-stage-twelve-media-shell">
  517. {if $stageTwelveIsVideo}
  518. <video class="spx-stage-twelve-video" src="{$stageTwelveMedia}" autoplay muted playsinline preload="metadata" loop></video>
  519. {else /}
  520. <img class="spx-stage-twelve-image" src="{$stageTwelveMedia}" alt="{$stageTwelveTitle|default=$title}">
  521. {/if}
  522. </div>
  523. </div>
  524. {/if}
  525. </div>
  526. </section>
  527. {/if}
  528. <?php
  529. $stageThirteenTitle = trim((string)($block['title_14_1'] ?? ''));
  530. $stageThirteenMedia = trim((string)($block['thumb_14'] ?? ''));
  531. $stageThirteenDesc = trim((string)($block['title_14_2'] ?? ''));
  532. $stageThirteenExt = $stageThirteenMedia ? strtolower(pathinfo(parse_url($stageThirteenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  533. $stageThirteenIsVideo = in_array($stageThirteenExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  534. ?>
  535. {if $stageThirteenTitle !== '' || $stageThirteenMedia !== '' || $stageThirteenDesc !== ''}
  536. <section class="spx-stage-thirteen">
  537. <div class="content-1300-wrap spx-stage-thirteen-wrap">
  538. <div class="spx-stage-thirteen-copy spx-stage-thirteen-copy-top">
  539. {if $stageThirteenTitle !== ''}
  540. <h2 class="spx-stage-thirteen-title spx-reveal">{$stageThirteenTitle|trim}</h2>
  541. {/if}
  542. </div>
  543. {if $stageThirteenMedia !== ''}
  544. <div class="spx-stage-thirteen-media">
  545. <div class="spx-stage-thirteen-media-shell">
  546. {if $stageThirteenIsVideo}
  547. <video class="spx-stage-thirteen-video" src="{$stageThirteenMedia}" autoplay muted playsinline preload="metadata" loop></video>
  548. {else /}
  549. <img class="spx-stage-thirteen-image" src="{$stageThirteenMedia}" alt="{$stageThirteenTitle|default=$title}">
  550. {/if}
  551. </div>
  552. </div>
  553. {/if}
  554. {if $stageThirteenDesc !== ''}
  555. <div class="spx-stage-thirteen-copy spx-stage-thirteen-copy-bottom">
  556. <div class="spx-stage-thirteen-desc spx-reveal spx-reveal--delay-1">{$stageThirteenDesc|trim|nl2br=###|raw}</div>
  557. </div>
  558. {/if}
  559. </div>
  560. </section>
  561. {/if}
  562. <?php
  563. $stageFourteenTitle = trim((string)($block['title_15_1'] ?? ''));
  564. $stageFourteenDesc = trim((string)($block['title_15_2'] ?? ''));
  565. $stageFourteenMedia = trim((string)($block['thumb_15'] ?? ''));
  566. $stageFourteenExt = $stageFourteenMedia ? strtolower(pathinfo(parse_url($stageFourteenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  567. $stageFourteenIsVideo = in_array($stageFourteenExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  568. ?>
  569. {if $stageFourteenTitle !== '' || $stageFourteenDesc !== '' || $stageFourteenMedia !== ''}
  570. <section class="spx-stage-fourteen">
  571. <div class="spx-stage-fourteen-media-shell">
  572. {if $stageFourteenMedia !== ''}
  573. {if $stageFourteenIsVideo}
  574. <video class="spx-stage-fourteen-video" src="{$stageFourteenMedia}" autoplay muted playsinline preload="metadata" loop></video>
  575. {else /}
  576. <img class="spx-stage-fourteen-image" src="{$stageFourteenMedia}" alt="{$stageFourteenTitle|default=$title}">
  577. {/if}
  578. {/if}
  579. <div class="spx-stage-fourteen-overlay"></div>
  580. </div>
  581. <div class="spx-stage-fourteen-content-wrap">
  582. <div class="spx-stage-fourteen-content">
  583. {if $stageFourteenTitle !== ''}
  584. <h2 class="spx-stage-fourteen-title spx-reveal">{$stageFourteenTitle|trim}</h2>
  585. {/if}
  586. {if $stageFourteenDesc !== ''}
  587. <div class="spx-stage-fourteen-desc spx-reveal spx-reveal--delay-1">{$stageFourteenDesc|trim|nl2br=###|raw}</div>
  588. {/if}
  589. </div>
  590. </div>
  591. </section>
  592. {/if}
  593. <?php
  594. $stageFifteenTitle = trim((string)($block['title_16_1'] ?? ''));
  595. $stageFifteenEyebrow = trim((string)($block['title_16_3'] ?? ''));
  596. if ($stageFifteenEyebrow === '') {
  597. $stageFifteenEyebrow = trim((string)($block['title_5_3'] ?? ''));
  598. }
  599. $stageFifteenDesc = trim((string)($block['title_16_2'] ?? ''));
  600. $stageFifteenMedia = trim((string)($block['thumb_16'] ?? ''));
  601. $stageFifteenExt = $stageFifteenMedia ? strtolower(pathinfo(parse_url($stageFifteenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  602. $stageFifteenIsVideo = in_array($stageFifteenExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  603. ?>
  604. {if $stageFifteenTitle !== '' || $stageFifteenEyebrow !== '' || $stageFifteenDesc !== '' || $stageFifteenMedia !== ''}
  605. <section class="spx-stage-fifteen">
  606. <div class="content-1300-wrap spx-stage-fifteen-wrap">
  607. <div class="spx-stage-fifteen-head">
  608. <div class="spx-stage-fifteen-head-left">
  609. {if $stageFifteenEyebrow !== ''}
  610. <div class="spx-stage-fifteen-eyebrow spx-reveal">{$stageFifteenEyebrow|trim}</div>
  611. {/if}
  612. {if $stageFifteenTitle !== ''}
  613. <h2 class="spx-stage-fifteen-title spx-reveal spx-reveal--delay-1">{$stageFifteenTitle|trim}</h2>
  614. {/if}
  615. </div>
  616. {if $stageFifteenDesc !== ''}
  617. <div class="spx-stage-fifteen-desc spx-reveal spx-reveal--delay-2">{$stageFifteenDesc|trim|nl2br=###|raw}</div>
  618. {/if}
  619. </div>
  620. {if $stageFifteenMedia !== ''}
  621. <div class="spx-stage-fifteen-media">
  622. <div class="spx-stage-fifteen-media-shell">
  623. {if $stageFifteenIsVideo}
  624. <video class="spx-stage-fifteen-video" src="{$stageFifteenMedia}" autoplay muted playsinline preload="metadata" loop></video>
  625. {else /}
  626. <img class="spx-stage-fifteen-image" src="{$stageFifteenMedia}" alt="{$stageFifteenTitle|default=$title}">
  627. {/if}
  628. </div>
  629. </div>
  630. {/if}
  631. </div>
  632. </section>
  633. {/if}
  634. <?php
  635. $stageSixteenTitle = trim((string)($block['title_17_1'] ?? ''));
  636. $stageSixteenMedia = trim((string)($block['thumb_17'] ?? ''));
  637. $stageSixteenDesc = trim((string)($block['title_17_2'] ?? ''));
  638. $stageSixteenExt = $stageSixteenMedia ? strtolower(pathinfo(parse_url($stageSixteenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  639. $stageSixteenIsVideo = in_array($stageSixteenExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  640. ?>
  641. {if $stageSixteenTitle !== '' || $stageSixteenMedia !== '' || $stageSixteenDesc !== ''}
  642. <section class="spx-stage-sixteen">
  643. <div class="content-1300-wrap spx-stage-sixteen-wrap">
  644. <div class="spx-stage-sixteen-copy spx-stage-sixteen-copy-top">
  645. {if $stageSixteenTitle !== ''}
  646. <h2 class="spx-stage-sixteen-title spx-reveal">{$stageSixteenTitle|trim}</h2>
  647. {/if}
  648. </div>
  649. {if $stageSixteenMedia !== ''}
  650. <div class="spx-stage-sixteen-media">
  651. <div class="spx-stage-sixteen-media-shell">
  652. {if $stageSixteenIsVideo}
  653. <video class="spx-stage-sixteen-video" src="{$stageSixteenMedia}" autoplay muted playsinline preload="metadata" loop></video>
  654. {else /}
  655. <img class="spx-stage-sixteen-image" src="{$stageSixteenMedia}" alt="{$stageSixteenTitle|default=$title}">
  656. {/if}
  657. </div>
  658. </div>
  659. {/if}
  660. {if $stageSixteenDesc !== ''}
  661. <div class="spx-stage-sixteen-copy spx-stage-sixteen-copy-bottom">
  662. <div class="spx-stage-sixteen-desc spx-reveal spx-reveal--delay-1">{$stageSixteenDesc|trim|nl2br=###|raw}</div>
  663. </div>
  664. {/if}
  665. </div>
  666. </section>
  667. {/if}
  668. <?php
  669. $stageSeventeenTitle = trim((string)($block['title_18_1'] ?? ''));
  670. $stageSeventeenDesc = trim((string)($block['title_18_2'] ?? ''));
  671. $stageSeventeenMedia = trim((string)($block['thumb_18'] ?? ''));
  672. $stageSeventeenNote = trim((string)($block['title_18_3'] ?? ''));
  673. $stageSeventeenExt = $stageSeventeenMedia ? strtolower(pathinfo(parse_url($stageSeventeenMedia, PHP_URL_PATH), PATHINFO_EXTENSION)) : '';
  674. $stageSeventeenIsVideo = in_array($stageSeventeenExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  675. ?>
  676. {if $stageSeventeenTitle !== '' || $stageSeventeenDesc !== '' || $stageSeventeenMedia !== '' || $stageSeventeenNote !== ''}
  677. <section class="spx-stage-seventeen">
  678. <div class="content-1300-wrap spx-stage-seventeen-wrap">
  679. <div class="spx-stage-seventeen-copy spx-stage-seventeen-copy-top">
  680. {if $stageSeventeenTitle !== ''}
  681. <h2 class="spx-stage-seventeen-title spx-reveal">{$stageSeventeenTitle|trim}</h2>
  682. {/if}
  683. {if $stageSeventeenDesc !== ''}
  684. <div class="spx-stage-seventeen-desc spx-reveal spx-reveal--delay-1">{$stageSeventeenDesc|trim|nl2br=###|raw}</div>
  685. {/if}
  686. </div>
  687. {if $stageSeventeenMedia !== ''}
  688. <div class="spx-stage-seventeen-media">
  689. <div class="spx-stage-seventeen-media-shell">
  690. {if $stageSeventeenIsVideo}
  691. <video class="spx-stage-seventeen-video" src="{$stageSeventeenMedia}" autoplay muted playsinline preload="metadata" loop></video>
  692. {else /}
  693. <img class="spx-stage-seventeen-image" src="{$stageSeventeenMedia}" alt="{$stageSeventeenTitle|default=$title}">
  694. {/if}
  695. </div>
  696. </div>
  697. {/if}
  698. {if $stageSeventeenNote !== ''}
  699. <div class="spx-stage-seventeen-copy spx-stage-seventeen-copy-bottom">
  700. <div class="spx-stage-seventeen-note spx-reveal spx-reveal--delay-2">{$stageSeventeenNote|trim|nl2br=###|raw}</div>
  701. </div>
  702. {/if}
  703. </div>
  704. </section>
  705. {/if}
  706. {/volist}
  707. {/yzn}
  708. {yzn module="cms" action="lists" catid="46" where="$where" order="listorder asc,id desc" num="5" return="stageEighteenCards" moreinfo="1"}
  709. {if !empty($stageEighteenCards)}
  710. <section class="spx-stage-eighteen">
  711. <div class="content-1300-wrap spx-stage-eighteen-wrap">
  712. <div class="spx-stage-eighteen-grid">
  713. {volist name="stageEighteenCards" id="card" key="cardIndex"}
  714. <button class="spx-stage-eighteen-card spx-stage-eighteen-card-{$cardIndex}" type="button" aria-label="{$card.title|default='查看详情'|trim}" data-stage-eighteen-trigger="{$card.id}">
  715. <span class="spx-stage-eighteen-card-media">
  716. {if !empty($card.thumb)}
  717. <img class="spx-stage-eighteen-card-image" src="{$card.thumb}" alt="{$card.title|default=$title}">
  718. {else /}
  719. <span class="spx-stage-eighteen-card-placeholder"></span>
  720. {/if}
  721. <span class="spx-stage-eighteen-card-overlay"></span>
  722. </span>
  723. <span class="spx-stage-eighteen-card-title">{$card.title|default='Untitled'|trim}</span>
  724. <span class="spx-stage-eighteen-card-plus" aria-hidden="true"><i class="bi bi-plus-lg"></i></span>
  725. </button>
  726. {/volist}
  727. </div>
  728. </div>
  729. </section>
  730. <div class="spx-stage-eighteen-modal" id="stageEighteenModal" hidden>
  731. <div class="spx-stage-eighteen-modal__backdrop" data-stage-eighteen-close></div>
  732. <div class="spx-stage-eighteen-modal__dialog" role="dialog" aria-modal="true" aria-label="{:cms_t('combo_detail','组合详情')}">
  733. <button class="spx-stage-eighteen-modal__close" type="button" aria-label="{:cms_t('close','关闭')}" data-stage-eighteen-close>
  734. <i class="bi bi-x-lg"></i>
  735. </button>
  736. <div class="spx-stage-eighteen-modal__body">
  737. {volist name="stageEighteenCards" id="card" key="cardIndex"}
  738. <?php
  739. $normalizeStageEighteenList = function ($value) {
  740. if (is_array($value)) {
  741. $result = [];
  742. foreach ($value as $item) {
  743. $text = trim((string)$item);
  744. if ($text !== '') $result[] = $text;
  745. }
  746. return $result;
  747. }
  748. $text = trim((string)$value);
  749. if ($text === '') return [];
  750. $json = json_decode($text, true);
  751. if (is_array($json)) {
  752. $result = [];
  753. foreach ($json as $item) {
  754. $itemText = trim((string)$item);
  755. if ($itemText !== '') $result[] = $itemText;
  756. }
  757. return $result;
  758. }
  759. $unserialized = @unserialize($text);
  760. if (is_array($unserialized)) {
  761. $result = [];
  762. foreach ($unserialized as $item) {
  763. $itemText = trim((string)$item);
  764. if ($itemText !== '') $result[] = $itemText;
  765. }
  766. return $result;
  767. }
  768. $parts = preg_split('/\r\n|\r|\n|\|\|\||\|/', $text);
  769. $result = [];
  770. if (is_array($parts)) {
  771. foreach ($parts as $item) {
  772. $itemText = trim((string)$item);
  773. if ($itemText !== '') $result[] = $itemText;
  774. }
  775. }
  776. return $result;
  777. };
  778. $cardTitles = $normalizeStageEighteenList($card['titles'] ?? []);
  779. $cardContents = $normalizeStageEighteenList($card['contents'] ?? []);
  780. $cardThumbs = $normalizeStageEighteenList($card['thumbs'] ?? []);
  781. $cardFeatureCount = max(count($cardTitles), count($cardContents), count($cardThumbs));
  782. ?>
  783. <div class="spx-stage-eighteen-modal-panel{if $cardIndex == 1} is-active{/if}" data-stage-eighteen-panel="{$card.id}">
  784. <div class="spx-stage-eighteen-modal-hero">
  785. <div class="spx-stage-eighteen-modal-media">
  786. {if !empty($card.thumb)}
  787. <img class="spx-stage-eighteen-modal-image" src="{$card.thumb}" alt="{$card.title|default=$title}">
  788. {else /}
  789. <span class="spx-stage-eighteen-modal-image spx-stage-eighteen-modal-image--placeholder"></span>
  790. {/if}
  791. <span class="spx-stage-eighteen-modal-hero-overlay"></span>
  792. <div class="spx-stage-eighteen-modal-copy">
  793. <h3 class="spx-stage-eighteen-modal-title">{$card.title|default='Untitled'|trim}</h3>
  794. </div>
  795. </div>
  796. </div>
  797. <?php if ($cardFeatureCount > 0): ?>
  798. <div class="spx-stage-eighteen-modal-features">
  799. <?php for ($featureIndex = 0; $featureIndex < $cardFeatureCount; $featureIndex++): ?>
  800. <?php
  801. $featureTitle = trim((string)($cardTitles[$featureIndex] ?? ''));
  802. $featureContent = trim((string)($cardContents[$featureIndex] ?? ''));
  803. $featureThumb = trim((string)($cardThumbs[$featureIndex] ?? ''));
  804. $hasFeature = $featureTitle !== '' || $featureContent !== '' || $featureThumb !== '';
  805. ?>
  806. <?php if ($hasFeature): ?>
  807. <?php
  808. $featureExt = strtolower(pathinfo(parse_url($featureThumb, PHP_URL_PATH) ?: $featureThumb, PATHINFO_EXTENSION));
  809. $featureIsVideo = in_array($featureExt, ['mp4', 'webm', 'ogg', 'mov', 'm4v']);
  810. ?>
  811. <div class="spx-stage-eighteen-feature<?php echo $featureIndex % 2 === 1 ? ' is-reverse' : ''; ?>">
  812. <div class="spx-stage-eighteen-feature-copy">
  813. <?php if ($featureTitle !== ''): ?>
  814. <h4 class="spx-stage-eighteen-feature-title"><?php echo htmlspecialchars($featureTitle, ENT_QUOTES, 'UTF-8'); ?></h4>
  815. <?php endif; ?>
  816. <?php if ($featureContent !== ''): ?>
  817. <div class="spx-stage-eighteen-feature-desc"><?php echo nl2br(htmlspecialchars($featureContent, ENT_QUOTES, 'UTF-8')); ?></div>
  818. <?php endif; ?>
  819. </div>
  820. <div class="spx-stage-eighteen-feature-media<?php echo $featureThumb === '' ? ' is-empty' : ''; ?>">
  821. <?php if ($featureThumb !== ''): ?>
  822. <?php if ($featureIsVideo): ?>
  823. <video class="spx-stage-eighteen-feature-video" src="<?php echo htmlspecialchars($featureThumb, ENT_QUOTES, 'UTF-8'); ?>" autoplay muted loop playsinline preload="metadata"></video>
  824. <?php else: ?>
  825. <img class="spx-stage-eighteen-feature-image" src="<?php echo htmlspecialchars($featureThumb, ENT_QUOTES, 'UTF-8'); ?>" alt="<?php echo htmlspecialchars($featureTitle !== '' ? $featureTitle : trim((string)$card['title']), ENT_QUOTES, 'UTF-8'); ?>">
  826. <?php endif; ?>
  827. <?php endif; ?>
  828. </div>
  829. </div>
  830. <?php endif; ?>
  831. <?php endfor; ?>
  832. </div>
  833. <?php endif; ?>
  834. </div>
  835. {/volist}
  836. </div>
  837. </div>
  838. </div>
  839. {/if}
  840. {/yzn}
  841. {include file="footer-links" /}
  842. </main>
  843. <script src="/assets/xtu/show-product.js?v=20260427-1848"></script>
  844. {include file="footer" /}