@zfqh/uniapp-x 0.0.0-stage → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/LICENSE +21 -0
  3. package/README.md +61 -3
  4. package/lib/apis/core.d.ts +18 -0
  5. package/lib/apis/core.js +19 -0
  6. package/lib/apis/index.d.ts +2 -0
  7. package/lib/apis/index.js +2 -0
  8. package/lib/apis/request.d.ts +4 -0
  9. package/lib/apis/request.js +57 -0
  10. package/lib/configs/api.d.ts +7 -0
  11. package/lib/configs/api.js +6 -0
  12. package/lib/configs/app.d.ts +20 -0
  13. package/lib/configs/app.js +18 -0
  14. package/lib/configs/cdn.d.ts +15 -0
  15. package/lib/configs/cdn.js +17 -0
  16. package/lib/configs/env.d.ts +37 -0
  17. package/lib/configs/env.js +71 -0
  18. package/lib/configs/index.d.ts +130 -0
  19. package/lib/configs/index.js +76 -0
  20. package/lib/configs/link.d.ts +11 -0
  21. package/lib/configs/link.js +3 -0
  22. package/lib/configs/log.d.ts +9 -0
  23. package/lib/configs/log.js +8 -0
  24. package/lib/configs/mp.d.ts +15 -0
  25. package/lib/configs/mp.js +9 -0
  26. package/lib/configs/navigate.d.ts +17 -0
  27. package/lib/configs/navigate.js +5 -0
  28. package/lib/configs/page.d.ts +18 -0
  29. package/lib/configs/page.js +14 -0
  30. package/lib/configs/path.d.ts +11 -0
  31. package/lib/configs/path.js +10 -0
  32. package/lib/configs/storage.d.ts +7 -0
  33. package/lib/configs/storage.js +6 -0
  34. package/lib/configs/tabbar.d.ts +7 -0
  35. package/lib/configs/tabbar.js +6 -0
  36. package/lib/configs/toast.d.ts +18 -0
  37. package/lib/configs/toast.js +29 -0
  38. package/lib/configs/updater.d.ts +15 -0
  39. package/lib/configs/updater.js +33 -0
  40. package/lib/configs/upload.d.ts +30 -0
  41. package/lib/configs/upload.js +19 -0
  42. package/lib/configs/ver.d.ts +8 -0
  43. package/lib/configs/ver.js +28 -0
  44. package/lib/configs/web.d.ts +5 -0
  45. package/lib/configs/web.js +2 -0
  46. package/lib/hooks/index.d.ts +11 -0
  47. package/lib/hooks/index.js +11 -0
  48. package/lib/hooks/useAppLifecycle.d.ts +8 -0
  49. package/lib/hooks/useAppLifecycle.js +87 -0
  50. package/lib/hooks/useBadge.d.ts +8 -0
  51. package/lib/hooks/useBadge.js +47 -0
  52. package/lib/hooks/useNeedLogin.d.ts +1 -0
  53. package/lib/hooks/useNeedLogin.js +27 -0
  54. package/lib/hooks/useOverlay.d.ts +1 -0
  55. package/lib/hooks/useOverlay.js +17 -0
  56. package/lib/hooks/usePageShow.d.ts +2 -0
  57. package/lib/hooks/usePageShow.js +16 -0
  58. package/lib/hooks/usePopup.d.ts +1 -0
  59. package/lib/hooks/usePopup.js +14 -0
  60. package/lib/hooks/useRedirect.d.ts +5 -0
  61. package/lib/hooks/useRedirect.js +92 -0
  62. package/lib/hooks/useReferrer.d.ts +1 -0
  63. package/lib/hooks/useReferrer.js +11 -0
  64. package/lib/hooks/useShare.d.ts +12 -0
  65. package/lib/hooks/useShare.js +49 -0
  66. package/lib/hooks/useVersion.d.ts +6 -0
  67. package/lib/hooks/useVersion.js +21 -0
  68. package/lib/hooks/useWebview.d.ts +14 -0
  69. package/lib/hooks/useWebview.js +294 -0
  70. package/lib/index.d.ts +27 -0
  71. package/lib/index.js +26 -0
  72. package/lib/stores/app.d.ts +51 -0
  73. package/lib/stores/app.js +57 -0
  74. package/lib/stores/dict.d.ts +35 -0
  75. package/lib/stores/dict.js +42 -0
  76. package/lib/stores/im.d.ts +57 -0
  77. package/lib/stores/im.js +102 -0
  78. package/lib/stores/index.d.ts +12 -0
  79. package/lib/stores/index.js +17 -0
  80. package/lib/stores/launch.d.ts +42 -0
  81. package/lib/stores/launch.js +39 -0
  82. package/lib/stores/location.d.ts +35 -0
  83. package/lib/stores/location.js +58 -0
  84. package/lib/stores/login.d.ts +80 -0
  85. package/lib/stores/login.js +91 -0
  86. package/lib/stores/network.d.ts +26 -0
  87. package/lib/stores/network.js +45 -0
  88. package/lib/stores/pinia.d.ts +2 -0
  89. package/lib/stores/pinia.js +3 -0
  90. package/lib/stores/system.d.ts +39 -0
  91. package/lib/stores/system.js +36 -0
  92. package/lib/styles/index.scss +9 -0
  93. package/lib/styles/reset-vue.scss +15 -0
  94. package/lib/utils/audio.d.ts +14 -0
  95. package/lib/utils/audio.js +43 -0
  96. package/lib/utils/consts.d.ts +74 -0
  97. package/lib/utils/consts.js +110 -0
  98. package/lib/utils/cos.d.ts +17 -0
  99. package/lib/utils/cos.js +141 -0
  100. package/lib/utils/file.d.ts +28 -0
  101. package/lib/utils/file.js +292 -0
  102. package/lib/utils/index.d.ts +166 -0
  103. package/lib/utils/index.js +486 -0
  104. package/lib/utils/message.d.ts +1 -0
  105. package/lib/utils/message.js +55 -0
  106. package/lib/utils/navigate.d.ts +28 -0
  107. package/lib/utils/navigate.js +192 -0
  108. package/lib/utils/pages.d.ts +21 -0
  109. package/lib/utils/pages.js +83 -0
  110. package/lib/utils/permission.d.ts +17 -0
  111. package/lib/utils/permission.js +278 -0
  112. package/lib/utils/query.d.ts +20 -0
  113. package/lib/utils/query.js +51 -0
  114. package/lib/utils/request.d.ts +8 -0
  115. package/lib/utils/request.js +139 -0
  116. package/lib/utils/storage.d.ts +40 -0
  117. package/lib/utils/storage.js +128 -0
  118. package/lib/utils/subscribe.d.ts +7 -0
  119. package/lib/utils/subscribe.js +94 -0
  120. package/lib/utils/toast.d.ts +17 -0
  121. package/lib/utils/toast.js +66 -0
  122. package/lib/utils/uni.d.ts +1 -0
  123. package/lib/utils/uni.js +141 -0
  124. package/lib/utils/update.d.ts +41 -0
  125. package/lib/utils/update.js +322 -0
  126. package/lib/utils/url.d.ts +14 -0
  127. package/lib/utils/url.js +40 -0
  128. package/package.json +38 -4
  129. package/types/index.d.ts +78 -0
  130. package/types/virtual.d.ts +1 -0
@@ -0,0 +1,192 @@
1
+ import { queryParams } from '@zfqh/uview-x/utils/function';
2
+ import page from '../configs/page';
3
+ import nav from '../configs/navigate';
4
+ import app from '../configs/app';
5
+ import { IS_WEBVIEW_ENV, WEBVIEW_ENV } from './consts';
6
+ import { inPages, getPage } from './pages';
7
+ import { joinPath } from './index';
8
+ import { pinia } from '../stores/pinia';
9
+ import { useLoginStore } from '../stores/login';
10
+ // 检测协议路�?
11
+ const checkProtocolMatch = (url) => url.match(/^([\w.]+):\//);
12
+ // 转换绝对路径
13
+ const getAbsoUrl = (url, current) => {
14
+ if (!url.startsWith('/') && !checkProtocolMatch(url)) {
15
+ url = joinPath(current, url);
16
+ if (!url.startsWith('/')) {
17
+ url = `/${url}`;
18
+ }
19
+ }
20
+ return url;
21
+ };
22
+ // 节流,防止重复执�?
23
+ let throttling = false;
24
+ const navigate = function (url = '', type = 'navigateTo') {
25
+ if (!throttling) {
26
+ throttling = true;
27
+ setTimeout(() => {
28
+ throttling = false;
29
+ }, 500);
30
+ let needLogin = false;
31
+ let isNative = !page.pages?.length;
32
+ let navigateOptions = {};
33
+ let webviewParams = {};
34
+ let webviewPage = getPage('webview');
35
+ let loginType = nav.loginType;
36
+ let referrerType = nav.referrerType;
37
+ let opts = {};
38
+ if (typeof url === 'string') {
39
+ url = { url };
40
+ }
41
+ if (typeof url === 'object') {
42
+ opts = url;
43
+ const { type: _type, url: _url = '', params: _params = {}, webviewParams: _webviewParams = {}, webviewUrl: _webviewPage = webviewPage, needLogin: _needLogin = needLogin, loginType: _loginType = loginType, referrerType: _referrerType = referrerType, native: _isNative = isNative, ...rest } = url;
44
+ url = `${_url}${queryParams(_params)}`;
45
+ needLogin = !!_needLogin;
46
+ isNative = !!_isNative;
47
+ loginType = _loginType;
48
+ referrerType = _referrerType;
49
+ type = _type || type;
50
+ webviewParams = _webviewParams;
51
+ webviewPage = _webviewPage;
52
+ navigateOptions = rest;
53
+ }
54
+ const indexPage = getPage('index').replace(/^\/+/, '');
55
+ const loginPage = getPage('login');
56
+ const { isLogin } = useLoginStore(pinia);
57
+ const { route = indexPage, options = {} } = (getCurrentPages().pop() || {});
58
+ const current = `/${route}${queryParams(options)}`;
59
+ let absoUrl = getAbsoUrl(url, current);
60
+ let originalUrl = url;
61
+ url = navigate.interceptor.call(this, url, absoUrl);
62
+ if (typeof url !== 'string') {
63
+ throttling = false;
64
+ return;
65
+ }
66
+ if (originalUrl !== url) {
67
+ originalUrl = url;
68
+ absoUrl = getAbsoUrl(url, current);
69
+ }
70
+ if (!originalUrl) {
71
+ if (isLogin) {
72
+ throttling = false;
73
+ return;
74
+ }
75
+ // 跳转地址为空表示需要登�?
76
+ needLogin = true;
77
+ }
78
+ // 路径转为绝对路径
79
+ url = absoUrl;
80
+ // 是否需要登�?
81
+ if (!needLogin) {
82
+ needLogin = inPages(page.needLoginPages, url);
83
+ }
84
+ // 是否是原生页�?
85
+ if (!isNative && url.startsWith('/')) {
86
+ isNative = inPages(page.nativePages, url);
87
+ }
88
+ if (!isNative) {
89
+ if (!checkProtocolMatch(url)) {
90
+ if (app?.code) {
91
+ url = `${app.code}:/${url}`;
92
+ }
93
+ else if (app?.appId) {
94
+ url = `${app.appId}:/${url}`;
95
+ }
96
+ }
97
+ }
98
+ else if (IS_WEBVIEW_ENV && opts['native'] === false) {
99
+ isNative = false;
100
+ }
101
+ const protocolMatch = checkProtocolMatch(url);
102
+ // 带协议路径需要转换为webview方式加载
103
+ if (protocolMatch) {
104
+ isNative = true;
105
+ const params = Object.assign({}, webviewParams);
106
+ if (/^https?:/.test(url)) {
107
+ // #ifdef H5
108
+ // 一些网站同源策略,无法iframe中打开
109
+ if ((WEBVIEW_ENV.h5 || !IS_WEBVIEW_ENV) && ['mp.weixin.qq.com'].includes(new URL(url).hostname)) {
110
+ top.location.href = url;
111
+ return false;
112
+ }
113
+ // #endif
114
+ // http协议
115
+ Object.assign(params, { url: encodeURIComponent(url) });
116
+ }
117
+ else {
118
+ // 自定义协�?
119
+ url = url.replace(new RegExp(`^(${protocolMatch[0]})`), '');
120
+ Object.assign(params, { url: encodeURIComponent(url), app: protocolMatch[1] });
121
+ }
122
+ url = `${webviewPage}${queryParams(params)}`;
123
+ }
124
+ if (needLogin) {
125
+ if (!isLogin) {
126
+ const opts = {
127
+ url: loginPage,
128
+ };
129
+ if (referrerType === 'combine') {
130
+ // 登录后会先跳转到来源页面,再跳转目标页面
131
+ if (url !== current) {
132
+ url = `/${route}${queryParams({ ...options, __navigate: encodeURIComponent(url) })}`;
133
+ }
134
+ }
135
+ else if (referrerType === 'referrer') {
136
+ // 登录后跳转到来源页面
137
+ url = current;
138
+ }
139
+ else if (referrerType === 'target') {
140
+ // 登录后跳转到目标页面
141
+ }
142
+ if (['target', 'referrer', 'combine'].includes(referrerType)) {
143
+ opts.url += `${opts.url.includes('?') ? '&' : '?'}__referrer=${encodeURIComponent(url)}`;
144
+ }
145
+ if (uni.webView && IS_WEBVIEW_ENV) {
146
+ uni.webView[loginType](opts);
147
+ }
148
+ else {
149
+ uni[loginType](opts);
150
+ }
151
+ return false;
152
+ }
153
+ }
154
+ if (originalUrl) {
155
+ if (inPages(page.tabBarPages, url)) {
156
+ if (['navigateTo', 'redirectTo'].includes(type)) {
157
+ type = 'switchTab';
158
+ }
159
+ }
160
+ if (isNative && uni.webView && IS_WEBVIEW_ENV) {
161
+ uni.webView[type]({
162
+ url,
163
+ });
164
+ }
165
+ else {
166
+ uni[type]({
167
+ url,
168
+ ...navigateOptions,
169
+ });
170
+ }
171
+ }
172
+ }
173
+ };
174
+ navigate.reLaunch = (url) => {
175
+ navigate(url, 'reLaunch');
176
+ };
177
+ navigate.navigateTo = (url) => {
178
+ navigate(url, 'navigateTo');
179
+ };
180
+ navigate.switchTab = (url) => {
181
+ navigate(url, 'switchTab');
182
+ };
183
+ navigate.redirectTo = (url) => {
184
+ navigate(url, 'redirectTo');
185
+ };
186
+ navigate.back = (e) => {
187
+ uni.navigateBack(e);
188
+ };
189
+ navigate.interceptor = (...args) => {
190
+ return args[0];
191
+ };
192
+ export default navigate;
@@ -0,0 +1,21 @@
1
+ export declare const getPage: (name: string) => string;
2
+ export declare const inPages: (pages: string[], url: string | {
3
+ url: string;
4
+ [key: string]: any;
5
+ }) => boolean;
6
+ export declare const createPages: (original?: {
7
+ pages?: any[];
8
+ subPackages?: any[];
9
+ tabBar?: any;
10
+ global?: {
11
+ native?: boolean;
12
+ needLogin?: boolean;
13
+ notRedirect?: boolean;
14
+ };
15
+ }, basePath?: string) => {
16
+ pages: string[];
17
+ tabBarPages: string[];
18
+ nativePages: string[];
19
+ needLoginPages: string[];
20
+ notRedirectPages: string[];
21
+ };
@@ -0,0 +1,83 @@
1
+ import path from '../configs/path';
2
+ export const getPage = (name) => {
3
+ let page = '';
4
+ if (path[name]) {
5
+ page = path[name];
6
+ }
7
+ return page;
8
+ };
9
+ export const inPages = (pages, url) => {
10
+ if (typeof url === 'object') {
11
+ url = url.url;
12
+ }
13
+ if (!Array.isArray(pages) || !url || typeof url !== 'string') {
14
+ return false;
15
+ }
16
+ return pages.some((page) => {
17
+ page = String(page);
18
+ const [path] = page.split('**');
19
+ if (path !== page) {
20
+ return url.startsWith(path);
21
+ }
22
+ return url.replace(/\?.*$/, '') === path;
23
+ });
24
+ };
25
+ export const createPages = (original = {}, basePath = '') => {
26
+ const pages = [];
27
+ const tabBarPages = [];
28
+ const nativePages = [];
29
+ const needLoginPages = [];
30
+ const notRedirectPages = [];
31
+ const create = ({ path: p, root, ...rest }) => {
32
+ if (p) {
33
+ const { native, needLogin, notRedirect } = { ...original.global, ...rest };
34
+ const { name } = rest;
35
+ const array = [''];
36
+ if (basePath) {
37
+ array.push(basePath);
38
+ }
39
+ if (root && basePath !== `/${root}`) {
40
+ array.push(root);
41
+ }
42
+ array.push(p);
43
+ const page = array.join('/').replace(/\/+/, '/');
44
+ pages.push(page);
45
+ if (name) {
46
+ path[name] = page;
47
+ }
48
+ if (native || native == null) {
49
+ nativePages.push(page);
50
+ }
51
+ if (needLogin) {
52
+ needLoginPages.push(page);
53
+ }
54
+ if (notRedirect) {
55
+ notRedirectPages.push(page);
56
+ }
57
+ }
58
+ };
59
+ if (original.pages) {
60
+ original.pages.forEach((page) => {
61
+ create(page);
62
+ });
63
+ }
64
+ if (original.subPackages) {
65
+ original.subPackages.forEach(({ root, pages: list }) => {
66
+ list.forEach((page) => {
67
+ create(Object.assign(page, { root }));
68
+ });
69
+ });
70
+ }
71
+ if (original.tabBar && original.tabBar.list) {
72
+ original.tabBar.list.forEach(({ pagePath }) => {
73
+ tabBarPages.push(`/${pagePath}`);
74
+ });
75
+ }
76
+ return {
77
+ pages,
78
+ tabBarPages,
79
+ nativePages,
80
+ needLoginPages,
81
+ notRedirectPages,
82
+ };
83
+ };
@@ -0,0 +1,17 @@
1
+ type PermissionName = 'location' | 'storage' | 'camera' | 'record' | 'bluetooth';
2
+ /**
3
+ * 打开权限设置
4
+ * - 经典 App:plus 打开系统设置页(定位 / 蓝牙总开关)
5
+ * - uni-app x App:uni.openAppAuthorizeSetting 打开应用授权设置页
6
+ * - H5 webview:向宿主发送消息
7
+ * - 小程序:uni.openAppAuthorizeSetting
8
+ */
9
+ export declare function openAuthorizeSetting(name: string): void;
10
+ /**
11
+ * 申请权限
12
+ * @param name 权限名称
13
+ * @param system 是否同时检查定位 / 蓝牙的系统级开关
14
+ * @returns 允许时 resolve(1);未授权或系统开关关闭时 reject(0)
15
+ */
16
+ export declare function requestPermission(name: PermissionName, system?: boolean): Promise<number>;
17
+ export {};
@@ -0,0 +1,278 @@
1
+ /**
2
+ * 权限申请
3
+ * - 经典 App(APP-PLUS):plus.android.requestPermissions(Android)+ uni.getSystemSetting
4
+ * - uni-app x App(APP + UNI-APP-X):uni.requestSystemPermission(Android 5.25+)+ uni.getSystemSetting
5
+ * - 小程序:uni.authorize / uni.openSetting
6
+ * - H5:webview 内通过 postMessage 通知宿主
7
+ */
8
+ import { config } from '@zfqh/uview-x';
9
+ import { SYSTEM_INFO, IS_WEBVIEW_ENV, TYPES } from './consts';
10
+ import { postMessage } from './index';
11
+ const permissionData = {
12
+ location: {
13
+ // #ifdef APP
14
+ system: '检测到系统未开启定位',
15
+ // #endif
16
+ content: '我们需要获取您的定位权限,用于城市定位、地址获取、位置获取,发现附近设备等服务',
17
+ },
18
+ storage: {
19
+ // #ifdef APP
20
+ system: '',
21
+ // #endif
22
+ content: '我们需要获取您的文件存储权限,用于设置头像、保存图片、上传文件、发布内容等服务',
23
+ },
24
+ camera: {
25
+ // #ifdef APP
26
+ system: '',
27
+ // #endif
28
+ content: '我们需要获取您的相机权限,用于拍摄照片、录制视频、视频通话、扫码识别、发布内容等服务',
29
+ },
30
+ record: {
31
+ // #ifdef APP
32
+ system: '',
33
+ // #endif
34
+ content: '我们需要获取您的麦克风权限,用于录制语音、语音通话,发布内容等服务',
35
+ },
36
+ bluetooth: {
37
+ // #ifdef APP
38
+ system: '检测到系统未开启蓝牙',
39
+ // #endif
40
+ content: '我们需要获取您的蓝牙权限,用于数据传输、设备配对、发现附近设备等服务',
41
+ },
42
+ };
43
+ // #ifdef APP
44
+ // Android 系统 API 版本:蓝牙、存储在 Android 10 / 12 以上需要的权限不同
45
+ const ANDROID_API_LEVEL = Number(uni.getSystemInfoSync().osAndroidAPILevel) || 0;
46
+ // #ifdef APP-PLUS
47
+ const CLASSIC_ANDROID_PERMISSIONS = {
48
+ location: ['android.permission.ACCESS_FINE_LOCATION'],
49
+ storage: ['android.permission.WRITE_EXTERNAL_STORAGE'],
50
+ camera: ['android.permission.CAMERA'],
51
+ record: ['android.permission.RECORD_AUDIO'],
52
+ bluetooth: ANDROID_API_LEVEL >= 31
53
+ ? ['android.permission.BLUETOOTH_SCAN', 'android.permission.BLUETOOTH_CONNECT']
54
+ : ['android.permission.BLUETOOTH'],
55
+ };
56
+ // #endif
57
+ // #ifdef UNI-APP-X
58
+ const UNI_APP_X_ANDROID_PERMISSIONS = {
59
+ location: ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION'],
60
+ // Android 10+ 使用分区存储,无需申请 WRITE_EXTERNAL_STORAGE
61
+ storage: ANDROID_API_LEVEL < 29 ? ['android.permission.WRITE_EXTERNAL_STORAGE'] : [],
62
+ camera: ['android.permission.CAMERA'],
63
+ record: ['android.permission.RECORD_AUDIO'],
64
+ bluetooth: ANDROID_API_LEVEL >= 31
65
+ ? ['android.permission.BLUETOOTH_SCAN', 'android.permission.BLUETOOTH_CONNECT']
66
+ : ['android.permission.BLUETOOTH'],
67
+ };
68
+ // #endif
69
+ // #endif
70
+ // #ifdef APP-PLUS
71
+ const requestAndroidPermission = async (name) => {
72
+ const permissions = CLASSIC_ANDROID_PERMISSIONS[name];
73
+ if (!permissions.length) {
74
+ return 1;
75
+ }
76
+ uni.showAppFromBackground = false;
77
+ return await new Promise((resolve) => {
78
+ plus.android.requestPermissions(permissions, (result) => {
79
+ if (result.deniedAlways?.length) {
80
+ resolve(-1);
81
+ }
82
+ else if (result.deniedPresent?.length) {
83
+ resolve(0);
84
+ }
85
+ else {
86
+ resolve(1);
87
+ }
88
+ },
89
+ // 申请失败时无法预判,交给实际能力调用时系统弹窗
90
+ () => resolve(1));
91
+ });
92
+ };
93
+ // #endif
94
+ // #ifdef APP
95
+ // #ifdef UNI-APP-X
96
+ const requestUniAppXPermission = async (name) => {
97
+ // #ifdef APP-ANDROID
98
+ if (typeof uni.requestSystemPermission === 'function') {
99
+ const permissions = UNI_APP_X_ANDROID_PERMISSIONS[name];
100
+ if (permissions.length) {
101
+ uni.showAppFromBackground = false;
102
+ return await new Promise((resolve) => {
103
+ uni.requestSystemPermission({
104
+ permissions,
105
+ success: (result) => {
106
+ if (result.doNotAskAgainList.length) {
107
+ resolve(-1);
108
+ }
109
+ else if (result.deniedList.length) {
110
+ resolve(0);
111
+ }
112
+ else {
113
+ resolve(1);
114
+ }
115
+ },
116
+ // 无法预申请(低版本、权限未声明等)时交给实际能力调用时系统弹窗
117
+ fail: () => resolve(1),
118
+ });
119
+ });
120
+ }
121
+ }
122
+ // #endif
123
+ return 1;
124
+ };
125
+ // #endif
126
+ // #endif
127
+ // #ifdef MP
128
+ const requestMpPermission = async (scope) => {
129
+ return await new Promise((res) => {
130
+ uni.authorize({
131
+ scope,
132
+ success() {
133
+ res(1);
134
+ },
135
+ fail() {
136
+ res(0);
137
+ },
138
+ });
139
+ });
140
+ };
141
+ // #endif
142
+ // 系统级开关:经典 App 与 uni-app x App 统一使用官方 uni.getSystemSetting
143
+ const isSystemEnabled = (name) => {
144
+ // #ifdef APP
145
+ const setting = uni.getSystemSetting();
146
+ if (name === 'location') {
147
+ // iOS 模块未配置时 locationError 非空,不阻塞业务
148
+ return !!setting.locationError || setting.locationEnabled;
149
+ }
150
+ if (name === 'bluetooth') {
151
+ // iOS 与经典 App 保持一致交给系统;Android 权限或模块配置错误不误导用户去设置
152
+ return SYSTEM_INFO.platform === 'ios' || !!setting.bluetoothError || setting.bluetoothEnabled !== false;
153
+ }
154
+ // #endif
155
+ return true;
156
+ };
157
+ /**
158
+ * 打开权限设置
159
+ * - 经典 App:plus 打开系统设置页(定位 / 蓝牙总开关)
160
+ * - uni-app x App:uni.openAppAuthorizeSetting 打开应用授权设置页
161
+ * - H5 webview:向宿主发送消息
162
+ * - 小程序:uni.openAppAuthorizeSetting
163
+ */
164
+ export function openAuthorizeSetting(name) {
165
+ // #ifdef H5
166
+ if (IS_WEBVIEW_ENV) {
167
+ postMessage({
168
+ type: name === 'location' ? TYPES.MESSAGE.PERM_LOCATION : TYPES.MESSAGE.PERM_BLUETOOTH,
169
+ payload: { name },
170
+ });
171
+ }
172
+ // #endif
173
+ // #ifdef APP-PLUS
174
+ if (SYSTEM_INFO.platform == 'ios') {
175
+ plus.runtime.openURL('app-settings://');
176
+ }
177
+ else {
178
+ const main = plus.android.runtimeMainActivity();
179
+ const Intent = plus.android.importClass('android.content.Intent');
180
+ const Settings = plus.android.importClass('android.provider.Settings');
181
+ let intent = null;
182
+ if (name === 'location') {
183
+ intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
184
+ }
185
+ else if (name === 'bluetooth') {
186
+ intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
187
+ }
188
+ if (intent) {
189
+ main.startActivity(intent);
190
+ }
191
+ }
192
+ // #endif
193
+ // #ifdef APP
194
+ // #ifdef UNI-APP-X
195
+ if (typeof uni.openAppAuthorizeSetting === 'function') {
196
+ uni.openAppAuthorizeSetting({});
197
+ }
198
+ // #endif
199
+ // #endif
200
+ // #ifdef MP
201
+ uni.openAppAuthorizeSetting();
202
+ // #endif
203
+ }
204
+ /**
205
+ * 申请权限
206
+ * @param name 权限名称
207
+ * @param system 是否同时检查定位 / 蓝牙的系统级开关
208
+ * @returns 允许时 resolve(1);未授权或系统开关关闭时 reject(0)
209
+ */
210
+ export async function requestPermission(name, system = true) {
211
+ let result = 1;
212
+ // #ifdef MP
213
+ switch (name) {
214
+ case 'location': {
215
+ result = await requestMpPermission('scope.userLocation');
216
+ break;
217
+ }
218
+ case 'storage': {
219
+ break;
220
+ }
221
+ default: {
222
+ result = await requestMpPermission(`scope.${name}`);
223
+ }
224
+ }
225
+ // #endif
226
+ // #ifdef APP-PLUS
227
+ if (SYSTEM_INFO.platform === 'android') {
228
+ result = await requestAndroidPermission(name);
229
+ }
230
+ // #endif
231
+ // #ifdef APP
232
+ // #ifdef UNI-APP-X
233
+ result = await requestUniAppXPermission(name);
234
+ // #endif
235
+ // #endif
236
+ if (system && result > 0 && !isSystemEnabled(name)) {
237
+ result = -2;
238
+ }
239
+ if (result <= 0) {
240
+ const { content, system: systemTips } = permissionData[name];
241
+ uni.showModal({
242
+ title: '提示',
243
+ content: `${result === -2 ? systemTips : `${content},检测到应用未开启权限`},是否开启?`,
244
+ confirmText: '去开启',
245
+ cancelText: '取消',
246
+ confirmColor: config.color.primary,
247
+ cancelColor: config.color.tipsColor,
248
+ success: (res) => {
249
+ if (res.confirm) {
250
+ try {
251
+ // #ifdef MP
252
+ uni.openSetting();
253
+ // #endif
254
+ // #ifdef APP-PLUS
255
+ uni.showAppFromBackground = false;
256
+ // app开启权限,系统没有开启
257
+ if (result === -2) {
258
+ openAuthorizeSetting(name);
259
+ // 系统开启权限,app没有开启
260
+ }
261
+ else {
262
+ uni.openAppAuthorizeSetting();
263
+ }
264
+ // #endif
265
+ // #ifdef APP
266
+ // #ifdef UNI-APP-X
267
+ openAuthorizeSetting(name);
268
+ // #endif
269
+ // #endif
270
+ }
271
+ catch (e) { }
272
+ }
273
+ },
274
+ });
275
+ return Promise.reject(0);
276
+ }
277
+ return Promise.resolve(1);
278
+ }
@@ -0,0 +1,20 @@
1
+ interface Query {
2
+ platform?: string;
3
+ channel?: string;
4
+ token?: string;
5
+ accessToken?: string;
6
+ primary?: string;
7
+ app?: string;
8
+ safeTop?: string | number;
9
+ safeBottom?: string | number;
10
+ tabbar?: string | number;
11
+ accelerate?: string | number;
12
+ [key: string]: any;
13
+ }
14
+ declare const query: Query;
15
+ export declare function parseQuery(search?: string): Query;
16
+ /** 将对象序列化为 query string(供 webview 参数拼装使用,避免依赖 qs)。 */
17
+ export declare function stringifyQuery(data: Record<string, any>, options?: {
18
+ encode?: boolean;
19
+ }): string;
20
+ export default query;
@@ -0,0 +1,51 @@
1
+ const query = {};
2
+ export function parseQuery(search = '') {
3
+ const q = {};
4
+ search.split('&').forEach((value) => {
5
+ if (!value)
6
+ return;
7
+ const [key, val] = value.split('=');
8
+ q[key] = decodeURIComponent(val);
9
+ });
10
+ return q;
11
+ }
12
+ /** 将对象序列化为 query string(供 webview 参数拼装使用,避免依赖 qs)。 */
13
+ export function stringifyQuery(data, options = {}) {
14
+ const shouldEncode = options.encode !== false;
15
+ const parts = [];
16
+ const append = (key, value) => {
17
+ if (value === undefined || value === null)
18
+ return;
19
+ const k = shouldEncode ? encodeURIComponent(key) : key;
20
+ const v = shouldEncode ? encodeURIComponent(String(value)) : String(value);
21
+ parts.push(`${k}=${v}`);
22
+ };
23
+ Object.keys(data || {}).forEach((key) => {
24
+ const value = data[key];
25
+ if (Array.isArray(value)) {
26
+ value.forEach((item) => append(key, item));
27
+ }
28
+ else {
29
+ append(key, value);
30
+ }
31
+ });
32
+ return parts.join('&');
33
+ }
34
+ // #ifdef H5
35
+ Object.assign(query, parseQuery(location.search.substring(1)));
36
+ const safeTop = Number(query.safeTop);
37
+ const safeBottom = Number(query.safeBottom);
38
+ if (safeTop > 0) {
39
+ query.safeTop = safeTop;
40
+ }
41
+ else {
42
+ query.safeTop = 0;
43
+ }
44
+ if (safeBottom > 0) {
45
+ query.safeBottom = safeBottom;
46
+ }
47
+ else {
48
+ query.safeBottom = 0;
49
+ }
50
+ // #endif
51
+ export default query;
@@ -0,0 +1,8 @@
1
+ export declare function formatURL(url: any, data: any): string;
2
+ export declare function createInterceptors(req: any): void;
3
+ export declare function createRequest(req: any, _opts?: any): {
4
+ GET: (url: string, data?: {}, options?: {}) => any;
5
+ DELETE: (url: string, data?: {}, options?: {}) => any;
6
+ POST: (url: string, data?: {}, options?: {}) => any;
7
+ PUT: (url: string, data?: {}, options?: {}) => any;
8
+ };