@hlw-uni/mp-vue 1.2.26 → 2.0.0
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 +33 -0
- package/dist/composables/ad/index.d.ts +134 -0
- package/dist/composables/color/index.d.ts +8 -0
- package/dist/composables/contact/index.d.ts +28 -0
- package/dist/composables/device/index.d.ts +129 -0
- package/dist/composables/format/index.d.ts +9 -0
- package/dist/composables/http/adapters/alist.d.ts +3 -0
- package/dist/composables/http/adapters/base.d.ts +19 -0
- package/dist/composables/http/adapters/cos.d.ts +3 -0
- package/dist/composables/http/adapters/index.d.ts +15 -0
- package/dist/composables/http/adapters/oss.d.ts +3 -0
- package/dist/composables/http/adapters/qiniu.d.ts +3 -0
- package/dist/composables/http/client.d.ts +66 -0
- package/dist/composables/http/index.d.ts +8 -0
- package/dist/composables/http/types.d.ts +51 -0
- package/dist/composables/index.d.ts +26 -0
- package/dist/composables/loading/index.d.ts +7 -0
- package/dist/composables/msg/index.d.ts +36 -0
- package/dist/composables/navigator/index.d.ts +47 -0
- package/dist/composables/page-meta/index.d.ts +18 -0
- package/dist/composables/refs/index.d.ts +8 -0
- package/dist/composables/share/index.d.ts +67 -0
- package/dist/composables/storage/index.d.ts +16 -0
- package/dist/composables/theme/font.d.ts +1 -1
- package/dist/composables/theme/index.d.ts +15 -2
- package/dist/composables/utils/index.d.ts +39 -0
- package/dist/composables/validate/index.d.ts +12 -0
- package/dist/directives/copy.d.ts +3 -0
- package/dist/directives/index.d.ts +1 -0
- package/dist/hlw.d.ts +14 -0
- package/dist/index.d.ts +10 -7
- package/dist/index.js +1722 -63
- package/dist/index.mjs +1721 -62
- package/package.json +5 -3
- package/src/app.ts +173 -0
- package/src/components/hlw-ad/index.vue +74 -30
- package/src/composables/ad/index.ts +386 -0
- package/src/composables/color/index.ts +44 -0
- package/src/composables/contact/index.ts +88 -0
- package/src/composables/device/index.ts +168 -0
- package/src/composables/format/index.ts +48 -0
- package/src/composables/http/adapters/alist.ts +19 -0
- package/src/composables/http/adapters/base.ts +21 -0
- package/src/composables/http/adapters/cos.ts +23 -0
- package/src/composables/http/adapters/index.ts +31 -0
- package/src/composables/http/adapters/oss.ts +22 -0
- package/src/composables/http/adapters/qiniu.ts +19 -0
- package/src/composables/http/client.ts +237 -0
- package/src/composables/http/index.ts +8 -0
- package/src/composables/http/types.ts +57 -0
- package/src/composables/http/useRequest.ts +107 -0
- package/src/composables/index.ts +82 -0
- package/src/composables/loading/index.ts +23 -0
- package/src/composables/msg/index.ts +132 -0
- package/src/composables/navigator/index.ts +104 -0
- package/src/composables/page-meta/index.ts +49 -0
- package/src/composables/refs/index.ts +30 -0
- package/src/composables/share/index.ts +185 -0
- package/src/composables/storage/index.ts +76 -0
- package/src/composables/theme/font.ts +26 -5
- package/src/composables/theme/index.ts +26 -11
- package/src/composables/theme/palette.ts +1 -1
- package/src/composables/utils/index.ts +160 -0
- package/src/composables/validate/index.ts +58 -0
- package/src/directives/copy.ts +50 -0
- package/src/directives/index.ts +1 -0
- package/src/hlw.ts +37 -0
- package/src/index.ts +21 -20
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hlw-uni/mp-vue",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "hlw-uni Vue
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "hlw-uni 小程序运行时 — Vue 组件 + composables + theme + http + 工具集(合并自原 mp-core)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -32,15 +32,17 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@dcloudio/types": "^3.4.30",
|
|
35
|
+
"@types/md5": "^2.3.6",
|
|
35
36
|
"@types/node": "^20.19.39",
|
|
36
37
|
"@vitejs/plugin-vue": "^5.2.4",
|
|
38
|
+
"pinia": "^2.3.1",
|
|
37
39
|
"typescript": "^4.9.5",
|
|
38
40
|
"vite": "5.2.8",
|
|
39
41
|
"vite-plugin-dts": "^4.5.4",
|
|
40
42
|
"vue": "^3.5.32"
|
|
41
43
|
},
|
|
42
44
|
"dependencies": {
|
|
43
|
-
"
|
|
45
|
+
"md5": "^2.3.0",
|
|
44
46
|
"z-paging": "^2.8.8"
|
|
45
47
|
}
|
|
46
48
|
}
|
package/src/app.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useApp - 应用根上下文
|
|
3
|
+
* 生命周期、Pinia、拦截器、hlw 注入全部收敛在此。
|
|
4
|
+
*/
|
|
5
|
+
import { createSSRApp, type App, type Component } from 'vue';
|
|
6
|
+
import { hlw } from '@/hlw';
|
|
7
|
+
import { http } from '@/composables/http';
|
|
8
|
+
import { useDevice } from '@/composables/device';
|
|
9
|
+
import md5 from 'md5';
|
|
10
|
+
import type { ApiResponse, RequestConfig } from '@/composables/http/types';
|
|
11
|
+
|
|
12
|
+
let _installed = false;
|
|
13
|
+
let _interceptorCleanup: Array<() => void> = [];
|
|
14
|
+
|
|
15
|
+
export interface InterceptorOptions {
|
|
16
|
+
/** API 基础地址 */
|
|
17
|
+
baseURL?: string;
|
|
18
|
+
/** 自动注入 Token 的 header 键名 */
|
|
19
|
+
tokenHeader?: string;
|
|
20
|
+
/** Token 来源函数 */
|
|
21
|
+
getToken?: () => string;
|
|
22
|
+
/** 登录失效时的处理函数 */
|
|
23
|
+
onUnauthorized?: () => void;
|
|
24
|
+
/** 接口业务错误码是否自动 toast */
|
|
25
|
+
autoToastError?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const _defaultOpts: InterceptorOptions = {
|
|
29
|
+
tokenHeader: 'x-token',
|
|
30
|
+
autoToastError: true,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 创建 uni-app 应用入口工具。
|
|
35
|
+
*/
|
|
36
|
+
export function useApp() {
|
|
37
|
+
/** 用于在导出前挂载插件。 */
|
|
38
|
+
const _plugins: Array<(app: App) => void> = [];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 注册一个待安装的应用插件。
|
|
42
|
+
*/
|
|
43
|
+
function use(pluginOrInstaller: any) {
|
|
44
|
+
_plugins.push((app) => app.use(pluginOrInstaller));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 生成符合 uni-app 约定的 createApp 入口函数。
|
|
49
|
+
*/
|
|
50
|
+
function install(AppComponent: Component) {
|
|
51
|
+
if (_installed) {
|
|
52
|
+
console.warn('[hlw] useApp().install() 应只调用一次');
|
|
53
|
+
}
|
|
54
|
+
_installed = true;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 创建并返回 uni-app 运行时应用实例。
|
|
58
|
+
*/
|
|
59
|
+
function createApp() {
|
|
60
|
+
const app = createSSRApp(AppComponent);
|
|
61
|
+
app.config.globalProperties['hlw'] = hlw;
|
|
62
|
+
_plugins.forEach((fn) => fn(app));
|
|
63
|
+
return { app };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return createApp;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { install, use, hlw, http };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 提取 URL 中的 query 参数,排序后拼接为签名字符串。
|
|
74
|
+
*/
|
|
75
|
+
function buildSignString(url: string): string {
|
|
76
|
+
try {
|
|
77
|
+
const [path, query] = url.split('?');
|
|
78
|
+
if (!query) return path + '&';
|
|
79
|
+
const params = query.split('&').filter(Boolean);
|
|
80
|
+
params.sort();
|
|
81
|
+
return params.join('&') + '&';
|
|
82
|
+
} catch {
|
|
83
|
+
return url;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** sig 签名密钥。 */
|
|
88
|
+
let _sigSecret = '';
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 注册默认请求、响应和错误拦截器。
|
|
92
|
+
*/
|
|
93
|
+
export function setupDefaultInterceptors(options: InterceptorOptions & { sigSecret?: string } = {}) {
|
|
94
|
+
const opts = { ..._defaultOpts, ...options };
|
|
95
|
+
if (opts.sigSecret) _sigSecret = opts.sigSecret;
|
|
96
|
+
if (opts.baseURL) http.setBaseURL(opts.baseURL);
|
|
97
|
+
|
|
98
|
+
_interceptorCleanup.forEach((dispose) => dispose());
|
|
99
|
+
_interceptorCleanup = [];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 请求拦截:注入设备信息、签名和 token。
|
|
103
|
+
*/
|
|
104
|
+
const offRequest = http.onRequest((config: RequestConfig) => {
|
|
105
|
+
const device = useDevice();
|
|
106
|
+
if (device.value) {
|
|
107
|
+
const d = device.value;
|
|
108
|
+
const query = [
|
|
109
|
+
['appid', d.appid],
|
|
110
|
+
['device_brand', d.device_brand],
|
|
111
|
+
['device_model', d.device_model],
|
|
112
|
+
['device_id', d.device_id],
|
|
113
|
+
['device_type', d.device_type],
|
|
114
|
+
['device_orientation', d.device_orientation],
|
|
115
|
+
['platform', d.platform],
|
|
116
|
+
['system', d.system],
|
|
117
|
+
['os', d.os],
|
|
118
|
+
['version', d.version],
|
|
119
|
+
['sdk_version', d.sdk_version],
|
|
120
|
+
['host_name', d.host_name],
|
|
121
|
+
['host_version', d.host_version],
|
|
122
|
+
['host_language', d.host_language],
|
|
123
|
+
['language', d.language],
|
|
124
|
+
['app_version', d.app_version],
|
|
125
|
+
['app_version_code', d.app_version_code],
|
|
126
|
+
['screen_width', String(d.screen_width)],
|
|
127
|
+
['screen_height', String(d.screen_height)],
|
|
128
|
+
]
|
|
129
|
+
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v ?? '')}`)
|
|
130
|
+
.join('&');
|
|
131
|
+
config.url = config.url + (config.url.includes('?') ? '&' : '?') + query;
|
|
132
|
+
config.headers = { ...config.headers, 'X-Appid': d.appid };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (_sigSecret) {
|
|
136
|
+
const signStr = buildSignString(config.url);
|
|
137
|
+
const sig = md5(signStr + _sigSecret);
|
|
138
|
+
config.url = config.url + '&sig=' + sig;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (opts.getToken) {
|
|
142
|
+
const token = opts.getToken();
|
|
143
|
+
if (token) {
|
|
144
|
+
config.headers = {
|
|
145
|
+
...config.headers,
|
|
146
|
+
[opts.tokenHeader!]: token,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return config;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 响应拦截:处理业务错误提示。
|
|
155
|
+
*/
|
|
156
|
+
const offResponse = http.onResponse((res: ApiResponse<unknown>) => {
|
|
157
|
+
if (opts.autoToastError && res.code !== 1) {
|
|
158
|
+
uni.showToast({ title: res.info || '请求失败', icon: 'none' });
|
|
159
|
+
}
|
|
160
|
+
return res;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 错误拦截:处理未授权场景。
|
|
165
|
+
*/
|
|
166
|
+
const offError = http.onError((err: Error) => {
|
|
167
|
+
if (err.message.includes('401')) {
|
|
168
|
+
opts.onUnauthorized?.();
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
_interceptorCleanup = [offRequest, offResponse, offError];
|
|
173
|
+
}
|
|
@@ -1,50 +1,94 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
HlwAd — 小程序展示型广告原子组件
|
|
3
|
+
------------------------------------------------------------------
|
|
4
|
+
用法(业务方从 mp-core useAd().config 取对应 unit_id 传入):
|
|
5
|
+
hlw-ad type="banner" :unit-id="config.banner_unit_id"
|
|
6
|
+
hlw-ad type="grid" :unit-id="config.grid_unit_id"
|
|
7
|
+
hlw-ad type="custom" :unit-id="config.custom_unit_id"
|
|
8
|
+
|
|
9
|
+
渲染分支:
|
|
10
|
+
- banner → ad type="banner" unit-id="..."(微信流量主自带样式)
|
|
11
|
+
- grid / custom → ad-custom unit-id="..."(原生模板广告)
|
|
12
|
+
|
|
13
|
+
video / reward / popup 不走这个组件:
|
|
14
|
+
- reward / popup → useAd().showReward() / showPopup()
|
|
15
|
+
- video(贴片)须嵌在 video 标签内,业务侧自己用 <ad type="video">
|
|
16
|
+
-->
|
|
1
17
|
<template>
|
|
2
|
-
<
|
|
18
|
+
<view
|
|
19
|
+
v-if="visible"
|
|
20
|
+
:class="['hlw-ad', `hlw-ad--${type}`, customClass]"
|
|
21
|
+
:style="customStyle"
|
|
22
|
+
>
|
|
23
|
+
<ad
|
|
24
|
+
v-if="type === 'banner'"
|
|
25
|
+
type="banner"
|
|
26
|
+
:unit-id="unitId"
|
|
27
|
+
@load="onLoad"
|
|
28
|
+
@error="onError"
|
|
29
|
+
/>
|
|
30
|
+
<ad-custom
|
|
31
|
+
v-else
|
|
32
|
+
:unit-id="unitId"
|
|
33
|
+
@load="onLoad"
|
|
34
|
+
@error="onError"
|
|
35
|
+
/>
|
|
36
|
+
</view>
|
|
3
37
|
</template>
|
|
38
|
+
|
|
4
39
|
<script setup lang="ts">
|
|
5
|
-
|
|
6
|
-
* HlwAd — 小程序信息流 / Banner 广告组件
|
|
7
|
-
*
|
|
8
|
-
* 对小程序原生 <ad> 组件的封装。
|
|
9
|
-
* 支持微信小程序、抖音小程序等,由 uni-app 编译器适配各平台。
|
|
10
|
-
*
|
|
11
|
-
* Props:
|
|
12
|
-
* unitId - 广告单元 ID(各平台在广告后台申请)
|
|
13
|
-
*
|
|
14
|
-
* Emits:
|
|
15
|
-
* load - 广告加载成功
|
|
16
|
-
* close - 用户关闭广告
|
|
17
|
-
* error - 广告加载/展示失败,携带 { errCode, errMsg }
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```vue
|
|
21
|
-
* <HlwAd unit-id="adunit-xxx" @load="onLoad" @error="onError" />
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
40
|
+
import { computed } from "vue";
|
|
24
41
|
|
|
25
42
|
defineOptions({ name: "HlwAd" });
|
|
26
43
|
|
|
27
|
-
|
|
28
|
-
/**
|
|
44
|
+
interface Props {
|
|
45
|
+
/** 广告类型 — 仅展示型(banner / grid / custom) */
|
|
46
|
+
type: "banner" | "grid" | "custom";
|
|
47
|
+
/** 微信广告单元 id;空字符串 → 不渲染 */
|
|
29
48
|
unitId: string;
|
|
30
|
-
|
|
49
|
+
/** 自定义样式(合并到根元素) */
|
|
50
|
+
customStyle?: string;
|
|
51
|
+
/** 自定义 class */
|
|
52
|
+
customClass?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
56
|
+
customStyle: "",
|
|
57
|
+
customClass: "",
|
|
58
|
+
});
|
|
31
59
|
|
|
32
60
|
const emit = defineEmits<{
|
|
33
61
|
(e: "load", event: any): void;
|
|
34
|
-
(e: "close", event: any): void;
|
|
35
62
|
(e: "error", event: any): void;
|
|
36
63
|
}>();
|
|
37
64
|
|
|
65
|
+
/** 有 unit_id 才渲染 */
|
|
66
|
+
const visible = computed(() => !!props.unitId);
|
|
67
|
+
|
|
38
68
|
function onLoad(event: any) {
|
|
39
69
|
emit("load", event);
|
|
40
70
|
}
|
|
41
|
-
|
|
42
|
-
function onClose(event: any) {
|
|
43
|
-
emit("close", event);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
71
|
function onError(event: any) {
|
|
47
|
-
console.
|
|
72
|
+
console.warn(`[HlwAd] type=${props.type} error`, event?.detail);
|
|
48
73
|
emit("error", event);
|
|
49
74
|
}
|
|
50
75
|
</script>
|
|
76
|
+
|
|
77
|
+
<style scoped>
|
|
78
|
+
.hlw-ad {
|
|
79
|
+
border-radius: var(--radius-lg);
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
background: var(--surface-card, #ffffff);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* 格子广告:默认右下悬浮;微信硬性规则要求 wrapper 透明无圆角,customStyle 可覆盖 */
|
|
85
|
+
.hlw-ad--grid {
|
|
86
|
+
position: fixed;
|
|
87
|
+
right: 20rpx;
|
|
88
|
+
bottom: 200rpx;
|
|
89
|
+
z-index: 99;
|
|
90
|
+
border-radius: 0;
|
|
91
|
+
overflow: visible;
|
|
92
|
+
background: transparent;
|
|
93
|
+
}
|
|
94
|
+
</style>
|