|
|
@@ -31,6 +31,8 @@
|
|
|
import { computed, unref } from 'vue';
|
|
|
import { getFileUrl } from '@/utils/file.js';
|
|
|
import { SCAN_QR_CACHE } from '@/settings/enums.js';
|
|
|
+import { useUserStore } from '@/store/user.js';
|
|
|
+import { TOKEN } from '@/settings/enums.js';
|
|
|
|
|
|
const menus = [
|
|
|
{ title: '首页', link: '/pages/index/index', img: 'img/tabbar/index1.png', imgon: 'img/tabbar/index2.png' },
|
|
|
@@ -46,40 +48,110 @@ const getTabBarWrapStyle = computed(() => ({
|
|
|
position: props.fixed ? 'fixed' : 'relative'
|
|
|
}));
|
|
|
|
|
|
-// 解析扫码内容:s=店铺id,t=桌号id
|
|
|
+// 解析扫码内容:支持 s=店铺id&t=桌号id、URL 的 query、scene 参数、JSON 等格式
|
|
|
function parseScanResult(str) {
|
|
|
const trim = (v) => (v == null ? '' : String(v).trim());
|
|
|
let storeId = '';
|
|
|
let tableId = '';
|
|
|
if (!str) return { storeId, tableId };
|
|
|
- const s = trim(str);
|
|
|
- try {
|
|
|
- const parts = s.split('&');
|
|
|
- parts.forEach((pair) => {
|
|
|
- const [k, v] = pair.split('=').map((x) => (x ? decodeURIComponent(String(x).trim()) : ''));
|
|
|
- if (k === 's' || k === 'storeId' || k === 'store_id') storeId = trim(v);
|
|
|
- if (k === 't' || k === 'tableId' || k === 'table_id' || k === 'tableid') tableId = trim(v);
|
|
|
+ let s = trim(str);
|
|
|
+ const parseKv = (text) => {
|
|
|
+ const out = { storeId: '', tableId: '' };
|
|
|
+ const keys = {
|
|
|
+ store: ['s', 'storeid', 'store_id'],
|
|
|
+ table: ['t', 'tableid', 'table_id', 'tableno', 'table']
|
|
|
+ };
|
|
|
+ text.split('&').forEach((pair) => {
|
|
|
+ const eq = pair.indexOf('=');
|
|
|
+ if (eq > 0) {
|
|
|
+ const k = pair.substring(0, eq).trim().toLowerCase();
|
|
|
+ let v = pair.substring(eq + 1).trim();
|
|
|
+ try {
|
|
|
+ v = decodeURIComponent(v);
|
|
|
+ } catch (_) {}
|
|
|
+ v = trim(v);
|
|
|
+ if (keys.store.includes(k)) out.storeId = v;
|
|
|
+ if (keys.table.includes(k)) out.tableId = v;
|
|
|
+ }
|
|
|
});
|
|
|
+ return out;
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ // 1. 若为 URL 或含 ?,提取 query 或 scene
|
|
|
+ const qIdx = s.indexOf('?');
|
|
|
+ const hIdx = s.indexOf('#');
|
|
|
+ if (qIdx >= 0) {
|
|
|
+ const queryPart = hIdx >= 0 ? s.substring(qIdx + 1, hIdx) : s.substring(qIdx + 1);
|
|
|
+ const params = new Map();
|
|
|
+ queryPart.split('&').forEach((pair) => {
|
|
|
+ const eq = pair.indexOf('=');
|
|
|
+ if (eq > 0) {
|
|
|
+ const k = decodeURIComponent(pair.substring(0, eq).trim());
|
|
|
+ const v = decodeURIComponent(pair.substring(eq + 1).trim());
|
|
|
+ params.set(k, v);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ const scene = params.get('scene') || params.get('Scene');
|
|
|
+ if (scene) {
|
|
|
+ const decoded = decodeURIComponent(scene);
|
|
|
+ if (decoded.startsWith('{') && decoded.endsWith('}')) {
|
|
|
+ const obj = JSON.parse(decoded);
|
|
|
+ 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 ?? '')
|
|
|
+ };
|
|
|
+ }
|
|
|
+ const fromKv = parseKv(decoded);
|
|
|
+ // scene 仅为数字时,视为桌号
|
|
|
+ if (!fromKv.tableId && /^\d+$/.test(trim(decoded))) {
|
|
|
+ fromKv.tableId = trim(decoded);
|
|
|
+ }
|
|
|
+ return fromKv;
|
|
|
+ }
|
|
|
+ const fromQuery = parseKv(queryPart);
|
|
|
+ return fromQuery;
|
|
|
+ }
|
|
|
+ // 2. 尝试 JSON 格式
|
|
|
+ if ((s.startsWith('{') && s.endsWith('}')) || (s.startsWith('[') && s.endsWith(']'))) {
|
|
|
+ const obj = JSON.parse(s);
|
|
|
+ storeId = trim(obj?.storeId ?? obj?.store_id ?? obj?.s ?? '');
|
|
|
+ tableId = trim(obj?.tableId ?? obj?.table_id ?? obj?.tableid ?? obj?.t ?? obj?.tableNo ?? obj?.table ?? '');
|
|
|
+ return { storeId, tableId };
|
|
|
+ }
|
|
|
+ // 3. key=value 格式
|
|
|
+ return parseKv(s);
|
|
|
} catch (err) {
|
|
|
console.warn('parseScanResult', err);
|
|
|
}
|
|
|
return { storeId, tableId };
|
|
|
}
|
|
|
|
|
|
-// 点击扫码点餐:先调起微信扫描二维码,解析后缓存再跳转
|
|
|
+// 点击扫码点餐:未登录提示请登录;已登录扫码后跳转点餐页
|
|
|
function handleScanOrder() {
|
|
|
+ const userStore = useUserStore();
|
|
|
+ const token = userStore.getToken || uni.getStorageSync(TOKEN) || '';
|
|
|
+ if (!token) {
|
|
|
+ uni.showToast({ title: '请登录', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
uni.scanCode({
|
|
|
scanType: ['qrCode'],
|
|
|
success: (res) => {
|
|
|
- const result = res?.result ?? '';
|
|
|
+ // 普通二维码用 result;小程序码用 path(含 scene)
|
|
|
+ const result = (res?.path || res?.result || '').trim();
|
|
|
const { storeId, tableId } = parseScanResult(result);
|
|
|
+ if (!tableId) {
|
|
|
+ console.warn('[扫码] 未解析到桌号,原始内容:', result, '解析结果:', { storeId, tableId });
|
|
|
+ }
|
|
|
const payload = { raw: result, storeId, tableId };
|
|
|
uni.setStorageSync(SCAN_QR_CACHE, JSON.stringify(payload));
|
|
|
if (storeId) uni.setStorageSync('currentStoreId', storeId);
|
|
|
if (tableId) uni.setStorageSync('currentTableId', tableId);
|
|
|
- if (unref(getPath) !== menus[1].link) {
|
|
|
- uni.switchTab({ url: menus[1].link });
|
|
|
- }
|
|
|
+ const diners = uni.getStorageSync('currentDiners') || '1';
|
|
|
+ uni.setStorageSync('currentDiners', diners);
|
|
|
+ uni.reLaunch({
|
|
|
+ url: `/pages/orderFood/index?tableid=${encodeURIComponent(tableId || '')}&diners=${encodeURIComponent(diners)}`
|
|
|
+ });
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
if (err?.errMsg && !String(err.errMsg).includes('cancel')) {
|