content-h5-test-template.html 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta
  6. name="viewport"
  7. content="width=device-width, initial-scale=1, viewport-fit=cover"
  8. />
  9. <title>CMR 内容体验测试页</title>
  10. <style>
  11. :root {
  12. color-scheme: light;
  13. --bg: #f4f8f5;
  14. --fg: #173127;
  15. --muted: #5e6f65;
  16. --accent: #1f7a5a;
  17. --accent-soft: #dcefe6;
  18. --card: rgba(255, 255, 255, 0.9);
  19. --border: rgba(23, 49, 39, 0.08);
  20. }
  21. * {
  22. box-sizing: border-box;
  23. }
  24. body {
  25. margin: 0;
  26. font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
  27. background:
  28. radial-gradient(circle at top left, rgba(31, 122, 90, 0.14), transparent 32%),
  29. linear-gradient(180deg, #eef6f1 0%, var(--bg) 100%);
  30. color: var(--fg);
  31. }
  32. .page {
  33. min-height: 100vh;
  34. padding: 28px 18px 32px;
  35. }
  36. .card {
  37. max-width: 720px;
  38. margin: 0 auto;
  39. background: var(--card);
  40. border: 1px solid var(--border);
  41. border-radius: 24px;
  42. padding: 24px;
  43. box-shadow: 0 18px 42px rgba(24, 49, 39, 0.12);
  44. backdrop-filter: blur(10px);
  45. }
  46. .eyebrow {
  47. margin: 0 0 8px;
  48. color: var(--muted);
  49. font-size: 12px;
  50. letter-spacing: 0.16em;
  51. text-transform: uppercase;
  52. }
  53. h1 {
  54. margin: 0 0 12px;
  55. font-size: 28px;
  56. line-height: 1.2;
  57. }
  58. .lead {
  59. margin: 0 0 18px;
  60. color: var(--muted);
  61. font-size: 15px;
  62. line-height: 1.7;
  63. }
  64. .context {
  65. margin: 18px 0 0;
  66. padding: 14px 16px;
  67. border-radius: 16px;
  68. background: var(--accent-soft);
  69. }
  70. .context pre {
  71. margin: 0;
  72. white-space: pre-wrap;
  73. word-break: break-word;
  74. font-size: 12px;
  75. line-height: 1.6;
  76. }
  77. .actions {
  78. display: grid;
  79. gap: 12px;
  80. margin-top: 22px;
  81. }
  82. button {
  83. appearance: none;
  84. border: 0;
  85. border-radius: 16px;
  86. padding: 14px 18px;
  87. font-size: 16px;
  88. font-weight: 600;
  89. cursor: pointer;
  90. }
  91. .btn-primary {
  92. background: var(--accent);
  93. color: #fff;
  94. }
  95. .btn-secondary {
  96. background: rgba(23, 49, 39, 0.08);
  97. color: var(--fg);
  98. }
  99. </style>
  100. </head>
  101. <body>
  102. <main class="page">
  103. <section class="card">
  104. <p class="eyebrow">content-v1 test</p>
  105. <h1 id="title">内容体验测试页</h1>
  106. <p class="lead" id="desc">
  107. 这个页面用于验证小程序内容 H5 容器、上下文传参和关闭/回退链路。
  108. </p>
  109. <div class="actions">
  110. <button class="btn-primary" id="closeBtn">关闭并返回小程序</button>
  111. <button class="btn-secondary" id="fallbackBtn">模拟失败并回退原生卡片</button>
  112. </div>
  113. <div class="context">
  114. <pre id="contextView">loading...</pre>
  115. </div>
  116. </section>
  117. </main>
  118. <script>
  119. function getQueryParam(key) {
  120. const params = new URLSearchParams(window.location.search);
  121. return params.get(key) || "";
  122. }
  123. function parseContext() {
  124. const raw = getQueryParam("cmrContext");
  125. if (!raw) {
  126. return {};
  127. }
  128. try {
  129. return JSON.parse(raw);
  130. } catch (error) {
  131. return { parseError: String(error), raw };
  132. }
  133. }
  134. function postToMiniProgram(action, payload) {
  135. const message = { action, payload: payload || {} };
  136. if (
  137. window.wx &&
  138. window.wx.miniProgram &&
  139. typeof window.wx.miniProgram.postMessage === "function"
  140. ) {
  141. window.wx.miniProgram.postMessage({ data: message });
  142. } else if (
  143. window.parent &&
  144. typeof window.parent.postMessage === "function"
  145. ) {
  146. window.parent.postMessage(message, "*");
  147. }
  148. }
  149. const context = parseContext();
  150. const titleEl = document.getElementById("title");
  151. const descEl = document.getElementById("desc");
  152. const contextViewEl = document.getElementById("contextView");
  153. if (context.title) {
  154. titleEl.textContent = context.title;
  155. }
  156. if (context.body) {
  157. descEl.textContent = context.body;
  158. }
  159. contextViewEl.textContent = JSON.stringify(
  160. {
  161. bridge: getQueryParam("cmrBridge"),
  162. kind: getQueryParam("cmrKind"),
  163. context,
  164. },
  165. null,
  166. 2
  167. );
  168. document.getElementById("closeBtn").addEventListener("click", function () {
  169. postToMiniProgram("close");
  170. });
  171. document.getElementById("fallbackBtn").addEventListener("click", function () {
  172. postToMiniProgram("fallback");
  173. });
  174. </script>
  175. </body>
  176. </html>