share.ejs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <!DOCTYPE html>
  2. <html lang="<%= lang %>">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="x-ua-compatible" content="ie=edge">
  7. <title>Art Color</title>
  8. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>?lang=en" hrefLang="en" />
  9. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>?lang=zh" hrefLang="zh" />
  10. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>?lang=es" hrefLang="es" />
  11. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>?lang=pt" hrefLang="pt" />
  12. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>?lang=ja" hrefLang="ja" />
  13. <link rel="alternate" href="https://art.pcoloring.com/share/<%= id %>" hrefLang="x-default" />
  14. <meta name="description" content="<%= translate.colorRelex[lang] %>">
  15. <meta name="keywords" content="color, paint, app, ios, android, game">
  16. <meta property="og:site_name" content="art.pcoloring.com">
  17. <meta property="og:title" content="Art Color">
  18. <meta property="og:description" content="<%= translate.colorRelex[lang] %>">
  19. <meta property="og:image" content="<%= imageUrl %>">
  20. <meta property="og:type" content="website">
  21. <!-- <meta property="fb:page_id" content="565152927316964"> -->
  22. <!-- MARK: Universal Link / Android App Link 的核心配置 -->
  23. <!-- 这些 meta 标签的值应该是完整的 HTTPS 链接,Facebook 会识别并尝试拉起 App -->
  24. <meta property="og:url" content="<%= applink %>" /> <!-- **Universal Link 路径** -->
  25. <meta property="al:ios:url" content="<%= applink %>" /> <!-- **Universal Link 路径** -->
  26. <meta property="al:ios:app_store_id" content="1575480118" /> <!-- **iOS App Store ID** -->
  27. <meta property="al:ios:app_name" content="Art Color" /> <!-- **iOS 应用名称** -->
  28. <meta property="al:android:package" content="com.pcoloring.art.puzzle.color.by.number" /> <!-- **Android 包名** -->
  29. <meta property="al:android:url" content="<%= applink %>" /> <!-- ** Universal Link 路径** -->
  30. <meta property="al:android:app_name" content="Art Color" /> <!-- **Android 应用名称** -->
  31. <meta name="apple-itunes-app" content="app-id=1575480118">
  32. <link rel="icon" href="/assets/icon/favicon.ico" type="image/x-icon">
  33. <link rel="apple-touch-icon" sizes="180x180" href="/assets/icon/icon.png">
  34. <script type="module" crossorigin src="/assets/share-DDyw1eeR.js"></script>
  35. <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
  36. <link rel="modulepreload" crossorigin href="/assets/WorkLayer-RuTV64WF.js">
  37. <style>
  38. :root {
  39. --primary-color: #ff6b6b;
  40. --secondary-color: #4ecdc4;
  41. --accent-color: #ffd166;
  42. --background-color: #f9f9f9;
  43. --text-color: #333;
  44. --light-text: #666;
  45. --border-color: #e0e0e0;
  46. }
  47. body {
  48. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  49. display: flex;
  50. flex-direction: column;
  51. height: 92vh;
  52. margin: 0;
  53. box-sizing: border-box;
  54. background-color: var(--background-color);
  55. color: var(--text-color);
  56. line-height: 1.6;
  57. align-items: center;
  58. }
  59. /* 头部容器 */
  60. .header-container {
  61. width: 100%;
  62. margin-top: 10px;
  63. display: flex;
  64. flex-direction: column;
  65. align-items: center;
  66. justify-content: center;
  67. flex-shrink: 0;
  68. z-index: 100;
  69. }
  70. /* 图片加载前隐藏,避免破碎的加载体验 */
  71. #header {
  72. opacity: 0;
  73. transition: opacity 0.3s ease;
  74. /* 加载完成后淡入 */
  75. }
  76. /* 图片加载完成后显示 */
  77. #header.loaded {
  78. opacity: 1;
  79. }
  80. .app-icon {
  81. display: flex;
  82. justify-content: center;
  83. align-items: center;
  84. margin: 0 auto;
  85. overflow: hidden;
  86. }
  87. .app-icon img {
  88. width: 90px;
  89. height: 90px;
  90. border: 3px solid #eeeeee;
  91. border-radius: 10px;
  92. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  93. object-fit: contain;
  94. }
  95. .app-title {
  96. font-size: 1.8rem;
  97. /* 标题调小 */
  98. font-weight: 700;
  99. margin-bottom: 15px;
  100. /* 调整为与图标的间距,略微缩小 */
  101. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  102. text-align: center;
  103. /* 确保标题在移动端也居中 */
  104. }
  105. /* 父容器,用于包裹图片和 Canvas,并使其相对定位 */
  106. .image-canvas-container {
  107. position: relative;
  108. max-width: 90%;
  109. height: auto;
  110. display: inline-block;
  111. box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
  112. border-radius: 12px;
  113. overflow: hidden;
  114. }
  115. /* 占位容器:全屏覆盖 */
  116. .image-placeholder {
  117. position: absolute;
  118. top: 0;
  119. left: 0;
  120. height: 100%;
  121. width: 100%;
  122. background-color: var(--background-color);
  123. display: flex;
  124. align-items: center;
  125. justify-content: center;
  126. z-index: 20;
  127. /* 位于 canvas 之上,图片之下 */
  128. }
  129. /* 简单的加载动画(旋转圆圈) */
  130. .loading-spinner {
  131. width: 40px;
  132. height: 40px;
  133. border: 4px solid #ddd;
  134. border-top: 4px solid var(--primary-color);
  135. border-radius: 50%;
  136. animation: spin 1s linear infinite;
  137. }
  138. @keyframes spin {
  139. 0% {
  140. transform: rotate(0deg);
  141. }
  142. 100% {
  143. transform: rotate(360deg);
  144. }
  145. }
  146. /* 图片样式:使其响应式并填充容器 */
  147. .image-canvas-container img {
  148. position: relative;
  149. display: block;
  150. max-width: 100%;
  151. height: 100%;
  152. object-fit: contain;
  153. border-radius: 12px;
  154. z-index: 100;
  155. }
  156. /* 图片加载前隐藏,避免破碎的加载体验 */
  157. #poster-img {
  158. opacity: 0;
  159. transition: opacity 0.3s ease;
  160. /* 加载完成后淡入 */
  161. }
  162. /* 图片加载完成后显示 */
  163. #poster-img.loaded {
  164. opacity: 1;
  165. }
  166. /* Canvas 样式:绝对定位,与图片完全重叠 */
  167. .image-canvas-container canvas {
  168. position: absolute;
  169. top: 0;
  170. left: 0;
  171. width: 100%;
  172. height: 100%;
  173. border-radius: 12px;
  174. z-index: 50;
  175. }
  176. /* 按钮容器在底部 */
  177. .buttons {
  178. width: 100%;
  179. max-width: 550px;
  180. display: flex;
  181. flex-wrap: wrap;
  182. flex-direction: column;
  183. justify-content: center;
  184. align-items: center;
  185. margin-top: 30px;
  186. flex-shrink: 0;
  187. z-index: 100;
  188. }
  189. /* buttons 淡入 */
  190. #buttons {
  191. opacity: 0;
  192. transition: opacity 0.3s ease;
  193. /* 加载完成后淡入 */
  194. }
  195. /* 图片加载完成后显示 */
  196. #buttons.loaded {
  197. opacity: 1;
  198. }
  199. .btn {
  200. display: inline-block;
  201. min-width: 180px;
  202. background-color: var(--primary-color);
  203. color: white;
  204. border: none;
  205. padding: 10px 20px;
  206. border-radius: 20px;
  207. font-size: 1.1rem;
  208. font-weight: 500;
  209. cursor: pointer;
  210. transition: background-color 0.3s ease;
  211. text-decoration: none;
  212. text-align: center;
  213. margin-right: 10px;
  214. margin-bottom: 10px;
  215. }
  216. .btn:hover {
  217. background-color: #ff4d4d;
  218. }
  219. .btn-secondary {
  220. background-color: var(--secondary-color);
  221. }
  222. .btn-secondary:hover {
  223. background-color: #37b0a8;
  224. }
  225. .play-button {
  226. position: absolute;
  227. display: block;
  228. top: 50%;
  229. left: 50%;
  230. transform: translate(-50%, -50%);
  231. width: 80px;
  232. height: 80px;
  233. background-color: rgba(255, 107, 107, 0.8);
  234. border-radius: 50%;
  235. display: flex;
  236. align-items: center;
  237. justify-content: center;
  238. transition: all 0.3s ease;
  239. z-index: 110;
  240. /* 确保播放按钮在图片之上 */
  241. }
  242. .play-button:hover {
  243. background-color: rgba(255, 107, 107, 1);
  244. transform: translate(-50%, -50%) scale(1.1);
  245. }
  246. .play-button::after {
  247. content: "";
  248. width: 0;
  249. height: 0;
  250. border-top: 15px solid transparent;
  251. border-bottom: 15px solid transparent;
  252. border-left: 25px solid white;
  253. margin-left: 5px;
  254. }
  255. /* MARK: 微信引导层样式 */
  256. .wechat-guide-overlay {
  257. position: fixed;
  258. top: 0;
  259. left: 0;
  260. width: 100%;
  261. height: 100%;
  262. background-color: rgba(0, 0, 0, 0.75);
  263. /* 半透明黑色背景 */
  264. z-index: 9999;
  265. /* 确保在最上层 */
  266. display: none;
  267. /* 默认隐藏 */
  268. justify-content: center;
  269. align-items: center;
  270. color: white;
  271. font-size: 1.5rem;
  272. text-align: center;
  273. padding: 20px;
  274. box-sizing: border-box;
  275. flex-direction: column;
  276. }
  277. .wechat-guide-overlay.active {
  278. display: flex;
  279. /* 显示引导层 */
  280. }
  281. .wechat-guide-arrow {
  282. position: absolute;
  283. top: 10px;
  284. /* 箭头位置靠近右上角 */
  285. right: 20px;
  286. width: 80px;
  287. height: 80px;
  288. background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" transform="rotate(90 12 12)"/></svg>') no-repeat center center;
  289. background-size: contain;
  290. transform: rotate(90deg);
  291. /* 旋转箭头指向右下 */
  292. }
  293. .wechat-guide-text {
  294. margin-top: 100px;
  295. /* 留出箭头空间 */
  296. line-height: 1.8;
  297. }
  298. .wechat-guide-text strong {
  299. color: var(--accent-color);
  300. /* 突出显示关键文字 */
  301. }
  302. @media (max-width: 768px) {
  303. .app-title {
  304. font-size: 1.5rem;
  305. margin-bottom: 10px;
  306. }
  307. .btn {
  308. min-width: 150px;
  309. font-size: 1rem;
  310. margin-right: 0;
  311. }
  312. }
  313. </style>
  314. </head>
  315. <!-- Google tag (gtag.js) -->
  316. <script async src="https://www.googletagmanager.com/gtag/js?id=G-JBGGVGLHTP"></script>
  317. <script>
  318. window.dataLayer = window.dataLayer || [];
  319. function gtag() { dataLayer.push(arguments); }
  320. gtag('js', new Date());
  321. gtag('config', 'G-JBGGVGLHTP');
  322. </script>
  323. <body>
  324. <div class="image-placeholder" id="imagePlaceholder">
  325. <div class="loading-spinner"></div>
  326. </div>
  327. <div id="header" class="header-container">
  328. <div class="app-icon">
  329. <img src="/assets/icon/logo_640x640.webp" alt="Art Color App Logo">
  330. </div>
  331. <div class="app-title">🎨 ArtColor 🎨</div>
  332. </div>
  333. <div class="image-canvas-container">
  334. <img id="poster-img" src="<%= imageUrl %>" alt="Art Color" />
  335. <canvas id="canvas"></canvas>
  336. <div id="play-button" class="play-button"></div>
  337. </div>
  338. <div id="buttons" class="buttons">
  339. <a href="<%= openapplink %>" target="_blank" class="btn btn-primary">
  340. <%= translate.claimBonus[lang] %>
  341. </a>
  342. <a href="<%= downlink %>" class="btn btn-secondary">
  343. <%= translate.downloadApp[lang] %>
  344. </a>
  345. </div>
  346. <!-- MARK: 微信引导层 -->
  347. <div id="wechat-guide-overlay" class="wechat-guide-overlay">
  348. <div class="wechat-guide-arrow" onclick="closeOverlay()"></div>
  349. <p class="wechat-guide-text">
  350. 请点击右上角 <strong>"..."</strong> 菜单<br>
  351. 选择 <strong>"在浏览器中打开"</strong><br>
  352. 即可跳转到 App 或下载页面
  353. </p>
  354. </div>
  355. <script>
  356. // claim bonus 超过1秒自动跳转到下载页
  357. document.addEventListener('DOMContentLoaded', function () {
  358. // 检查 URL 中是否包含 check=1 参数
  359. const urlParams = new URLSearchParams(window.location.search);
  360. const hasCheckParam = urlParams.has('check');
  361. console.log(window.location.search);
  362. console.log('hasCheckParam:', hasCheckParam);
  363. // 定义下载页面 URL(与 Download App 按钮保持一致)
  364. const downloadUrl = document.querySelector('.btn-secondary').href;
  365. // 如果是带 check 参数的页面,则执行拉起检测逻辑
  366. if (hasCheckParam) {
  367. let appLaunched = false;
  368. // 监听页面可见性变化(判断 App 是否被拉起)
  369. document.addEventListener('visibilitychange', function () {
  370. if (document.hidden) {
  371. // 页面被隐藏,说明 App 可能被成功拉起
  372. appLaunched = true;
  373. }
  374. });
  375. // 监听页面焦点变化(辅助判断)
  376. window.addEventListener('blur', function () {
  377. appLaunched = true;
  378. });
  379. // 1 秒后检查是否成功拉起 App
  380. setTimeout(function () {
  381. if (!appLaunched) {
  382. // 未拉起 App,跳转到下载页
  383. window.location.href = downloadUrl;
  384. }
  385. }, 1000);
  386. }
  387. // 为 Claim Bonus 按钮添加防重复点击逻辑(可选)
  388. const claimButton = document.querySelector('.btn-primary');
  389. if (claimButton) {
  390. claimButton.addEventListener('click', function (e) {
  391. // 只有在没有 check 参数时才允许跳转(避免循环跳转)
  392. if (!hasCheckParam) {
  393. // 可添加加载状态
  394. this.textContent = 'Launching...';
  395. this.disabled = true;
  396. }
  397. });
  398. }
  399. });
  400. // 图片加载逻辑
  401. const header = document.getElementById('header');
  402. const posterImg = document.getElementById('poster-img');
  403. const imagePlaceholder = document.getElementById('imagePlaceholder');
  404. const buttons = document.getElementById('buttons');
  405. // 图片加载完成后
  406. posterImg.onload = function () {
  407. // header淡入
  408. header.classList.add('loaded');
  409. // 标记图片已加载,触发 CSS 淡入效果
  410. posterImg.classList.add('loaded');
  411. // buttons淡入
  412. buttons.classList.add('loaded');
  413. // 隐藏占位符
  414. if (imagePlaceholder) {
  415. imagePlaceholder.style.display = 'none';
  416. }
  417. };
  418. // 图片加载失败时(备选方案)
  419. posterImg.onerror = function () {
  420. imagePlaceholder.innerHTML = '<p>图片加载失败</p>'; // 显示错误提示
  421. };
  422. const wechatGuideOverlay = document.getElementById('wechat-guide-overlay');
  423. // MARK: 微信环境检测
  424. function isWeChatBrowser() {
  425. const ua = window.navigator.userAgent.toLowerCase();
  426. return ua.includes('micromessenger');
  427. }
  428. function closeOverlay() {
  429. wechatGuideOverlay.classList.remove('active');
  430. }
  431. if (isWeChatBrowser()) {
  432. wechatGuideOverlay.classList.add('active');
  433. console.log("检测到微信浏览器,显示引导层。");
  434. } else {
  435. wechatGuideOverlay.classList.remove('active'); // 确保隐藏
  436. }
  437. </script>
  438. </body>
  439. </html>