@hlw-uni/mp-vue 2.1.52 → 2.1.55
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.
- package/dist/app.d.ts +2 -20
- package/dist/composables/ad/index.d.ts +11 -73
- package/dist/composables/device/index.d.ts +5 -70
- package/dist/composables/index.d.ts +6 -14
- package/dist/composables/navigator/index.d.ts +15 -39
- package/dist/composables/request/client.d.ts +21 -0
- package/dist/composables/request/index.d.ts +6 -0
- package/dist/composables/request/service.d.ts +30 -0
- package/dist/composables/{http → request}/types.d.ts +0 -3
- package/dist/composables/share/index.d.ts +7 -66
- package/dist/composables/utils/index.d.ts +25 -32
- package/dist/hlw.d.ts +2 -4
- package/dist/index.d.ts +2 -3
- package/dist/index.js +614 -1253
- package/dist/index.mjs +613 -1252
- package/package.json +2 -1
- package/src/app.ts +3 -143
- package/src/components/hlw-ad/index.vue +6 -5
- package/src/components/hlw-page/index.vue +1 -1
- package/src/composables/ad/README.md +58 -0
- package/src/composables/ad/index.ts +117 -376
- package/src/composables/device/README.md +50 -0
- package/src/composables/device/index.ts +110 -83
- package/src/composables/index.ts +10 -39
- package/src/composables/msg/README.md +79 -0
- package/src/composables/navigator/README.md +71 -0
- package/src/composables/navigator/index.ts +77 -77
- package/src/composables/refs/README.md +40 -0
- package/src/composables/request/README.md +124 -0
- package/src/composables/{http → request}/adapters/oss.ts +1 -0
- package/src/composables/request/client.ts +204 -0
- package/src/composables/request/index.ts +15 -0
- package/src/composables/request/service.ts +54 -0
- package/src/composables/{http → request}/types.ts +0 -4
- package/src/composables/share/README.md +53 -0
- package/src/composables/share/index.ts +64 -168
- package/src/composables/theme/README.md +131 -0
- package/src/composables/theme/index.ts +4 -2
- package/src/composables/theme/palette.ts +22 -4
- package/src/composables/utils/README.md +81 -0
- package/src/composables/utils/index.ts +131 -95
- package/src/hlw.ts +6 -14
- package/src/index.ts +2 -3
- package/dist/composables/_internal/unwrap.d.ts +0 -15
- package/dist/composables/algo/index.d.ts +0 -7
- package/dist/composables/algo/uuid.d.ts +0 -17
- package/dist/composables/color/index.d.ts +0 -8
- package/dist/composables/contact/index.d.ts +0 -32
- package/dist/composables/format/index.d.ts +0 -9
- package/dist/composables/http/client.d.ts +0 -66
- package/dist/composables/http/index.d.ts +0 -8
- package/dist/composables/loading/index.d.ts +0 -7
- package/dist/composables/page-meta/index.d.ts +0 -18
- package/dist/composables/storage/index.d.ts +0 -16
- package/dist/composables/validate/index.d.ts +0 -12
- package/dist/error.d.ts +0 -1
- package/src/composables/_internal/unwrap.ts +0 -19
- package/src/composables/algo/index.ts +0 -7
- package/src/composables/algo/uuid.ts +0 -27
- package/src/composables/color/index.ts +0 -44
- package/src/composables/contact/index.ts +0 -92
- package/src/composables/format/index.ts +0 -48
- package/src/composables/http/client.ts +0 -237
- package/src/composables/http/index.ts +0 -8
- package/src/composables/http/useRequest.ts +0 -107
- package/src/composables/loading/index.ts +0 -23
- package/src/composables/page-meta/index.ts +0 -49
- package/src/composables/storage/index.ts +0 -76
- package/src/composables/validate/index.ts +0 -58
- package/src/error.ts +0 -5
- /package/dist/composables/{http → request}/adapters/alist.d.ts +0 -0
- /package/dist/composables/{http → request}/adapters/base.d.ts +0 -0
- /package/dist/composables/{http → request}/adapters/cos.d.ts +0 -0
- /package/dist/composables/{http → request}/adapters/index.d.ts +0 -0
- /package/dist/composables/{http → request}/adapters/oss.d.ts +0 -0
- /package/dist/composables/{http → request}/adapters/qiniu.d.ts +0 -0
- /package/src/composables/{http → request}/adapters/alist.ts +0 -0
- /package/src/composables/{http → request}/adapters/base.ts +0 -0
- /package/src/composables/{http → request}/adapters/cos.ts +0 -0
- /package/src/composables/{http → request}/adapters/index.ts +0 -0
- /package/src/composables/{http → request}/adapters/qiniu.ts +0 -0
|
@@ -1,412 +1,153 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 内置了:
|
|
5
|
-
* - 6 个 unit_id 配置(store 缓存,调 getConfig 拉一次)
|
|
6
|
-
* - 激励视频:广告加载 loading → onShown 自动关闭 → 中途关闭挽留 modal → 看完调业务方的 claim 发奖
|
|
7
|
-
* - 插屏:一行调用
|
|
8
|
-
* - 底层 SDK 适配(onLoad / offClose / show 兜底 / 实例缓存)
|
|
9
|
-
*
|
|
10
|
-
* 业务侧使用方式:
|
|
11
|
-
*
|
|
12
|
-
* 1. 在 App.vue 注入「全局」回调(拿配置 + 校验登录):
|
|
13
|
-
*
|
|
14
|
-
* import { setConfigAd } from "@hlw-uni/mp-vue";
|
|
15
|
-
* import { getAdConfig } from "@/api/ad";
|
|
16
|
-
* import { useUserStore } from "@/store";
|
|
17
|
-
*
|
|
18
|
-
* setConfigAd({
|
|
19
|
-
* getConfig: async () => {
|
|
20
|
-
* const res = await getAdConfig();
|
|
21
|
-
* return res.code === 1 && res.data ? res.data : null;
|
|
22
|
-
* },
|
|
23
|
-
* isAuth: () => !!useUserStore().token,
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* 2. 任意页面拉配置 / 用 unit_id 渲染:
|
|
27
|
-
*
|
|
28
|
-
* const { config, loadConfig, showPopup } = useAd();
|
|
29
|
-
* await loadConfig();
|
|
30
|
-
* <hlw-ad type="banner" :unit-id="config.banner" />
|
|
31
|
-
*
|
|
32
|
-
* 3. 看广告领奖励(业务方按场景传不同的 claim 接口):
|
|
33
|
-
*
|
|
34
|
-
* const ok = await showReward(async () => {
|
|
35
|
-
* const res = await claimAdReward();
|
|
36
|
-
* return res.code === 1
|
|
37
|
-
* ? { ok: true, reward: res.data?.reward }
|
|
38
|
-
* : { ok: false, msg: res.info };
|
|
39
|
-
* });
|
|
40
|
-
*
|
|
41
|
-
* // 不传 claim 就是纯展示,看完即返回 true
|
|
42
|
-
* const ok = await showReward();
|
|
2
|
+
* 小程序广告工具。
|
|
43
3
|
*/
|
|
44
4
|
|
|
45
|
-
|
|
46
|
-
import { ref, computed } from "vue";
|
|
47
|
-
import { useMsg, type HlwMsg } from "../msg";
|
|
48
|
-
import { unwrapPayload, type AdapterPayload } from "../_internal/unwrap";
|
|
5
|
+
declare const wx: any;
|
|
49
6
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export type AdType = "banner" | "grid" | "custom" | "video" | "reward" | "popup";
|
|
55
|
-
|
|
56
|
-
/** 广告配置 —— 字段名跟后端表列名对齐(plugin_qz_mp.{type}_unit_id) */
|
|
57
|
-
export interface AdConfig {
|
|
58
|
-
banner_unit_id: string;
|
|
59
|
-
grid_unit_id: string;
|
|
60
|
-
custom_unit_id: string;
|
|
61
|
-
video_unit_id: string;
|
|
62
|
-
reward_unit_id: string;
|
|
63
|
-
popup_unit_id: string;
|
|
64
|
-
/** VIP 屏蔽展示型广告(reward 除外):0=否,1=屏蔽 banner/grid/custom/video/popup */
|
|
65
|
-
vip_no_ad?: 0 | 1;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** 广告错误对象(onError 回调参数) */
|
|
69
|
-
export interface AdError {
|
|
70
|
-
errCode: number;
|
|
71
|
-
errMsg: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* 业务回调注入接口 —— setConfigAd 时由项目提供。
|
|
76
|
-
*
|
|
77
|
-
* getConfig 支持两种返回:
|
|
78
|
-
* - 已解包:直接返回 AdConfig 或 null
|
|
79
|
-
* - ThinkAdmin envelope:返回 { code, data } 对象,库自动按 code===1 解包
|
|
80
|
-
*
|
|
81
|
-
* 业务方可以直接传 envelope-returning 的接口函数引用:
|
|
82
|
-
* setConfigAd({ getConfig: getAdConfig })
|
|
83
|
-
*/
|
|
84
|
-
export interface AdAdapter {
|
|
85
|
-
getConfig: () => Promise<AdapterPayload<AdConfig>>;
|
|
86
|
-
/** 是否已登录;不传 = 不校验(showReward 调用前会问一次) */
|
|
87
|
-
isAuth?: () => boolean;
|
|
88
|
-
/** 是否 VIP;配合 config.vip_no_ad=1 时屏蔽展示型广告(reward 不受影响) */
|
|
89
|
-
isVip?: () => boolean;
|
|
90
|
-
/**
|
|
91
|
-
* 用户级强制屏蔽:返回 true 直接屏蔽展示型广告(reward 不受影响),
|
|
92
|
-
* 优先级高于 mp.vip_no_ad + isVip 的联合判断;不传 = 不强制。
|
|
93
|
-
*/
|
|
94
|
-
userNoAd?: () => boolean;
|
|
7
|
+
export interface AdRes {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
isEnded?: boolean;
|
|
10
|
+
err?: unknown;
|
|
95
11
|
}
|
|
96
12
|
|
|
97
|
-
|
|
98
|
-
export interface AdCloseResult {
|
|
99
|
-
/** 用户是否完整观看 */
|
|
100
|
-
isEnded: boolean;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const EMPTY: AdConfig = {
|
|
104
|
-
banner_unit_id: "",
|
|
105
|
-
grid_unit_id: "",
|
|
106
|
-
custom_unit_id: "",
|
|
107
|
-
video_unit_id: "",
|
|
108
|
-
reward_unit_id: "",
|
|
109
|
-
popup_unit_id: "",
|
|
110
|
-
vip_no_ad: 0,
|
|
111
|
-
};
|
|
13
|
+
type AdDone = (res: AdRes) => void;
|
|
112
14
|
|
|
113
|
-
let
|
|
15
|
+
let popupAd: any = null;
|
|
16
|
+
let popupDone: ((ok: boolean) => void) | undefined;
|
|
17
|
+
let popupClose: (() => void) | null = null;
|
|
18
|
+
let popupError: ((err: unknown) => void) | null = null;
|
|
114
19
|
|
|
115
|
-
|
|
116
|
-
let
|
|
20
|
+
let rewardAd: any = null;
|
|
21
|
+
let rewardDone: AdDone | undefined;
|
|
22
|
+
let rewardPromise: Promise<AdRes> | null = null;
|
|
23
|
+
let rewardResolve: ((res: AdRes) => void) | null = null;
|
|
24
|
+
let rewardClose: ((res: { isEnded?: boolean }) => void) | null = null;
|
|
25
|
+
let rewardError: ((err: unknown) => void) | null = null;
|
|
117
26
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
* 不调用也不会崩,但 loadConfig / showReward 会无效。
|
|
121
|
-
*/
|
|
122
|
-
export function setConfigAd(a: AdAdapter): void {
|
|
123
|
-
adapter = a;
|
|
27
|
+
function api() {
|
|
28
|
+
return typeof wx === "undefined" ? null : wx;
|
|
124
29
|
}
|
|
125
30
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
/* ============================================================
|
|
133
|
-
* 内部状态:消息单例 + 广告实例缓存
|
|
134
|
-
* ============================================================ */
|
|
135
|
-
|
|
136
|
-
let _msg: HlwMsg | null = null;
|
|
137
|
-
const msg = (): HlwMsg => (_msg ??= useMsg());
|
|
138
|
-
|
|
139
|
-
interface RewardedEntry {
|
|
140
|
-
ad: any;
|
|
141
|
-
/** 同一 unit_id 是否在 load 中,避免并发 */
|
|
142
|
-
loading: boolean;
|
|
31
|
+
function finish(res: AdRes) {
|
|
32
|
+
rewardDone?.(res);
|
|
33
|
+
rewardResolve?.(res);
|
|
34
|
+
rewardResolve = null;
|
|
35
|
+
rewardPromise = null;
|
|
143
36
|
}
|
|
144
|
-
const rewardedCache = new Map<string, RewardedEntry>();
|
|
145
|
-
const interstitialCache = new Map<string, any>();
|
|
146
|
-
|
|
147
|
-
/* ============================================================
|
|
148
|
-
* 公共 composable
|
|
149
|
-
* ============================================================ */
|
|
150
37
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
* 2. raw.vip_no_ad === 1 && adapter.isVip() —— 小程序级 VIP 隐藏开关
|
|
159
|
-
*/
|
|
160
|
-
const config = computed<AdConfig>(() => {
|
|
161
|
-
const raw = store.config;
|
|
162
|
-
const userForce = adapter?.userNoAd?.() === true;
|
|
163
|
-
const vipHide = raw.vip_no_ad === 1 && adapter?.isVip?.() === true;
|
|
164
|
-
if (userForce || vipHide) {
|
|
165
|
-
return { ...EMPTY, reward_unit_id: raw.reward_unit_id, vip_no_ad: 1 };
|
|
166
|
-
}
|
|
167
|
-
return raw;
|
|
168
|
-
});
|
|
38
|
+
function clearReward() {
|
|
39
|
+
if (!rewardAd) return;
|
|
40
|
+
if (rewardClose) rewardAd.offClose?.(rewardClose);
|
|
41
|
+
if (rewardError) rewardAd.offError?.(rewardError);
|
|
42
|
+
rewardClose = null;
|
|
43
|
+
rewardError = null;
|
|
44
|
+
}
|
|
169
45
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (!adapter?.getConfig) {
|
|
178
|
-
console.warn("[useAd] adapter.getConfig 未注入;先调用 setConfigAd()");
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const fn = adapter.getConfig;
|
|
182
|
-
const flight = (async () => {
|
|
183
|
-
try {
|
|
184
|
-
const cfg = unwrapPayload(await fn());
|
|
185
|
-
if (cfg) {
|
|
186
|
-
store.config = cfg;
|
|
187
|
-
store.loaded = true;
|
|
188
|
-
}
|
|
189
|
-
} catch (e) {
|
|
190
|
-
console.warn("[useAd] load config failed", e);
|
|
191
|
-
} finally {
|
|
192
|
-
if (pending === flight) pending = null;
|
|
193
|
-
}
|
|
194
|
-
})();
|
|
195
|
-
pending = flight;
|
|
196
|
-
return flight;
|
|
46
|
+
export function useHlwAd() {
|
|
47
|
+
function clearPopup() {
|
|
48
|
+
if (!popupAd) return;
|
|
49
|
+
if (popupClose) popupAd.offClose?.(popupClose);
|
|
50
|
+
if (popupError) popupAd.offError?.(popupError);
|
|
51
|
+
popupClose = null;
|
|
52
|
+
popupError = null;
|
|
197
53
|
}
|
|
198
54
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
55
|
+
function setAdPopup(adId: string, done?: (ok: boolean) => void): boolean {
|
|
56
|
+
popupDone = done;
|
|
57
|
+
const wxApi = api();
|
|
58
|
+
if (!adId || !wxApi?.createInterstitialAd) return false;
|
|
59
|
+
|
|
60
|
+
clearPopup();
|
|
61
|
+
popupAd = wxApi.createInterstitialAd({ adUnitId: adId });
|
|
62
|
+
popupAd.onLoad?.(() => {});
|
|
63
|
+
popupError = (err: unknown) => {
|
|
64
|
+
console.error("插屏广告加载失败", err);
|
|
65
|
+
popupDone?.(false);
|
|
66
|
+
};
|
|
67
|
+
popupClose = () => {
|
|
68
|
+
popupDone?.(true);
|
|
69
|
+
};
|
|
70
|
+
popupAd.onError?.(popupError);
|
|
71
|
+
popupAd.onClose?.(popupClose);
|
|
72
|
+
return true;
|
|
202
73
|
}
|
|
203
74
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (!unitId) {
|
|
217
|
-
msg().toast("激励广告未配置");
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (adapter?.isAuth && !adapter.isAuth()) {
|
|
221
|
-
msg().toast("请先登录");
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
const closeRes = await playRewardedOnce(unitId);
|
|
225
|
-
if (onClose) await onClose(closeRes);
|
|
226
|
-
}
|
|
75
|
+
function showAdPopup(delay = 3000): Promise<boolean> {
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
if (!popupAd) {
|
|
78
|
+
resolve(false);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const done = popupDone;
|
|
83
|
+
popupDone = (ok: boolean) => {
|
|
84
|
+
done?.(ok);
|
|
85
|
+
resolve(ok);
|
|
86
|
+
};
|
|
227
87
|
|
|
228
|
-
/**
|
|
229
|
-
* 显示插屏广告
|
|
230
|
-
* @returns true=展示成功;false=配置缺失 / show 失败(如近期已展示过)
|
|
231
|
-
*/
|
|
232
|
-
/**
|
|
233
|
-
* 显示插屏广告,默认延迟 3000ms 避免一进页面就弹打扰;传 0 立即弹。
|
|
234
|
-
* @returns true=展示成功;false=配置缺失 / show 失败(如近期已展示过)
|
|
235
|
-
*
|
|
236
|
-
* 实现注意:用 setTimeout + .then() 串接而非 async/await,保持 WX 插屏
|
|
237
|
-
* ad.show() 的调用栈跟 setTimeout 回调一致 —— 小程序引擎对插屏的合法
|
|
238
|
-
* 触发时机敏感,async/await 多插的 microtask 会被判为"非合法触发"导致
|
|
239
|
-
* 静默不弹。
|
|
240
|
-
*/
|
|
241
|
-
function showPopup(delayMs: number = DEFAULT_POPUP_DELAY_MS): Promise<boolean> {
|
|
242
|
-
return new Promise<boolean>((resolve) => {
|
|
243
88
|
setTimeout(() => {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
resolve(false);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
showInterstitialAd(unitId).then(resolve);
|
|
89
|
+
popupAd.show().catch((err: unknown) => {
|
|
90
|
+
console.error("插屏广告显示失败", err);
|
|
91
|
+
popupDone?.(false);
|
|
251
92
|
});
|
|
252
|
-
},
|
|
93
|
+
}, Math.max(0, delay));
|
|
253
94
|
});
|
|
254
95
|
}
|
|
255
96
|
|
|
256
|
-
return {
|
|
257
|
-
// 状态
|
|
258
|
-
config,
|
|
259
|
-
loaded,
|
|
260
|
-
// 方法
|
|
261
|
-
loadConfig,
|
|
262
|
-
getUnitId,
|
|
263
|
-
showReward,
|
|
264
|
-
showPopup,
|
|
265
|
-
confirm: confirmModal,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/* ============================================================
|
|
270
|
-
* 内部 helper:业务流程层
|
|
271
|
-
* ============================================================ */
|
|
272
|
-
|
|
273
|
-
/** 播放一次激励视频,期间显示加载提示,广告 UI 弹出后自动 hide */
|
|
274
|
-
async function playRewardedOnce(unitId: string): Promise<AdCloseResult> {
|
|
275
|
-
msg().showLoading("广告加载中");
|
|
276
|
-
let hidden = false;
|
|
277
|
-
const hide = () => {
|
|
278
|
-
if (hidden) return;
|
|
279
|
-
hidden = true;
|
|
280
|
-
msg().hideLoading();
|
|
281
|
-
};
|
|
282
|
-
try {
|
|
283
|
-
const isEnded = await showRewardedAd(unitId, { onShown: hide });
|
|
284
|
-
return { isEnded };
|
|
285
|
-
} finally {
|
|
286
|
-
// 兜底:如果 onShown 没触发(show 直接 reject 等),最终也得关 loading
|
|
287
|
-
hide();
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
97
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
* showReward(async ({ isEnded }) => {
|
|
296
|
-
* if (!isEnded) return { ok: false, retry: await confirm() };
|
|
297
|
-
* const r = await claimAdReward();
|
|
298
|
-
* return r.code === 1 ? { ok: true, reward: r.data?.reward } : { ok: false, msg: r.info };
|
|
299
|
-
* });
|
|
300
|
-
*
|
|
301
|
-
* @returns true=用户选「继续观看」 / false=放弃
|
|
302
|
-
*/
|
|
303
|
-
function confirmModal(): Promise<boolean> {
|
|
304
|
-
return new Promise((resolve) => {
|
|
305
|
-
uni.showModal({
|
|
306
|
-
title: "提示",
|
|
307
|
-
content: "看完广告才可以领取奖励哦,要继续观看吗?",
|
|
308
|
-
confirmText: "继续观看",
|
|
309
|
-
cancelText: "放弃",
|
|
310
|
-
success: (r) => resolve(!!r.confirm),
|
|
311
|
-
fail: () => resolve(false),
|
|
98
|
+
function setAdReward(adId: string, done?: AdDone): Promise<AdRes> {
|
|
99
|
+
rewardDone = done;
|
|
100
|
+
rewardPromise = new Promise((resolve) => {
|
|
101
|
+
rewardResolve = resolve;
|
|
312
102
|
});
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
103
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* 底层激励视频包装:onClose / onError 解绑 + load + show 兜底
|
|
322
|
-
*
|
|
323
|
-
* @param hooks.onShown 广告 UI 已渲染时回调(业务用来关 loading)
|
|
324
|
-
*/
|
|
325
|
-
function showRewardedAd(unitId: string, hooks?: { onShown?: () => void }): Promise<boolean> {
|
|
326
|
-
return new Promise((resolve) => {
|
|
327
|
-
let entry = rewardedCache.get(unitId);
|
|
328
|
-
if (!entry) {
|
|
329
|
-
const ad: any = uni.createRewardedVideoAd({ adUnitId: unitId });
|
|
330
|
-
if (!ad) { resolve(false); return; }
|
|
331
|
-
ad.onError?.((err: AdError) => {
|
|
332
|
-
console.warn(`[useAd] reward onError (${unitId})`, err);
|
|
333
|
-
});
|
|
334
|
-
entry = { ad, loading: false };
|
|
335
|
-
rewardedCache.set(unitId, entry);
|
|
104
|
+
const wxApi = api();
|
|
105
|
+
if (!adId || !wxApi?.createRewardedVideoAd) {
|
|
106
|
+
finish({ ok: false });
|
|
107
|
+
return rewardPromise;
|
|
336
108
|
}
|
|
337
|
-
const { ad } = entry;
|
|
338
109
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
};
|
|
345
|
-
closeHandler = (res) => {
|
|
346
|
-
cleanup();
|
|
347
|
-
resolve(!!(res && res.isEnded));
|
|
110
|
+
clearReward();
|
|
111
|
+
rewardAd = wxApi.createRewardedVideoAd({ adUnitId: adId });
|
|
112
|
+
rewardAd.onLoad?.(() => {});
|
|
113
|
+
rewardClose = (res: { isEnded?: boolean }) => {
|
|
114
|
+
finish({ ok: !!res?.isEnded, isEnded: !!res?.isEnded });
|
|
348
115
|
};
|
|
349
|
-
|
|
350
|
-
console.
|
|
351
|
-
|
|
352
|
-
resolve(false);
|
|
116
|
+
rewardError = (err: unknown) => {
|
|
117
|
+
console.error("激励视频广告加载失败", err);
|
|
118
|
+
finish({ ok: false, err });
|
|
353
119
|
};
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
ad.show()
|
|
359
|
-
.then(() => {
|
|
360
|
-
try { hooks?.onShown?.(); } catch (e) { console.warn("[useAd] onShown error", e); }
|
|
361
|
-
})
|
|
362
|
-
.catch(() => {
|
|
363
|
-
cleanup();
|
|
364
|
-
resolve(false);
|
|
365
|
-
});
|
|
120
|
+
rewardAd.onClose?.(rewardClose);
|
|
121
|
+
rewardAd.onError?.(rewardError);
|
|
122
|
+
return rewardPromise;
|
|
123
|
+
}
|
|
366
124
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
entry.loading = true;
|
|
371
|
-
ad.load()
|
|
372
|
-
.then(doShow)
|
|
373
|
-
.catch(doShow)
|
|
374
|
-
.finally(() => { if (entry) entry.loading = false; });
|
|
125
|
+
function showAdReward(): Promise<AdRes> {
|
|
126
|
+
if (!rewardAd) {
|
|
127
|
+
return Promise.resolve({ ok: false });
|
|
375
128
|
}
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
129
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
ad.onError?.((err: AdError) => {
|
|
393
|
-
console.warn(`[useAd] popup onError (${unitId})`, err);
|
|
394
|
-
});
|
|
395
|
-
interstitialCache.set(unitId, ad);
|
|
396
|
-
}
|
|
397
|
-
ad.show()
|
|
398
|
-
.then(() => resolve(true))
|
|
399
|
-
.catch((err: any) => {
|
|
400
|
-
console.warn(`[useAd] popup show error (${unitId})`, err);
|
|
401
|
-
resolve(false);
|
|
402
|
-
});
|
|
403
|
-
});
|
|
404
|
-
}
|
|
130
|
+
const current = rewardPromise || new Promise<AdRes>((resolve) => {
|
|
131
|
+
rewardResolve = resolve;
|
|
132
|
+
});
|
|
133
|
+
rewardPromise = current;
|
|
134
|
+
|
|
135
|
+
rewardAd.show().catch(() => {
|
|
136
|
+
rewardAd.load()
|
|
137
|
+
.then(() => rewardAd.show())
|
|
138
|
+
.catch((err: unknown) => {
|
|
139
|
+
console.error("激励视频广告显示失败", err);
|
|
140
|
+
finish({ ok: false, err });
|
|
141
|
+
});
|
|
142
|
+
});
|
|
405
143
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
144
|
+
return current;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
setAdPopup,
|
|
149
|
+
showAdPopup,
|
|
150
|
+
setAdReward,
|
|
151
|
+
showAdReward,
|
|
152
|
+
};
|
|
412
153
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# device 调用文档
|
|
2
|
+
|
|
3
|
+
`useDevice` 采集并缓存设备、窗口、宿主和小程序信息,同时提供常用设备字段组成的 query 字符串。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useDevice, clearDeviceCache } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const { info, query } = useDevice();
|
|
15
|
+
|
|
16
|
+
console.log(info.appid);
|
|
17
|
+
console.log(info.device_model);
|
|
18
|
+
console.log(query);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`useDevice` 内部会优先读取 `uni.getDeviceInfo`、`uni.getWindowInfo`、`uni.getAppBaseInfo`,旧环境会回退到 `uni.getSystemInfoSync`。
|
|
22
|
+
|
|
23
|
+
## 清除缓存
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
clearDeviceCache();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
切换账号、切换宿主环境或需要重新采集设备信息时可以手动清理缓存。
|
|
30
|
+
|
|
31
|
+
## 返回值
|
|
32
|
+
|
|
33
|
+
| 字段 | 说明 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `info` | 完整 `DeviceInfo` |
|
|
36
|
+
| `query` | 常用设备字段组成的 URL query 字符串 |
|
|
37
|
+
|
|
38
|
+
## 常用字段
|
|
39
|
+
|
|
40
|
+
| 字段 | 说明 |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `appid` | 小程序 appId |
|
|
43
|
+
| `device_brand` | 设备品牌 |
|
|
44
|
+
| `device_model` | 设备型号 |
|
|
45
|
+
| `device_id` | 设备 ID |
|
|
46
|
+
| `platform` | 平台类型 |
|
|
47
|
+
| `system` | 系统版本 |
|
|
48
|
+
| `sdk_version` | 基础库版本 |
|
|
49
|
+
| `screen_width` | 屏幕宽度 |
|
|
50
|
+
| `screen_height` | 屏幕高度 |
|