@hlw-uni/mp-vue 2.0.0 → 2.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.
- package/dist/app.d.ts +1 -1
- package/dist/composables/_internal/unwrap.d.ts +15 -0
- package/dist/composables/ad/index.d.ts +14 -47
- package/dist/composables/contact/index.d.ts +8 -4
- package/dist/composables/index.d.ts +3 -3
- package/dist/composables/share/index.d.ts +8 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +25 -14
- package/dist/index.mjs +25 -14
- package/package.json +1 -1
- package/src/app.ts +1 -1
- package/src/composables/_internal/unwrap.ts +19 -0
- package/src/composables/ad/index.ts +17 -8
- package/src/composables/contact/index.ts +11 -7
- package/src/composables/index.ts +3 -3
- package/src/composables/share/index.ts +11 -7
- package/src/index.ts +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -28,6 +28,6 @@ export declare function useApp(): {
|
|
|
28
28
|
/**
|
|
29
29
|
* 注册默认请求、响应和错误拦截器。
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function setupInterceptors(options?: InterceptorOptions & {
|
|
32
32
|
sigSecret?: string;
|
|
33
33
|
}): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter 返回值解包:兼容业务方传「已解包 T」或「ThinkAdmin envelope { code, data }」。
|
|
3
|
+
*
|
|
4
|
+
* 业务方写法:
|
|
5
|
+
* setConfigAd({ getConfig: getAdConfig }) // 直接传 envelope-returning 函数
|
|
6
|
+
* setConfigAd({ getConfig: async () => myUnwrapped }) // 也支持已解包
|
|
7
|
+
*
|
|
8
|
+
* 鸭子类型识别:raw 是对象且有 number 类型的 code 字段 → 当 envelope 处理。
|
|
9
|
+
*/
|
|
10
|
+
export type AdapterPayload<T> = T | null | {
|
|
11
|
+
code: number;
|
|
12
|
+
data?: T;
|
|
13
|
+
info?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function unwrapPayload<T>(raw: AdapterPayload<T>): T | null;
|
|
@@ -1,47 +1,6 @@
|
|
|
1
|
+
import { AdapterPayload } from '../_internal/unwrap';
|
|
1
2
|
import { Ref } from 'vue';
|
|
2
|
-
|
|
3
|
-
* useAd —— 完整的广告业务封装
|
|
4
|
-
*
|
|
5
|
-
* 内置了:
|
|
6
|
-
* - 6 个 unit_id 配置(store 缓存,调 getConfig 拉一次)
|
|
7
|
-
* - 激励视频:广告加载 loading → onShown 自动关闭 → 中途关闭挽留 modal → 看完调业务方的 claim 发奖
|
|
8
|
-
* - 插屏:一行调用
|
|
9
|
-
* - 底层 SDK 适配(onLoad / offClose / show 兜底 / 实例缓存)
|
|
10
|
-
*
|
|
11
|
-
* 业务侧使用方式:
|
|
12
|
-
*
|
|
13
|
-
* 1. 在 App.vue 注入「全局」回调(拿配置 + 校验登录):
|
|
14
|
-
*
|
|
15
|
-
* import { configAd } from "@hlw-uni/mp-vue";
|
|
16
|
-
* import { getAdConfig } from "@/api/ad";
|
|
17
|
-
* import { useUserStore } from "@/store";
|
|
18
|
-
*
|
|
19
|
-
* configAd({
|
|
20
|
-
* getConfig: async () => {
|
|
21
|
-
* const res = await getAdConfig();
|
|
22
|
-
* return res.code === 1 && res.data ? res.data : null;
|
|
23
|
-
* },
|
|
24
|
-
* isAuth: () => !!useUserStore().token,
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* 2. 任意页面拉配置 / 用 unit_id 渲染:
|
|
28
|
-
*
|
|
29
|
-
* const { config, loadConfig, showPopup } = useAd();
|
|
30
|
-
* await loadConfig();
|
|
31
|
-
* <hlw-ad type="banner" :unit-id="config.banner" />
|
|
32
|
-
*
|
|
33
|
-
* 3. 看广告领奖励(业务方按场景传不同的 claim 接口):
|
|
34
|
-
*
|
|
35
|
-
* const ok = await showReward(async () => {
|
|
36
|
-
* const res = await claimAdReward();
|
|
37
|
-
* return res.code === 1
|
|
38
|
-
* ? { ok: true, reward: res.data?.reward }
|
|
39
|
-
* : { ok: false, msg: res.info };
|
|
40
|
-
* });
|
|
41
|
-
*
|
|
42
|
-
* // 不传 claim 就是纯展示,看完即返回 true
|
|
43
|
-
* const ok = await showReward();
|
|
44
|
-
*/
|
|
3
|
+
|
|
45
4
|
/** 6 种广告类型 */
|
|
46
5
|
export type AdType = "banner" | "grid" | "custom" | "video" | "reward" | "popup";
|
|
47
6
|
/** 广告配置 —— 字段名跟后端表列名对齐(plugin_qz_mp.{type}_unit_id) */
|
|
@@ -58,10 +17,18 @@ export interface AdError {
|
|
|
58
17
|
errCode: number;
|
|
59
18
|
errMsg: string;
|
|
60
19
|
}
|
|
61
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* 业务回调注入接口 —— setConfigAd 时由项目提供。
|
|
22
|
+
*
|
|
23
|
+
* getConfig 支持两种返回:
|
|
24
|
+
* - 已解包:直接返回 AdConfig 或 null
|
|
25
|
+
* - ThinkAdmin envelope:返回 { code, data } 对象,库自动按 code===1 解包
|
|
26
|
+
*
|
|
27
|
+
* 业务方可以直接传 envelope-returning 的接口函数引用:
|
|
28
|
+
* setConfigAd({ getConfig: getAdConfig })
|
|
29
|
+
*/
|
|
62
30
|
export interface AdAdapter {
|
|
63
|
-
|
|
64
|
-
getConfig: () => Promise<AdConfig | null>;
|
|
31
|
+
getConfig: () => Promise<AdapterPayload<AdConfig>>;
|
|
65
32
|
/** 是否已登录;不传 = 不校验(showReward 调用前会问一次) */
|
|
66
33
|
isAuth?: () => boolean;
|
|
67
34
|
}
|
|
@@ -92,7 +59,7 @@ export type AdClaimFn = (closeRes: AdCloseResult) => Promise<AdClaimResult>;
|
|
|
92
59
|
* 注入业务回调,应用启动时调用一次。
|
|
93
60
|
* 不调用也不会崩,但 loadConfig / showReward 会无效。
|
|
94
61
|
*/
|
|
95
|
-
export declare function
|
|
62
|
+
export declare function setConfigAd(a: AdAdapter): void;
|
|
96
63
|
export declare function useAd(): {
|
|
97
64
|
config: Ref<{
|
|
98
65
|
banner_unit_id: string;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { AdapterPayload } from '../_internal/unwrap';
|
|
1
2
|
import { ComputedRef } from 'vue';
|
|
3
|
+
|
|
2
4
|
/** 后端返回的客服配置(按 button open-type=contact 标准属性命名) */
|
|
3
5
|
export interface ContactConfig {
|
|
4
6
|
send_message_title: string;
|
|
@@ -6,10 +8,12 @@ export interface ContactConfig {
|
|
|
6
8
|
send_message_img: string;
|
|
7
9
|
show_message_card: boolean;
|
|
8
10
|
}
|
|
9
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Adapter 注入接口 —— getConfig 支持「已解包」或「ThinkAdmin envelope」两种返回。
|
|
13
|
+
* 业务方可以直接传 envelope-returning 接口:setConfigContact({ getConfig: getContactConfig })
|
|
14
|
+
*/
|
|
10
15
|
export interface ContactAdapter {
|
|
11
|
-
|
|
12
|
-
getConfig: () => Promise<ContactConfig | null>;
|
|
16
|
+
getConfig: () => Promise<AdapterPayload<ContactConfig>>;
|
|
13
17
|
}
|
|
14
18
|
/** v-bind 到 button 的 camelCase props(微信原生属性约定) */
|
|
15
19
|
export interface ContactBindProps {
|
|
@@ -21,7 +25,7 @@ export interface ContactBindProps {
|
|
|
21
25
|
/**
|
|
22
26
|
* 注入业务回调(应用启动时调用一次;不调用则 useContact 始终返回空字段)。
|
|
23
27
|
*/
|
|
24
|
-
export declare function
|
|
28
|
+
export declare function setConfigContact(a: ContactAdapter): void;
|
|
25
29
|
/**
|
|
26
30
|
* 返回 v-bind 友好的客服配置 computed(首次调用会异步拉一次配置)。
|
|
27
31
|
*/
|
|
@@ -10,9 +10,9 @@ export { usePageMeta } from './page-meta';
|
|
|
10
10
|
export { useStorage, type StorageInstance } from './storage';
|
|
11
11
|
export { useValidate } from './validate';
|
|
12
12
|
export { useFormat } from './format';
|
|
13
|
-
export { useAd,
|
|
14
|
-
export { useShare, useShareConfig,
|
|
15
|
-
export { useContact,
|
|
13
|
+
export { useAd, setConfigAd, destroyAds, confirmReward, type AdType, type AdConfig, type AdError, type AdAdapter, type AdCloseResult, type AdClaimResult, type AdClaimFn, } from './ad';
|
|
14
|
+
export { useShare, useShareConfig, setConfigShare, type ShareConfig, type ShareConfigResolver, type ShareFrom, type ShareAppMessageContent, type ShareTimelineContent, type ShareConfigMap, type ShareConfigAdapter, type PageShareItem, type PageShareFallback, type SharePayload, } from './share';
|
|
15
|
+
export { useContact, setConfigContact, type ContactConfig, type ContactAdapter, type ContactBindProps, } from './contact';
|
|
16
16
|
export { useUtils, type DownloadFileOptions, type DownloadFileResult, type TapEvent } from './utils';
|
|
17
17
|
export { useColor } from './color';
|
|
18
18
|
export { useRouter, type NavigateType, type NavigateOptions } from './navigator';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AdapterPayload } from '../_internal/unwrap';
|
|
2
|
+
|
|
1
3
|
export interface ShareAppMessageContent {
|
|
2
4
|
/** 分享标题 */
|
|
3
5
|
title?: string;
|
|
@@ -36,10 +38,12 @@ export interface PageShareItem {
|
|
|
36
38
|
}
|
|
37
39
|
/** 后端返回的页面 key → 配置映射 */
|
|
38
40
|
export type ShareConfigMap = Record<string, PageShareItem>;
|
|
39
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Adapter 注入接口 —— getConfig 支持「已解包」或「ThinkAdmin envelope」两种返回值。
|
|
43
|
+
* 业务方可以直接传 envelope-returning 接口:setConfigShare({ getConfig: getShareConfig })
|
|
44
|
+
*/
|
|
40
45
|
export interface ShareConfigAdapter {
|
|
41
|
-
|
|
42
|
-
getConfig: () => Promise<ShareConfigMap | null>;
|
|
46
|
+
getConfig: () => Promise<AdapterPayload<ShareConfigMap>>;
|
|
43
47
|
}
|
|
44
48
|
/** 页面声明的兜底文案 / 跳转路径 */
|
|
45
49
|
export interface PageShareFallback {
|
|
@@ -59,7 +63,7 @@ export interface SharePayload {
|
|
|
59
63
|
/**
|
|
60
64
|
* 注入业务回调(应用启动时调用一次;不调用则始终用 fallback)。
|
|
61
65
|
*/
|
|
62
|
-
export declare function
|
|
66
|
+
export declare function setConfigShare(a: ShareConfigAdapter): void;
|
|
63
67
|
/**
|
|
64
68
|
* 业务级分享配置 helper —— 返回 resolver,可直接喂 onShareAppMessage / onShareTimeline。
|
|
65
69
|
* 后端配置异步加载,加载完成前先用 fallback、加载完后自动切到后端值。
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,6 @@ export * from './composables';
|
|
|
11
11
|
export type { HlwMenuItem } from './components/hlw-menu/types';
|
|
12
12
|
export type { HlwPagingRef, HlwPagingInstance } from './components/hlw-paging/types';
|
|
13
13
|
export { useThemeStore } from './stores/theme';
|
|
14
|
-
export { useApp,
|
|
14
|
+
export { useApp, setupInterceptors } from './app';
|
|
15
15
|
export { hlw, type HlwInstance } from './hlw';
|
|
16
16
|
export { vCopy } from './directives';
|
package/dist/index.js
CHANGED
|
@@ -619,6 +619,15 @@ var __publicField = (obj, key, value) => {
|
|
|
619
619
|
}
|
|
620
620
|
return { date, fileSize, phone, money };
|
|
621
621
|
}
|
|
622
|
+
function unwrapPayload(raw) {
|
|
623
|
+
if (raw == null)
|
|
624
|
+
return null;
|
|
625
|
+
if (typeof raw === "object" && "code" in raw && typeof raw.code === "number") {
|
|
626
|
+
const env = raw;
|
|
627
|
+
return env.code === 1 && env.data ? env.data : null;
|
|
628
|
+
}
|
|
629
|
+
return raw;
|
|
630
|
+
}
|
|
622
631
|
const EMPTY = {
|
|
623
632
|
banner_unit_id: "",
|
|
624
633
|
grid_unit_id: "",
|
|
@@ -628,7 +637,7 @@ var __publicField = (obj, key, value) => {
|
|
|
628
637
|
popup_unit_id: ""
|
|
629
638
|
};
|
|
630
639
|
let adapter$1 = null;
|
|
631
|
-
function
|
|
640
|
+
function setConfigAd(a) {
|
|
632
641
|
adapter$1 = a;
|
|
633
642
|
}
|
|
634
643
|
const useAdStore = pinia.defineStore("hlw_ad", () => {
|
|
@@ -647,11 +656,11 @@ var __publicField = (obj, key, value) => {
|
|
|
647
656
|
if (loaded.value && !force)
|
|
648
657
|
return;
|
|
649
658
|
if (!(adapter$1 == null ? void 0 : adapter$1.getConfig)) {
|
|
650
|
-
console.warn("[useAd] adapter.getConfig 未注入;先调用
|
|
659
|
+
console.warn("[useAd] adapter.getConfig 未注入;先调用 setConfigAd()");
|
|
651
660
|
return;
|
|
652
661
|
}
|
|
653
662
|
try {
|
|
654
|
-
const cfg = await adapter$1.getConfig();
|
|
663
|
+
const cfg = unwrapPayload(await adapter$1.getConfig());
|
|
655
664
|
if (cfg) {
|
|
656
665
|
store.config = cfg;
|
|
657
666
|
store.loaded = true;
|
|
@@ -877,7 +886,7 @@ var __publicField = (obj, key, value) => {
|
|
|
877
886
|
let shareAdapter = null;
|
|
878
887
|
const shareCache = vue.ref(null);
|
|
879
888
|
let sharePending = null;
|
|
880
|
-
function
|
|
889
|
+
function setConfigShare(a) {
|
|
881
890
|
shareAdapter = a;
|
|
882
891
|
}
|
|
883
892
|
function loadShareConfig() {
|
|
@@ -886,10 +895,11 @@ var __publicField = (obj, key, value) => {
|
|
|
886
895
|
if (sharePending)
|
|
887
896
|
return sharePending;
|
|
888
897
|
if (!(shareAdapter == null ? void 0 : shareAdapter.getConfig)) {
|
|
889
|
-
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用
|
|
898
|
+
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用 setConfigShare()");
|
|
890
899
|
return Promise.resolve();
|
|
891
900
|
}
|
|
892
|
-
sharePending = shareAdapter.getConfig().then((
|
|
901
|
+
sharePending = shareAdapter.getConfig().then((raw) => {
|
|
902
|
+
const cfg = unwrapPayload(raw);
|
|
893
903
|
if (cfg)
|
|
894
904
|
shareCache.value = cfg;
|
|
895
905
|
}).catch((e) => {
|
|
@@ -915,7 +925,7 @@ var __publicField = (obj, key, value) => {
|
|
|
915
925
|
let adapter = null;
|
|
916
926
|
const config = vue.ref(null);
|
|
917
927
|
let pending = null;
|
|
918
|
-
function
|
|
928
|
+
function setConfigContact(a) {
|
|
919
929
|
adapter = a;
|
|
920
930
|
}
|
|
921
931
|
function loadConfig() {
|
|
@@ -924,10 +934,11 @@ var __publicField = (obj, key, value) => {
|
|
|
924
934
|
if (pending)
|
|
925
935
|
return pending;
|
|
926
936
|
if (!(adapter == null ? void 0 : adapter.getConfig)) {
|
|
927
|
-
console.warn("[useContact] adapter.getConfig 未注入;先调用
|
|
937
|
+
console.warn("[useContact] adapter.getConfig 未注入;先调用 setConfigContact()");
|
|
928
938
|
return Promise.resolve();
|
|
929
939
|
}
|
|
930
|
-
pending = adapter.getConfig().then((
|
|
940
|
+
pending = adapter.getConfig().then((raw) => {
|
|
941
|
+
const cfg = unwrapPayload(raw);
|
|
931
942
|
if (cfg)
|
|
932
943
|
config.value = cfg;
|
|
933
944
|
}).catch((e) => {
|
|
@@ -1774,7 +1785,7 @@ var __publicField = (obj, key, value) => {
|
|
|
1774
1785
|
}
|
|
1775
1786
|
}
|
|
1776
1787
|
let _sigSecret = "";
|
|
1777
|
-
function
|
|
1788
|
+
function setupInterceptors(options = {}) {
|
|
1778
1789
|
const opts = { ..._defaultOpts, ...options };
|
|
1779
1790
|
if (opts.sigSecret)
|
|
1780
1791
|
_sigSecret = opts.sigSecret;
|
|
@@ -1889,9 +1900,6 @@ var __publicField = (obj, key, value) => {
|
|
|
1889
1900
|
exports2.alistAdapter = alistAdapter;
|
|
1890
1901
|
exports2.buildThemeStyle = buildThemeStyle;
|
|
1891
1902
|
exports2.clearDeviceCache = clearDeviceCache;
|
|
1892
|
-
exports2.configAd = configAd;
|
|
1893
|
-
exports2.configContact = configContact;
|
|
1894
|
-
exports2.configShare = configShare;
|
|
1895
1903
|
exports2.confirmReward = confirmReward;
|
|
1896
1904
|
exports2.cosAdapter = cosAdapter;
|
|
1897
1905
|
exports2.destroyAds = destroyAds;
|
|
@@ -1910,7 +1918,10 @@ var __publicField = (obj, key, value) => {
|
|
|
1910
1918
|
exports2.ossAdapter = ossAdapter;
|
|
1911
1919
|
exports2.qiniuAdapter = qiniuAdapter;
|
|
1912
1920
|
exports2.resolveAppearance = resolveAppearance;
|
|
1913
|
-
exports2.
|
|
1921
|
+
exports2.setConfigAd = setConfigAd;
|
|
1922
|
+
exports2.setConfigContact = setConfigContact;
|
|
1923
|
+
exports2.setConfigShare = setConfigShare;
|
|
1924
|
+
exports2.setupInterceptors = setupInterceptors;
|
|
1914
1925
|
exports2.useAd = useAd;
|
|
1915
1926
|
exports2.useApp = useApp;
|
|
1916
1927
|
exports2.useColor = useColor;
|
package/dist/index.mjs
CHANGED
|
@@ -618,6 +618,15 @@ function useFormat() {
|
|
|
618
618
|
}
|
|
619
619
|
return { date, fileSize, phone, money };
|
|
620
620
|
}
|
|
621
|
+
function unwrapPayload(raw) {
|
|
622
|
+
if (raw == null)
|
|
623
|
+
return null;
|
|
624
|
+
if (typeof raw === "object" && "code" in raw && typeof raw.code === "number") {
|
|
625
|
+
const env = raw;
|
|
626
|
+
return env.code === 1 && env.data ? env.data : null;
|
|
627
|
+
}
|
|
628
|
+
return raw;
|
|
629
|
+
}
|
|
621
630
|
const EMPTY = {
|
|
622
631
|
banner_unit_id: "",
|
|
623
632
|
grid_unit_id: "",
|
|
@@ -627,7 +636,7 @@ const EMPTY = {
|
|
|
627
636
|
popup_unit_id: ""
|
|
628
637
|
};
|
|
629
638
|
let adapter$1 = null;
|
|
630
|
-
function
|
|
639
|
+
function setConfigAd(a) {
|
|
631
640
|
adapter$1 = a;
|
|
632
641
|
}
|
|
633
642
|
const useAdStore = defineStore("hlw_ad", () => {
|
|
@@ -646,11 +655,11 @@ function useAd() {
|
|
|
646
655
|
if (loaded.value && !force)
|
|
647
656
|
return;
|
|
648
657
|
if (!(adapter$1 == null ? void 0 : adapter$1.getConfig)) {
|
|
649
|
-
console.warn("[useAd] adapter.getConfig 未注入;先调用
|
|
658
|
+
console.warn("[useAd] adapter.getConfig 未注入;先调用 setConfigAd()");
|
|
650
659
|
return;
|
|
651
660
|
}
|
|
652
661
|
try {
|
|
653
|
-
const cfg = await adapter$1.getConfig();
|
|
662
|
+
const cfg = unwrapPayload(await adapter$1.getConfig());
|
|
654
663
|
if (cfg) {
|
|
655
664
|
store.config = cfg;
|
|
656
665
|
store.loaded = true;
|
|
@@ -876,7 +885,7 @@ function useShare(config2) {
|
|
|
876
885
|
let shareAdapter = null;
|
|
877
886
|
const shareCache = ref(null);
|
|
878
887
|
let sharePending = null;
|
|
879
|
-
function
|
|
888
|
+
function setConfigShare(a) {
|
|
880
889
|
shareAdapter = a;
|
|
881
890
|
}
|
|
882
891
|
function loadShareConfig() {
|
|
@@ -885,10 +894,11 @@ function loadShareConfig() {
|
|
|
885
894
|
if (sharePending)
|
|
886
895
|
return sharePending;
|
|
887
896
|
if (!(shareAdapter == null ? void 0 : shareAdapter.getConfig)) {
|
|
888
|
-
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用
|
|
897
|
+
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用 setConfigShare()");
|
|
889
898
|
return Promise.resolve();
|
|
890
899
|
}
|
|
891
|
-
sharePending = shareAdapter.getConfig().then((
|
|
900
|
+
sharePending = shareAdapter.getConfig().then((raw) => {
|
|
901
|
+
const cfg = unwrapPayload(raw);
|
|
892
902
|
if (cfg)
|
|
893
903
|
shareCache.value = cfg;
|
|
894
904
|
}).catch((e) => {
|
|
@@ -914,7 +924,7 @@ function useShareConfig(pageKey, fallback) {
|
|
|
914
924
|
let adapter = null;
|
|
915
925
|
const config = ref(null);
|
|
916
926
|
let pending = null;
|
|
917
|
-
function
|
|
927
|
+
function setConfigContact(a) {
|
|
918
928
|
adapter = a;
|
|
919
929
|
}
|
|
920
930
|
function loadConfig() {
|
|
@@ -923,10 +933,11 @@ function loadConfig() {
|
|
|
923
933
|
if (pending)
|
|
924
934
|
return pending;
|
|
925
935
|
if (!(adapter == null ? void 0 : adapter.getConfig)) {
|
|
926
|
-
console.warn("[useContact] adapter.getConfig 未注入;先调用
|
|
936
|
+
console.warn("[useContact] adapter.getConfig 未注入;先调用 setConfigContact()");
|
|
927
937
|
return Promise.resolve();
|
|
928
938
|
}
|
|
929
|
-
pending = adapter.getConfig().then((
|
|
939
|
+
pending = adapter.getConfig().then((raw) => {
|
|
940
|
+
const cfg = unwrapPayload(raw);
|
|
930
941
|
if (cfg)
|
|
931
942
|
config.value = cfg;
|
|
932
943
|
}).catch((e) => {
|
|
@@ -1773,7 +1784,7 @@ function buildSignString(url) {
|
|
|
1773
1784
|
}
|
|
1774
1785
|
}
|
|
1775
1786
|
let _sigSecret = "";
|
|
1776
|
-
function
|
|
1787
|
+
function setupInterceptors(options = {}) {
|
|
1777
1788
|
const opts = { ..._defaultOpts, ...options };
|
|
1778
1789
|
if (opts.sigSecret)
|
|
1779
1790
|
_sigSecret = opts.sigSecret;
|
|
@@ -1889,9 +1900,6 @@ export {
|
|
|
1889
1900
|
alistAdapter,
|
|
1890
1901
|
buildThemeStyle,
|
|
1891
1902
|
clearDeviceCache,
|
|
1892
|
-
configAd,
|
|
1893
|
-
configContact,
|
|
1894
|
-
configShare,
|
|
1895
1903
|
confirmReward,
|
|
1896
1904
|
cosAdapter,
|
|
1897
1905
|
destroyAds,
|
|
@@ -1910,7 +1918,10 @@ export {
|
|
|
1910
1918
|
ossAdapter,
|
|
1911
1919
|
qiniuAdapter,
|
|
1912
1920
|
resolveAppearance,
|
|
1913
|
-
|
|
1921
|
+
setConfigAd,
|
|
1922
|
+
setConfigContact,
|
|
1923
|
+
setConfigShare,
|
|
1924
|
+
setupInterceptors,
|
|
1914
1925
|
useAd,
|
|
1915
1926
|
useApp,
|
|
1916
1927
|
useColor,
|
package/package.json
CHANGED
package/src/app.ts
CHANGED
|
@@ -90,7 +90,7 @@ let _sigSecret = '';
|
|
|
90
90
|
/**
|
|
91
91
|
* 注册默认请求、响应和错误拦截器。
|
|
92
92
|
*/
|
|
93
|
-
export function
|
|
93
|
+
export function setupInterceptors(options: InterceptorOptions & { sigSecret?: string } = {}) {
|
|
94
94
|
const opts = { ..._defaultOpts, ...options };
|
|
95
95
|
if (opts.sigSecret) _sigSecret = opts.sigSecret;
|
|
96
96
|
if (opts.baseURL) http.setBaseURL(opts.baseURL);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter 返回值解包:兼容业务方传「已解包 T」或「ThinkAdmin envelope { code, data }」。
|
|
3
|
+
*
|
|
4
|
+
* 业务方写法:
|
|
5
|
+
* setConfigAd({ getConfig: getAdConfig }) // 直接传 envelope-returning 函数
|
|
6
|
+
* setConfigAd({ getConfig: async () => myUnwrapped }) // 也支持已解包
|
|
7
|
+
*
|
|
8
|
+
* 鸭子类型识别:raw 是对象且有 number 类型的 code 字段 → 当 envelope 处理。
|
|
9
|
+
*/
|
|
10
|
+
export type AdapterPayload<T> = T | null | { code: number; data?: T; info?: string };
|
|
11
|
+
|
|
12
|
+
export function unwrapPayload<T>(raw: AdapterPayload<T>): T | null {
|
|
13
|
+
if (raw == null) return null;
|
|
14
|
+
if (typeof raw === "object" && "code" in raw && typeof (raw as { code: unknown }).code === "number") {
|
|
15
|
+
const env = raw as { code: number; data?: T };
|
|
16
|
+
return env.code === 1 && env.data ? env.data : null;
|
|
17
|
+
}
|
|
18
|
+
return raw as T;
|
|
19
|
+
}
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
*
|
|
12
12
|
* 1. 在 App.vue 注入「全局」回调(拿配置 + 校验登录):
|
|
13
13
|
*
|
|
14
|
-
* import {
|
|
14
|
+
* import { setConfigAd } from "@hlw-uni/mp-vue";
|
|
15
15
|
* import { getAdConfig } from "@/api/ad";
|
|
16
16
|
* import { useUserStore } from "@/store";
|
|
17
17
|
*
|
|
18
|
-
*
|
|
18
|
+
* setConfigAd({
|
|
19
19
|
* getConfig: async () => {
|
|
20
20
|
* const res = await getAdConfig();
|
|
21
21
|
* return res.code === 1 && res.data ? res.data : null;
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
import { defineStore, storeToRefs } from "pinia";
|
|
46
46
|
import { ref } from "vue";
|
|
47
47
|
import { useMsg, type HlwMsg } from "../msg";
|
|
48
|
+
import { unwrapPayload, type AdapterPayload } from "../_internal/unwrap";
|
|
48
49
|
|
|
49
50
|
/** 6 种广告类型 */
|
|
50
51
|
export type AdType = "banner" | "grid" | "custom" | "video" | "reward" | "popup";
|
|
@@ -65,10 +66,18 @@ export interface AdError {
|
|
|
65
66
|
errMsg: string;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* 业务回调注入接口 —— setConfigAd 时由项目提供。
|
|
71
|
+
*
|
|
72
|
+
* getConfig 支持两种返回:
|
|
73
|
+
* - 已解包:直接返回 AdConfig 或 null
|
|
74
|
+
* - ThinkAdmin envelope:返回 { code, data } 对象,库自动按 code===1 解包
|
|
75
|
+
*
|
|
76
|
+
* 业务方可以直接传 envelope-returning 的接口函数引用:
|
|
77
|
+
* setConfigAd({ getConfig: getAdConfig })
|
|
78
|
+
*/
|
|
69
79
|
export interface AdAdapter {
|
|
70
|
-
|
|
71
|
-
getConfig: () => Promise<AdConfig | null>;
|
|
80
|
+
getConfig: () => Promise<AdapterPayload<AdConfig>>;
|
|
72
81
|
/** 是否已登录;不传 = 不校验(showReward 调用前会问一次) */
|
|
73
82
|
isAuth?: () => boolean;
|
|
74
83
|
}
|
|
@@ -114,7 +123,7 @@ let adapter: AdAdapter | null = null;
|
|
|
114
123
|
* 注入业务回调,应用启动时调用一次。
|
|
115
124
|
* 不调用也不会崩,但 loadConfig / showReward 会无效。
|
|
116
125
|
*/
|
|
117
|
-
export function
|
|
126
|
+
export function setConfigAd(a: AdAdapter): void {
|
|
118
127
|
adapter = a;
|
|
119
128
|
}
|
|
120
129
|
|
|
@@ -151,11 +160,11 @@ export function useAd() {
|
|
|
151
160
|
async function loadConfig(force = false): Promise<void> {
|
|
152
161
|
if (loaded.value && !force) return;
|
|
153
162
|
if (!adapter?.getConfig) {
|
|
154
|
-
console.warn("[useAd] adapter.getConfig 未注入;先调用
|
|
163
|
+
console.warn("[useAd] adapter.getConfig 未注入;先调用 setConfigAd()");
|
|
155
164
|
return;
|
|
156
165
|
}
|
|
157
166
|
try {
|
|
158
|
-
const cfg = await adapter.getConfig();
|
|
167
|
+
const cfg = unwrapPayload(await adapter.getConfig());
|
|
159
168
|
if (cfg) {
|
|
160
169
|
store.config = cfg;
|
|
161
170
|
store.loaded = true;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 1. App.vue / bootstrap 注入回调:
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* setConfigContact({
|
|
11
11
|
* getConfig: async () => {
|
|
12
12
|
* const res = await getContactConfig();
|
|
13
13
|
* return res.code === 1 ? res.data : null;
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* <hlw-button open-type="contact" v-bind="contact">联系客服</hlw-button>
|
|
21
21
|
*/
|
|
22
22
|
import { computed, ref } from "vue";
|
|
23
|
+
import { unwrapPayload, type AdapterPayload } from "../_internal/unwrap";
|
|
23
24
|
|
|
24
25
|
/** 后端返回的客服配置(按 button open-type=contact 标准属性命名) */
|
|
25
26
|
export interface ContactConfig {
|
|
@@ -29,10 +30,12 @@ export interface ContactConfig {
|
|
|
29
30
|
show_message_card: boolean;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Adapter 注入接口 —— getConfig 支持「已解包」或「ThinkAdmin envelope」两种返回。
|
|
35
|
+
* 业务方可以直接传 envelope-returning 接口:setConfigContact({ getConfig: getContactConfig })
|
|
36
|
+
*/
|
|
33
37
|
export interface ContactAdapter {
|
|
34
|
-
|
|
35
|
-
getConfig: () => Promise<ContactConfig | null>;
|
|
38
|
+
getConfig: () => Promise<AdapterPayload<ContactConfig>>;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/** v-bind 到 button 的 camelCase props(微信原生属性约定) */
|
|
@@ -50,7 +53,7 @@ let pending: Promise<void> | null = null;
|
|
|
50
53
|
/**
|
|
51
54
|
* 注入业务回调(应用启动时调用一次;不调用则 useContact 始终返回空字段)。
|
|
52
55
|
*/
|
|
53
|
-
export function
|
|
56
|
+
export function setConfigContact(a: ContactAdapter): void {
|
|
54
57
|
adapter = a;
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -58,11 +61,12 @@ function loadConfig(): Promise<void> {
|
|
|
58
61
|
if (config.value) return Promise.resolve();
|
|
59
62
|
if (pending) return pending;
|
|
60
63
|
if (!adapter?.getConfig) {
|
|
61
|
-
console.warn("[useContact] adapter.getConfig 未注入;先调用
|
|
64
|
+
console.warn("[useContact] adapter.getConfig 未注入;先调用 setConfigContact()");
|
|
62
65
|
return Promise.resolve();
|
|
63
66
|
}
|
|
64
67
|
pending = adapter.getConfig()
|
|
65
|
-
.then((
|
|
68
|
+
.then((raw) => {
|
|
69
|
+
const cfg = unwrapPayload(raw);
|
|
66
70
|
if (cfg) config.value = cfg;
|
|
67
71
|
})
|
|
68
72
|
.catch((e) => {
|
package/src/composables/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { useValidate } from "./validate";
|
|
|
12
12
|
export { useFormat } from "./format";
|
|
13
13
|
export {
|
|
14
14
|
useAd,
|
|
15
|
-
|
|
15
|
+
setConfigAd,
|
|
16
16
|
destroyAds,
|
|
17
17
|
confirmReward,
|
|
18
18
|
type AdType,
|
|
@@ -26,7 +26,7 @@ export {
|
|
|
26
26
|
export {
|
|
27
27
|
useShare,
|
|
28
28
|
useShareConfig,
|
|
29
|
-
|
|
29
|
+
setConfigShare,
|
|
30
30
|
type ShareConfig,
|
|
31
31
|
type ShareConfigResolver,
|
|
32
32
|
type ShareFrom,
|
|
@@ -40,7 +40,7 @@ export {
|
|
|
40
40
|
} from "./share";
|
|
41
41
|
export {
|
|
42
42
|
useContact,
|
|
43
|
-
|
|
43
|
+
setConfigContact,
|
|
44
44
|
type ContactConfig,
|
|
45
45
|
type ContactAdapter,
|
|
46
46
|
type ContactBindProps,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app';
|
|
9
9
|
import { ref } from 'vue';
|
|
10
|
+
import { unwrapPayload, type AdapterPayload } from '../_internal/unwrap';
|
|
10
11
|
|
|
11
12
|
export interface ShareAppMessageContent {
|
|
12
13
|
/** 分享标题 */
|
|
@@ -88,7 +89,7 @@ export function useShare(config: ShareConfig | ShareConfigResolver) {
|
|
|
88
89
|
*
|
|
89
90
|
* 1. App.vue / bootstrap 注入回调:
|
|
90
91
|
*
|
|
91
|
-
*
|
|
92
|
+
* setConfigShare({
|
|
92
93
|
* getConfig: async () => {
|
|
93
94
|
* const res = await getShareConfig();
|
|
94
95
|
* return res.code === 1 ? res.data : null;
|
|
@@ -114,10 +115,12 @@ export interface PageShareItem {
|
|
|
114
115
|
/** 后端返回的页面 key → 配置映射 */
|
|
115
116
|
export type ShareConfigMap = Record<string, PageShareItem>;
|
|
116
117
|
|
|
117
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Adapter 注入接口 —— getConfig 支持「已解包」或「ThinkAdmin envelope」两种返回值。
|
|
120
|
+
* 业务方可以直接传 envelope-returning 接口:setConfigShare({ getConfig: getShareConfig })
|
|
121
|
+
*/
|
|
118
122
|
export interface ShareConfigAdapter {
|
|
119
|
-
|
|
120
|
-
getConfig: () => Promise<ShareConfigMap | null>;
|
|
123
|
+
getConfig: () => Promise<AdapterPayload<ShareConfigMap>>;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
/** 页面声明的兜底文案 / 跳转路径 */
|
|
@@ -144,7 +147,7 @@ let sharePending: Promise<void> | null = null;
|
|
|
144
147
|
/**
|
|
145
148
|
* 注入业务回调(应用启动时调用一次;不调用则始终用 fallback)。
|
|
146
149
|
*/
|
|
147
|
-
export function
|
|
150
|
+
export function setConfigShare(a: ShareConfigAdapter): void {
|
|
148
151
|
shareAdapter = a;
|
|
149
152
|
}
|
|
150
153
|
|
|
@@ -152,11 +155,12 @@ function loadShareConfig(): Promise<void> {
|
|
|
152
155
|
if (shareCache.value) return Promise.resolve();
|
|
153
156
|
if (sharePending) return sharePending;
|
|
154
157
|
if (!shareAdapter?.getConfig) {
|
|
155
|
-
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用
|
|
158
|
+
console.warn("[useShareConfig] adapter.getConfig 未注入;先调用 setConfigShare()");
|
|
156
159
|
return Promise.resolve();
|
|
157
160
|
}
|
|
158
161
|
sharePending = shareAdapter.getConfig()
|
|
159
|
-
.then((
|
|
162
|
+
.then((raw) => {
|
|
163
|
+
const cfg = unwrapPayload(raw);
|
|
160
164
|
if (cfg) shareCache.value = cfg;
|
|
161
165
|
})
|
|
162
166
|
.catch((e) => {
|
package/src/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type { HlwPagingRef, HlwPagingInstance } from "./components/hlw-paging/ty
|
|
|
19
19
|
export { useThemeStore } from "./stores/theme";
|
|
20
20
|
|
|
21
21
|
// App 根上下文
|
|
22
|
-
export { useApp,
|
|
22
|
+
export { useApp, setupInterceptors } from "./app";
|
|
23
23
|
|
|
24
24
|
// hlw 全局命名空间
|
|
25
25
|
export { hlw, type HlwInstance } from "./hlw";
|