merge limo to daylight

This commit is contained in:
Mauve
2026-09-22 16:37:00 +08:00
parent 0c92868836
commit a7359d443b
73 changed files with 11614 additions and 1040 deletions
+389 -35
View File
@@ -1,6 +1,6 @@
<script>
import config from './common/config.js'
import {writeDebugLog,writePublicDebugLog,getSettingByKey,getSettings,verifyToken,logout} from './api/commonApi.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'
@@ -9,7 +9,7 @@
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} from './api/notification.js';
import { saveDeviceToken, saveNotification } from './api/notificationApi.js';
// #ifdef APP-PLUS
var networkModule = uni.requireNativePlugin("NetworkUtils-NetworkUtilsModule")
// #endif
@@ -17,7 +17,9 @@
data() {
return {
timer: null, // 定时器引用
backgroundTaskId: 0 // iOS 后台任务ID
backgroundTaskId: 0, // iOS 后台任务ID
lastPushNotificationTitle: '',
lastPushNotificationContent: ''
}
},
onLaunch: function() {
@@ -28,22 +30,18 @@
type: 'wgs84',
success: (res) => {}
});
/*plus.globalEvent.addEventListener('newintent', (e)=>{
var args= plus.runtime.arguments;
console.log(args)
uni.showToast({
title: 'APP LAUNCH-newintent'
});
if(args){
var code = this.getSchemeParam('code',args)
uni.showToast({
title: code
});
uni.redirectTo({
url:'/pages/login/login?code='+encodeURIComponent(code)
})
}
});*/
// 延迟触发推送注册:避免 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() {
@@ -80,12 +78,248 @@
// #endif
},
beforeDestroy() {
// 组件销毁时清理资源
// #ifdef APP-PLUS
this.stopTimer();
this.stopTimer();
// #endif
},
methods:{
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();
@@ -135,6 +369,10 @@
}
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{
@@ -168,13 +406,14 @@
plus.screen.lockOrientation("portrait");
// #endif
await this.initCfg(); // 获取配置参数
this.setupGlobalEventListeners();
},
// 初始化方法
async initCfg(){
// 配置站点信息
const cfg = new config();
// 判断外网还是内网
// 現在內外網改成由後端判斷
// 現在內外網改成由後端判斷
// 如果是外网
const userData = uni.getStorageSync('userData');
@@ -371,10 +610,6 @@
},
//根据Permission显示Tabbar
showTabbarByPermission(userData){
uni.setTabBarItem({
index: 3,
visible: !!userData && userData.canViewCalendar === true
});
if(userData!==null && userData!==undefined){
console.log('Setting Tabbar');
if(userData.canViewDashboard){
@@ -395,6 +630,12 @@
visible:true
});
}
if(userData.canViewCalendar){
uni.setTabBarItem({
index:3,
visible:true
});
}
}
},
// 返回
@@ -421,6 +662,110 @@
});
},
/** 从原生读取当前缓存的 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;
@@ -472,10 +817,9 @@
icon: "none"
})*/
this.writeLog(userId,"getLocationVPN","","[APP][App.vue][checkLocationAndVPN][Success]"+result.isInMacau+ ", city:"+result.city+ ", address:"+result.fullAddress+ ", IP address:"+ipAddress,"","",1,false);
/*uni.showToast({
title:'是否在澳门:'+isInMacau+',是否使用VPN:'+isOpenVPN,
icon: "none"
})*/
if(!isInMacau){
let macauStringList = uni.getStorageSync("macauString").split(";");
for(let i=0;i<macauStringList.length;i++){
@@ -488,8 +832,12 @@
}
}
}
//isInMacau = true;
//模擬數據 模拟数据
// isInMacau = true;
// isOpenVPN = false;
//模擬數據 模拟数据
if((isInMacau===null||isInMacau===undefined) && isOpenVPN!==null){ //调用地址出错
msgType = "1";
}
@@ -572,6 +920,8 @@
return;
}
}
const token = uni.getStorageSync("token");
let obj = {};
obj.loginId = userId;
@@ -585,8 +935,11 @@
//console.log(obj);
try{
const token = uni.getStorageSync('token');
const response = token ? await writeDebugLog(obj) : await writePublicDebugLog(obj);
if(token != undefined && token != null && token !=""){
const response = await writeDebugLog(obj);
}else{
const response = await writePublicDebugLog(obj);
}
}
catch(e){
console.error(e.errMsg);
@@ -616,7 +969,6 @@
index:2,
visible:false
});
uni.setTabBarItem({ index: 3, visible: false });
if(siteData.mockSSO==false&&!siteData.internalTag){
//this.logoutWithADFSApp()
uni.redirectTo({
@@ -737,6 +1089,8 @@
}
},
kickout() {
this.logout();
uni.removeStorageSync("userData");
uni.removeStorageSync("token");
uni.removeStorageSync("idToken");