App.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <script>
  2. import initConfig from '@/initConfig.js';
  3. // #ifdef MP-WEIXIN
  4. import { SCAN_QR_CACHE } from '@/settings/enums.js';
  5. // #endif
  6. /** 从 scene 解析:支持小程序码 s=店铺id&t=桌号id、storeId_tableId、纯数字桌号、JSON 等 */
  7. function parseSceneToStoreTable(sceneStr) {
  8. const trim = (v) => (v == null ? '' : String(v).trim());
  9. let storeId = '';
  10. let tableId = '';
  11. if (!sceneStr) return { storeId, tableId };
  12. let decoded = sceneStr;
  13. try {
  14. decoded = decodeURIComponent(decoded);
  15. } catch (_) {}
  16. decoded = trim(decoded);
  17. const parseKv = (text) => {
  18. const out = { storeId: '', tableId: '' };
  19. text.split('&').forEach((pair) => {
  20. const eq = pair.indexOf('=');
  21. if (eq > 0) {
  22. const k = pair.substring(0, eq).trim().toLowerCase();
  23. let v = pair.substring(eq + 1).trim();
  24. try { v = decodeURIComponent(v); } catch (_) {}
  25. v = trim(v);
  26. if (['s', 'storeid', 'store_id'].includes(k)) out.storeId = v;
  27. if (['t', 'tableid', 'table_id', 'tableno', 'table'].includes(k)) out.tableId = v;
  28. }
  29. });
  30. return out;
  31. };
  32. try {
  33. if (decoded.startsWith('{') && decoded.endsWith('}')) {
  34. const obj = JSON.parse(decoded);
  35. return { storeId: trim(obj?.storeId ?? obj?.store_id ?? obj?.s ?? ''), tableId: trim(obj?.tableId ?? obj?.table_id ?? obj?.tableid ?? obj?.t ?? obj?.tableNo ?? obj?.table ?? '') };
  36. }
  37. if (/^\d+_\d+$/.test(decoded)) {
  38. const [s, t] = decoded.split('_');
  39. return { storeId: trim(s), tableId: trim(t) };
  40. }
  41. if (/^\d+$/.test(decoded)) return { storeId: '', tableId: decoded };
  42. return parseKv(decoded);
  43. } catch (err) {
  44. console.warn('parseSceneToStoreTable', err);
  45. }
  46. return { storeId, tableId };
  47. }
  48. export default {
  49. onLaunch: function (e) {
  50. // 只有小程序执行
  51. // #ifdef MP-WEIXIN
  52. initConfig();
  53. // 通过二维码编译/扫码进入:将二维码携带的信息缓存(query.scene 为小程序码参数,query.q 为普通链接二维码)
  54. try {
  55. const sceneEnc = e?.query?.scene;
  56. const qEnc = e?.query?.q;
  57. const scene = sceneEnc != null && sceneEnc !== '' ? decodeURIComponent(String(sceneEnc)) : '';
  58. const q = qEnc != null && qEnc !== '' ? decodeURIComponent(String(qEnc)) : '';
  59. const rawFromQR = scene || q || '';
  60. if (rawFromQR) {
  61. const { storeId, tableId } = parseSceneToStoreTable(rawFromQR);
  62. const payload = { raw: rawFromQR, storeId, tableId };
  63. uni.setStorageSync(SCAN_QR_CACHE, JSON.stringify(payload));
  64. if (storeId) uni.setStorageSync('currentStoreId', storeId);
  65. if (tableId) uni.setStorageSync('currentTableId', tableId);
  66. }
  67. } catch (err) {
  68. console.warn('缓存二维码启动参数失败', err);
  69. }
  70. // #endif
  71. },
  72. onShow: function (res) {
  73. console.log('App Show', res);
  74. // 是否是从被打开的小程序返回
  75. const { appId, extraData } = res.referrerInfo;
  76. if (appId && extraData) {
  77. uni.$emit('listener:ArBack', res.referrerInfo);
  78. }
  79. },
  80. onHide: function () {
  81. console.log('App Hide');
  82. }
  83. };
  84. </script>
  85. <style lang="scss">
  86. view,
  87. image,
  88. label {
  89. box-sizing: border-box;
  90. word-break: break-all;
  91. }
  92. image {
  93. height: auto;
  94. width: auto;
  95. }
  96. /* #ifndef APP-NVUE */
  97. // 设置整个项目的背景色
  98. page {
  99. background-color: #f7f9fa;
  100. }
  101. /* #endif */
  102. // 弹性盒子
  103. .flex {
  104. display: flex;
  105. &-none {
  106. flex: none;
  107. }
  108. &-1 {
  109. flex: 1;
  110. }
  111. &-y {
  112. flex-direction: column;
  113. }
  114. &-top {
  115. align-items: flex-start !important;
  116. }
  117. // 顶部对齐
  118. &-bottom {
  119. align-items: flex-end;
  120. }
  121. // 底部对齐
  122. &-content-end {
  123. justify-content: flex-end;
  124. }
  125. // 水平靠右 || 垂直靠下对齐
  126. &-center {
  127. align-items: center;
  128. }
  129. // 水平居中对齐
  130. &-center-center {
  131. align-items: center;
  132. justify-content: center;
  133. }
  134. // 水平垂直居中
  135. &-between {
  136. justify-content: space-between;
  137. }
  138. // 两端不留间隙对齐
  139. &-around {
  140. justify-content: space-around;
  141. }
  142. // 两端留间隙对齐
  143. &-wrap {
  144. flex-wrap: wrap;
  145. }
  146. // 允许换行
  147. }
  148. .w-0 {
  149. width: 0;
  150. }
  151. .h-0 {
  152. height: 0;
  153. }
  154. // 隐藏显示多少行
  155. .ellipsis {
  156. overflow: hidden;
  157. text-overflow: ellipsis;
  158. display: -webkit-box;
  159. -webkit-box-orient: vertical;
  160. -webkit-line-clamp: 1;
  161. word-break: break-all;
  162. @for $i from 2 through 10 {
  163. &.ellipsis-#{$i} {
  164. -webkit-line-clamp: $i;
  165. }
  166. }
  167. &-no {
  168. display: block;
  169. }
  170. }
  171. // 点击时的透明度
  172. .hover-active {
  173. opacity: 0.8 !important;
  174. }
  175. // 底部安全区
  176. .safe-area {
  177. padding-bottom: constant(safe-area-inset-bottom);
  178. /* 兼容 iOS < 11.2 */
  179. padding-bottom: env(safe-area-inset-bottom);
  180. /* 兼容 iOS >= 11.2 */
  181. }
  182. .ql-editor.ql-blank:before {
  183. color: #999999;
  184. font-size: 28rpx;
  185. font-style: normal;
  186. }
  187. </style>