@hlw-uni/mp-vue 2.1.71 → 2.1.97

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 (86) hide show
  1. package/README.md +230 -386
  2. package/dist/app.d.ts +1 -1
  3. package/dist/core/index.d.ts +3 -0
  4. package/dist/core/{theme.d.ts → theme/index.d.ts} +6 -1
  5. package/dist/hlw.d.ts +1 -10
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js +834 -804
  8. package/dist/index.mjs +836 -806
  9. package/dist/utils/ad/index.d.ts +61 -0
  10. package/dist/{composables/utils → utils/common}/index.d.ts +1 -24
  11. package/dist/{composables → utils}/device/index.d.ts +7 -8
  12. package/dist/utils/index.d.ts +5 -0
  13. package/dist/{composables → utils}/navigator/index.d.ts +14 -30
  14. package/dist/{composables → utils}/request/client.d.ts +2 -8
  15. package/dist/{composables → utils}/request/index.d.ts +1 -1
  16. package/dist/{composables → utils}/request/service.d.ts +2 -2
  17. package/package.json +1 -1
  18. package/src/app.ts +2 -2
  19. package/src/components/hlw-add-mini/README.md +56 -9
  20. package/src/components/hlw-add-mini/index.vue +12 -9
  21. package/src/components/hlw-avatar-upload/index.vue +103 -0
  22. package/src/components/hlw-back-top/index.vue +1 -1
  23. package/src/components/hlw-button/index.vue +5 -16
  24. package/src/components/hlw-canvas/index.vue +7 -7
  25. package/src/components/hlw-cell/index.vue +1 -1
  26. package/src/components/{hlw-custom/hlw-custom.vue → hlw-custom-service/hlw-custom-service.vue} +27 -15
  27. package/src/components/hlw-empty/index.vue +14 -0
  28. package/src/components/hlw-header/index.vue +1 -1
  29. package/src/components/hlw-menu/index.vue +40 -37
  30. package/src/components/hlw-nav-bar/index.vue +23 -8
  31. package/src/components/hlw-nickname/index.vue +185 -0
  32. package/src/components/hlw-notice-bar/index.vue +23 -0
  33. package/src/components/hlw-page/index.vue +18 -0
  34. package/src/components/hlw-paging/index.vue +36 -0
  35. package/src/components/hlw-popup/index.vue +23 -0
  36. package/src/components/hlw-reward-ad/index.vue +133 -0
  37. package/src/components/hlw-search/index.vue +25 -0
  38. package/src/components/hlw-sheet/index.vue +1 -1
  39. package/src/components/hlw-status-bar/index.vue +113 -0
  40. package/src/components/hlw-tag/index.vue +22 -0
  41. package/src/core/index.ts +3 -0
  42. package/src/{composables → core}/msg/index.ts +0 -1
  43. package/src/{composables → core}/refs/index.ts +0 -1
  44. package/src/core/theme/index.ts +115 -0
  45. package/src/hlw.ts +1 -21
  46. package/src/index.ts +3 -11
  47. package/src/utils/ad/README.md +114 -0
  48. package/src/utils/ad/index.ts +234 -0
  49. package/src/{composables/utils → utils/common}/index.ts +1 -27
  50. package/src/{composables → utils}/device/index.ts +13 -21
  51. package/src/utils/index.ts +5 -0
  52. package/src/{composables → utils}/navigator/index.ts +30 -31
  53. package/src/{composables → utils}/request/client.ts +3 -11
  54. package/src/{composables → utils}/request/index.ts +1 -1
  55. package/src/{composables → utils}/request/service.ts +5 -6
  56. package/src/{composables → utils}/request/types.ts +0 -1
  57. package/dist/composables/ad/index.d.ts +0 -42
  58. package/dist/composables/index.d.ts +0 -11
  59. package/src/composables/ad/README.md +0 -58
  60. package/src/composables/ad/index.ts +0 -227
  61. package/src/composables/device/README.md +0 -50
  62. package/src/composables/index.ts +0 -38
  63. package/src/composables/msg/README.md +0 -79
  64. package/src/composables/navigator/README.md +0 -71
  65. package/src/composables/refs/README.md +0 -40
  66. package/src/composables/request/README.md +0 -124
  67. package/src/composables/share/README.md +0 -53
  68. package/src/composables/utils/README.md +0 -81
  69. package/src/core/theme.ts +0 -62
  70. /package/dist/{composables → core}/msg/index.d.ts +0 -0
  71. /package/dist/{composables → core}/refs/index.d.ts +0 -0
  72. /package/dist/{composables → core}/share/index.d.ts +0 -0
  73. /package/dist/{composables → utils}/request/adapters/alist.d.ts +0 -0
  74. /package/dist/{composables → utils}/request/adapters/base.d.ts +0 -0
  75. /package/dist/{composables → utils}/request/adapters/cos.d.ts +0 -0
  76. /package/dist/{composables → utils}/request/adapters/index.d.ts +0 -0
  77. /package/dist/{composables → utils}/request/adapters/oss.d.ts +0 -0
  78. /package/dist/{composables → utils}/request/adapters/qiniu.d.ts +0 -0
  79. /package/dist/{composables → utils}/request/types.d.ts +0 -0
  80. /package/src/{composables → core}/share/index.ts +0 -0
  81. /package/src/{composables → utils}/request/adapters/alist.ts +0 -0
  82. /package/src/{composables → utils}/request/adapters/base.ts +0 -0
  83. /package/src/{composables → utils}/request/adapters/cos.ts +0 -0
  84. /package/src/{composables → utils}/request/adapters/index.ts +0 -0
  85. /package/src/{composables → utils}/request/adapters/oss.ts +0 -0
  86. /package/src/{composables → utils}/request/adapters/qiniu.ts +0 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 小程序广告工具。
3
+ * 提供插屏广告 (Interstitial Ad) 与激励视频广告 (Rewarded Video Ad) 的注册、缓存与展示能力。
4
+ */
5
+ /**
6
+ * 广告播放/加载结果数据结构。
7
+ */
8
+ export interface AdRes {
9
+ /** 广告是否正常加载或成功展示完成 */
10
+ success: boolean;
11
+ /** 激励视频是否完全播放完毕 (仅激励视频有此属性) */
12
+ isEnded: boolean;
13
+ /** 加载或展示失败时的错误对象 */
14
+ err?: any;
15
+ }
16
+ /**
17
+ * 配置/预加载插屏广告
18
+ *
19
+ * @param adId 广告单元 ID
20
+ * @param done 广告关闭后的回调(可选)
21
+ * @returns 是否配置成功
22
+ */
23
+ export declare function setPopupAd(adId: string, done?: (ok: boolean) => void): boolean;
24
+ /**
25
+ * 延迟展示已配置的插屏广告
26
+ *
27
+ * @param delay 延迟毫秒数,默认 3000ms
28
+ * @returns 返回 Promise,指示是否成功显示且被关闭
29
+ */
30
+ export declare function showPopupAd(delay?: number): Promise<boolean>;
31
+ /**
32
+ * 配置/预加载激励视频广告
33
+ *
34
+ * @param adId 广告单元 ID
35
+ * @param done 播放结束的回调(可选)
36
+ * @returns 返回 Promise<AdRes>
37
+ */
38
+ export declare function setRewardAd(adId: string, done?: (res: AdRes) => void): Promise<AdRes>;
39
+ /**
40
+ * 立即播放已加载的激励视频广告
41
+ *
42
+ * @param onShowSuccess 广告成功拉起播放时的回调(常用于关闭 Loading 等待提示)
43
+ * @returns 返回 Promise<AdRes>,指示广告是否正常播放完毕
44
+ */
45
+ export declare function showRewardAd(onShowSuccess?: () => void): Promise<AdRes>;
46
+ /**
47
+ * 弹窗提示需要看完广告才有奖励。
48
+ * 提供“继续观看”和“取消”按钮。
49
+ * @returns 返回 Promise<boolean>,用户点击“继续”返回 true,点击“取消”返回 false
50
+ */
51
+ export declare function confirmRewardAd(): Promise<boolean>;
52
+ /**
53
+ * @deprecated 推荐直接从库导入独立函数使用 (例如:import { showRewardAd } from '@hlw-uni/mp-vue')
54
+ */
55
+ export declare function useHlwAd(): {
56
+ setPopupAd: typeof setPopupAd;
57
+ showPopupAd: typeof showPopupAd;
58
+ setRewardAd: typeof setRewardAd;
59
+ showRewardAd: typeof showRewardAd;
60
+ confirmRewardAd: typeof confirmRewardAd;
61
+ };
@@ -37,7 +37,7 @@ export interface DownloadRes {
37
37
  */
38
38
  export declare function withQuery(url: string, qs: string): string;
39
39
  /**
40
- * 将键值对对象转换为 URL 编码的 Query String。
40
+ * 将键值对对象转换为 URL 编码 of Query String。
41
41
  * 会自动过滤值为 `undefined` 或 `null` 的键。
42
42
  * @param data 需要转换的键值对数据对象
43
43
  * @returns 格式化后的 Query String 字符串
@@ -117,26 +117,3 @@ export declare function saveImageUrl(url: string, progress?: (value: number) =>
117
117
  * @returns 操作是否成功
118
118
  */
119
119
  export declare function saveVideoUrl(url: string, progress?: (value: number) => void): Promise<boolean>;
120
- /**
121
- * 获取系统通用工具方法的 hook。
122
- *
123
- * @example
124
- * ```ts
125
- * const { copy, saveImageUrl } = useUtils();
126
- * copy('hello');
127
- * ```
128
- */
129
- export declare function useUtils(): {
130
- withQuery: typeof withQuery;
131
- toQuery: typeof toQuery;
132
- signText: typeof signText;
133
- toNumber: typeof toNumber;
134
- toBoolean: typeof toBoolean;
135
- copy: typeof copy;
136
- paste: typeof paste;
137
- saveImage: typeof saveImage;
138
- saveVideoFile: typeof saveVideoFile;
139
- download: typeof download;
140
- saveImageUrl: typeof saveImageUrl;
141
- saveVideoUrl: typeof saveVideoUrl;
142
- };
@@ -12,7 +12,7 @@ export interface DeviceInfo {
12
12
  app_version_code: string;
13
13
  /** 小程序来源渠道 */
14
14
  app_channel: string;
15
- /** 设备品牌。如:apple、huawei */
15
+ /** 设备 brand。如:apple、huawei */
16
16
  device_brand: string;
17
17
  /** 设备型号 */
18
18
  device_model: string;
@@ -64,14 +64,13 @@ export interface DeviceInfo {
64
64
  */
65
65
  export type DeviceQueryInfo = Pick<DeviceInfo, "appid" | "device_brand" | "device_model" | "device_id" | "device_type" | "device_orientation" | "platform" | "system" | "os" | "version" | "sdk_version" | "host_name" | "host_version" | "host_language" | "language" | "app_version" | "app_version_code" | "screen_width" | "screen_height">;
66
66
  /**
67
- * 访问当前设备配置信息的 hooks。
68
- *
69
- * @returns 包含 `info` (原始数据) 和 `query` (用于 HTTP 报头/URL query 的 urlencoded 字符串)
67
+ * 获取缓存后的设备信息数据。
70
68
  */
71
- export declare function useDevice(): {
72
- info: DeviceInfo;
73
- query: string;
74
- };
69
+ export declare function getDevice(): DeviceInfo;
70
+ /**
71
+ * 获取接口请求专用的设备信息 query 字符串。
72
+ */
73
+ export declare function getDeviceQuery(): string;
75
74
  /**
76
75
  * 清除本地设备信息缓存,使下一次读取重新走系统调用收集。
77
76
  */
@@ -0,0 +1,5 @@
1
+ export * from './ad';
2
+ export * from './common';
3
+ export * from './navigator';
4
+ export * from './device';
5
+ export * from './request';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * useNavigate - uni-app 路由跳转工具
2
+ * uni-app 路由跳转工具
3
3
  * 封装并统一原生的页面跳转、重定向、Switch Tab、返回、以及打开外部小程序或 WebView 等方法。
4
4
  */
5
5
  /** 页面跳转类型,支持微信小程序的各类路由动作与 WebView/小程序跳转 */
@@ -28,32 +28,16 @@ export interface NavigateOptions {
28
28
  * @param url 跳转目标路径或小程序 AppId
29
29
  * @param options 额外的控制参数
30
30
  */
31
- declare function navigate(type?: NavigateType, url?: string, options?: NavigateOptions): void;
32
- /**
33
- * 路由跳转工具 hooks。
34
- *
35
- * @example
36
- * ```ts
37
- * const router = useNavigate();
38
- * router.to('/pages/index/index');
39
- * router.back();
40
- * router.miniProgram('app-id');
41
- * ```
42
- */
43
- export declare function useNavigate(): {
44
- /** 核心底层路由分发函数 */
45
- navigate: typeof navigate;
46
- /** 保留当前页面,跳转到应用内的某个页面 */
47
- to: (url: string, options?: NavigateOptions) => void;
48
- /** 关闭当前页面,跳转到应用内的某个页面 */
49
- redirect: (url: string, options?: NavigateOptions) => void;
50
- /** 跳转到 switchTab 页面,并关闭其他所有非 tabBar 页面 */
51
- tab: (url: string, options?: NavigateOptions) => void;
52
- /** 关闭所有页面,打开到应用内的某个页面 */
53
- reLaunch: (url: string, options?: NavigateOptions) => void;
54
- /** 关闭当前页面,返回上一页面或多级页面 */
55
- back: (delta?: number, options?: NavigateOptions) => void;
56
- /** 打开另一个小程序 */
57
- miniProgram: (appId: string, options?: NavigateOptions) => void;
58
- };
59
- export {};
31
+ export declare function navigate(type?: NavigateType, url?: string, options?: NavigateOptions): void;
32
+ /** 保留当前页面,跳转到应用内的某个页面 */
33
+ export declare function navigateTo(url: string, options?: NavigateOptions): void;
34
+ /** 关闭当前页面,跳转到应用内的某个页面 */
35
+ export declare function redirectTo(url: string, options?: NavigateOptions): void;
36
+ /** 跳转到 switchTab 页面,并关闭其他所有非 tabBar 页面 */
37
+ export declare function switchTab(url: string, options?: NavigateOptions): void;
38
+ /** 关闭所有页面,打开到应用内的某个页面 */
39
+ export declare function reLaunch(url: string, options?: NavigateOptions): void;
40
+ /** 关闭当前页面,返回上一页面或多级页面 */
41
+ export declare function navigateBack(delta?: number, options?: NavigateOptions): void;
42
+ /** 打开另一个小程序 */
43
+ export declare function navigateToMiniProgram(appId: string, options?: NavigateOptions): void;
@@ -79,15 +79,9 @@ export interface RequestClient {
79
79
  onError(fn: ErrorInterceptor): () => void;
80
80
  }
81
81
  /**
82
- * 获取全局请求客户端单例。
83
- *
84
- * @example
85
- * ```ts
86
- * const http = useRequest();
87
- * http.setBaseURL('https://api.example.com');
88
- * ```
82
+ * 全局请求客户端单例。
89
83
  */
90
- export declare function useRequest(): RequestClient;
84
+ export declare const request: RequestClient;
91
85
  /**
92
86
  * 文件上传 composable。
93
87
  * 提供 `uploading` 状态与上传方法。
@@ -1,4 +1,4 @@
1
- export { useRequest, useUpload } from './client';
1
+ export { request, useUpload } from './client';
2
2
  export { BaseService, ServiceNamespace, ServicePrefix, PluginService } from './service';
3
3
  export type { RequestClient } from './client';
4
4
  export type { ApiResponse, PageResult, RequestConfig, RequestInterceptor, ResponseInterceptor, ErrorInterceptor, UploadConfig, UploadResult, } from './types';
@@ -56,13 +56,13 @@ export declare class BaseService {
56
56
  /**
57
57
  * 快捷发送 POST 请求。
58
58
  * @param url 请求相对路径
59
- * @param data 请求携带的 body
59
+ * @param data 请求携带 the body
60
60
  */
61
61
  post<T = unknown>(url: string, data?: unknown): Promise<ApiResponse<T>>;
62
62
  /**
63
63
  * 快捷发送 PUT 请求。
64
64
  * @param url 请求相对路径
65
- * @param data 请求携带的 body
65
+ * @param data 请求携带 the body
66
66
  */
67
67
  put<T = unknown>(url: string, data?: unknown): Promise<ApiResponse<T>>;
68
68
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlw-uni/mp-vue",
3
- "version": "2.1.71",
3
+ "version": "2.1.97",
4
4
  "description": "hlw-uni 小程序运行时 — Vue 组件 + composables + theme + http + 工具集(合并自原 mp-core)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/app.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { createSSRApp, type App, type Component } from 'vue';
6
6
  import { hlw } from '@/hlw';
7
- import { useRequest } from '@/composables/request';
7
+ import { request } from '@/utils/request';
8
8
 
9
9
  let _installed = false;
10
10
 
@@ -60,6 +60,6 @@ export function useApp() {
60
60
  return createApp;
61
61
  }
62
62
 
63
- return { install, use, hlw, request: useRequest() };
63
+ return { install, use, hlw, request };
64
64
  }
65
65
 
@@ -1,16 +1,63 @@
1
- # 添加到我的小程序提示
1
+ # hlw-add-mini 添加小程序提示气泡组件
2
2
 
3
- 轻量提示用户从右上角菜单添加小程序。
3
+ 用于在页面顶部高亮显示提示气泡,指引并提示用户点击右上角将当前小程序“添加到我的小程序”中,以提升小程序的用户留存与二次回访率。
4
4
 
5
- | 参数 | 说明 | 类型 | 默认值 |
6
- | :-- | :-- | :-- | :-- |
7
- | show | 是否显示 | Boolean | false |
8
- | navigationStyle | 顶部导航栏样式,可选 `default`、`custom` | String | default |
9
- | title | 标题 | String | 添加到我的小程序 |
10
- | desc | 描述 | String | 点击右上角 ··· 添加 |
5
+ ---
6
+
7
+ ## 特性
8
+
9
+ * **智能避让与精准指向**:利用小程序 `getMenuButtonBoundingClientRect` 胶囊元数据,气泡箭头将**像素级精准指向**右上角胶囊的“···”三点按钮中心。
10
+ * **零配置自适应导航栏**:组件内部自动探测宿主页面的 `navigationStyle`(包括全局配置与页面单体配置)。若检测为全局/页面**自定义导航栏(`custom`)**,组件会自动避让胶囊按钮并下移气泡;若为默认原生导航栏,则自动贴顶展示,完全无需开发者手动传入导航栏参数。
11
+ * **跨端优雅容错**:在不支持胶囊数据探测的非微信小程序平台,自动执行安全像素高度与宽度的优雅降级。
12
+
13
+ ---
14
+
15
+ ## 属性说明 (Props)
16
+
17
+ | 属性名 | 说明 | 类型 | 默认值 |
18
+ | :--- | :--- | :--- | :--- |
19
+ | `show` | 控制气泡的显示与隐藏 | `Boolean` | `false` |
20
+ | `title` | 提示气泡的主标题文字 | `String` | `"添加到我的小程序"` |
21
+ | `desc` | 提示气泡的副标题/描述文字(传入空字符将不渲染描述行) | `String` | `"点击右上角 ··· 添加"` |
22
+
23
+ ---
24
+
25
+ ## 事件说明 (Events)
26
+
27
+ | 事件名 | 说明 | 参数 |
28
+ | :--- | :--- | :--- |
29
+ | `@close` | 用户点击气泡右侧“×”关闭按钮时触发,开发者应在此事件中修改 `show` 为 `false` | 无 |
30
+
31
+ ---
32
+
33
+ ## 使用示例
11
34
 
12
35
  ```vue
13
36
  <template>
14
- <hlw-add-mini :show="show" @close="close" />
37
+ <view class="container">
38
+ <!-- 指引添加小程序气泡 -->
39
+ <hlw-add-mini
40
+ :show="showAddMiniTip"
41
+ @close="showAddMiniTip = false"
42
+ />
43
+
44
+ <view class="content">
45
+ 页面其它主体内容...
46
+ </view>
47
+ </view>
15
48
  </template>
49
+
50
+ <script setup lang="ts">
51
+ import { ref, onMounted } from "vue";
52
+
53
+ const showAddMiniTip = ref(false);
54
+
55
+ onMounted(() => {
56
+ // 首次进入页面时展示,或根据用户本地缓存判断是否展示
57
+ const hasAdded = uni.getStorageSync("has_added_mini");
58
+ if (!hasAdded) {
59
+ showAddMiniTip.value = true;
60
+ }
61
+ });
62
+ </script>
16
63
  ```
@@ -19,7 +19,7 @@
19
19
  * 会根据是否为自定义导航栏(custom),自动调整气泡浮动位置(避开胶囊按钮与状态栏)。
20
20
  */
21
21
  import { computed, ref, onMounted } from "vue";
22
- import { useDevice } from "../../composables/device";
22
+ import { getDevice } from "../../utils/device";
23
23
 
24
24
  defineOptions({ name: "HlwAddMini" });
25
25
 
@@ -43,8 +43,8 @@ const emit = defineEmits<{
43
43
  close: [];
44
44
  }>();
45
45
 
46
- // 从 useDevice 获取缓存的设备系统信息,规避在 computed 中频繁调用同步系统 API 的性能问题
47
- const { info } = useDevice();
46
+ // 从 getDevice 获取缓存的设备系统信息,规避在 computed 中频繁调用同步系统 API 的性能问题
47
+ const info = getDevice();
48
48
 
49
49
  const isCustomNav = ref(false);
50
50
 
@@ -131,9 +131,10 @@ function close() {
131
131
 
132
132
  <style lang="scss" scoped>
133
133
  .hlw-add-mini {
134
+ --add-mini-bg: rgba(0, 0, 0, 0.72);
134
135
  position: fixed;
135
136
  right: 22rpx;
136
- z-index: 99999;
137
+ z-index: 999;
137
138
  width: 340rpx;
138
139
  animation: hlw-add-mini-in 0.22s ease-out both;
139
140
  }
@@ -147,7 +148,7 @@ function close() {
147
148
  z-index: 99999;
148
149
  border-left: 12rpx solid transparent;
149
150
  border-right: 12rpx solid transparent;
150
- border-bottom: 14rpx solid rgba(17, 24, 39, 0.82);
151
+ border-bottom: 14rpx solid var(--add-mini-bg);
151
152
  }
152
153
 
153
154
  .hlw-add-mini__content {
@@ -156,8 +157,10 @@ function close() {
156
157
  gap: 12rpx;
157
158
  padding: 16rpx 14rpx 16rpx 20rpx;
158
159
  border-radius: 14rpx;
159
- background: rgba(17, 24, 39, 0.82);
160
- box-shadow: 0 12rpx 34rpx rgba(15, 23, 42, 0.22);
160
+ background: var(--add-mini-bg);
161
+ backdrop-filter: blur(12rpx);
162
+ -webkit-backdrop-filter: blur(12rpx);
163
+ box-shadow: 0 12rpx 34rpx rgba(15, 23, 42, 0.15);
161
164
  }
162
165
 
163
166
  .hlw-add-mini__text {
@@ -174,11 +177,11 @@ function close() {
174
177
  }
175
178
 
176
179
  .hlw-add-mini__desc {
177
- margin-top: 4rpx;
180
+ margin-top: 6rpx;
178
181
  color: rgba(255, 255, 255, 0.72);
179
182
  font-size: 21rpx;
180
183
  line-height: 1.3;
181
- letter-spacing: 1rpx;
184
+ letter-spacing: 2rpx;
182
185
  }
183
186
 
184
187
  .hlw-add-mini__close {
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <view class="hlw-avatar-upload">
3
+ <button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar" @click="onClick">
4
+ <hlw-avatar :src="props.src || ''" :name="props.name || '微信用户'" :size="props.size" :border="props.border" />
5
+ <view class="edit-avatar">
6
+ <span class="iconfont icon-xiangji edit-avatar-icon" />
7
+ </view>
8
+ </button>
9
+ </view>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ defineOptions({ name: "HlwAvatarUpload" });
14
+
15
+ interface Props {
16
+ /** 当前头像的网络/本地路径 */
17
+ src?: string;
18
+ /** 无头像时的备用展示昵称 */
19
+ name?: string;
20
+ /** 头像尺寸,可选 'small' | 'medium' | 'large' */
21
+ size?: "small" | "medium" | "large";
22
+ /** 边框线宽 */
23
+ border?: number;
24
+ }
25
+
26
+ const props = withDefaults(defineProps<Props>(), {
27
+ src: "",
28
+ name: "微信用户",
29
+ size: "large",
30
+ border: 3,
31
+ });
32
+
33
+ const emit = defineEmits<{
34
+ (e: "onAvatar", filePath: string): void;
35
+ }>();
36
+
37
+ function onChooseAvatar(event: any) {
38
+ const filePath = String(event?.detail?.avatarUrl || "");
39
+ if (filePath) {
40
+ emit("onAvatar", filePath);
41
+ }
42
+ }
43
+
44
+ function onClick() {
45
+ // #ifndef MP-WEIXIN
46
+ uni.chooseImage({
47
+ count: 1,
48
+ success: (res) => {
49
+ const filePath = res.tempFilePaths[0];
50
+ if (filePath) {
51
+ emit("onAvatar", filePath);
52
+ }
53
+ },
54
+ });
55
+ // #endif
56
+ }
57
+ </script>
58
+
59
+ <style scoped>
60
+ .hlw-avatar-upload {
61
+ display: inline-block;
62
+ }
63
+
64
+ .avatar-wrapper {
65
+ position: relative;
66
+ display: inline-block;
67
+ border-radius: 50%;
68
+ margin: 0;
69
+ padding: 0;
70
+ background: transparent;
71
+ line-height: normal;
72
+ border: none;
73
+ overflow: visible;
74
+ cursor: pointer;
75
+ }
76
+
77
+ .avatar-wrapper::after {
78
+ border: none;
79
+ display: none;
80
+ }
81
+
82
+ .edit-avatar {
83
+ position: absolute;
84
+ bottom: -8rpx;
85
+ right: -8rpx;
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ width: 44rpx;
90
+ height: 44rpx;
91
+ margin: 0;
92
+ padding: 0;
93
+ border: 1rpx solid #e2e8f0; /* 圆角灰线 */
94
+ border-radius: 999rpx;
95
+ background: #ffffff; /* 白色背景 */
96
+ color: #64748b; /* 灰色相机图标 */
97
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
98
+ }
99
+
100
+ .edit-avatar .edit-avatar-icon {
101
+ font-size: 22rpx;
102
+ }
103
+ </style>
@@ -7,7 +7,7 @@
7
7
  @tap="onTap"
8
8
  >
9
9
  <slot>
10
- <text class="i-fa6-solid-chevron-up hlw-back-top__icon" />
10
+ <span class="i-fa6-solid-chevron-up hlw-back-top__icon" />
11
11
  </slot>
12
12
  </view>
13
13
  </template>
@@ -37,24 +37,15 @@
37
37
  <script setup lang="ts">
38
38
  /**
39
39
  * HlwButton - 语义化/响应式通用按钮组件
40
- *
40
+ *
41
41
  * 扩展了原生小程序 button 属性。支持丰富的语义色彩预设、尺寸自适应、圆角与 Block 状态,
42
42
  * 并且内置了快捷的 uni-app 路由跳转逻辑与 Native `open-type` 会话消息配置。
43
43
  */
44
44
  import { computed, useSlots } from "vue";
45
- import { useNavigate } from "@/composables/navigator";
45
+ import { navigate } from "../../utils/navigator";
46
46
 
47
47
  /** 按钮类型:语义化颜色预设、边框模式、文本模式及幽灵模式 */
48
- type ButtonType =
49
- | "primary"
50
- | "success"
51
- | "warning"
52
- | "danger"
53
- | "error"
54
- | "info"
55
- | "outline"
56
- | "text"
57
- | "ghost";
48
+ type ButtonType = "primary" | "success" | "warning" | "danger" | "error" | "info" | "outline" | "text" | "ghost";
58
49
 
59
50
  /** 路由动作类型 */
60
51
  type NavigateType = "navigateTo" | "redirectTo" | "switchTab" | "reLaunch" | "navigateBack";
@@ -121,7 +112,7 @@ const props = withDefaults(defineProps<Props>(), {
121
112
 
122
113
  const emit = defineEmits<{
123
114
  /** 按钮点击事件(在未禁用且非 loading 时触发) */
124
- click: []
115
+ click: [];
125
116
  }>();
126
117
 
127
118
  const slots = useSlots();
@@ -144,8 +135,6 @@ const buttonStyle = computed(() => {
144
135
  return style;
145
136
  });
146
137
 
147
- const navigator = useNavigate();
148
-
149
138
  /**
150
139
  * 处理点击事件与快捷页面跳转。
151
140
  */
@@ -156,7 +145,7 @@ const handleTap = () => {
156
145
 
157
146
  if (!props.url && props.navigateType !== "navigateBack") return;
158
147
 
159
- navigator.navigate(props.navigateType, props.url, { delta: props.delta });
148
+ navigate(props.navigateType, props.url, { delta: props.delta });
160
149
  };
161
150
  </script>
162
151
 
@@ -6,7 +6,7 @@
6
6
  hover-class="trigger--hover"
7
7
  @tap="onEnter"
8
8
  >
9
- <text class="i-fa6-solid-pen-nib trigger-icon" />
9
+ <span class="i-fa6-solid-pen-nib trigger-icon" />
10
10
  </view>
11
11
 
12
12
  <!-- 全屏批注层,激活时覆盖整个页面(含 hlw-header) -->
@@ -25,7 +25,7 @@
25
25
  <!-- 顶部状态条:左关闭,右模式切换(避开右上角微信胶囊) -->
26
26
  <view class="bar">
27
27
  <view class="bar-close" hover-class="bar-close--hover" @tap="onExit">
28
- <text class="i-fa6-solid-xmark bar-icon" />
28
+ <span class="i-fa6-solid-xmark bar-icon" />
29
29
  </view>
30
30
  <view
31
31
  class="bar-toggle"
@@ -33,7 +33,7 @@
33
33
  hover-class="bar-toggle--hover"
34
34
  @tap="scrollMode = !scrollMode"
35
35
  >
36
- <text :class="[scrollMode ? 'i-ri-arrow-up-down-line' : 'i-ri-pencil-line', 'bar-icon']" />
36
+ <span :class="[scrollMode ? 'i-ri-arrow-up-down-line' : 'i-ri-pencil-line', 'bar-icon']" />
37
37
  <text class="bar-toggle-text">{{ scrollMode ? "滚动" : "绘画" }}</text>
38
38
  </view>
39
39
  </view>
@@ -50,7 +50,7 @@
50
50
  hover-class="mode--hover"
51
51
  @tap="mode = m.value"
52
52
  >
53
- <text :class="m.icon" class="mode-icon" />
53
+ <span :class="m.icon" class="mode-icon" />
54
54
  </view>
55
55
  </view>
56
56
 
@@ -65,7 +65,7 @@
65
65
  :style="{ background: c }"
66
66
  @tap="color = c"
67
67
  >
68
- <text v-if="c === color" class="i-fa6-solid-check color-check" />
68
+ <span v-if="c === color" class="i-fa6-solid-check color-check" />
69
69
  </view>
70
70
  </view>
71
71
 
@@ -90,10 +90,10 @@
90
90
 
91
91
  <view class="actions">
92
92
  <view class="action" hover-class="action--hover" @tap="onUndo">
93
- <text class="i-ri-arrow-go-back-line action-icon" />
93
+ <span class="i-ri-arrow-go-back-line action-icon" />
94
94
  </view>
95
95
  <view class="action" hover-class="action--hover" @tap="onClear">
96
- <text class="i-fa6-solid-trash-can action-icon" />
96
+ <span class="i-fa6-solid-trash-can action-icon" />
97
97
  </view>
98
98
  </view>
99
99
  </view>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <navigator v-if="url" :url="url" class="hlw-cell" :class="{ 'hlw-cell--border': border }" hover-class="hlw-cell--hover">
2
+ <navigator v-if="url" :url="url" animation-type="none" class="hlw-cell" :class="{ 'hlw-cell--border': border }" hover-class="hlw-cell--hover">
3
3
  <view v-if="icon || $slots.icon" class="hlw-cell-icon">
4
4
  <slot name="icon"><view :class="icon" /></slot>
5
5
  </view>