app.js 4.61 KB
/*
 * @Date: 2025-06-28 10:33:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-12 23:48:04
 * @FilePath: /xyxBooking-weapp/src/app.js
 * @Description: 文件描述
 */
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './utils/polyfill'
import './app.less'
import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
import Taro from '@tarojs/taro'
import { qrcodeListAPI } from '@/api/index'
import { formatDatetime } from '@/utils/tools'

/**
 * 格式化支付记录,按 pay_id 分组,相同 pay_id 下的记录 sort 为 0,否则为 1
 * @param {*} data 支付记录数组
 * @returns 格式化后的支付记录数组
 */
const formatGroup = (data) => {
  let lastPayId = null;
  for (let i = 0; i < data.length; i++) {
    if (data[i].pay_id !== lastPayId) {
      data[i].sort = 1;
      lastPayId = data[i].pay_id;
    } else {
      data[i].sort = 0;
    }
  }
  return data;
}

const App = createApp({
    // 对应 onLaunch
  async onLaunch(options) {
    const path = options?.path || ''
    const query = options?.query || {}

    const query_string = Object.keys(query)
      .map((key) => `${key}=${encodeURIComponent(query[key])}`)
      .join('&')
    const full_path = query_string ? `${path}?${query_string}` : path

    // 保存当前页面路径,用于授权后跳转回原页面
    if (full_path) {
      saveCurrentPagePath(full_path)
    }

    /**
     * 预加载二维码数据
     * - 仅在有网络连接时调用
     * - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA)
     * - 失败则移除缓存
     */
    const preloadQrData = async () => {
        try {
            const { code, data } = await qrcodeListAPI();
            if (code && data) {
                data.forEach(item => {
                    item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time })
                    item.sort = 0;
                  });
                  const validData = data.filter(item => item.qr_code !== '');
                  if (validData.length > 0) {
                      const processed = formatGroup(validData);
                      const offline_data = processed.map(item => ({
                          name: item.name,
                          id_number: item.id_number,
                          qr_code: item.qr_code,
                          begin_time: item.begin_time,
                          end_time: item.end_time,
                          datetime: item.datetime,
                          pay_id: item.pay_id,
                          sort: item.sort,
                      }));
                      Taro.setStorageSync('OFFLINE_QR_DATA', offline_data);
                  } else {
                      Taro.removeStorageSync('OFFLINE_QR_DATA');
                  }
            }
        } catch (e) {
            console.error('Preload QR failed', e);
        }
    };

    /**
     * 监听网络状态变化
     * - 当网络连接且有授权时,调用 preloadQrData 预加载二维码数据
     */
    Taro.onNetworkStatusChange((res) => {
        if (res.isConnected && hasAuth()) {
            preloadQrData()
        }
    })

    const is_usable_network = (network_type) => {
        return ['wifi', '4g', '5g', '3g'].includes(network_type)
    }

    /**
     * 尝试在网络可用时预加载二维码数据
     * - 仅在有授权时调用
     * - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA)
     * - 失败则移除缓存
     * @returns {Promise<void>}
     */
    const try_preload_when_online = () => {
        if (!hasAuth()) return
        Taro.getNetworkType({
            success: (res) => {
                if (is_usable_network(res.networkType)) {
                    preloadQrData()
                }
            }
        })
    }

    /**
     * 尝试在有授权时预加载二维码数据
     * - 若无授权,则尝试静默授权
     * - 授权成功后调用 try_preload_when_online 预加载数据
     * - 授权失败则跳转至授权页面
     */
    if (hasAuth()) {
        try_preload_when_online()
        return
    }

    if (path === 'pages/auth/index') return

    try {
        // 尝试静默授权
        await silentAuth()
        // 授权成功后预加载数据
        try_preload_when_online()
    } catch (error) {
        console.error('静默授权失败:', error)
        // 授权失败则跳转至授权页面
        navigateToAuth(full_path || undefined)
    }
  },
  onShow() {
  },
  // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
});

App.use(createPinia())

export default App