|
@@ -0,0 +1,170 @@
|
|
|
|
|
+import { onLoad } from "@dcloudio/uni-app";
|
|
|
|
|
+const useTransferPage = () => {
|
|
|
|
|
+ const funcMap = {
|
|
|
|
|
+ redirect: uni.redirectTo,
|
|
|
|
|
+ reLaunch: uni.reLaunch,
|
|
|
|
|
+ switchTab: uni.switchTab
|
|
|
|
|
+ };
|
|
|
|
|
+ let prevData = ref<Record<string, any>>({});
|
|
|
|
|
+ let transferResolver: ((value: unknown) => void) | null = null;
|
|
|
|
|
+ let eventChannel: UniApp.EventChannel | null = null;
|
|
|
|
|
+ // onMounted(() => {
|
|
|
|
|
+ // 使用instance获取getOpenerEventChannel在非页面级组件中会报错
|
|
|
|
|
+ // const instance = getCurrentInstance().proxy
|
|
|
|
|
+ // if (instance) {
|
|
|
|
|
+ // eventChannel = instance.getOpenerEventChannel();
|
|
|
|
|
+ // }
|
|
|
|
|
+ // });
|
|
|
|
|
+ type Callback = (() => void) | null;
|
|
|
|
|
+ type TransferOptions = {
|
|
|
|
|
+ data?: Record<string, any> | null,
|
|
|
|
|
+ type?: string,
|
|
|
|
|
+ bigData?: Record<string, any> | null,
|
|
|
|
|
+ callback?: Callback
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onLoad((opt) => {
|
|
|
|
|
+ const pages = getCurrentPages();
|
|
|
|
|
+ const page = pages[pages.length - 1];
|
|
|
|
|
+ eventChannel = (page as any).getOpenerEventChannel();
|
|
|
|
|
+ emit('onPageOpen');
|
|
|
|
|
+ for (const key in opt) {
|
|
|
|
|
+ if (opt.hasOwnProperty(key) && !['data', 'storageKey'].includes(key)) {
|
|
|
|
|
+ prevData.value[key] = decodeURIComponent(opt[key]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!opt) return;
|
|
|
|
|
+ let originData = opt.data;
|
|
|
|
|
+ if (opt.data) {
|
|
|
|
|
+ if (opt.data.startsWith('%257B')) {
|
|
|
|
|
+ originData = decodeURIComponent(opt.data);
|
|
|
|
|
+ }
|
|
|
|
|
+ const data = JSON.parse(decodeURIComponent(originData || '{}'));
|
|
|
|
|
+ Object.assign(prevData.value, data);
|
|
|
|
|
+ }
|
|
|
|
|
+ const storageKey = opt.storageKey;
|
|
|
|
|
+ if (storageKey) {
|
|
|
|
|
+ const storageData = uni.getStorageSync(storageKey);
|
|
|
|
|
+ Object.assign(prevData.value, storageData);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ function getTransferUrl(url: string, data: any, bigData: any) {
|
|
|
|
|
+ const urlParams = {
|
|
|
|
|
+ data: data ? encodeURIComponent(JSON.stringify(data)) : null,
|
|
|
|
|
+ storageKey: bigData ? 'transferBigData' : null
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 处理URL中已存在的参数
|
|
|
|
|
+ const [baseUrl, existingQuery] = url.split('?');
|
|
|
|
|
+ const existingParams = {};
|
|
|
|
|
+
|
|
|
|
|
+ // 解析现有参数
|
|
|
|
|
+ if (existingQuery) {
|
|
|
|
|
+ existingQuery.split('&').forEach(param => {
|
|
|
|
|
+ const [key, value] = param.split('=');
|
|
|
|
|
+ if (key) {
|
|
|
|
|
+ // 为 existingParams 显式声明类型为 Record<string, string>
|
|
|
|
|
+ (existingParams as Record<string, string>)[key] = value;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 合并新参数
|
|
|
|
|
+ Object.entries(urlParams)
|
|
|
|
|
+ .filter(([_, value]) => value)
|
|
|
|
|
+ .forEach(([key, value]) => {
|
|
|
|
|
+ (existingParams as Record<string, string>)[key] = value as string;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 构建查询字符串
|
|
|
|
|
+ const queryString = Object.entries(existingParams)
|
|
|
|
|
+ .map(([key, value]) => `${key}=${value}`)
|
|
|
|
|
+ .join('&');
|
|
|
|
|
+
|
|
|
|
|
+ return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function transferTo(url: string, { data = null, type = 'navigate', bigData = null, callback = null }: TransferOptions = {}) {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ transferResolver = resolve;
|
|
|
|
|
+ if (bigData) {
|
|
|
|
|
+ uni.setStorageSync('transferBigData', bigData);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // clear big data by force
|
|
|
|
|
+ uni.removeStorageSync('transferBigData');
|
|
|
|
|
+ }
|
|
|
|
|
+ const nextUrl = getTransferUrl(url, data, bigData);
|
|
|
|
|
+ if (type === 'navigate') {
|
|
|
|
|
+ uni.navigateTo({
|
|
|
|
|
+ url: nextUrl,
|
|
|
|
|
+ events: {
|
|
|
|
|
+ transferEnd: (data: any) => {
|
|
|
|
|
+ transferResolver?.(data);
|
|
|
|
|
+ },
|
|
|
|
|
+ onPageOpen: () => {
|
|
|
|
|
+ if (callback) {
|
|
|
|
|
+ callback?.();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.log('transferTo fail', err);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const routeFunc = funcMap[type as keyof typeof funcMap];
|
|
|
|
|
+ routeFunc({
|
|
|
|
|
+ url: nextUrl,
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.log('transferTo fail', err);
|
|
|
|
|
+ reject(err);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ function transferBack(data:any = null, delta = 1) {
|
|
|
|
|
+ emit('transferEnd', data);
|
|
|
|
|
+ // force clear big data
|
|
|
|
|
+ uni.removeStorageSync('transferBigData');
|
|
|
|
|
+ const pages = getCurrentPages();
|
|
|
|
|
+ if (pages.length === 1) {
|
|
|
|
|
+ switchTab('/pages/splash/splash');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.navigateBack({
|
|
|
|
|
+ delta: delta,
|
|
|
|
|
+ success: () => { },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ switchTab('/pages/splash/splash');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ function switchTab(url: string) {
|
|
|
|
|
+ uni.switchTab({
|
|
|
|
|
+ url: url,
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.log(err);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function emit(event: string, data = null) {
|
|
|
|
|
+ if (eventChannel?.emit) {
|
|
|
|
|
+ eventChannel.emit(event, data);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.warn('上级页面丢失,无法触发transferEnd');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ prevData,
|
|
|
|
|
+ transferTo,
|
|
|
|
|
+ transferBack,
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export default useTransferPage;
|