添加 navigate_page 和 rediect_page 方法

This commit is contained in:
陆柯 2022-04-21 20:15:51 +08:00
parent 8b1cd9ff6a
commit f64e3f5737

View File

@ -15,56 +15,56 @@ export default {
// [todo] 能否把这些默认值放到 export 以外? // [todo] 能否把这些默认值放到 export 以外?
BACKEND_DEFAULT: 'SERVER', // 服务器 SERVER 或云服务 UNICLOUD BACKEND_DEFAULT: 'SERVER', // 服务器 SERVER 或云服务 UNICLOUD
thisPage() { thisPage () {
return this.__page__ ? this // 1) constructor.name==='VueComponent' 只在 development 环境有用,在 production 环境会被简化成 'o'。2)对于组件内定义的 i18nText要使用 this 来获得组建内的 i18nText而不是 getCurrentPages[...] 去访问全局页面的 i18nText。 return this.__page__
: ( getCurrentPages()[getCurrentPages().length - 1] // [20220401] 发现在 topWindow 里, getCurrentPages 是 undefined ? this // 1) constructor.name==='VueComponent' 只在 development 环境有用,在 production 环境会被简化成 'o'。2)对于组件内定义的 i18nText要使用 this 来获得组建内的 i18nText而不是 getCurrentPages[...] 去访问全局页面的 i18nText
|| {} ) // 在 App.vue 中调用 getCurrentPages() 返回的是空数组 [],因此在这里默认 {} 做保护。 : getCurrentPages()[getCurrentPages().length - 1] || {} // [20220401] 发现在 topWindow 里, getCurrentPages 是 undefined。 // 在 App.vue 中调用 getCurrentPages() 返回的是空数组 [],因此在这里默认 {} 做保护。
}, },
// 输出命令行提示,可用来取代 console.log/info/warn/error // 输出命令行提示,可用来取代 console.log/info/warn/error
cclog(...args) { cclog (...args) {
const pageName = this.thisPage()?.route || 'VueApp' const pageName = this.thisPage()?.route || 'VueApp'
console.log('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:blue', ...args) console.log('%c ' + JSON.stringify({ time: new Date().toJSON(), page: pageName }), 'color:blue', ...args)
}, },
ccinfo(...args) { ccinfo (...args) {
const pageName = this.thisPage()?.route || 'VueApp' const pageName = this.thisPage()?.route || 'VueApp'
console.info('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:green', ...args) console.info('%c ' + JSON.stringify({ time: new Date().toJSON(), page: pageName }), 'color:green', ...args)
}, },
ccwarn(...args) { ccwarn (...args) {
const pageName = this.thisPage().route || 'VueApp' const pageName = this.thisPage().route || 'VueApp'
console.warn('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:orange', ...args) console.warn('%c ' + JSON.stringify({ time: new Date().toJSON(), page: pageName }), 'color:orange', ...args)
}, },
ccerr(...args) { ccerr (...args) {
const pageName = this.thisPage()?.route || 'VueApp' const pageName = this.thisPage()?.route || 'VueApp'
console.error('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:red', ...args) console.error('%c ' + JSON.stringify({ time: new Date().toJSON(), page: pageName }), 'color:red', ...args)
}, },
ccdebug(...args) { ccdebug (...args) {
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
const pageName = this.thisPage()?.route || 'VueApp' const pageName = this.thisPage()?.route || 'VueApp'
console.debug('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:cyan', ...args) console.debug('%c ' + JSON.stringify({ time: new Date().toJSON(), page: pageName }), 'color:cyan', ...args)
} }
}, },
localizeText(i18nText) { localizeText (i18nText) {
i18nText = i18nText?.__page__ ? this.i18nText // 如果挂载到具体页面的 computed { lote: wo.localizeText } 那么 i18nText 会被自动赋值为 this 就是当前页面,直接取用 this.i18nText 即可。 i18nText = i18nText?.__page__
: ( i18nText // 如果传入i18n参数 ({zhCN:'...', enUS:'...'}) ? this.i18nText // 如果挂载到具体页面的 computed { lote: wo.localizeText } 那么 i18nText 会被自动赋值为 this 就是当前页面,直接取用 this.i18nText 即可。
|| this.thisPage()?.i18nText) // 如果不是挂载到 Vue.prototype 而是 挂载到 wo 下调用,那么 this.i18nText 就报错了。因此通过 thisPage().i18nText 访问。 : i18nText || this.thisPage()?.i18nText // 如果传入i18n参数 ({zhCN:'...', enUS:'...'}) // 如果不是挂载到 Vue.prototype 而是 挂载到 wo 下调用,那么 this.i18nText 就报错了。因此通过 thisPage().i18nText 访问。
const mylang = getApp().$store.state.i18n.mylang // this.thisPage() 有可能为空(例如在 topWindow 里,或者在 App.vue 里),所以用 getApp().$store 更安全 const mylang = getApp().$store.state.i18n.mylang // this.thisPage() 有可能为空(例如在 topWindow 里,或者在 App.vue 里),所以用 getApp().$store 更安全
return i18nText?.[mylang] || (typeof i18nText === 'string' ? i18nText : '') // 必须检测是否string如果直接返回 i18nText 可能返回{}等,导致依赖于返回空值的前端出错 return i18nText?.[mylang] || (typeof i18nText === 'string' ? i18nText : '') // 必须检测是否string如果直接返回 i18nText 可能返回{}等,导致依赖于返回空值的前端出错
}, },
localeText() { // 专供绑定到 computed { lote: wo.localeText } 使用,这时 this 就是当前页面。 localeText () {
// 专供绑定到 computed { lote: wo.localeText } 使用,这时 this 就是当前页面。
return this.i18nText?.[getApp().$store.state.i18n.mylang] || {} return this.i18nText?.[getApp().$store.state.i18n.mylang] || {}
}, },
setBarTitles ({ windowTitle, pageTitle, setBarTitles ({ windowTitle, pageTitle, pagesJson = this.pagesJson || wo?.pagesJson, envar = this.envar || wo?.envar } = {}) {
pagesJson=this.pagesJson || wo?.pagesJson } = {}
) {
const mylang = getApp()?.$store?.state?.i18n?.mylang // 不要用 pageNow.$store防止在 App.vue 里无法获取当前页面。 const mylang = getApp()?.$store?.state?.i18n?.mylang // 不要用 pageNow.$store防止在 App.vue 里无法获取当前页面。
const pageNow = this.thisPage() // 需要兼顾在 App.vue 时无法获取当前页面的情况,因为如果在 topWindow 里调用本函数getApp() 和 getCurrentPages()[getCurrentPages().length-1] 就是 undefined。 const pageNow = this.thisPage() // 需要兼顾在 App.vue 时无法获取当前页面的情况,因为如果在 topWindow 里调用本函数getApp() 和 getCurrentPages()[getCurrentPages().length-1] 就是 undefined。
// #ifdef H5 // #ifdef H5
document.title = windowTitle || wo?.envar?.Sys_Brand_Name?.[mylang] || pagesJson?.appInfo?.i18nText?.[mylang] || pagesJson?.globalStyle?.navigationBarTitleText // 必须放在 setNavigationBarTitle 之后,否则会被其覆盖掉。 document.title =
windowTitle || wo?.envar?.Sys_Brand_Name?.[mylang] || pagesJson?.appInfo?.i18nText?.[mylang] || pagesJson?.globalStyle?.navigationBarTitleText // 必须放在 setNavigationBarTitle 之后,否则会被其覆盖掉。
// #endif // #endif
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
@ -81,7 +81,7 @@ export default {
if (tab.i18nText && tab.i18nText[mylang]) { if (tab.i18nText && tab.i18nText[mylang]) {
uni.setTabBarItem({ uni.setTabBarItem({
// #ifdef H5 // #ifdef H5
index: tabIndex, // + ((pagesJson?.tabBar?.midButton?.iconPath && tabIndex >= midIndex)?1:0), // H5 里,如果使用了 midButtontabBarItem的index出现错位需hack调整。推测在H5里 midButton 作为一个普通tab被插入到 tabBar 里,导致 tabBar 的 index 和 pagesJson.tabBar.list 的 index 错位了。[20211031] 注意到,从 HBuilderX 3.2.12.20211029 起,在 H5 里也没有错位了。 index: tabIndex, // + ((pagesJson?.tabBar?.midButton?.iconPath && tabIndex >= midIndex)?1:0), // H5 里,如果使用了 midButtontabBarItem的index出现错位需hack调整。推测在H5里 midButton 作为一个普通tab被插入到 tabBar 里,导致 tabBar 的 index 和 pagesJson.tabBar.list 的 index 错位了。[20211031] 注意到,从 HBuilderX 3.2.12.20211029 起,在 H5 里也没有错位了。
// #endif // #endif
// #ifndef H5 // #ifndef H5
index: tabIndex, index: tabIndex,
@ -94,22 +94,24 @@ export default {
// #ifdef H5 // #ifdef H5
// 响应式方案:仅仅根据当前设备类型,如果是 PC 大屏幕,则始终显示 topWindow 并且隐藏顶部 navibar 和底部 tabBar。 // 响应式方案:仅仅根据当前设备类型,如果是 PC 大屏幕,则始终显示 topWindow 并且隐藏顶部 navibar 和底部 tabBar。
const envar = this.envar || wo?.envar if (pagesJson?.topWindow || envar?.Hide_Bars_On_PC) {
if (pagesJson?.topWindow || envar.Hide_Bars_On_PC) { // 如果页头不是通过 pagesJson.topWindow 而是作为组件来引入个别页面,那么定义配置参数 Hide_Bars_On_PC 来控制。 // 如果页头不是通过 pagesJson.topWindow 而是作为组件来引入个别页面,那么定义配置参数 Hide_Bars_On_PC 来控制。
if (uni.getSystemInfoSync().model==='PC') { if (uni.getSystemInfoSync().model === 'PC') {
if (window.screen.width > (pagesJson?.topWindow?.matchMedia?.minWidth || 0)) { if (window.screen.width > (pagesJson?.topWindow?.matchMedia?.minWidth || 0)) {
uni.hideTabBar() uni.hideTabBar()
// 不知为何,同一个二级页面,如果第二次进入,就仍然会显示 navibar, 必须通过 setTimeout 执行才能彻底隐藏。 // 不知为何,同一个二级页面,如果第二次进入,就仍然会显示 navibar, 必须通过 setTimeout 执行才能彻底隐藏。
setTimeout(()=>{ document.getElementsByTagName('uni-page-head')?.[0]?.remove() },0) setTimeout(() => {
document.getElementsByTagName('uni-page-head')?.[0]?.remove()
}, 0)
} }
}else { } else {
document.getElementsByTagName('uni-top-window')?.[0]?.remove() // hide topWindow document.getElementsByTagName('uni-top-window')?.[0]?.remove() // hide topWindow
} }
} }
// #endif // #endif
}, },
makeServerUrl(route = '') { makeServerUrl (route = '') {
const envar = this.envar || wo?.envar || {} const envar = this.envar || wo?.envar || {}
if (typeof route !== 'string') route = '' // 防止 route 为 null, undefined 等由于后台数据库默认值而造成的异常。 if (typeof route !== 'string') route = '' // 防止 route 为 null, undefined 等由于后台数据库默认值而造成的异常。
@ -124,51 +126,43 @@ export default {
protocol = envar.Base_Protocol || 'https' protocol = envar.Base_Protocol || 'https'
hostname = envar.Base_Hostname hostname = envar.Base_Hostname
port = envar.Base_Port port = envar.Base_Port
}else{ } else {
protocol = envar.Base_Protocol_Dev || 'http' protocol = envar.Base_Protocol_Dev || 'http'
hostname = envar.Base_Hostname_Dev hostname =
envar.Base_Hostname_Dev ||
// #ifdef H5 // #ifdef H5
|| window.location.hostname window.location.hostname
// #endif // #endif
port = envar.Base_Port_Dev || envar.Base_Port port =
envar.Base_Port_Dev ||
envar.Base_Port ||
// #ifdef H5 // #ifdef H5
|| window.location.port.replace(':','') window.location.port.replace(':', '')
// #endif // #endif
} }
return `${protocol}://${hostname}:${port}/${route.replace(/^\//, '')}` return `${protocol}://${hostname}:${port}/${route.replace(/^\//, '')}`
}, },
makeBgUrl(path) { makeBgUrl (path) {
if (path) { if (path) {
return `url(${this.makeServerUrl(path)})` return `url(${this.makeServerUrl(path)})`
} }
return '' return ''
}, },
relaunchForAll ({envar=this.envar || wo?.envar || {}} = {}) {
uni.reLaunch({ url: envar?.Start_Page_For_All })
},
relaunchForOnline ({envar=this.envar || wo?.envar || {}} = {}) {
process.env.NODE_ENV === 'production' &&
wo.ss.User.onlineUser.uuid &&
uni.reLaunch({ url: envar?.Start_Page_For_Online })
},
relaunchForOffline ({envar=this.envar || wo?.envar || {}} ={}) {
process.env.NODE_ENV === 'production' &&
! wo.ss.User.onlineUser.uuid &&
uni.reLaunch({ url: envar?.Start_Page_For_Offline })
},
/** uni.request uniCloud.callFunction /** uni.request uniCloud.callFunction
* 返回值{ _state, 成功结果或错误结果 }其中 _state 除了后台返回的还可以是 * 返回值{ _state, 成功结果或错误结果 }其中 _state 除了后台返回的还可以是
* - CLIENT_BACKEND_BROKEN: 前端发现后台断线 * - CLIENT_BACKEND_BROKEN: 前端发现后台断线
* - CLIENT_BACKEND_TIMEOUT: 前端发现后台超时 * - CLIENT_BACKEND_TIMEOUT: 前端发现后台超时
* - CLINET_BACKEND_EXCEPTION: 前端发现后台异常 * - CLINET_BACKEND_EXCEPTION: 前端发现后台异常
**/ **/
async callBackend({ async callBackend ({
backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT, backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT,
httpMethod = 'POST', httpMethod = 'POST',
apiVersion = 'api', apiWho, apiTodo, apiWhat = {} apiVersion = 'api',
apiWho,
apiTodo,
apiWhat = {},
}) { }) {
const thisRoute = this.thisPage()?.route || 'VueApp' // 立刻保存 this.thisPage().route因为在调用后台后可能已切换到了其他页面。 const thisRoute = this.thisPage()?.route || 'VueApp' // 立刻保存 this.thisPage().route因为在调用后台后可能已切换到了其他页面。
const startTime = new Date().toJSON() const startTime = new Date().toJSON()
@ -185,8 +179,9 @@ export default {
// uniIdToken // uniCloud自动getStorageSync('uni_id_token')并传递为 uniIdToken也可自行组装传入 uniIdToken // uniIdToken // uniCloud自动getStorageSync('uni_id_token')并传递为 uniIdToken也可自行组装传入 uniIdToken
}, },
}) })
.catch((error) => { // {errMsg, stack} = error .catch((error) => {
if (/request:fail/.test(error.errMsg)) { // {errMsg, stack} = error
if (/request:fail/.test(error.errMsg)) {
// 后台云服务无法连接 // 后台云服务无法连接
return { _state: 'CLIENT_BACKEND_BROKEN', error } return { _state: 'CLIENT_BACKEND_BROKEN', error }
} else { } else {
@ -228,15 +223,21 @@ export default {
// 注意2虽然预设了 resultServer 和 resultCloud = {},但如果后台返回了 null那么 resultServer/resultCloud 也是 null。 // 注意2虽然预设了 resultServer 和 resultCloud = {},但如果后台返回了 null那么 resultServer/resultCloud 也是 null。
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
console.log( console.log(
'%c '+JSON.stringify({startTime:startTime, page:thisRoute, endTime:new Date().toJSON()}) + '%c ' +
' %c '+ JSON.stringify({ backend, apiWho, apiTodo, apiWhat, url }) + JSON.stringify({ startTime: startTime, page: thisRoute, endTime: new Date().toJSON() }) +
' %c '+ JSON.stringify(result), ' %c ' +
'color:blue', 'background:skyblue', 'background:magenta') // 不知为何,直接用 result 会输出一个奇怪的对象,要主动添加 JSON.stringify 才按照期望输出。 JSON.stringify({ backend, apiWho, apiTodo, apiWhat, url }) +
' %c ' +
JSON.stringify(result),
'color:blue',
'background:skyblue',
'background:magenta'
) // 不知为何,直接用 result 会输出一个奇怪的对象,要主动添加 JSON.stringify 才按照期望输出。
} }
return result return result
}, },
async pickupFile2Server({ async pickupFile2Server ({
mediaType = 'image', mediaType = 'image',
count = 1, count = 1,
sizeType = ['original', 'compressed'], sizeType = ['original', 'compressed'],
@ -277,25 +278,26 @@ export default {
// url 所在方法进一步处理后,通过 uploadFile 存在 data 里返回结果 // url 所在方法进一步处理后,通过 uploadFile 存在 data 里返回结果
uni.hideLoading() uni.hideLoading()
if (typeof(data)==='string') { // 不知为何uni.uploadFile返回的 data 是字符串而不是对象 if (typeof data === 'string') {
try{ // 不知为何uni.uploadFile返回的 data 是字符串而不是对象
try {
data = JSON.parse(data) data = JSON.parse(data)
}catch(exp){ } catch (exp) {
return { _state: 'CLIENT_FAIL_RESPONSE_JSON_MALFORMED'} return { _state: 'CLIENT_FAIL_RESPONSE_JSON_MALFORMED' }
} }
} }
if (data?._state==='SUCCESS' && data?.path) { if (data?._state === 'SUCCESS' && data?.path) {
return { _state: 'SUCCESS', fileUrl: this.makeServerUrl(data.path), filePath: data.path, ...data } return { _state: 'SUCCESS', fileUrl: this.makeServerUrl(data.path), filePath: data.path, ...data }
}else { } else {
return { _state: 'CLIENT_FAIL_UPLOAD_FILE', errorUpload } return { _state: 'CLIENT_FAIL_UPLOAD_FILE', errorUpload }
} }
}else { } else {
return { _state: 'CLIENT_FAIL_CHOOSE_FILE' } return { _state: 'CLIENT_FAIL_CHOOSE_FILE' }
} }
}, },
async pickupFile2Cloud({ mediaType = 'image', count = 1, sizeType = ['original', 'compressed'], sourceType = ['album', 'camera'], maxDuration } = {}) { async pickupFile2Cloud ({ mediaType = 'image', count = 1, sizeType = ['original', 'compressed'], sourceType = ['album', 'camera'], maxDuration } = {}) {
// 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。 // 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。
// if (!uni.getStorageSync('_passtoken')) { // if (!uni.getStorageSync('_passtoken')) {
// return { _state: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' } // return { _state: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' }
@ -356,23 +358,30 @@ export default {
return { _state: 'CLIENT_FAIL_CHOOSE_FILE' } return { _state: 'CLIENT_FAIL_CHOOSE_FILE' }
}, },
async pickupFile({ async pickupFile ({
backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT, backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT,
mediaType = 'image', count = 1, sizeType = ['original', 'compressed'], sourceType = ['album', 'camera'], maxDuration, mediaType = 'image',
url, header = {}, formData = {}, name = 'file', count = 1,
sizeType = ['original', 'compressed'],
sourceType = ['album', 'camera'],
maxDuration,
url,
header = {},
formData = {},
name = 'file',
} = {}) { } = {}) {
if (backend==='UNICLOUD'){ if (backend === 'UNICLOUD') {
const resultCloud = await this.pickupFile2Cloud({mediaType, count, sizeType, sourceType, maxDuration }) const resultCloud = await this.pickupFile2Cloud({ mediaType, count, sizeType, sourceType, maxDuration })
return resultCloud return resultCloud
}else if (backend==='SERVER'){ } else if (backend === 'SERVER') {
const resultServer = await this.pickupFile2Server({mediaType, count, sizeType, sourceType, maxDuration, url, header, formData, name}) const resultServer = await this.pickupFile2Server({ mediaType, count, sizeType, sourceType, maxDuration, url, header, formData, name })
return resultServer return resultServer
}else { } else {
return { _state: 'CLEINT_FAIL_UNKNOWN_BACKEND_TYPE', backend } return { _state: 'CLEINT_FAIL_UNKNOWN_BACKEND_TYPE', backend }
} }
}, },
openUrl(url) { openUrl (url) {
// #ifdef APP-PLUS // #ifdef APP-PLUS
plus.runtime.openURL(url) plus.runtime.openURL(url)
// #endif // #endif
@ -381,7 +390,7 @@ export default {
// #endif // #endif
}, },
getSystemInfo() { getSystemInfo () {
let systemInfo = uni.getSystemInfoSync() let systemInfo = uni.getSystemInfoSync()
// model=PC|iPhone|iPad|Nexus 6|..., // model=PC|iPhone|iPad|Nexus 6|...,
// platform=ios|android|mac|windows|linux|other, // platform=ios|android|mac|windows|linux|other,
@ -434,9 +443,9 @@ export default {
callback // 发生在 toast 之后 callback // 发生在 toast 之后
}) })
*/ */
showToast({ tool, type, image, title, duration = 2000, ...rest }) { showToast ({ tool, type, image, title, duration = 2000, ...rest }) {
const pageNow = this.thisPage() const pageNow = this.thisPage()
if (tool === 'uni' || ! pageNow?.$refs?.toast) { if (tool === 'uni' || !pageNow?.$refs?.toast) {
// #ifdef APP-PLUS // #ifdef APP-PLUS
uni.showToast({ icon: 'none', title, duration, ...rest }) uni.showToast({ icon: 'none', title, duration, ...rest })
// #endif // #endif
@ -449,15 +458,15 @@ export default {
} }
}, },
formatMoney(value, precision=2) { formatMoney (value, precision = 2) {
return Number(value || 0).toFixed(precision) // Number(undefined)===NaN return Number(value || 0).toFixed(precision) // Number(undefined)===NaN
}, },
formatPercent(value, precision=2) { formatPercent (value, precision = 2) {
return Number(value * 100 || 0).toFixed(precision) return Number(value * 100 || 0).toFixed(precision)
}, },
formatDate(date, format) { formatDate (date, format) {
if (!(date instanceof Date)) { if (!(date instanceof Date)) {
if (typeof date === 'string' && /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d$/.test(date)) { if (typeof date === 'string' && /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d$/.test(date)) {
// 这是从 typeorm 数据库得到的Date类型的值 // 这是从 typeorm 数据库得到的Date类型的值
@ -486,47 +495,75 @@ export default {
return format return format
}, },
getUserEndLanIp(callback) { getUserEndLanIp (callback) {
let recode = {} let recode = {}
let RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection let RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection
// 如果不存在则使用一个iframe绕过 // 如果不存在则使用一个iframe绕过
if (!RTCPeerConnection) { if (!RTCPeerConnection) {
// 因为这里用到了iframe所以在调用这个方法的script上必须有一个iframe标签 // 因为这里用到了iframe所以在调用这个方法的script上必须有一个iframe标签
// <iframe id="iframe" sandbox="allow-same-origin" style="display:none;"></iframe> // <iframe id="iframe" sandbox="allow-same-origin" style="display:none;"></iframe>
let win = iframe.contentWindow let win = iframe.contentWindow
RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection
} }
//创建实例,生成连接 //创建实例,生成连接
let pc = new RTCPeerConnection() let pc = new RTCPeerConnection()
// 匹配字符串中符合ip地址的字段 // 匹配字符串中符合ip地址的字段
function handleCandidate(candidate) { function handleCandidate (candidate) {
let ip_regexp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|([a-f0-9]{1,4}((:[a-f0-9]{1,4}){7}|:+[a-f0-9]{1,4}){6}))/ let ip_regexp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|([a-f0-9]{1,4}((:[a-f0-9]{1,4}){7}|:+[a-f0-9]{1,4}){6}))/
let ip_isMatch = candidate.match(ip_regexp)[1] let ip_isMatch = candidate.match(ip_regexp)[1]
if (!recode[ip_isMatch]) { if (!recode[ip_isMatch]) {
callback(ip_isMatch) callback(ip_isMatch)
recode[ip_isMatch] = true recode[ip_isMatch] = true
} }
} }
//监听icecandidate事件 //监听icecandidate事件
pc.onicecandidate = (ice) => { pc.onicecandidate = (ice) => {
if (ice.candidate) { if (ice.candidate) {
handleCandidate(ice.candidate.candidate) handleCandidate(ice.candidate.candidate)
} }
}; }
//建立一个伪数据的通道 //建立一个伪数据的通道
pc.createDataChannel('') pc.createDataChannel('')
pc.createOffer((res) => { pc.createOffer(
pc.setLocalDescription(res) (res) => {
}, () => {}) pc.setLocalDescription(res)
//延迟,让一切都能完成 },
setTimeout(() => { () => {}
let lines = pc.localDescription.sdp.split('\n') )
lines.forEach(item => { //延迟,让一切都能完成
if (item.indexOf('a=candidate:') === 0) { setTimeout(() => {
handleCandidate(item) let lines = pc.localDescription.sdp.split('\n')
} lines.forEach((item) => {
}) if (item.indexOf('a=candidate:') === 0) {
}, 1000) handleCandidate(item)
}, }
})
}, 1000)
},
relaunchForAll ({ envar = this.envar || wo?.envar } = {}) {
uni.reLaunch({ url: envar?.Start_Page_For_All })
},
relaunchForOnline ({ envar = this.envar || wo?.envar } = {}) {
process.env.NODE_ENV === 'production' && wo.ss.User.onlineUser.uuid && uni.reLaunch({ url: envar?.Start_Page_For_Online })
},
relaunchForOffline ({ envar = this.envar || wo?.envar } = {}) {
process.env.NODE_ENV === 'production' && ! wo.ss.User.onlineUser.uuid && uni.reLaunch({ url: envar?.Start_Page_For_Offline })
},
// 在手机上跳转到标签页需要 switchTab在PC上跳转到菜单页需要 navigateTo 或 redirectTo。因此在这里用 gotoPage 和 backtoPage 来弥补差异。
navigate_page (pageName, { pagesJson = this.pagesJson || wo?.pagesJson, envar = this.envar || wo?.envar } = {}) {
if (! envar?.onPC && pagesJson?.tabBar?.list?.find((item) => item?.pagePath?.substr(6) === pageName)) {
uni.switchTab({ url: pageName })
} else {
uni.navigateTo({ url: pageName })
}
},
redirect_page (pageName, { pagesJson = this.pagesJson || wo?.pagesJson, envar = this.envar || wo?.envar } = {}) {
if (! envar?.onPC && pagesJson?.tabBar?.list?.find((item) => item?.pagePath?.substr(6) === pageName)) {
uni.switchTab({ url: pageName })
} else {
uni.redirectTo({ url: pageName })
}
},
} }