1133 lines
35 KiB
Vue
1133 lines
35 KiB
Vue
<script>
|
||
import config from './common/config.js'
|
||
import {writeDebugLog,getSettings,verifyToken,logout,writePublicDebugLog} from './api/commonApi.js'
|
||
import { getCfgSettingByKey } from './api/configApi.js'
|
||
import store from './store/index.js'
|
||
import FixedCoordinateConverter from './common/fixedCoordinateConverter.js'
|
||
import { getDeviceToken, refreshDeviceTokenAsync, refreshDeviceTokenAndFetch } from './common/pushDeviceToken.js';
|
||
import { listenPushNotification, syncPendingPushNotifications } from './common/pushNotification.js';
|
||
import {refreshToken} from './api/commonApi.js'
|
||
import dayjs from './uni_modules/uview-ui/libs/util/dayjs.js';
|
||
import { decryptCfgSettingValue } from './common/cfgSettingCrypto.js';
|
||
import { saveDeviceToken, saveNotification } from './api/notificationApi.js';
|
||
// #ifdef APP-PLUS
|
||
var networkModule = uni.requireNativePlugin("NetworkUtils-NetworkUtilsModule")
|
||
// #endif
|
||
export default {
|
||
data() {
|
||
return {
|
||
timer: null, // 定时器引用
|
||
backgroundTaskId: 0, // iOS 后台任务ID
|
||
lastPushNotificationTitle: '',
|
||
lastPushNotificationContent: ''
|
||
}
|
||
},
|
||
onLaunch: function() {
|
||
this.initApp();
|
||
// #ifdef APP-PLUS
|
||
this.checkJailbreak();
|
||
uni.getLocation({
|
||
type: 'wgs84',
|
||
success: (res) => {}
|
||
});
|
||
// 延迟触发推送注册:避免 plus/原生桥尚未就绪导致 refresh 未真正调到原生(Xcode 看不到 refreshDeviceTokenAsync ENTER)
|
||
setTimeout(() => {
|
||
this.refreshPushDeviceTokenAndSync({ requestAuthorization: true }).catch((err) => {
|
||
console.warn('[APNs] refreshDeviceTokenAsync failed', err)
|
||
})
|
||
}, 1200)
|
||
|
||
this.setupPushNotificationListener();
|
||
setTimeout(() => {
|
||
this.syncPendingPushNotificationsFromNative();
|
||
}, 2000);
|
||
|
||
// #endif
|
||
},
|
||
onShow: function() {
|
||
//console.log("APP.vue:onShow()");
|
||
// 监听网络状态变化
|
||
/*uni.onNetworkStatusChange(function(res) {
|
||
if (res.isConnected) {
|
||
if (res.networkType === 'wifi') {
|
||
console.log('网络已连接,并且是Wi-Fi');
|
||
} else {
|
||
console.log('网络已连接,但不是Wi-Fi');
|
||
}
|
||
} else {
|
||
console.log('网络已断开');
|
||
}
|
||
});*/
|
||
// #ifdef APP-PLUS
|
||
this.getSettingByKey('MACAU_STRING');
|
||
|
||
let userData = uni.getStorageSync("userData");
|
||
if(userData != null && userData != undefined && userData != '' && userData.userId !=null){
|
||
this.syncPushDeviceTokenFromNative();
|
||
// 同步点击通知产生的 pending push,并在有 ConfirmNo 时跳转到 Limo Detail
|
||
setTimeout(() => {
|
||
this.syncPendingPushNotificationsFromNative();
|
||
this.tryConsumePendingPushNavigation();
|
||
}, 300);
|
||
}
|
||
// #endif
|
||
},
|
||
onHide: function() {
|
||
// #ifdef APP-PLUS
|
||
this.stopTimer();
|
||
// #endif
|
||
},
|
||
beforeDestroy() {
|
||
// #ifdef APP-PLUS
|
||
this.stopTimer();
|
||
// #endif
|
||
},
|
||
methods: {
|
||
parsePushMessageReceivedPayload(rawPayload) {
|
||
const root =
|
||
rawPayload &&
|
||
rawPayload.detail != null &&
|
||
typeof rawPayload.detail === 'object'
|
||
? rawPayload.detail
|
||
: rawPayload;
|
||
if (!root || typeof root !== 'object') {
|
||
return { notificationTitle: '', notificationContent: '' };
|
||
}
|
||
let merged = Object.assign({}, root);
|
||
let extra = merged.data ?? merged.payload ?? merged.message ?? merged.content;
|
||
if (typeof extra === 'string') {
|
||
const text = extra.trim();
|
||
if (text.startsWith('{') || text.startsWith('[')) {
|
||
try {
|
||
extra = JSON.parse(text);
|
||
} catch (parseError) {
|
||
extra = null;
|
||
}
|
||
} else if (text) {
|
||
merged._dataStringFallback = text;
|
||
}
|
||
}
|
||
if (extra != null && typeof extra === 'object' && !Array.isArray(extra)) {
|
||
merged = Object.assign({}, merged, extra);
|
||
}
|
||
const aps = merged.aps;
|
||
let alertBody = '';
|
||
let alertTitle = '';
|
||
if (aps && typeof aps.alert === 'object' && aps.alert !== null) {
|
||
alertTitle = String(aps.alert.title || '').trim();
|
||
alertBody = String(
|
||
aps.alert.body ?? aps.alert.subtitle ?? ''
|
||
).trim();
|
||
} else if (aps && typeof aps.alert === 'string') {
|
||
alertBody = String(aps.alert).trim();
|
||
}
|
||
const notificationTitle =
|
||
String(
|
||
alertTitle ||
|
||
merged.title ||
|
||
merged.Title ||
|
||
merged.notificationTitle ||
|
||
merged.notification_title ||
|
||
''
|
||
).trim();
|
||
const notificationContent = String(
|
||
alertBody ||
|
||
merged.body ||
|
||
merged.content ||
|
||
merged.Content ||
|
||
merged.message ||
|
||
merged.Message ||
|
||
merged.text ||
|
||
merged.description ||
|
||
merged._dataStringFallback ||
|
||
''
|
||
).trim();
|
||
return { notificationTitle, notificationContent };
|
||
},
|
||
getCachedUserId() {
|
||
const userData = uni.getStorageSync('userData');
|
||
if (
|
||
userData != null &&
|
||
userData !== '' &&
|
||
userData != undefined &&
|
||
userData.userId != null &&
|
||
userData.userId !== ''
|
||
) {
|
||
return userData.userId;
|
||
}
|
||
return '';
|
||
},
|
||
isUserLoggedIn() {
|
||
const user = uni.getStorageSync('userData');
|
||
const token = uni.getStorageSync('token');
|
||
const clientId = uni.getStorageSync('clientId');
|
||
const timeOut = uni.getStorageSync('timeOut');
|
||
const now = Math.floor(new Date().getTime() / 1000);
|
||
let loginTag = false;
|
||
if (user) {
|
||
loginTag = user.loginTag === true;
|
||
}
|
||
if (
|
||
token == undefined ||
|
||
token == null ||
|
||
token === '' ||
|
||
clientId == undefined ||
|
||
clientId == null ||
|
||
clientId === ''
|
||
) {
|
||
loginTag = false;
|
||
}
|
||
if (timeOut != null && timeOut !== '' && now >= timeOut) {
|
||
loginTag = false;
|
||
}
|
||
return loginTag === true;
|
||
},
|
||
getPushNotificationPageUrl() {
|
||
return '/limo/notification/notification';
|
||
},
|
||
getPushConfirmNo(payload = {}) {
|
||
const confirmNo = payload.confirmNo || payload.raw?.ConfirmNo || payload.raw?.confirmNo || payload.raw?.confNo;
|
||
return confirmNo ? String(confirmNo) : '';
|
||
},
|
||
getPushTargetUrl(payload = {}) {
|
||
const confirmNo = this.getPushConfirmNo(payload);
|
||
if (confirmNo) {
|
||
return `/limo/bookingDetail/bookingDetail?confNo=${encodeURIComponent(confirmNo)}&from=push`;
|
||
}
|
||
return this.getPushNotificationPageUrl();
|
||
},
|
||
setPendingPushNavigation(url) {
|
||
if (!url) {
|
||
return;
|
||
}
|
||
uni.setStorageSync('pendingPushNavigation', url);
|
||
console.log('[Push] pending navigation saved:', url);
|
||
},
|
||
tryConsumePendingPushNavigation() {
|
||
const pendingUrl = uni.getStorageSync('pendingPushNavigation');
|
||
if (!pendingUrl) {
|
||
return false;
|
||
}
|
||
if (!this.isUserLoggedIn()) {
|
||
return false;
|
||
}
|
||
uni.removeStorageSync('pendingPushNavigation');
|
||
console.log('[Push] consume pending navigation:', pendingUrl);
|
||
this.navTo(pendingUrl, 0, false);
|
||
return true;
|
||
},
|
||
shouldOpenNotificationPageFromPush(payload = {}, meta = {}) {
|
||
return meta.userTapped === true || payload.userTapped === true;
|
||
},
|
||
navigateToNotificationPageFromPush(payload = {}) {
|
||
const targetUrl = this.getPushTargetUrl(payload);
|
||
console.log('[Push] navigateToNotificationPageFromPush targetUrl=', targetUrl, 'confirmNo=', this.getPushConfirmNo(payload));
|
||
if (!this.isUserLoggedIn()) {
|
||
this.setPendingPushNavigation(targetUrl);
|
||
uni.redirectTo({
|
||
url: '/pages/login/login'
|
||
});
|
||
return;
|
||
}
|
||
this.navTo(targetUrl, 0, false);
|
||
},
|
||
queuePushForSaveLater(title, content) {
|
||
const queue = uni.getStorageSync('pendingPushSaveQueue') || []
|
||
queue.push({ title, content, at: Date.now() })
|
||
uni.setStorageSync('pendingPushSaveQueue', queue)
|
||
console.warn('[Push] userId 未就绪,已暂存待 saveNotification,条数=', queue.length)
|
||
},
|
||
async flushPendingPushSaveQueue() {
|
||
const userId = this.getCachedUserId()
|
||
if (!userId) {
|
||
return
|
||
}
|
||
const queue = uni.getStorageSync('pendingPushSaveQueue') || []
|
||
if (!queue.length) {
|
||
return
|
||
}
|
||
uni.removeStorageSync('pendingPushSaveQueue')
|
||
console.log('[Push] flushPendingPushSaveQueue count=', queue.length)
|
||
for (const item of queue) {
|
||
try {
|
||
await saveNotification({
|
||
title: item.title,
|
||
content: item.content,
|
||
userId
|
||
})
|
||
console.log('[Push] saveNotification success (flushed)', item.title)
|
||
} catch (saveError) {
|
||
console.error('[Push] saveNotification failed (flushed)', saveError)
|
||
}
|
||
}
|
||
},
|
||
async persistReceivedPushNotification(notificationTitle, notificationContent) {
|
||
const userId = this.getCachedUserId();
|
||
if (!userId) {
|
||
this.queuePushForSaveLater(notificationTitle, notificationContent)
|
||
return;
|
||
}
|
||
try {
|
||
await saveNotification({
|
||
title: notificationTitle,
|
||
content: notificationContent,
|
||
userId
|
||
});
|
||
console.log('[Push] saveNotification success', {
|
||
title: notificationTitle,
|
||
content: notificationContent,
|
||
userId
|
||
});
|
||
} catch (saveError) {
|
||
console.error('[Push] saveNotification failed', saveError);
|
||
}
|
||
},
|
||
setupGlobalEventListeners() {
|
||
if (this._globalPushHookRegistered) {
|
||
return;
|
||
}
|
||
this._globalPushHookRegistered = true;
|
||
uni.$on('onPushMessageReceived', (rawPayload) => {
|
||
try {
|
||
const { notificationTitle, notificationContent } =
|
||
this.parsePushMessageReceivedPayload(rawPayload);
|
||
this.lastPushNotificationTitle = notificationTitle;
|
||
this.lastPushNotificationContent = notificationContent;
|
||
console.log(
|
||
'[Push] onPushMessageReceived',
|
||
notificationTitle || '(no title)',
|
||
notificationContent || '(no content)',
|
||
rawPayload
|
||
);
|
||
this.persistReceivedPushNotification(
|
||
notificationTitle,
|
||
notificationContent
|
||
);
|
||
const toastText =
|
||
notificationTitle ||
|
||
notificationContent ||
|
||
'Received push message';
|
||
uni.showToast({
|
||
title:
|
||
toastText.length > 36
|
||
? `${toastText.slice(0, 33)}…`
|
||
: toastText,
|
||
icon: 'none',
|
||
duration: 2800
|
||
});
|
||
} catch (handlerError) {
|
||
console.error('[Push] handler error', handlerError, rawPayload);
|
||
}
|
||
});
|
||
},
|
||
startTimer() {
|
||
// 先清除可能存在的旧定时器
|
||
this.stopTimer();
|
||
// 每60秒执行一次目标方法
|
||
this.timer = setInterval(() => {
|
||
this.checkLocationVPNByTimer(null);
|
||
// this.checkToken()
|
||
}, 10000);
|
||
},
|
||
// 停止定时器
|
||
stopTimer() {
|
||
if (this.timer) {
|
||
clearInterval(this.timer);
|
||
this.timer = null;
|
||
}
|
||
},
|
||
checkLocationVPNByTimer(type){
|
||
let url = this.getCurrentUrl();
|
||
if(
|
||
url!==null && url!==undefined
|
||
&& url.indexOf('logout')==-1
|
||
&& url.indexOf('Logout')==-1
|
||
&& url.indexOf('login')==-1
|
||
&& url.indexOf('Login')==-1
|
||
&& url.indexOf('setting')==-1
|
||
&& url.indexOf('regionRestrict')==-1
|
||
&& url.indexOf('callback')==-1
|
||
&& url.indexOf('adfs')==-1
|
||
){
|
||
let siteData = uni.getStorageSync("siteData");
|
||
//只有外网才检查
|
||
if(siteData!==undefined && siteData!==null && siteData.internalTag===false)
|
||
{
|
||
this.checkLocationAndVPN(type);
|
||
}
|
||
}
|
||
},
|
||
async getSettingByKey(key){
|
||
try{
|
||
let params = {
|
||
keyName : key
|
||
}
|
||
const res = await getCfgSettingByKey(params);
|
||
const cfg = new config();
|
||
if (res && res.data && res.data.keyValues) {
|
||
res.data.keyValues = await decryptCfgSettingValue(res.data.keyValues, cfg.allowKey);
|
||
}
|
||
this.macauString = res.data;
|
||
uni.setStorageSync("macauString",this.macauString.keyValues);
|
||
// uni.showToast({
|
||
// title:'Macau String = '+this.macauString.keyValues,
|
||
// icon: "none"
|
||
// })
|
||
}catch(e){
|
||
console.log(e);
|
||
}finally{
|
||
this.startTimer();
|
||
}
|
||
},
|
||
getCurrentUrl(){
|
||
const pages = getCurrentPages();
|
||
if (!pages.length) return null;
|
||
// 获取当前页面实例
|
||
const currentPage = pages[pages.length - 1];
|
||
// 获取页面路径(如:pages/index/index)
|
||
const route = currentPage.route;
|
||
// 获取页面参数对象(如:{ id: 123 })
|
||
const options = currentPage.options;
|
||
// 拼接完整路径(带参数)
|
||
let url = `/${route}`;
|
||
const query = Object.keys(options).map(key =>
|
||
`${key}=${encodeURIComponent(options[key])}`
|
||
).join('&');
|
||
if (query) url += `?${query}`;
|
||
return url;
|
||
},
|
||
getSchemeParam(name,scheme) {
|
||
var reg = new RegExp("(^|\\?|&)"+ name +"=([^&]*)(\\s|&|$)", "i");
|
||
if (reg.test(scheme)) return unescape(RegExp.$2.replace(/\+/g, " "));
|
||
return "";
|
||
},
|
||
async initApp(){
|
||
// #ifdef APP-PLUS
|
||
plus.screen.lockOrientation("portrait");
|
||
// #endif
|
||
await this.initCfg(); // 获取配置参数
|
||
this.setupGlobalEventListeners();
|
||
},
|
||
// 初始化方法
|
||
async initCfg(){
|
||
// 配置站点信息
|
||
const cfg = new config();
|
||
// 判断外网还是内网
|
||
// 現在內外網改成由後端判斷
|
||
|
||
// 如果是外网
|
||
const userData = uni.getStorageSync('userData');
|
||
const oldSiteData = uni.getStorageSync('siteData');
|
||
let oldDebugMode = cfg.debugMode;
|
||
let userId = "";
|
||
if(oldSiteData!=undefined && oldSiteData!=null && oldSiteData!=''){
|
||
oldDebugMode = oldSiteData.debugMode;
|
||
}
|
||
if(userData!=undefined && userData!=null && userData!=''){
|
||
userId = userData.userId;
|
||
}
|
||
let isInternal = true;
|
||
let macauString = "";
|
||
let siteData = {
|
||
internalUrl : cfg.internalUrl,
|
||
externalUrl : cfg.externalUrl,
|
||
apiPath : cfg.apiPath,
|
||
internalTag : isInternal,
|
||
macauIp: true,
|
||
internalSSOUrl: cfg.internalSSOUrl,
|
||
externalSSOUrl: cfg.externalSSOUrl,
|
||
version:cfg.version,
|
||
debugMode: true,
|
||
mockSSO:false,
|
||
mockTPD:false
|
||
};
|
||
store.dispatch('setSiteData',siteData);
|
||
uni.setStorageSync('siteData', siteData);
|
||
// 初始化uview http请求配置
|
||
uni.$u.http.setConfig((config) => {
|
||
if(isInternal){
|
||
config.baseURL = store.state.siteData.internalUrl + store.state.siteData.apiPath;
|
||
}
|
||
else{
|
||
config.baseURL = store.state.siteData.externalUrl + store.state.siteData.apiPath;
|
||
}
|
||
config.custom.auth = true;
|
||
config.custom.origin = cfg.originUrl;
|
||
config.custom.appId = cfg.appId;
|
||
config.custom.allowKey = cfg.allowKey;
|
||
|
||
return config;
|
||
})
|
||
//this.writeLog(userId,"app_init","","[APP][App.vue][initCfg][Begin]","[SiteData]" + JSON.stringify(siteData),"",0,false);
|
||
// 获取配置设备信息
|
||
let safeArea = false;
|
||
await uni.getSystemInfo({
|
||
success: res => {
|
||
//console.log(res.statusBarHeight);
|
||
if (res.safeArea.top > 20) {
|
||
//x及以上的异形屏top为44,非异形屏为20
|
||
safeArea = true;
|
||
}
|
||
}
|
||
})
|
||
let info = uni.getSystemInfoSync()//获取设备信息
|
||
let statusBarHeight = info.statusBarHeight
|
||
let windowWidth = info.windowWidth
|
||
let windowHeight = info.windowHeight
|
||
const deviceData = {
|
||
statusBarHeight : statusBarHeight,
|
||
windowWidth : windowWidth,
|
||
windowHeight : windowHeight,
|
||
saveArea : safeArea,
|
||
};
|
||
store.dispatch('setDeviceData',deviceData);
|
||
uni.setStorageSync('deviceData', deviceData);
|
||
//this.writeLog(userId,"app_init","","[APP][App.vue][initCfg][End]","[DeviceData]"+JSON.stringify(deviceData),"",0,false);
|
||
this.$isResolve();
|
||
},
|
||
// 全局函数,main.js中注册
|
||
// 判断login
|
||
isLogin(){
|
||
let loginTag = false;
|
||
let user = uni.getStorageSync('userData');
|
||
let site = uni.getStorageSync('siteData');
|
||
let timeOut = uni.getStorageSync('timeOut');
|
||
let token = uni.getStorageSync("token")
|
||
let clientId = uni.getStorageSync("clientId")
|
||
var now = Math.floor(new Date().getTime() / 1000);
|
||
if(user){
|
||
loginTag = user.loginTag;
|
||
}
|
||
if(token==undefined||token==null||token==""||clientId==undefined||clientId==null||clientId==""){
|
||
loginTag = false;
|
||
}
|
||
if(now >= timeOut) loginTag = false;
|
||
if(loginTag!==true){
|
||
uni.removeStorageSync("userData");
|
||
uni.removeStorageSync("token");
|
||
uni.removeStorageSync("idToken");
|
||
this.navTo('/pages/login/login',2,false);
|
||
}
|
||
},
|
||
tryConsumePendingPushNavigation() {
|
||
const pendingUrl = uni.getStorageSync('pendingPushNavigation');
|
||
if (!pendingUrl) {
|
||
return false;
|
||
}
|
||
if (!this.isUserLoggedIn()) {
|
||
return false;
|
||
}
|
||
uni.removeStorageSync('pendingPushNavigation');
|
||
console.log('[Push] consume pending navigation:', pendingUrl);
|
||
this.navTo(pendingUrl, 0, false);
|
||
return true;
|
||
},
|
||
async syncPendingPushNotificationsFromNative() {
|
||
console.log('[Push] syncPendingPushNotificationsFromNative')
|
||
await syncPendingPushNotifications((payload, meta) => {
|
||
this.handlePushNotificationMessage(payload, {
|
||
...meta,
|
||
showToast: meta?.fromPending ? false : meta?.showToast
|
||
})
|
||
}, { showToast: false })
|
||
await this.flushPendingPushSaveQueue()
|
||
},
|
||
//判断是否有Permission
|
||
redirectByPermission(userData,needRedirect){
|
||
if (this.tryConsumePendingPushNavigation()) {
|
||
return;
|
||
}
|
||
if(userData!==null && userData!==undefined){
|
||
if(userData.canViewDashboard){
|
||
this.navTo('/pages/dashboard/dashboard',1,false);
|
||
}else if(userData.canViewTodoList){
|
||
this.navTo('/salessupport/todoList/todoList',1,false);
|
||
}else if(userData.canViewBooking){
|
||
this.navTo('/pages/findPlayer/findPlayer',1,false);
|
||
}else{
|
||
this.navTo('/pages/setting/setting',1,false);
|
||
}
|
||
}
|
||
},
|
||
/** 从原生读取当前缓存的 APNs DeviceToken,并写入本地 Storage(供业务上报) */
|
||
syncPushDeviceTokenFromNative() {
|
||
getDeviceToken({})
|
||
.then(async (ret) => {
|
||
console.log('[APNs] getDeviceToken', ret.status, ret.updatedAt);
|
||
const deviceToken = ret.deviceToken ? String(ret.deviceToken).trim() : '';
|
||
let useLanguage = 0;
|
||
//获取AppSetting,后端可以判断发中文还是发英文 英文:0 中文:1 默认为0
|
||
if(uni.getLocale()!==null && uni.getLocale()!==undefined){
|
||
useLanguage = uni.getLocale()=='en'? 0 : 1;
|
||
}
|
||
if (deviceToken) {
|
||
const userId = this.getCachedUserId();
|
||
console.log('[APNs] saveDeviceToken params', {
|
||
userId,
|
||
deviceToken,
|
||
rawUserData: uni.getStorageSync('userData'),
|
||
rawRet: ret,
|
||
useLanguage
|
||
});
|
||
this.writeLog(
|
||
userId,
|
||
'syncPushDeviceTokenFromNative',
|
||
'',
|
||
'[APP][App.vue][getDevice Token][Success]' + deviceToken,
|
||
'',
|
||
'',
|
||
1,
|
||
false
|
||
);
|
||
uni.setStorageSync('apnsDeviceToken', deviceToken);
|
||
uni.setStorageSync('apnsDeviceTokenUpdatedAt', ret.updatedAt || 0);
|
||
try {
|
||
const res = await saveDeviceToken({ userId, deviceToken, useLanguage});
|
||
console.log('[APNs] saveDeviceToken success', res);
|
||
} catch (saveErr) {
|
||
console.error('[APNs] saveDeviceToken failed', saveErr);
|
||
}
|
||
}
|
||
})
|
||
.catch((e) => {
|
||
console.warn('[APNs] getDeviceToken fail', e);
|
||
uni.showToast({
|
||
title: 'error = ' + e,
|
||
icon: 'none'
|
||
});
|
||
const userId = this.getCachedUserId();
|
||
this.writeLog(
|
||
userId,
|
||
'syncPushDeviceTokenFromNative',
|
||
'',
|
||
'[APP][App.vue][getDevice Token][Fail] Error Message :' + e,
|
||
'',
|
||
'',
|
||
1,
|
||
false
|
||
);
|
||
});
|
||
},
|
||
//根据Permission显示Tabbar
|
||
showTabbarByPermission(userData){
|
||
if(userData!==null && userData!==undefined){
|
||
console.log('Setting Tabbar');
|
||
if(userData.canViewDashboard){
|
||
uni.setTabBarItem({
|
||
index:0,
|
||
visible:true
|
||
});
|
||
}
|
||
if(userData.canViewTodoList){
|
||
uni.setTabBarItem({
|
||
index:1,
|
||
visible:true
|
||
});
|
||
}
|
||
if(userData.canViewBooking){
|
||
uni.setTabBarItem({
|
||
index:2,
|
||
visible:true
|
||
});
|
||
}
|
||
if(userData.canViewCalendar){
|
||
uni.setTabBarItem({
|
||
index:3,
|
||
visible:true
|
||
});
|
||
}
|
||
}
|
||
},
|
||
// 返回
|
||
navBack(delta){
|
||
if(delta){
|
||
uni.navigateBack({
|
||
delta: delta
|
||
});
|
||
}
|
||
else{
|
||
uni.navigateBack();
|
||
}
|
||
},
|
||
checkJailbreak(){
|
||
// 调用同步方法
|
||
networkModule.checkJailbreakAsync({
|
||
}, (result) => {
|
||
if(result.status === 'success'){
|
||
if(result.isJailbroken==true){
|
||
this.stopTimer();
|
||
this.navTo('/pages/disableApp/disableApp',0,false); //2
|
||
}
|
||
}
|
||
});
|
||
|
||
},
|
||
/** 从原生读取当前缓存的 APNs DeviceToken,并写入本地 Storage(供业务上报) */
|
||
syncPushDeviceTokenFromNative() {
|
||
getDeviceToken({})
|
||
.then(async (ret) => {
|
||
console.log('[APNs] getDeviceToken', ret.status, ret.updatedAt);
|
||
const deviceToken = ret.deviceToken ? String(ret.deviceToken).trim() : '';
|
||
let useLanguage = 0;
|
||
//获取AppSetting,后端可以判断发中文还是发英文 英文:0 中文:1 默认为0
|
||
if(uni.getLocale()!==null && uni.getLocale()!==undefined){
|
||
useLanguage = uni.getLocale()=='en'? 0 : 1;
|
||
}
|
||
if (deviceToken) {
|
||
const userId = this.getCachedUserId();
|
||
console.log('[APNs] saveDeviceToken params', {
|
||
userId,
|
||
deviceToken,
|
||
rawUserData: uni.getStorageSync('userData'),
|
||
rawRet: ret,
|
||
useLanguage
|
||
});
|
||
this.writeLog(
|
||
userId,
|
||
'syncPushDeviceTokenFromNative',
|
||
'',
|
||
'[APP][App.vue][getDevice Token][Success]' + deviceToken,
|
||
'',
|
||
'',
|
||
1,
|
||
false
|
||
);
|
||
uni.setStorageSync('apnsDeviceToken', deviceToken);
|
||
uni.setStorageSync('apnsDeviceTokenUpdatedAt', ret.updatedAt || 0);
|
||
try {
|
||
const res = await saveDeviceToken({ userId, deviceToken, useLanguage});
|
||
console.log('[APNs] saveDeviceToken success', res);
|
||
} catch (saveErr) {
|
||
console.error('[APNs] saveDeviceToken failed', saveErr);
|
||
}
|
||
}
|
||
})
|
||
.catch((e) => {
|
||
console.warn('[APNs] getDeviceToken fail', e);
|
||
uni.showToast({
|
||
title: 'error = ' + e,
|
||
icon: 'none'
|
||
});
|
||
const userId = this.getCachedUserId();
|
||
this.writeLog(
|
||
userId,
|
||
'syncPushDeviceTokenFromNative',
|
||
'',
|
||
'[APP][App.vue][getDevice Token][Fail] Error Message :' + e,
|
||
'',
|
||
'',
|
||
1,
|
||
false
|
||
);
|
||
});
|
||
},
|
||
/**
|
||
* 触发 refreshDeviceTokenAsync(重新向 APNs 注册),随后轮询 getDeviceToken。
|
||
* @param {{ requestAuthorization?: boolean }} opts 默认可不传;已授权场景可传 { requestAuthorization: false }
|
||
*/
|
||
refreshPushDeviceTokenNative(opts) {
|
||
return refreshDeviceTokenAsync(opts || { requestAuthorization: true })
|
||
},
|
||
/** 刷新并尽量拿到新 token(适合服务端返回推送失效时调用) */
|
||
refreshPushDeviceTokenAndSync(opts) {
|
||
return refreshDeviceTokenAndFetch(opts || { requestAuthorization: true }).then((ret) => {
|
||
if (ret.deviceToken) {
|
||
uni.setStorageSync('apnsDeviceToken', ret.deviceToken)
|
||
uni.setStorageSync('apnsDeviceTokenUpdatedAt', ret.updatedAt || 0)
|
||
}
|
||
return ret
|
||
})
|
||
},
|
||
setupPushNotificationListener() {
|
||
listenPushNotification((payload, meta) => {
|
||
this.handlePushNotificationMessage(payload, meta)
|
||
})
|
||
},
|
||
async handlePushNotificationMessage(payload = {}, meta = {}) {
|
||
const { title, content } = payload
|
||
this.lastPushNotificationTitle = title
|
||
this.lastPushNotificationContent = content
|
||
|
||
|
||
await this.persistReceivedPushNotification(title, content)
|
||
|
||
console.log('[Push] handlePushNotificationMessage userTapped=', payload.userTapped, meta?.userTapped, 'confirmNo=', this.getPushConfirmNo(payload))
|
||
if (this.shouldOpenNotificationPageFromPush(payload, meta)) {
|
||
this.navigateToNotificationPageFromPush(payload)
|
||
}
|
||
},
|
||
async syncPendingPushNotificationsFromNative() {
|
||
console.log('[Push] syncPendingPushNotificationsFromNative')
|
||
await syncPendingPushNotifications((payload, meta) => {
|
||
this.handlePushNotificationMessage(payload, {
|
||
...meta,
|
||
showToast: meta?.fromPending ? false : meta?.showToast
|
||
})
|
||
}, { showToast: false })
|
||
await this.flushPendingPushSaveQueue()
|
||
},
|
||
checkLocationAndVPN(type){
|
||
let objVPNData = this.checkVPNOpen();
|
||
let isOpenVPN = false;
|
||
let ipAddress = "";
|
||
let userId = "";
|
||
let userData = uni.getStorageSync("userData");
|
||
if(userData!==undefined && userData!==null && userData!=="" && userData.userId!==undefined && userData.userId!==null && userData.userId!==""){
|
||
userId = userData.userId;
|
||
}
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]step1","","",1,false);
|
||
if(objVPNData === null)
|
||
{
|
||
isOpenVPN = null;
|
||
}
|
||
else
|
||
{
|
||
isOpenVPN = objVPNData.isVPNConnected;
|
||
ipAddress = objVPNData.ipAddress;
|
||
}
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]vpn:"+isOpenVPN,"","",1,false);
|
||
//检查如果使用了VPN或不在澳门
|
||
// let isInMacau = this.checkInMacau();
|
||
// 在页面中请求定位权限
|
||
uni.getLocation({
|
||
type: 'wgs84',
|
||
success: (res) => {
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]step3","","",1,false);
|
||
const converter = new FixedCoordinateConverter();
|
||
//console.log('经纬度数据:', res);
|
||
const gcjPoint = converter.wgs84ToGcj02Fixed(res.latitude, res.longitude);
|
||
//console.log(gcjPoint);
|
||
networkModule.getCityNameByCoordinate({
|
||
latitude: gcjPoint.lat,
|
||
longitude: gcjPoint.lng
|
||
//latitude: res.latitude,
|
||
//longitude: res.longitude
|
||
|
||
//模拟澳门IP
|
||
// latitude: 22.142149,
|
||
// longitude: 113.562888,
|
||
//模拟澳门IP
|
||
|
||
}, (result) => {
|
||
let msgType = "0";
|
||
if (result.status === 'success') {
|
||
let isInMacau = (result.isInMacau == 'YES')? true:false;
|
||
/*uni.showToast({
|
||
title:'城市:' + result.city + ',地址:'+result.fullAddress,
|
||
icon: "none"
|
||
})*/
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]"+result.isInMacau+ ", city:"+result.city+ ", address:"+result.fullAddress+ ", IP address:"+ipAddress,"","",1,false);
|
||
|
||
|
||
|
||
if(!isInMacau){
|
||
let macauStringList = uni.getStorageSync("macauString").split(";");
|
||
for(let i=0;i<macauStringList.length;i++){
|
||
if(result.fullAddress.indexOf(macauStringList[i]) !== -1
|
||
&& macauStringList[i] !== "" && macauStringList[i] !== null){
|
||
isInMacau = true;
|
||
break;
|
||
}else{
|
||
isInMacau = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
//模擬數據 模拟数据
|
||
// isInMacau = true;
|
||
// isOpenVPN = false;
|
||
//模擬數據 模拟数据
|
||
|
||
if((isInMacau===null||isInMacau===undefined) && isOpenVPN!==null){ //调用地址出错
|
||
msgType = "1";
|
||
}
|
||
else if((isInMacau!==null&&isInMacau!==undefined) && isOpenVPN===null){ //调用VPN出错
|
||
msgType = "2";
|
||
}
|
||
else if((isInMacau===null||isInMacau===undefined) && isOpenVPN===null){ //调用地址和VPN出错
|
||
msgType = "3";
|
||
}
|
||
else if(isInMacau === false && isOpenVPN===false){ //不在澳门,没开了VPN,不通过
|
||
msgType = "4";
|
||
}
|
||
else if(isInMacau === true && isOpenVPN===true){ //在澳门,但是开了VPN,不通过
|
||
msgType = "5";
|
||
}
|
||
else if(isInMacau === false && isOpenVPN===true){ //不在澳门,开了VPN,不通过
|
||
msgType = "6";
|
||
}
|
||
else if(isInMacau===null||isInMacau===undefined){ //调用地址出错
|
||
msgType = "1";
|
||
}
|
||
//重新调用isMacauApi 获取定位信息
|
||
|
||
let siteData = uni.getStorageSync("siteData");
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]Site data:"+JSON.stringify(siteData)+"IsInMacau:"+isInMacau,"","",1,false);
|
||
if(siteData.internalTag==false && siteData.macauIp == false){
|
||
msgType = "7";
|
||
}
|
||
} else {
|
||
msgType = "1";
|
||
/*uni.showToast({
|
||
title:'错误:' + result.error + ", latitude:"+res.latitude+ ", longitude:"+res.longitude,
|
||
icon: "none"
|
||
})*/
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Error]"+result.error+ ", old latitude:"+res.latitude+ ", old longitude:"+res.longitude+ ", latitude:"+gcjPoint.lat+ ", longitude:"+gcjPoint.lng+ ", IP address:"+ipAddress,"","",1,false);
|
||
}
|
||
if(msgType!=="0" && type!==true){
|
||
//跳转去一个页面
|
||
this.navTo('/pages/regionRestrict/regionRestrict?type='+msgType,0,false); //2
|
||
}
|
||
if(msgType==="0" && type === true){ // retry的情况
|
||
this.navBack();
|
||
}
|
||
else if(msgType==="0" && type === false){ //登录的情况
|
||
let userData= uni.getStorageSync("userData");
|
||
this.redirectByPermission(userData,true);
|
||
}
|
||
});
|
||
},
|
||
fail: (err) => {
|
||
/*uni.showToast({
|
||
title:'uni.getLocation fail',
|
||
icon: "none"
|
||
});*/
|
||
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Error]uni.getLocation fail"+ ", IP address:"+ipAddress,"","",1,false);
|
||
this.navTo('/pages/regionRestrict/regionRestrict?type=1',0,false);
|
||
}
|
||
});
|
||
},
|
||
checkVPNOpen() {
|
||
// 调用同步方法
|
||
let ret = networkModule.checkVPNSync({'testVPN': 'Sync'})
|
||
let respData = JSON.parse(ret);
|
||
if(respData.status === 'success'){
|
||
return respData;
|
||
}else{
|
||
return null;
|
||
}
|
||
/*uni.showToast({
|
||
title:'是否连接VPN:' + respData.isVPNConnected + ',IP地址:'+ respData.ipAddress + ',状态:'+ respData.status,
|
||
icon: "none"
|
||
})*/
|
||
},
|
||
// 跳转
|
||
async writeLog(userId,eventCode,transactionId,description,requestBody,responseBody,successTag,debugTag){
|
||
|
||
if(debugTag===undefined || debugTag===false){
|
||
const siteData = uni.getStorageSync('siteData');
|
||
if(siteData.debugMode==false){
|
||
return;
|
||
}
|
||
}
|
||
|
||
const token = uni.getStorageSync("token");
|
||
|
||
let obj = {};
|
||
obj.loginId = userId;
|
||
obj.eventCode = eventCode;
|
||
obj.transId = transactionId;
|
||
obj.logDesc = description;
|
||
obj.requestBody = requestBody;
|
||
obj.responseBody = responseBody;
|
||
obj.tagSuccess = successTag;
|
||
|
||
//console.log(obj);
|
||
|
||
try{
|
||
if(token != undefined && token != null && token !=""){
|
||
const response = await writeDebugLog(obj);
|
||
}else{
|
||
const response = await writePublicDebugLog(obj);
|
||
}
|
||
}
|
||
catch(e){
|
||
console.error(e.errMsg);
|
||
}
|
||
|
||
},
|
||
async logout(){
|
||
let siteData = uni.getStorageSync("siteData");
|
||
let userData = uni.getStorageSync("userData");
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
try{
|
||
let params = {};
|
||
const res = await logout(params);
|
||
if(res.success == true){
|
||
if(res.data !== null){
|
||
uni.setTabBarItem({
|
||
index:0,
|
||
visible:false
|
||
});
|
||
uni.setTabBarItem({
|
||
index:1,
|
||
visible:false
|
||
});
|
||
uni.setTabBarItem({
|
||
index:2,
|
||
visible:false
|
||
});
|
||
if(siteData.mockSSO==false&&!siteData.internalTag){
|
||
//this.logoutWithADFSApp()
|
||
uni.redirectTo({
|
||
url:'/pages/azureLogout/azureLogout'
|
||
});
|
||
}else{
|
||
uni.removeStorageSync("userData");
|
||
uni.removeStorageSync("token");
|
||
uni.removeStorageSync("idToken");
|
||
this.navTo('/pages/login/login',2,false);
|
||
}
|
||
}
|
||
}else{
|
||
if(siteData.mockSSO==false&&!siteData.internalTag){
|
||
//this.logoutWithADFSApp()
|
||
uni.redirectTo({
|
||
url:'/pages/azureLogout/azureLogout'
|
||
});
|
||
}else{
|
||
uni.removeStorageSync("userData");
|
||
uni.removeStorageSync("token");
|
||
uni.removeStorageSync("idToken");
|
||
this.navTo('/pages/login/login',2,false);
|
||
}
|
||
}
|
||
}catch(e){
|
||
console.error(e);
|
||
uni.$u.toast(e.errMsg,5000);
|
||
await this.writeLog(userData.userId,"logout","","[APP][setting.vue][logout][Catch Exception]"+e.errMsg,"","",1,false);
|
||
}finally{
|
||
uni.hideLoading();
|
||
}
|
||
},
|
||
getCachedUserId() {
|
||
const userData = uni.getStorageSync('userData');
|
||
if (
|
||
userData != null &&
|
||
userData !== '' &&
|
||
userData != undefined &&
|
||
userData.userId != null &&
|
||
userData.userId !== ''
|
||
) {
|
||
return userData.userId;
|
||
}
|
||
return '';
|
||
},
|
||
async navTo(url,type,auth){
|
||
let token = uni.getStorageSync('token');
|
||
if(token){
|
||
const response = await verifyToken({});
|
||
if(response.status==200){
|
||
|
||
}else{
|
||
console.error(response)
|
||
}
|
||
}
|
||
if(auth==true){
|
||
let user = uni.getStorageSync('userData');
|
||
let loginTag = false;
|
||
if(user){
|
||
loginTag = user.loginTag;
|
||
}
|
||
if(loginTag==true){
|
||
if(type===1)
|
||
{
|
||
uni.switchTab({
|
||
url
|
||
})
|
||
}
|
||
else if(type===2)
|
||
{
|
||
uni.redirectTo({
|
||
url
|
||
})
|
||
}else{
|
||
uni.navigateTo({
|
||
url
|
||
})
|
||
}
|
||
}else{
|
||
uni.showModal({
|
||
title: this.$t("common.warning"),
|
||
content: this.$t("common.loginAlert"),
|
||
cancelText: this.$t("common.cancel"), // 取消按钮的文字
|
||
confirmText: this.$t("common.login"), // 确认按钮的文字
|
||
showCancel: true, // 是否显示取消按钮,默认为 true
|
||
confirmColor: '#C39A4B',
|
||
success: (res) => {
|
||
if(res.confirm) {
|
||
uni.redirectTo({
|
||
url:'/pages/login/login'
|
||
})
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
})
|
||
return;
|
||
}
|
||
}
|
||
else{
|
||
if(type===1)
|
||
{
|
||
uni.switchTab({
|
||
url
|
||
})
|
||
}
|
||
else if(type===2)
|
||
{
|
||
uni.redirectTo({
|
||
url
|
||
})
|
||
}else{
|
||
uni.navigateTo({
|
||
url
|
||
})
|
||
}
|
||
}
|
||
},
|
||
kickout() {
|
||
|
||
this.logout();
|
||
uni.removeStorageSync("userData");
|
||
uni.removeStorageSync("token");
|
||
uni.removeStorageSync("idToken");
|
||
uni.removeStorageSync("clientId");
|
||
uni.redirectTo({
|
||
url:'/pages/login/login'
|
||
})
|
||
},
|
||
checkToken(){
|
||
let now = Math.floor(new Date().getTime() / 1000);
|
||
let tokenTime = uni.getStorageSync("tokenTime");
|
||
let token = uni.getStorageSync("token")
|
||
//4 min refresh token
|
||
if(token!="" && now - tokenTime>240){
|
||
let oldToken = uni.getStorageSync("token");
|
||
if (oldToken !== null && oldToken !== '') {
|
||
return refreshToken({})
|
||
.then((data) => {
|
||
uni.setStorageSync("token",data.token);
|
||
uni.setStorageSync("tokenTime",dayjs().unix());
|
||
return Promise.resolve(true)
|
||
})
|
||
.catch(error => {
|
||
this.kickout()
|
||
})
|
||
} else {
|
||
this.kickout()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
/*每个页面公共css */
|
||
@import './static/css/custom.scss';
|
||
@import "@/uni_modules/uview-ui/index.scss";
|
||
</style>
|