/** * Copyright (c) 2013-Now http://aidex.vip All rights reserved. */ import config, { getDefaultApiUrl } from '@/common/config.js'; import util from '@/common/util.js'; import Vue from 'vue' import Vuex from 'vuex' import { audioManager } from '@/utils/audioManager' import dayjs from 'dayjs' Vue.use(Vuex) let lifeData = {}; try{ // 尝试获取本地是否存在lifeData变量,第一次启动APP时是不存在的 lifeData = uni.getStorageSync('lifeData'); }catch(e){ } // 初始化API URL(默认正式环境) function initApiUrl() { const defaultUrl = getDefaultApiUrl(); try { uni.setStorageSync('ApiUrl', defaultUrl); } catch (e) { console.log('写入正式环境地址失败', e); } return defaultUrl; } // 需要永久存储,且下次APP启动需要取出的,在state中的变量名 let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_remember', 'vuex_locale','vuex_isAgent', 'vuex_notificationEnabled']; // 保存变量到本地存储中 const saveLifeData = function(key, value){ // 判断变量名是否在需要存储的数组中 if(saveStateKeys.indexOf(key) != -1) { // 获取本地存储的lifeData对象,将变量添加到对象中 let tmp = uni.getStorageSync('lifeData'); // 第一次打开APP,不存在lifeData变量,故放一个{}空对象 tmp = tmp ? tmp : {}; tmp[key] = value; // 执行这一步后,所有需要存储的变量,都挂载在本地的lifeData对象中 uni.setStorageSync('lifeData', tmp); } } // 简化 vuex 操作,文档:https://uviewui.com/components/vuexDetail.html const store = new Vuex.Store({ state: { // 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量 // 加上vuex_前缀,是防止变量名冲突,也让人一目了然 vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {userName: 'Aidex'}, vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '', vuex_remember: lifeData.vuex_remember ? lifeData.vuex_remember : '', vuex_locale: lifeData.vuex_locale ? lifeData.vuex_locale : '', vuex_isAgent: lifeData.vuex_isAgent ? lifeData.vuex_isAgent : '', // 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式 vuex_config: config, // 自定义tabbar数据 // 新增通知相关状态 vuex_notificationEnabled: lifeData.vuex_notificationEnabled != null ? lifeData.vuex_notificationEnabled : true, vuex_deliveryIds: [], // 存储已知的配布单ID vuex_messageList: [], // 存储消息列表 vuex_notificationAudio: null, vuex_pollingTimer: null, apiurl: initApiUrl() // 根据环境初始化URL }, mutations: { $uStore(state, payload) { // 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1 let nameArr = payload.name.split('.'); let saveKey = ''; let len = nameArr.length; if(len >= 2) { let obj = state[nameArr[0]]; for(let i = 1; i < len - 1; i ++) { obj = obj[nameArr[i]]; } obj[nameArr[len - 1]] = payload.value; saveKey = nameArr[0]; } else { // 单层级变量,在state就是一个普通变量的情况 state[payload.name] = payload.value; saveKey = payload.name; } // 保存变量到本地,见顶部函数定义 saveLifeData(saveKey, state[saveKey]) }, // 新增通知相关 mutation setPollingTimer(state, timer) { state.vuex_pollingTimer = timer; }, setNotificationAudio(state, audio) { state.vuex_notificationAudio = audio; }, SET_API_URL(state, url) { state.apiurl = url uni.setStorageSync('ApiUrl', url) } }, actions: { // 初始化通知 initNotification({ state, commit, dispatch }) { // 创建音频实例 const audio = uni.createInnerAudioContext(); audio.src = '/static/audio/ninyouxindepeibudan.mp3'; // 监听音频播放错误 audio.onError((res) => { console.error('Audio error:', res.errMsg); }); // 监听音频播放结束 audio.onEnded(() => { console.log('Audio playback completed'); }); commit('setNotificationAudio', audio); if(!state.vuex_notificationEnabled || !uni.getStorageSync("RemoteTokenData").token) return dispatch('stopPolling'); // 开始轮询 dispatch('startPolling'); // 监听网络状态 uni.onNetworkStatusChange(function(res) { if (res.isConnected) { dispatch('startPolling'); } else { dispatch('stopPolling'); } }); }, // 开始轮询 startPolling({ state, commit, dispatch }) { if (state.vuex_pollingTimer || !state.vuex_notificationEnabled) return; const timer = setInterval(() => { dispatch('checkNewDeliveries'); }, 20 * 1000); // }, 1 * 1000); commit('setPollingTimer', timer); }, // 停止轮询 stopPolling({ state, commit }) { if (state.vuex_pollingTimer) { clearInterval(state.vuex_pollingTimer); commit('setPollingTimer', null); } }, // 检查新配布单 async checkNewDeliveries({ state, commit, dispatch }) { uni.request({ url: util.apiurl + "/product/fpmArrangeOrder/getFpmArrangeOrderList", method: "GET", // #ifdef APP-PLUS sslVerify: false, // #endif header: { platform: "2", Authorization: uni.getStorageSync("RemoteTokenData").token, }, data: { business_status_ids: '1,2', // 根据tab传递对应的状态组合 page: 1, size: 10, }, success: (res) => { console.log('res',res) if (res.data.code != 0) { throw new Error('检查配布单失败'); } console.log("data", res.data.data.list); const data = res.data.data.list // 获取所有配布单ID const newDeliveryIds = data.map(item => item.id); // 找出新增的配布单ID const newIds = newDeliveryIds.filter(id => !state.vuex_deliveryIds.includes(id)); console.log("newIds", newIds.length); // 如果有新增配布单,触发通知 if (newIds.length > 0) { // 播放声音 audioManager.play() // 触发振动 uni.vibrateLong(); // 显示通知消息 // uni.showToast({ // title: `有${newIds.length}个新的配布单待处理`, // icon: 'none', // }); // 构建新的消息列表项 const newMessages = data.filter(item => newIds.includes(item.id)).map((item) => ({ title: '新配布单通知', content: `销售单号:${item.order_no}`, path: `/pages/saleship/salepickscandetail?billid=${item.id}`, time: dayjs().format('HH:mm') })); const newList = [...newMessages, ...state.vuex_messageList] // 更新消息列表 commit('$uStore', { name: 'vuex_messageList', value: newList }); } // 使用 $uStore 方式更新状态 commit('$uStore', { name: 'vuex_deliveryIds', value: newDeliveryIds }); }, fail: (error) => { console.log('error',error) if (error.code === 401 || error.errMsg.includes('Failed to connect')) { dispatch('stopPolling'); } }, complete: () => { }, }); }, updateApiUrl({ commit }, url) { commit('SET_API_URL', url) } }, getters: { apiurl: state => state.apiurl } }) export default store