123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- import {onLoad} from "@dcloudio/uni-app"
- import {computed, onUnmounted, readonly, ref, nextTick} from "vue"
- import {array, empty, object, string} from "@/uni_modules/uv-ui-tools/libs/function/test";
- import mxConst, {getTabRoutes} from "@/common/mxConst";
- import {guid, sleep} from "@/uni_modules/uv-ui-tools/libs/function";
- import baseConfig from "@/config";
- import mxConfig from "@/common/mxConfig";
- import {useH5BackHome} from "@/components/mx-nav-bar/useH5BackHome";
- import {createEventHook, injectLocal, provideLocal} from "@vueuse/core";
- import _ from 'lodash';
- export const useTransfer = function () {
- // data
- const cacheKey = ref('')
- const prevData = ref({})
- const usingCacheTransfer = computed(() => !!cacheKey.value)
- // 回传事件,只要在transferTo中定义一个callback字符串标识即可响应回调事件
- // 用uni.$on/$off/$emit来实现,如果要通用的话,可以考虑自行实现一个全局的eventBus
- const pageCallback = createEventHook() // 使用hook给transfer外部用户提供钩子
- const eventName = ref('') // 给发起跳转的页面记录事件注册, 用于自动注销
- const callbackEventData = ref(null) // 给当前页面存放数据,用于回传
- // hooks
- onLoad((opt) => {
- if (opt.cacheKey) cacheKey.value = opt.cacheKey, prevData.value = uni.getStorageSync(opt.cacheKey)
- else prevData.value = JSON.parse(decodeURIComponent(opt.data || '{}'))
- })
- onUnmounted(() => {
- if (usingCacheTransfer.value) uni.removeStorageSync(cacheKey.value)
- // 发起跳转的页面注销事件
- if (eventName.value) uni.$off(eventName.value)
- })
- // methods
- /*
- * main function for route, it keeps params type and supports big data transfer.
- * Note: if you defined `callback` in params, 2 pages will auto support onPageCallback event.
- * @param {String|Object} urlOrOptions - route url or options
- * @param {Object} props - indicates props to pickup from source data
- * @param {Array} source - source data array, default is [prevData.value]
- * @param {Boolean} usingCache - whether to use cache, default is false, for big data transfer
- * */
- const transferTo = function (urlOrOptions, props = {}, source = null, usingCache = false) {
- const options = object(urlOrOptions) ? urlOrOptions
- : {url: urlOrOptions, type: getTabRoutes().includes(urlOrOptions) ? 'tab' : 'to'}
- // confirm params
- let params = options.params || {}
- let extra = {}
- // prevData 自动包含是名学测评系统的逻辑,暂时不用去掉,以免引起一些数值覆盖的问题
- const extraSource = [/*prevData.value*/].concat(source)
- if (array(props)) extra = _.merge({}, ..._.map(extraSource, obj => _.pick(obj, props)))
- else if (object(props)) extra = _.merge(props, ..._.map(extraSource, obj => _.pick(obj, _.keys(props))))
- params = _.merge(params, extra)
- // handle params, using JSON.stringify or uni.setStorageSync
- let formatParams = params
- if (!empty(params)) {
- if (usingCache) {
- const storageKey = mxConst.keyCacheUniquePrefix + guid()
- uni.setStorageSync(storageKey, params)
- formatParams = {cacheKey: storageKey}
- } else {
- formatParams = {data: encodeURIComponent(JSON.stringify(params))}
- }
- }
- // page callback event // 注意这是在发起跳转的页面监听
- if (string(params.callback) && params.callback) {
- eventName.value = params.callback
- uni.$off(eventName.value) // 先清除其它注册,只注册一次
- uni.$on(eventName.value, handleCallback)
- }
- // 这里并没有干涉其它参数,所以$uv.route支持的功能这里应该都能用
- options.params = formatParams
- uni.$uv.route(options)
- console.log('transferTo:', options, params)
- }
- const handleCallback = async function (event) {
- await pageCallback.trigger(event)
- }
- const transferBack = function (options = {type: 'back'}) {
- // 主动调用transferBack的地方自动处理回调
- if (prevData.value.callback) {
- // 这里做了一个延迟处理,让回调发生在页面跳转之后,
- // 这样的话,页面因为数据变化引起的滚动条重置问题看起来平滑一些。
- // 如entry-single页面,换选学校之后滚动条由于缓存机制会停在选择学校之前的位置,
- // 即使设置了scrollTop也不起作用,这里延迟可以保证重置行为发生在滚动条缓存机制之后。
- const e = prevData.value.callback, arg = callbackEventData.value
- sleep().then(() => uni.$emit(e, arg))
- }
- const {hasPreviousPage} = useH5BackHome()
- if (hasPreviousPage.value) transferTo(options)
- else relaunch()
- }
- const transferToIndex = function () {
- transferTo(mxConst.routes.index)
- }
- const relaunch = function () {
- transferTo({...mxConst.routes.index, type: 'launch'})
- }
- const transferToWebView = function (url, title = '') {
- const nextPage = '/pages/h5/h5'
- transferTo(nextPage, {url, title})
- }
- const transferToProtocolUser = function () {
- const path = baseConfig.inlineSiteBaseUrl + mxConfig.inlineSiteFunctionPaths.protocolUser
- transferToWebView(path, '用户协议')
- }
- const transferToProtocolPrivacy = function () {
- const path = baseConfig.inlineSiteBaseUrl + mxConfig.inlineSiteFunctionPaths.protocolPrivacy
- transferToWebView(path, '隐私协议')
- }
- const transferToFAQ = function () {
- const path = baseConfig.inlineSiteBaseUrl + mxConfig.inlineSiteFunctionPaths.FAQ
- transferToWebView(path, '常见问题')
- }
- const playVideo = function (idOrSrc, aliIdType, title, callback = false) {
- transferTo(mxConst.routes.videoPlay, {aliId: idOrSrc, aliIdType, title, callback})
- }
- /*
- * tool function for clean all transfer cache data,
- * 这里提供了一个清除所有缓存数据的工具函数,
- * 可以用在一些管理性功能页中,如果页面非正常中断可能会累积一些缓存,
- * 这个函数可以用来清除所有缓存数据。
- * 注意:这个函数只是清除 transferTo 中 usingCache=true 产生缓存数据.
- * */
- const cleanAllTransferCacheData = function () {
- // 根据mxConst.keyCacheUniquePrefix清除所有缓存
- // 提供给某些管理性功能页使用,如果页面非正常中断可能会累积一些缓存
- const keys = uni.getStorageInfoSync().keys
- keys.forEach(key => {
- if (key.startsWith(mxConst.keyCacheUniquePrefix))
- uni.removeStorageSync(key)
- })
- }
- return {
- cacheKey: readonly(cacheKey), // 安全考虑,不允许外部修改
- prevData,
- usingCacheTransfer,
- eventName: readonly(eventName),
- onPageCallback: pageCallback.on,
- callbackEventData,
- transferTo,
- transferBack,
- transferToIndex,
- relaunch,
- transferToWebView,
- transferToProtocolUser,
- transferToProtocolPrivacy,
- transferToFAQ,
- playVideo,
- cleanAllTransferCacheData
- }
- }
- const key = Symbol('TRANSFER_SERVICE')
- export const useProvideTransfer = function () {
- const options = useTransfer()
- provideLocal(key, options)
- return options
- }
- export const useInjectTransfer = function () {
- return injectLocal(key)
- }
|