demo.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>ColorMapRun SDK 全功能测试台</title>
  7. <style>
  8. body { font-family: sans-serif; padding: 20px; background: #f0f2f5; display: flex; gap: 20px; }
  9. .sidebar { width: 300px; flex-shrink: 0; display: flex; flex-direction: column; gap: 10px; height: 90vh; overflow-y: auto; padding-right: 10px; }
  10. .main { flex: 1; display: flex; flex-direction: column; height: 90vh; }
  11. h2, h3 { margin-top: 0; color: #333; }
  12. h3 { font-size: 16px; margin-bottom: 10px; padding-bottom: 5px; border-bottom: 2px solid #007aff; display: inline-block; }
  13. .group { margin-bottom: 20px; background: white; padding: 15px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
  14. .group-title { font-weight: bold; margin-bottom: 10px; color: #555; }
  15. .btn-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
  16. button { padding: 8px 12px; font-size: 13px; border: 1px solid #ddd; background: #fff; border-radius: 4px; cursor: pointer; text-align: left; transition: all 0.2s; }
  17. button:hover { background: #f0f8ff; border-color: #007aff; color: #007aff; }
  18. button.active { background: #007aff; color: white; border-color: #007aff; }
  19. .log-area { flex: 1; background: #1e1e1e; color: #0f0; padding: 15px; border-radius: 8px; font-family: 'Consolas', monospace; font-size: 13px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; line-height: 1.5; }
  20. .log-entry { margin-bottom: 10px; border-bottom: 1px dashed #444; padding-bottom: 5px; }
  21. .log-time { color: #888; font-size: 11px; }
  22. .log-label { color: #fff; font-weight: bold; }
  23. .log-error { color: #ff4d4f; }
  24. </style>
  25. <!-- SDK -->
  26. <script src="./mock_flutter.js"></script> <!-- 确保 mock_flutter.js 在 bridge.js 和 api.js 之前引入,以便正确模拟全局对象 -->
  27. <script src="./bridge.js"></script>
  28. <script src="./api.js"></script>
  29. </head>
  30. <body>
  31. <div class="sidebar">
  32. <h2>SDK 测试台</h2>
  33. <div style="font-size: 12px; color: #666; margin-bottom: 10px;">当前环境: <span id="envInfo">检测中...</span></div>
  34. <button onclick="clearLog()" style="text-align: center; margin-bottom: 10px;">🗑️ 清空日志</button>
  35. <!-- App Bridge -->
  36. <div class="group">
  37. <div class="group-title">📱 App 交互 (Bridge)</div>
  38. <div class="btn-grid">
  39. <button onclick="run('Bridge.openMap(latitude, longitude, name)', Bridge.openMap, 39.9, 116.4, '北京')">打开地图</button>
  40. <button onclick="run('Bridge.openMatch(id, type)', Bridge.openMatch, MOCK_MCID, 1)">打开赛事详情</button>
  41. <button onclick="run('Bridge.openActivityList(id, mapName)', Bridge.openActivityList, 202, '奥体')">打开活动列表</button>
  42. <button onclick="run('Bridge.shareWx({title, url, image, scene})', Bridge.shareWx, {title:'Demo分享', url:location.href, image:'https://picsum.photos/100/100'})">微信分享</button>
  43. <button onclick="run('Bridge.launchWxMini(username, path)', Bridge.launchWxMini, 'gh_bea09156da8d', 'pages/index/index')">打开小程序</button>
  44. <button onclick="run('Bridge.saveImage(base64Str)', Bridge.saveImage, 'data:image/png;base64,iVBORw0KGgoAAA...')">保存图片</button>
  45. <button onclick="run('Bridge.back()', Bridge.back)">返回上一页</button>
  46. <button onclick="run('Bridge.toHome()', Bridge.toHome)">返回App首页</button>
  47. <button onclick="run('Bridge.toLogin()', Bridge.toLogin)">跳转登录</button>
  48. <button onclick="run('Bridge.setTitle(title)', Bridge.setTitle, '新标题')">设置标题</button>
  49. <button onclick="getToken()">获取 Token (Bridge)</button>
  50. </div>
  51. </div>
  52. <!-- API: Config -->
  53. <div class="group">
  54. <div class="group-title">1. 配置与基础</div>
  55. <div class="btn-grid">
  56. <button onclick="api('API.getCardBase(ecId, pageName)', API.getCardBase, MOCK_ECID, 'index')">getCardBase</button>
  57. <button onclick="api('API.getCardConfig(ecId, pageName)', API.getCardConfig, MOCK_ECID, 'index')">getCardConfig</button>
  58. <button onclick="api('API.getUserConfig(ecId, pageName)', API.getUserConfig, MOCK_ECID, 'index')">getUserConfig</button>
  59. </div>
  60. </div>
  61. <!-- API: Activity -->
  62. <div class="group">
  63. <div class="group-title">2. 活动与报名</div>
  64. <div class="btn-grid">
  65. <button onclick="api('API.getCardDetail(ecId)', API.getCardDetail, MOCK_ECID)">getCardDetail</button>
  66. <button onclick="api('API.getMatchRsDetail(ecId)', API.getMatchRsDetail, MOCK_ECID)">getMatchRsDetail</button>
  67. <button onclick="api('API.getUserJoinStatus(ecId)', API.getUserJoinStatus, MOCK_ECID)">getUserJoinStatus</button>
  68. <button onclick="api('API.isNewUserInCardComp(ecId)', API.isNewUserInCardComp, MOCK_ECID)">isNewUserInCardComp</button>
  69. <button onclick="api('API.getOnlineMcSignUpDetail(ecId)', API.getOnlineMcSignUpDetail, MOCK_ECID)">getOnlineMcSignUpDetail</button>
  70. <button onclick="api('API.signUpOnline(mcId, coiId, selectTeam, nickName)', API.signUpOnline, MOCK_MCID, 0, 0, '测试用户')">signUpOnline (报名)</button>
  71. <button onclick="api('API.isAllowMcSignUp(ecId)', API.isAllowMcSignUp, MOCK_ECID)">isAllowMcSignUp</button>
  72. </div>
  73. </div>
  74. <!-- API: Rank -->
  75. <div class="group">
  76. <div class="group-title">3. 排名与成就</div>
  77. <div class="btn-grid">
  78. <button onclick="api('API.getRankDetail(mcIdListStr, mcType, dispArrStr)', API.getRankDetail, String(MOCK_MCID), 1, 'total')">getRankDetail</button>
  79. <button onclick="api('API.getUserCurrentRank(ecId)', API.getUserCurrentRank, MOCK_ECID)">getUserCurrentRank</button>
  80. <button onclick="api('API.getCurrentMonthlyChallenge()', API.getCurrentMonthlyChallenge)">getCurrentMonthlyChallenge</button>
  81. <button onclick="api('API.getMonthlyChallenge()', API.getMonthlyChallenge)">getMonthlyChallenge</button>
  82. <button onclick="api('API.getMonthRankDetail()', API.getMonthRankDetail)">getMonthRankDetail</button>
  83. <button onclick="api('API.getAchievement()', API.getAchievement)">getAchievement</button>
  84. <button onclick="api('API.getCompStatistic(ecId)', API.getCompStatistic, MOCK_ECID)">getCompStatistic</button>
  85. </div>
  86. </div>
  87. <!-- API: Exchange -->
  88. <div class="group">
  89. <div class="group-title">4. 积分与兑换</div>
  90. <div class="btn-grid">
  91. <button onclick="api('API.getScore(ecId)', API.getScore, MOCK_ECID)">getScore</button>
  92. <button onclick="api('API.getGoodsList(ecId)', API.getGoodsList, MOCK_ECID)">getGoodsList</button>
  93. <button onclick="api('API.getGoodsDetail(goodsId)', API.getGoodsDetail, 1)">getGoodsDetail</button>
  94. <button onclick="api('API.exchangeGoods(ecId, goodsId)', API.exchangeGoods, MOCK_ECID, 1)">exchangeGoods</button>
  95. <button onclick="api('API.getExchangeList(ecId)', API.getExchangeList, MOCK_ECID)">getExchangeList</button>
  96. <button onclick="api('API.getExchangeDetail(ecId, exchangeId)', API.getExchangeDetail, MOCK_ECID, 1)">getExchangeDetail</button>
  97. </div>
  98. </div>
  99. <!-- API: Message -->
  100. <div class="group">
  101. <div class="group-title">5. 消息与通知</div>
  102. <div class="btn-grid">
  103. <button onclick="api('API.getUnReadMessages(relationId, relationType)', API.getUnReadMessages, MOCK_ECID, 2)">getUnReadMessages</button>
  104. <button onclick="api('API.readMessage(mqIdListStr)', API.readMessage, '1,2,3')">readMessage</button>
  105. <button onclick="api('API.getWarnMessage(ecId)', API.getWarnMessage, MOCK_ECID)">getWarnMessage</button>
  106. </div>
  107. </div>
  108. <!-- API: Cert -->
  109. <div class="group">
  110. <div class="group-title">6. 电子证书</div>
  111. <div class="btn-grid">
  112. <button onclick="api('API.getCertStyle(ecId)', API.getCertStyle, MOCK_ECID)">getCertStyle</button>
  113. <button onclick="api('API.getUserBaseInCertificate(ecId)', API.getUserBaseInCertificate, MOCK_ECID)">getUserBaseInCertificate</button>
  114. <button onclick="api('API.createCertificate({ecId, certStyleId, ...})', API.createCertificate, {ecId:MOCK_ECID, certStyleId:1, userName:'测试用户'})">createCertificate</button>
  115. </div>
  116. </div>
  117. <!-- API: Other -->
  118. <div class="group">
  119. <div class="group-title">7. 其他</div>
  120. <div class="btn-grid">
  121. <button onclick="api('API.getUserInfo()', API.getUserInfo)">getUserInfo</button>
  122. <button onclick="api('API.getMapList(ecId)', API.getMapList, MOCK_ECID)">getMapList</button>
  123. <button onclick="api('API.getGrids(ecId)', API.getGrids, MOCK_ECID)">getGrids</button>
  124. </div>
  125. </div>
  126. </div>
  127. <div class="main">
  128. <h3>执行日志</h3>
  129. <div class="log-area" id="log">
  130. <div class="log-entry" style="color: #aaa;">等待操作...</div>
  131. </div>
  132. </div>
  133. <script>
  134. var TOKEN = '96ba3c924394934f7d30fa869a94ce0d';
  135. var MOCK_ECID = 1; // 模拟卡片/活动ID (ecId)
  136. var MOCK_MCID = 101; // 模拟赛事ID (mcId)
  137. var isLocal = window.location.protocol === 'file:' || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
  138. document.getElementById('envInfo').innerText = isLocal ? '本地开发 (Mock ON)' : '生产环境';
  139. // 初始化 API SDK
  140. API.init({
  141. token: TOKEN,
  142. useMock: isLocal
  143. });
  144. // ===========================================
  145. // 日志功能
  146. // ===========================================
  147. function log(label, data, isError = false) {
  148. var el = document.getElementById('log');
  149. var div = document.createElement('div');
  150. div.className = 'log-entry';
  151. var time = new Date().toLocaleTimeString();
  152. var content = typeof data === 'object' ? JSON.stringify(data, null, 2) : data;
  153. div.innerHTML = `<div class="log-time">[${time}]</div><div class="log-label ${isError?'log-error':''}">${label}</div><div>${content}</div>`;
  154. el.prepend(div);
  155. }
  156. function clearLog() {
  157. document.getElementById('log').innerHTML = '';
  158. }
  159. // ===========================================
  160. // Bridge 调用通用函数
  161. // fnDesc: Bridge 方法的描述字符串,如 'Bridge.openMap(latitude, longitude, name)'
  162. // fn: 实际要调用的 Bridge 方法
  163. // ...args: 实际参数
  164. // ===========================================
  165. function run(fnDesc, fn, ...args) {
  166. log('调用 ' + fnDesc, '参数: ' + JSON.stringify(args));
  167. fn.apply(Bridge, args);
  168. }
  169. function getToken() {
  170. log('调用 Bridge.getToken', '等待 App 回调 Token...');
  171. Bridge.onToken(function(t) {
  172. log('✅ Bridge 回调成功', 'Token: ' + t);
  173. });
  174. Bridge.getToken();
  175. }
  176. // ===========================================
  177. // API 调用通用函数
  178. // fnDesc: API 方法的描述字符串,如 'API.getCardDetail(ecId)'
  179. // fn: 实际要调用的 API 方法
  180. // ...args: 实际参数
  181. // ===========================================
  182. function api(fnDesc, fn, ...args) {
  183. log('请求 ' + fnDesc, '实际参数: ' + JSON.stringify(args));
  184. fn.apply(API, args)
  185. .then(function(res) {
  186. log('✅ 成功', res);
  187. })
  188. .catch(function(err) {
  189. log('❌ 失败', err.message || err, true);
  190. });
  191. }
  192. </script>
  193. </body>
  194. </html>