useTransferPage.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { onLoad } from "@dcloudio/uni-app";
  2. const useTransferPage = () => {
  3. const funcMap = {
  4. redirect: uni.redirectTo,
  5. reLaunch: uni.reLaunch,
  6. switchTab: uni.switchTab
  7. };
  8. let prevData = ref<Record<string, any>>({});
  9. let transferResolver: ((value: unknown) => void) | null = null;
  10. let eventChannel: UniApp.EventChannel | null = null;
  11. // onMounted(() => {
  12. // 使用instance获取getOpenerEventChannel在非页面级组件中会报错
  13. // const instance = getCurrentInstance().proxy
  14. // if (instance) {
  15. // eventChannel = instance.getOpenerEventChannel();
  16. // }
  17. // });
  18. type Callback = (() => void) | null;
  19. type TransferOptions = {
  20. data?: Record<string, any> | null,
  21. type?: string,
  22. bigData?: Record<string, any> | null,
  23. callback?: Callback
  24. }
  25. onLoad((opt) => {
  26. const pages = getCurrentPages();
  27. const page = pages[pages.length - 1];
  28. eventChannel = (page as any).getOpenerEventChannel();
  29. emit('onPageOpen');
  30. for (const key in opt) {
  31. if (opt.hasOwnProperty(key) && !['data', 'storageKey'].includes(key)) {
  32. prevData.value[key] = decodeURIComponent(opt[key]);
  33. }
  34. }
  35. if (!opt) return;
  36. let originData = opt.data;
  37. if (opt.data) {
  38. if (opt.data.startsWith('%257B')) {
  39. originData = decodeURIComponent(opt.data);
  40. }
  41. const data = JSON.parse(decodeURIComponent(originData || '{}'));
  42. Object.assign(prevData.value, data);
  43. }
  44. const storageKey = opt.storageKey;
  45. if (storageKey) {
  46. const storageData = uni.getStorageSync(storageKey);
  47. Object.assign(prevData.value, storageData);
  48. }
  49. });
  50. function getTransferUrl(url: string, data: any, bigData: any) {
  51. const urlParams = {
  52. data: data ? encodeURIComponent(JSON.stringify(data)) : null,
  53. storageKey: bigData ? 'transferBigData' : null
  54. };
  55. // 处理URL中已存在的参数
  56. const [baseUrl, existingQuery] = url.split('?');
  57. const existingParams = {};
  58. // 解析现有参数
  59. if (existingQuery) {
  60. existingQuery.split('&').forEach(param => {
  61. const [key, value] = param.split('=');
  62. if (key) {
  63. // 为 existingParams 显式声明类型为 Record<string, string>
  64. (existingParams as Record<string, string>)[key] = value;
  65. }
  66. });
  67. }
  68. // 合并新参数
  69. Object.entries(urlParams)
  70. .filter(([_, value]) => value)
  71. .forEach(([key, value]) => {
  72. (existingParams as Record<string, string>)[key] = value as string;
  73. });
  74. // 构建查询字符串
  75. const queryString = Object.entries(existingParams)
  76. .map(([key, value]) => `${key}=${value}`)
  77. .join('&');
  78. return queryString ? `${baseUrl}?${queryString}` : baseUrl;
  79. }
  80. function transferTo(url: string, { data = null, type = 'navigate', bigData = null, callback = null }: TransferOptions = {}) {
  81. return new Promise((resolve, reject) => {
  82. transferResolver = resolve;
  83. if (bigData) {
  84. uni.setStorageSync('transferBigData', bigData);
  85. } else {
  86. // clear big data by force
  87. uni.removeStorageSync('transferBigData');
  88. }
  89. const nextUrl = getTransferUrl(url, data, bigData);
  90. if (type === 'navigate') {
  91. uni.navigateTo({
  92. url: nextUrl,
  93. events: {
  94. transferEnd: (data: any) => {
  95. transferResolver?.(data);
  96. },
  97. onPageOpen: () => {
  98. if (callback) {
  99. callback?.();
  100. }
  101. }
  102. },
  103. fail: (err) => {
  104. console.log('transferTo fail', err);
  105. }
  106. });
  107. } else {
  108. const routeFunc = funcMap[type as keyof typeof funcMap];
  109. routeFunc({
  110. url: nextUrl,
  111. fail: (err) => {
  112. console.log('transferTo fail', err);
  113. reject(err);
  114. }
  115. });
  116. }
  117. });
  118. }
  119. function transferBack(data:any = null, delta = 1) {
  120. emit('transferEnd', data);
  121. // force clear big data
  122. uni.removeStorageSync('transferBigData');
  123. const pages = getCurrentPages();
  124. if (pages.length === 1) {
  125. switchTab('/pages/splash/splash');
  126. } else {
  127. uni.navigateBack({
  128. delta: delta,
  129. success: () => { },
  130. fail: (err) => {
  131. switchTab('/pages/splash/splash');
  132. }
  133. });
  134. }
  135. }
  136. function switchTab(url: string) {
  137. uni.switchTab({
  138. url: url,
  139. fail: (err) => {
  140. console.log(err);
  141. }
  142. });
  143. }
  144. function emit(event: string, data = null) {
  145. if (eventChannel?.emit) {
  146. eventChannel.emit(event, data);
  147. } else {
  148. console.warn('上级页面丢失,无法触发transferEnd');
  149. }
  150. }
  151. return {
  152. prevData,
  153. transferTo,
  154. transferBack,
  155. }
  156. };
  157. export default useTransferPage;