@zfqh/uniapp 0.2.10 → 0.2.14

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.
@@ -1,376 +1,170 @@
1
- import color from '../configs/color';
2
- import update from '../configs/update';
3
- import ver from '../configs/ver';
4
1
  import app from '../configs/app';
5
- import { SYSTEM_INFO } from './consts';
6
- // 防止弹窗多次弹出
7
- let visibleModal = false;
8
- function showModal(options) {
9
- uni.showModal({
10
- title: '更新提示',
11
- content: options?.content || '检测到新版本,下载并重启应用?',
12
- confirmColor: color.primary,
13
- showCancel: options?.showCancel,
14
- fail() {
15
- visibleModal = false;
16
- },
17
- success(res) {
18
- if (res.confirm) {
19
- options?.confirm && options.confirm();
20
- }
21
- else {
22
- visibleModal = false;
23
- }
24
- },
25
- });
26
- }
2
+ import env from '../configs/env';
3
+ import ver from '../configs/ver';
4
+ import { SYSTEM_INFO, IS_WEBVIEW_ENV, TYPES } from './consts';
5
+ import { postMessage } from './index';
6
+ import { getLastVersion } from '../apis/core';
7
+ const { platform, brand } = SYSTEM_INFO;
8
+ let _installMessageHandler = null;
27
9
  // #ifdef APP
28
- function appFileDownload(url, restart = true) {
29
- let downloaded = false;
30
- const showWaiting = plus.nativeUI.showWaiting('下载中...');
31
- const downloadTask = uni.downloadFile({
32
- url,
33
- success(downloadResult) {
34
- if (downloadResult.statusCode === 200) {
35
- showWaiting.setTitle('安装中...');
36
- setTimeout(() => {
37
- plus.runtime.install(downloadResult.tempFilePath, {
38
- force: true,
39
- }, () => {
40
- plus.nativeUI.closeWaiting();
41
- if (restart) {
42
- visibleModal = false;
43
- uni.showModal({
44
- title: '提示',
45
- content: '应用更新完成',
46
- showCancel: false,
47
- confirmText: '重启应用',
48
- confirmColor: color.primary,
49
- success() {
50
- plus.runtime.restart();
51
- },
52
- });
53
- }
54
- });
55
- }, 500);
56
- }
57
- else {
58
- visibleModal = false;
59
- plus.nativeUI.alert('更新失败');
60
- plus.nativeUI.closeWaiting();
61
- }
62
- },
63
- fail() {
64
- visibleModal = false;
65
- plus.nativeUI.closeWaiting();
66
- },
67
- });
68
- downloadTask.onProgressUpdate(({ progress }) => {
69
- if (!downloaded) {
70
- showWaiting.setTitle('下载中...' + progress + '%');
71
- if (progress === 100) {
72
- downloaded = true;
73
- }
10
+ function appGetProperty(appid) {
11
+ return new Promise((resolve) => {
12
+ if (appid === app.appId) {
13
+ plus.runtime.getProperty(String(plus.runtime.appid), (res) => resolve(res));
74
14
  }
75
- });
76
- }
77
- function checkAppUpdate(immediate = false) {
78
- return new Promise((resolve, reject) => {
79
- plus.runtime.getProperty(plus.runtime.appid, async ({ versionCode, version: versionName }) => {
80
- try {
81
- const { platform, appName, appId, appVersion: appVersionName, appVersionCode } = SYSTEM_INFO;
82
- const params = {
83
- appId: app.appId || appId,
84
- appName: app.name || appName,
85
- versionCode: Number(ver.code || versionCode),
86
- versionName: ver.name || versionName,
87
- appVersionCode: Number(appVersionCode),
88
- appVersionName,
89
- platform,
90
- };
91
- const data = await update.request(params);
92
- if (data) {
93
- let url = '';
94
- if (data.hot_update == 1) {
95
- url = data.wgt_url;
96
- }
97
- else {
98
- if (platform === 'android') {
99
- url = data.apk_url;
100
- }
101
- else if (platform === 'ios') {
102
- url = data.ipa_url;
15
+ else {
16
+ plus.io.resolveLocalFileSystemURL(`_doc/${appid}/manifest.json`, (entry) => {
17
+ entry.file((file) => {
18
+ const reader = new plus.io.FileReader();
19
+ reader.onloadend = (e) => {
20
+ try {
21
+ resolve(JSON.parse(e.target.result));
103
22
  }
104
- }
105
- if (url) {
106
- resolve();
107
- if (!visibleModal) {
108
- visibleModal = true;
109
- if (data.hot_update == 1) {
110
- // 热更新
111
- if (immediate) {
112
- appFileDownload(url);
113
- }
114
- else {
115
- showModal({
116
- showCancel: !data.force_update,
117
- confirm() {
118
- appFileDownload(url);
119
- },
120
- });
121
- }
122
- }
123
- else {
124
- // 整包更新
125
- if (params.platform == 'android') {
126
- if (immediate) {
127
- if (data.external_install) {
128
- plus.runtime.openURL(url);
129
- }
130
- else {
131
- appFileDownload(url, false);
132
- }
133
- }
134
- else {
135
- showModal({
136
- showCancel: !data.force_update,
137
- confirm() {
138
- if (data.external_install) {
139
- plus.runtime.openURL(url);
140
- }
141
- else {
142
- appFileDownload(url, false);
143
- }
144
- },
145
- });
146
- }
147
- }
148
- else if (params.platform == 'ios') {
149
- showModal({
150
- content: '检测到新版本,前往应用市场更新?',
151
- confirm() {
152
- plus.runtime.openURL(url);
153
- },
154
- });
155
- }
156
- }
23
+ catch {
24
+ resolve({});
157
25
  }
158
- }
159
- else {
160
- reject();
161
- }
162
- }
163
- else {
164
- reject();
165
- }
166
- }
167
- catch (e) {
168
- reject(e);
169
- }
170
- });
26
+ };
27
+ reader.readAsText(file);
28
+ }, () => resolve({}));
29
+ }, () => resolve({}));
30
+ }
171
31
  });
172
32
  }
173
33
  // #endif
174
34
  // #ifdef H5
175
- function fileDownload(url, restart = true) {
176
- const ipcRenderer = window['electron'].ipcRenderer;
177
- ipcRenderer.send('update', url);
178
- function updateDownload() {
179
- uni.showLoading({
180
- title: '下载中...',
181
- mask: true,
182
- });
183
- }
184
- function uploadProgress(e, progress) {
185
- uni.showLoading({
186
- title: `下载中...${progress}%`,
187
- mask: true,
35
+ function h5GetProperty(appid) {
36
+ return new Promise((resolve) => {
37
+ if (appid === app.appId) {
38
+ resolve({ version: ver.name, versionCode: ver.code });
39
+ }
40
+ else if (window.electron) {
41
+ window.electron.webUtils.getProperty(appid, (manifest) => resolve(manifest || {}));
42
+ }
43
+ });
44
+ }
45
+ // #endif
46
+ export async function checkVersion(appid) {
47
+ try {
48
+ let version = 0;
49
+ let packageName = appid;
50
+ let data = null;
51
+ // #ifdef APP
52
+ data = await appGetProperty(appid);
53
+ version = data.versionCode || 0;
54
+ // #endif
55
+ // #ifdef H5
56
+ data = await h5GetProperty(appid);
57
+ version = data.versionCode || 0;
58
+ // #endif
59
+ let type = 1;
60
+ // #ifdef H5
61
+ if (IS_WEBVIEW_ENV) {
62
+ type = 3;
63
+ }
64
+ // #endif
65
+ const res = await getLastVersion({
66
+ version,
67
+ packageName,
68
+ type,
69
+ platform: { android: 1, ios: 2, windows: 4 }[platform],
188
70
  });
189
- }
190
- function updateSuccess() {
191
- if (restart) {
192
- uni.showModal({
193
- title: '提示',
194
- content: '应用更新完成',
195
- showCancel: false,
196
- confirmText: '重启应用',
197
- confirmColor: color.primary,
198
- success() {
199
- ipcRenderer.send('relaunch');
200
- },
201
- });
71
+ const lastVer = { ...res?.data };
72
+ // #ifdef APP
73
+ if (uni.$store.state.dict && platform === 'android' && appid === app.appId && env.key === 'prod') {
74
+ await uni.$store.dispatch('getDictInfo', { name: 'group_relation', cache: true });
75
+ if (uni.$store.state.dict.info.group_relation?.values?.includes(brand)) {
76
+ lastVer.hotUpdateUrl = '';
77
+ }
202
78
  }
79
+ // #endif
80
+ if (lastVer.status > 2 && Number(lastVer.version) > Number(version)) {
81
+ return lastVer;
82
+ }
83
+ return null;
203
84
  }
204
- function updateFail() {
205
- setTimeout(() => {
206
- uni.showToast({
207
- title: '更新失败',
208
- icon: 'error',
209
- duration: 2000,
210
- });
211
- }, 300);
212
- }
213
- function updateComplete() {
214
- visibleModal = false;
215
- uni.hideLoading();
216
- ipcRenderer.removeListener('update-download', updateDownload);
217
- ipcRenderer.removeListener('update-progress', uploadProgress);
218
- ipcRenderer.removeListener('update-success', updateSuccess);
219
- ipcRenderer.removeListener('update-fail', updateFail);
85
+ catch {
86
+ return null;
220
87
  }
221
- ipcRenderer.on('update-download', updateDownload);
222
- ipcRenderer.on('update-progress', uploadProgress);
223
- ipcRenderer.on('update-success', updateSuccess);
224
- ipcRenderer.on('update-fail', updateFail);
225
- ipcRenderer.once('update-complete', updateComplete);
226
88
  }
227
- async function checkUpdate(immediate = false) {
228
- return new Promise((resolve, reject) => {
229
- const { platform, appName, appId, appVersion: versionName, appVersionCode: versionCode } = SYSTEM_INFO;
230
- const params = {
231
- appId: app.appId || appId,
232
- appName: app.name || appName,
233
- versionCode: Number(ver.code || versionCode),
234
- versionName: ver.name || versionName,
235
- appVersionCode: Number(window['versionCode'] || versionCode),
236
- appVersionName: window['versionName'] || versionName,
237
- platform: window['platform'] || platform,
238
- };
239
- update
240
- .request(params)
241
- .then((data) => {
242
- if (data) {
243
- let url = '';
244
- if (data.hot_update == 1) {
245
- url = data.zip_url;
246
- }
247
- else {
248
- if (params.platform === 'windows') {
249
- url = data.exe_url;
250
- }
251
- else if (params.platform === 'macos') {
252
- url = data.dmg_url;
253
- }
254
- }
255
- if (url) {
256
- resolve();
257
- if (!visibleModal) {
258
- visibleModal = true;
259
- if (data.hot_update == 1) {
260
- // 热更新
261
- if (immediate) {
262
- fileDownload(url);
263
- }
264
- else {
265
- showModal({
266
- showCancel: !data.force_update,
267
- confirm() {
268
- fileDownload(url);
269
- },
270
- });
271
- }
272
- }
273
- else {
274
- // 整包更新
275
- if (immediate) {
276
- fileDownload(url, false);
277
- }
278
- else {
279
- showModal({
280
- showCancel: !data.force_update,
281
- confirm() {
282
- fileDownload(url, false);
283
- },
284
- });
285
- }
286
- }
287
- }
288
- }
289
- else {
290
- reject();
291
- }
89
+ // #ifdef APP
90
+ function appInstall({ appid, url, progress, success, fail }) {
91
+ const downloadTask = uni.downloadFile({
92
+ url,
93
+ success(res) {
94
+ if (res.statusCode !== 200)
95
+ return fail?.({ message: 'download failed' });
96
+ progress?.(100);
97
+ if (appid === app.appId) {
98
+ plus.runtime.install(res.tempFilePath, { force: true }, success, fail);
292
99
  }
293
100
  else {
294
- reject();
101
+ plus.io.resolveLocalFileSystemURL('_doc/', (docDir) => {
102
+ plus.zip.decompress(res.tempFilePath, docDir.fullPath, success, () => {
103
+ plus.zip.decompress(res.tempFilePath, docDir.fullPath, success, fail);
104
+ });
105
+ }, (e) => fail?.({ message: e?.message || String(e) }));
295
106
  }
296
- })
297
- .catch((e) => {
298
- reject(e);
299
- });
107
+ },
108
+ fail: (e) => fail?.({ message: e?.errMsg || String(e) }),
300
109
  });
110
+ downloadTask.onProgressUpdate(({ progress: p }) => progress?.(p));
301
111
  }
302
112
  // #endif
303
- // #ifdef MP
304
- function mpDownload(updateManager) {
305
- uni.showLoading({ title: '更新中...' });
306
- updateManager.onUpdateReady(() => {
307
- uni.hideLoading();
308
- setTimeout(() => {
309
- visibleModal = false;
310
- updateManager.applyUpdate();
311
- }, 300);
312
- });
313
- updateManager.onUpdateFailed(() => {
314
- visibleModal = false;
315
- uni.hideLoading();
316
- uni.showModal({
317
- title: '更新失败',
318
- content: `请您删除当前小程序,并搜索“${app.name || SYSTEM_INFO.appName}”重新打开应用`,
319
- confirmColor: color.primary,
113
+ // #ifdef H5
114
+ function h5Install(options) {
115
+ if (IS_WEBVIEW_ENV) {
116
+ postMessage({
117
+ type: TYPES.MESSAGE.APP_INSTALL,
118
+ payload: {
119
+ appid: options.appid,
120
+ url: options.url,
121
+ },
320
122
  });
321
- });
322
- }
323
- function checkMpUpdate(immediate = false) {
324
- return new Promise((resolve, reject) => {
325
- if (uni.canIUse('getUpdateManager')) {
326
- const updateManager = uni.getUpdateManager();
327
- updateManager.onCheckForUpdate((e) => {
328
- if (e.hasUpdate) {
329
- visibleModal = true;
330
- resolve();
331
- if (immediate) {
332
- mpDownload(updateManager);
333
- }
334
- else {
335
- showModal({
336
- confirm() {
337
- mpDownload(updateManager);
338
- },
339
- });
340
- }
123
+ if (_installMessageHandler) {
124
+ uni.$off(TYPES.MESSAGE.WEBVIEW_MESSAGE, _installMessageHandler);
125
+ _installMessageHandler = null;
126
+ }
127
+ _installMessageHandler = (e) => {
128
+ if (e?.type === TYPES.MESSAGE.APP_INSTALL) {
129
+ if (e.payload?.progress != null) {
130
+ options.progress?.(e.payload.progress);
131
+ }
132
+ else if (e.payload?.success) {
133
+ options.success?.();
341
134
  }
342
135
  else {
343
- reject();
136
+ options.fail?.({ message: e.payload.message });
344
137
  }
345
- });
346
- }
347
- else {
348
- reject();
349
- }
350
- });
138
+ }
139
+ };
140
+ uni.$on(TYPES.MESSAGE.WEBVIEW_MESSAGE, _installMessageHandler);
141
+ }
142
+ else if (window.electron) {
143
+ window.electron.webUtils.updateApp(options);
144
+ }
351
145
  }
352
146
  // #endif
353
- /**
354
- * 检测更新
355
- * @param immediate 是否立即更新,不显示确认框
356
- */
357
- function check(immediate = false) {
358
- let res = Promise.resolve();
359
- if (!visibleModal) {
360
- // #ifdef H5
361
- if (typeof window['electron'] === 'object') {
362
- res = checkUpdate(immediate);
363
- }
364
- // #endif
365
- // #ifdef APP
366
- res = checkAppUpdate(immediate);
367
- // #endif
368
- // #ifdef MP
369
- res = checkMpUpdate(immediate);
370
- // #endif
147
+ export function installUpdate(options) {
148
+ // #ifdef H5
149
+ h5Install(options);
150
+ // #endif
151
+ // #ifdef APP
152
+ appInstall(options);
153
+ // #endif
154
+ }
155
+ export function restartApp() {
156
+ // #ifdef H5
157
+ if (IS_WEBVIEW_ENV) {
158
+ postMessage({
159
+ type: TYPES.MESSAGE.APP_RESTART,
160
+ payload: {},
161
+ });
162
+ }
163
+ else if (window.electron) {
164
+ window.electron.ipcRenderer.send('relaunch');
371
165
  }
372
- return res;
166
+ // #endif
167
+ // #ifdef APP
168
+ plus.runtime.restart();
169
+ // #endif
373
170
  }
374
- export default {
375
- check,
376
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zfqh/uniapp",
3
- "version": "0.2.10",
3
+ "version": "0.2.14",
4
4
  "description": "uniapp公共模块",
5
5
  "author": "yinjiazeng@163.com",
6
6
  "license": "MIT",
@@ -46,5 +46,5 @@
46
46
  "@types/qs": "^6.9.16",
47
47
  "@types/url-parse": "^1.4.11"
48
48
  },
49
- "gitHead": "a5025de96bb920ff3d8a94972b1842e21260fafe"
49
+ "gitHead": "7d5e40d024158c954ee9bd913650d11f87aac083"
50
50
  }
@@ -1,25 +0,0 @@
1
- # update
2
-
3
- 更新配置。发布路径:`@zfqh/uniapp/lib/configs/update`
4
-
5
- | 字段 | 类型 | 默认值 | 说明 |
6
- | --- | --- | --- | --- |
7
- | `request(data)` | `function` | `Promise<null>` | 获取最新版本信息;返回 hot_update、force_update、wgt_url/apk_url/ipa_url/zip_url 等字段。 |
8
-
9
- ## 基本使用
10
-
11
- App.vue 全局 mixin 会在合适时机调用更新检查;业务项目只需要配置获取最新版本的请求函数。
12
-
13
- ```ts
14
- import { defineConfig } from '@zfqh/uniapp';
15
- import { POST } from '@zfqh/uniapp/lib/apis';
16
-
17
- defineConfig({
18
- update: {
19
- async request(data) {
20
- const { data: version } = await POST('/app-api/system/app/version/get-last-version', data);
21
- return version;
22
- },
23
- },
24
- });
25
- ```
@@ -1,75 +0,0 @@
1
- # g-env 环境显示
2
-
3
- ::: tip 组件名
4
- `g-env`
5
-
6
- 发布路径:`@zfqh/uniapp/lib/components/g-env/g-env.vue`
7
- :::
8
-
9
- 环境切换入口,主要给 H5/Electron 调试环境使用,用于查看和切换当前 env。
10
-
11
- ## 平台兼容性
12
-
13
- | App(vue) | App(nvue) | H5 | 小程序 | Vue 2 | Vue 3 |
14
- | --- | --- | --- | --- | --- | --- |
15
- | √ | 依赖源码条件编译 | √ | √ | - | √ |
16
-
17
- ## 使用前提
18
-
19
- - 已安装并注册 `@zfqh/uniapp` 插件。
20
- - 已按 [项目接入](./usage) 配置 easycom,或手动从构建产物导入组件。
21
- - 尺寸类属性通常支持数字或带单位字符串;数字值会在组件内部通过 `uni.$uv.addUnit` 转成样式单位。
22
- - 样式类属性中,`customStyle`、`xxxStyle` 接收对象,`customClass`、`xxxClass` 接收 class 字符串。
23
-
24
- ## 基本使用
25
-
26
- ```vue
27
- <template>
28
- <view class="user-version">
29
- 当前环境
30
- <g-env :env="env" prefix="(" suffix=")" />
31
- </view>
32
- </template>
33
-
34
- <script setup>
35
- import { config } from '@zfqh/uniapp';
36
-
37
- const env = config.env;
38
- </script>
39
- ```
40
-
41
- ## API
42
-
43
- ### 环境显示 Props
44
-
45
- | 属性 | 类型 | 默认值 | 必填 | 说明 |
46
- | --- | --- | --- | --- | --- |
47
- | `env` | `Object` | `() => ({})` | 否 | 组件公开属性 env,用于控制该组件对应的渲染、交互或业务参数。 |
48
- | `data` | `Array` | `() => [ { name: '开发环境', key: 'dev', }, { name: '测试环境', key: 'sit', }, { name: '演示环境', key: 'uat', }, { name: '预生产环境', key: 'pre', }, ]` | 否 | 组件渲染或业务计算使用的数据源。 |
49
- | `prefix` | `String` | `''` | 否 | 组件公开属性 prefix,用于控制该组件对应的渲染、交互或业务参数。 |
50
- | `suffix` | `String` | `''` | 否 | 组件公开属性 suffix,用于控制该组件对应的渲染、交互或业务参数。 |
51
- | `switchable` | `Boolean` | `true` | 否 | 组件公开属性 switchable,用于控制该组件对应的渲染、交互或业务参数。 |
52
-
53
- ### 环境显示 Events
54
-
55
- 无显式组件事件。
56
-
57
- ### 环境显示 Slots
58
-
59
- | 插槽 | 说明 |
60
- | --- | --- |
61
- | `default` | 默认内容区域。 |
62
-
63
- ### 环境显示 Methods
64
-
65
- | 方法 | 说明 |
66
- | --- | --- |
67
- | `open()` | 打开组件或弹层;部分组件支持传入选项覆盖当前展示内容。 |
68
- | `select(e)` | 处理选中/取消选中逻辑并触发 change。 |
69
-
70
- ### 环境显示 Internal State
71
-
72
- | 类型 | 名称 | 说明 |
73
- | --- | --- | --- |
74
- | computed | `show` | 内部计算属性,用于把 props、平台信息或样式配置转换为模板可用值。 |
75
- | computed | `list` | 内部计算属性,用于把 props、平台信息或样式配置转换为模板可用值。 |