share-simple.ejs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  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="og:url" content="<%= applink %>" />
  22. <!-- =============== 新增: Facebook App Links 元标签 =============== -->
  23. <meta property="fb:app_id" content="2402037183154121" />
  24. <meta property="al:web:should_fallback" content="false" />
  25. <meta property="al:web:url" content="<%= applink %>" />
  26. <meta property="al:ios:url" content="<%= applink %>" />
  27. <meta property="al:ios:app_store_id" content="1575480118" />
  28. <meta property="al:ios:app_name" content="Art Color" />
  29. <meta property="al:android:url" content="<%= applink %>" />
  30. <meta property="al:android:package" content="com.pcoloring.art.puzzle.color.by.number" />
  31. <meta property="al:android:app_name" content="Art Color" />
  32. <meta property="al:android:class" content="com.pcoloring.book.activity.SimpleSplashActivity" />
  33. <meta name="apple-itunes-app" content="app-id=1575480118">
  34. <link rel="icon" href="/assets/icon/favicon.ico" type="image/x-icon">
  35. <link rel="apple-touch-icon" sizes="180x180" href="/assets/icon/icon.png">
  36. <script type="module" crossorigin src="/assets/share-DDyw1eeR.js"></script>
  37. <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
  38. <link rel="modulepreload" crossorigin href="/assets/WorkLayer-RuTV64WF.js">
  39. <style>
  40. :root {
  41. --primary-color: #ff6b6b;
  42. --secondary-color: #4ecdc4;
  43. --accent-color: #ffd166;
  44. --background-color: #f9f9f9;
  45. --text-color: #333;
  46. --light-text: #666;
  47. --border-color: #e0e0e0;
  48. }
  49. body {
  50. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  51. display: flex;
  52. flex-direction: column;
  53. height: 92vh;
  54. margin: 0;
  55. box-sizing: border-box;
  56. background-color: var(--background-color);
  57. color: var(--text-color);
  58. line-height: 1.6;
  59. align-items: center;
  60. }
  61. /* 头部容器 */
  62. .header-container {
  63. width: 100%;
  64. margin-top: 10px;
  65. display: flex;
  66. flex-direction: column;
  67. align-items: center;
  68. justify-content: center;
  69. flex-shrink: 0;
  70. z-index: 100;
  71. }
  72. /* 图片加载前隐藏,避免破碎的加载体验 */
  73. #header {
  74. opacity: 0;
  75. transition: opacity 0.3s ease;
  76. /* 加载完成后淡入 */
  77. }
  78. /* 图片加载完成后显示 */
  79. #header.loaded {
  80. opacity: 1;
  81. }
  82. .app-icon {
  83. display: flex;
  84. justify-content: center;
  85. align-items: center;
  86. margin: 0 auto;
  87. overflow: hidden;
  88. }
  89. .app-icon img {
  90. width: 64px;
  91. height: 64px;
  92. border: 3px solid #eeeeee;
  93. border-radius: 10px;
  94. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  95. object-fit: contain;
  96. }
  97. .app-title {
  98. color: var(--text-color);
  99. font-size: 1.8rem;
  100. font-weight: 700;
  101. margin-bottom: 15px;
  102. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  103. text-align: center;
  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. #buttons.loaded {
  196. opacity: 1;
  197. }
  198. .btn {
  199. display: inline-block;
  200. min-width: 180px;
  201. background-color: var(--primary-color);
  202. color: white;
  203. border: none;
  204. padding: 10px 20px;
  205. border-radius: 20px;
  206. font-size: 1.1rem;
  207. font-weight: 500;
  208. cursor: pointer;
  209. transition: background-color 0.3s ease;
  210. text-decoration: none;
  211. text-align: center;
  212. margin-right: 10px;
  213. margin-bottom: 10px;
  214. }
  215. .btn:hover {
  216. background-color: #ff4d4d;
  217. }
  218. .btn-secondary {
  219. background-color: var(--secondary-color);
  220. }
  221. .btn-secondary:hover {
  222. background-color: #37b0a8;
  223. }
  224. .play-button {
  225. position: absolute;
  226. display: block;
  227. top: 50%;
  228. left: 50%;
  229. transform: translate(-50%, -50%);
  230. width: 80px;
  231. height: 80px;
  232. background-color: rgba(255, 107, 107, 0.8);
  233. border-radius: 50%;
  234. display: flex;
  235. align-items: center;
  236. justify-content: center;
  237. transition: all 0.3s ease;
  238. z-index: 0;
  239. }
  240. .play-button:hover {
  241. background-color: rgba(255, 107, 107, 1);
  242. transform: translate(-50%, -50%) scale(1.1);
  243. }
  244. .play-button::after {
  245. content: "";
  246. width: 0;
  247. height: 0;
  248. border-top: 15px solid transparent;
  249. border-bottom: 15px solid transparent;
  250. border-left: 25px solid white;
  251. margin-left: 5px;
  252. }
  253. /* MARK: 微信引导层样式 */
  254. .wechat-guide-overlay {
  255. position: fixed;
  256. top: 0;
  257. left: 0;
  258. width: 100%;
  259. height: 100%;
  260. background-color: rgba(0, 0, 0, 0.75);
  261. /* 半透明黑色背景 */
  262. z-index: 9999;
  263. /* 确保在最上层 */
  264. display: none;
  265. /* 默认隐藏 */
  266. justify-content: center;
  267. align-items: center;
  268. color: white;
  269. font-size: 1.5rem;
  270. text-align: center;
  271. padding: 20px;
  272. box-sizing: border-box;
  273. flex-direction: column;
  274. }
  275. .wechat-guide-overlay.active {
  276. display: flex;
  277. /* 显示引导层 */
  278. }
  279. .wechat-guide-arrow {
  280. position: absolute;
  281. top: 10px;
  282. /* 箭头位置靠近右上角 */
  283. right: 20px;
  284. width: 80px;
  285. height: 80px;
  286. 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;
  287. background-size: contain;
  288. transform: rotate(90deg);
  289. /* 旋转箭头指向右下 */
  290. }
  291. .wechat-guide-text {
  292. margin-top: 100px;
  293. /* 留出箭头空间 */
  294. line-height: 1.8;
  295. }
  296. .wechat-guide-text strong {
  297. color: var(--accent-color);
  298. /* 突出显示关键文字 */
  299. }
  300. @media (max-width: 768px) {
  301. .app-title {
  302. font-size: 1.5rem;
  303. margin-bottom: 10px;
  304. }
  305. .btn {
  306. min-width: 150px;
  307. font-size: 1rem;
  308. margin-right: 0;
  309. }
  310. }
  311. </style>
  312. </head>
  313. <!-- Google tag (gtag.js) -->
  314. <script async src="https://www.googletagmanager.com/gtag/js?id=G-JBGGVGLHTP"></script>
  315. <script>
  316. window.dataLayer = window.dataLayer || [];
  317. function gtag() { dataLayer.push(arguments); }
  318. gtag('js', new Date());
  319. gtag('config', 'G-JBGGVGLHTP');
  320. </script>
  321. <body>
  322. <div class="image-placeholder" id="imagePlaceholder">
  323. <div class="loading-spinner"></div>
  324. </div>
  325. <div id="header" class="header-container">
  326. <div class="app-icon">
  327. <a href="/"><img src="/assets/icon/logo_640x640.webp" alt="Art Color App Logo"></a>
  328. </div>
  329. <div class="app-title">Art Color</div>
  330. </div>
  331. <div class="image-canvas-container">
  332. <img id="poster-img" src="<%= imageUrl %>" alt="Art Color" />
  333. <canvas id="canvas"></canvas>
  334. <div id="play-button" class="play-button"></div>
  335. </div>
  336. <div id="buttons" class="buttons">
  337. <a href="<%= openapplink %>" target="_blank" class="btn btn-primary">
  338. <%= translate.colorNow[lang] %>
  339. </a>
  340. <a href="<%= downlink %>" class="btn btn-secondary">
  341. <%= translate.downloadApp[lang] %>
  342. </a>
  343. </div>
  344. <!-- MARK: 微信引导层 -->
  345. <div id="wechat-guide-overlay" class="wechat-guide-overlay">
  346. <div class="wechat-guide-arrow" onclick="closeOverlay()"></div>
  347. <p class="wechat-guide-text">
  348. 请点击右上角 <strong>"..."</strong> 菜单<br>
  349. 选择 <strong>"在浏览器中打开"</strong><br>
  350. 即可跳转到 App 或下载页面
  351. </p>
  352. </div>
  353. <script>
  354. // =============== 新增: Facebook App Links SDK ===============
  355. (function (d, s, id) {
  356. var js, fjs = d.getElementsByTagName(s)[0];
  357. if (d.getElementById(id)) return;
  358. js = d.createElement(s); js.id = id;
  359. js.src = "https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v12.0&appId=2402037183154121";
  360. fjs.parentNode.insertBefore(js, fjs);
  361. }(document, 'script', 'facebook-jssdk'));
  362. // =============== Facebook App Links SDK 结束 ===============
  363. // claim bonus 超过1秒自动跳转到下载页
  364. document.addEventListener('DOMContentLoaded', function () {
  365. const urlScheme = `anc://page/<%= id %>`
  366. const userAgent = navigator.userAgent || navigator.vendor || window.opera;
  367. const isFacebookBrowser = navigator.userAgent.match(/FBAN|FBAV/i);
  368. const isWeChatBrowser = /micromessenger/i.test(userAgent);
  369. const isAndroid = /android/i.test(userAgent);
  370. const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
  371. // 检查 URL 中是否包含 check=1 参数
  372. const urlParams = new URLSearchParams(window.location.search);
  373. const hasCheckParam = urlParams.has('check');
  374. // 定义下载页面 URL(与 Download App 按钮保持一致)
  375. const downloadUrl = document.querySelector('.btn-secondary').href;
  376. if (isFacebookBrowser) {
  377. console.log("检测到Facebook应用内浏览器");
  378. }
  379. // 微信环境相关
  380. const wechatGuideOverlay = document.getElementById('wechat-guide-overlay');
  381. function closeOverlay() {
  382. wechatGuideOverlay.classList.remove('active');
  383. }
  384. if (isWeChatBrowser) {
  385. wechatGuideOverlay.classList.add('active');
  386. return; // 微信浏览器直接返回,不执行后续自动跳转逻辑
  387. }
  388. // 如果是带 check 参数的页面,则执行拉起检测逻辑
  389. if (hasCheckParam) {
  390. // 通用下载页,一般是在pc浏览器而非android/ios环境,直接跳转,不用等待
  391. if (downloadUrl === 'https://art.pcoloring.com/app') {
  392. window.location.href = downloadUrl;
  393. return;
  394. }
  395. let appLaunched = false;
  396. // 监听页面可见性变化(判断 App 是否被拉起)
  397. document.addEventListener('visibilitychange', function () {
  398. if (document.hidden) {
  399. // 页面被隐藏,说明 App 可能被成功拉起
  400. appLaunched = true;
  401. }
  402. });
  403. // 监听页面焦点变化(辅助判断)
  404. window.addEventListener('blur', function () {
  405. appLaunched = true;
  406. });
  407. setTimeout(function () {
  408. if (!appLaunched) {
  409. // 尝试 URL Scheme
  410. window.location.href = urlScheme;
  411. // 再次设置一个更短的定时器,如果 URL Scheme 也失败,则跳转下载页
  412. setTimeout(function () {
  413. if (!appLaunched) {
  414. window.location.href = downloadUrl;
  415. }
  416. }, 500); // 500ms 足够判断 URL Scheme 是否有效
  417. }
  418. }, 1000); // 1 秒后检查,给 Universal Link / App Link 足够时间响应
  419. }
  420. // 为 Color Now 按钮添加防重复点击逻辑(可选)
  421. const colorNowButton = document.querySelector('.btn-primary');
  422. if (colorNowButton) {
  423. colorNowButton.addEventListener('click', function (e) {
  424. // 只有在没有 check 参数时才允许跳转(避免循环跳转)
  425. if (!hasCheckParam) {
  426. // 可添加加载状态
  427. this.textContent = 'Launching...';
  428. this.disabled = true;
  429. }
  430. });
  431. }
  432. });
  433. // 图片加载逻辑
  434. const header = document.getElementById('header');
  435. const posterImg = document.getElementById('poster-img');
  436. const imagePlaceholder = document.getElementById('imagePlaceholder');
  437. const buttons = document.getElementById('buttons');
  438. // 图片加载完成后
  439. posterImg.onload = function () {
  440. // header淡入
  441. header.classList.add('loaded');
  442. // 标记图片已加载,触发 CSS 淡入效果
  443. posterImg.classList.add('loaded');
  444. // buttons淡入
  445. buttons.classList.add('loaded');
  446. // 隐藏占位符
  447. if (imagePlaceholder) {
  448. imagePlaceholder.style.display = 'none';
  449. }
  450. };
  451. // 图片加载失败时(备选方案)
  452. posterImg.onerror = function () {
  453. imagePlaceholder.innerHTML = '<p>图片加载失败</p>'; // 显示错误提示
  454. };
  455. </script>
  456. </body>
  457. </html>