vite-uni-dev-tool 1.1.0 → 1.2.1

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 (195) hide show
  1. package/README.md +21 -1
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +2 -1
  4. package/dist/const.js +1 -1
  5. package/dist/core-shared.d.ts +2 -3
  6. package/dist/core.d.ts +8 -8
  7. package/dist/core.js +2 -2
  8. package/dist/i18n/index.d.ts +0 -1
  9. package/dist/i18n/instance.d.ts +0 -1
  10. package/dist/i18n/locales/en.cjs +1 -1
  11. package/dist/i18n/locales/en.d.ts +6 -1
  12. package/dist/i18n/locales/en.js +1 -1
  13. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  14. package/dist/i18n/locales/zh-Hans.d.ts +6 -1
  15. package/dist/i18n/locales/zh-Hans.js +1 -1
  16. package/dist/index.d.ts +0 -1
  17. package/dist/modules/devConsole/index.cjs +4 -4
  18. package/dist/modules/devConsole/index.d.ts +6 -107
  19. package/dist/modules/devConsole/index.js +4 -4
  20. package/dist/modules/devEvent/index.cjs +3 -3
  21. package/dist/modules/devEvent/index.d.ts +2 -3
  22. package/dist/modules/devEvent/index.js +3 -3
  23. package/dist/modules/devIntercept/index.cjs +14 -14
  24. package/dist/modules/devIntercept/index.d.ts +34 -6
  25. package/dist/modules/devIntercept/index.js +14 -14
  26. package/dist/modules/devStore/index.cjs +1 -1
  27. package/dist/modules/devStore/index.d.ts +48 -40
  28. package/dist/modules/devStore/index.js +1 -1
  29. package/dist/modules/devToolInfo/index.cjs +1 -1
  30. package/dist/modules/devToolInfo/index.d.ts +6 -25
  31. package/dist/modules/devToolInfo/index.js +1 -1
  32. package/dist/plugins/uniDevTool/transform/transformApp.d.ts +0 -1
  33. package/dist/plugins/uniDevTool/transform/transformMain.cjs +3 -3
  34. package/dist/plugins/uniDevTool/transform/transformMain.d.ts +2 -2
  35. package/dist/plugins/uniDevTool/transform/transformMain.js +3 -3
  36. package/dist/plugins/uniDevTool/transform/transformVue.cjs +31 -25
  37. package/dist/plugins/uniDevTool/transform/transformVue.d.ts +2 -2
  38. package/dist/plugins/uniDevTool/transform/transformVue.js +30 -24
  39. package/dist/plugins/uniDevTool/uniDevTool.cjs +3 -3
  40. package/dist/plugins/uniDevTool/uniDevTool.d.ts +3 -2
  41. package/dist/plugins/uniDevTool/uniDevTool.js +3 -3
  42. package/dist/plugins/uniGlobalComponents/uniGlobalComponents.d.ts +0 -1
  43. package/dist/plugins/utils/index.d.ts +0 -1
  44. package/dist/shims-uni.d.ts +26 -22
  45. package/dist/type.d.ts +47 -43
  46. package/dist/utils/array.d.ts +0 -1
  47. package/dist/utils/date.d.ts +0 -1
  48. package/dist/utils/file.d.ts +0 -1
  49. package/dist/utils/function.d.ts +0 -1
  50. package/dist/utils/index.d.ts +0 -1
  51. package/dist/utils/ip.d.ts +0 -1
  52. package/dist/utils/language.d.ts +14 -15
  53. package/dist/utils/object.cjs +1 -1
  54. package/dist/utils/object.d.ts +7 -8
  55. package/dist/utils/object.js +1 -1
  56. package/dist/utils/openLink.d.ts +0 -1
  57. package/dist/utils/page.d.ts +0 -1
  58. package/dist/utils/platform.d.ts +0 -1
  59. package/dist/utils/string.d.ts +0 -1
  60. package/dist/utils/utils.d.ts +0 -1
  61. package/dist/v3/DevTool/components/BluetoothList/BluetoothItem.vue +199 -199
  62. package/dist/v3/DevTool/components/BluetoothList/BluetoothTool.vue +730 -730
  63. package/dist/v3/DevTool/components/BluetoothList/index.vue +167 -167
  64. package/dist/v3/DevTool/components/CaptureScreen/index.vue +109 -109
  65. package/dist/v3/DevTool/components/ConsoleList/ConsoleItem.vue +230 -225
  66. package/dist/v3/DevTool/components/ConsoleList/RunJSInput.vue +247 -247
  67. package/dist/v3/DevTool/components/ConsoleList/index.vue +171 -171
  68. package/dist/v3/DevTool/components/ConsoleList/staticTips.ts +1145 -1145
  69. package/dist/v3/DevTool/components/DevToolButton/index.vue +42 -6
  70. package/dist/v3/DevTool/components/DevToolTitle/index.vue +24 -24
  71. package/dist/v3/DevTool/components/DevToolWindow/DevToolOverlay.vue +197 -197
  72. package/dist/v3/DevTool/components/DevToolWindow/hooks/dataUtils.ts +48 -48
  73. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolData.ts +411 -387
  74. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolHandlers.ts +644 -629
  75. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolOverlay.ts +201 -197
  76. package/dist/v3/DevTool/components/DevToolWindow/index.vue +27 -64
  77. package/dist/v3/DevTool/components/ElEvent/ElEventItem.vue +105 -105
  78. package/dist/v3/DevTool/components/ElEvent/index.vue +106 -106
  79. package/dist/v3/DevTool/components/Instance/components/InstanceTreeNode.vue +265 -265
  80. package/dist/v3/DevTool/components/Instance/flatten.ts +226 -226
  81. package/dist/v3/DevTool/components/Instance/index.vue +94 -94
  82. package/dist/v3/DevTool/components/Instance/registry.ts +49 -49
  83. package/dist/v3/DevTool/components/Instance/transformTree.ts +393 -375
  84. package/dist/v3/DevTool/components/Instance/transformTreeCtx.ts +268 -268
  85. package/dist/v3/DevTool/components/Instance/typing.d.ts +43 -43
  86. package/dist/v3/DevTool/components/InstanceDetail/index.vue +485 -485
  87. package/dist/v3/DevTool/components/JsonDetail/index.vue +70 -70
  88. package/dist/v3/DevTool/components/NFCList/NFCItem.vue +112 -112
  89. package/dist/v3/DevTool/components/NFCList/NFCTool.vue +454 -454
  90. package/dist/v3/DevTool/components/NFCList/const.ts +56 -56
  91. package/dist/v3/DevTool/components/NFCList/index.vue +94 -94
  92. package/dist/v3/DevTool/components/NetworkList/InterceptConfig.vue +624 -624
  93. package/dist/v3/DevTool/components/NetworkList/InterceptItem.vue +140 -140
  94. package/dist/v3/DevTool/components/NetworkList/NetworkDetail.vue +287 -287
  95. package/dist/v3/DevTool/components/NetworkList/NetworkIntercept.vue +88 -88
  96. package/dist/v3/DevTool/components/NetworkList/NetworkItem.vue +163 -163
  97. package/dist/v3/DevTool/components/NetworkList/NetworkSend.vue +589 -589
  98. package/dist/v3/DevTool/components/NetworkList/const.ts +4 -4
  99. package/dist/v3/DevTool/components/NetworkList/hooks/useNetworkForm.ts +86 -86
  100. package/dist/v3/DevTool/components/NetworkList/index.vue +160 -160
  101. package/dist/v3/DevTool/components/NetworkList/utils.ts +101 -101
  102. package/dist/v3/DevTool/components/Performance/index.vue +498 -498
  103. package/dist/v3/DevTool/components/Performance/modules/PerformanceMetrics.vue +153 -153
  104. package/dist/v3/DevTool/components/Performance/modules/usePerformanceChart.ts +460 -460
  105. package/dist/v3/DevTool/components/Performance/modules/usePerformanceData.ts +258 -258
  106. package/dist/v3/DevTool/components/PiniaList/index.vue +93 -93
  107. package/dist/v3/DevTool/components/RunJS/index.vue +148 -148
  108. package/dist/v3/DevTool/components/ScanCodeList/ScanCodeItem.vue +97 -97
  109. package/dist/v3/DevTool/components/ScanCodeList/index.vue +100 -100
  110. package/dist/v3/DevTool/components/SettingButton/index.vue +45 -45
  111. package/dist/v3/DevTool/components/SettingList/index.vue +226 -218
  112. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +320 -304
  113. package/dist/v3/DevTool/components/SettingList/modules/SettingDevTool.vue +212 -212
  114. package/dist/v3/DevTool/components/SettingList/modules/SettingInfo.vue +157 -157
  115. package/dist/v3/DevTool/components/SettingList/modules/SettingLanguage.vue +74 -74
  116. package/dist/v3/DevTool/components/SettingList/modules/SettingLog.vue +230 -230
  117. package/dist/v3/DevTool/components/SettingList/typing.d.ts +2 -2
  118. package/dist/v3/DevTool/components/SourceCode/Line.vue +127 -127
  119. package/dist/v3/DevTool/components/SourceCode/parseCode.ts +609 -609
  120. package/dist/v3/DevTool/components/StorageList/index.vue +174 -174
  121. package/dist/v3/DevTool/components/TransferList/TransferDetail.vue +268 -268
  122. package/dist/v3/DevTool/components/VuexList/index.vue +84 -84
  123. package/dist/v3/DevTool/index.vue +85 -138
  124. package/dist/v3/components/AppTransition/index.vue +156 -176
  125. package/dist/v3/components/AutoSizer/index.vue +192 -192
  126. package/dist/v3/components/AutoSizer/index1.vue +184 -184
  127. package/dist/v3/components/AutoSizer/utils.ts +49 -49
  128. package/dist/v3/components/Barrage/BarrageItem.vue +194 -137
  129. package/dist/v3/components/Barrage/index.vue +205 -202
  130. package/dist/v3/components/CircularButton/index.vue +84 -84
  131. package/dist/v3/components/CustomSwiper/CustomSwiperItem.vue +49 -49
  132. package/dist/v3/components/CustomSwiper/index.vue +104 -104
  133. package/dist/v3/components/DevErrorBoundary/index.vue +388 -0
  134. package/dist/v3/components/DraggableContainer/index.vue +186 -73
  135. package/dist/v3/components/Empty/index.vue +29 -29
  136. package/dist/v3/components/FilterSelect/index.vue +179 -179
  137. package/dist/v3/components/JsonPretty/components/Brackets/index.vue +27 -27
  138. package/dist/v3/components/JsonPretty/components/Carets/index.vue +59 -59
  139. package/dist/v3/components/JsonPretty/components/CheckController/index.vue +136 -136
  140. package/dist/v3/components/JsonPretty/components/TreeNode/index.vue +387 -387
  141. package/dist/v3/components/JsonPretty/hooks/useClipboard.ts +21 -21
  142. package/dist/v3/components/JsonPretty/hooks/useError.ts +21 -21
  143. package/dist/v3/components/JsonPretty/type.ts +127 -127
  144. package/dist/v3/components/JsonPretty/utils/index.ts +169 -169
  145. package/dist/v3/components/MovableContainer/index.vue +10 -4
  146. package/dist/v3/components/Pick/index.vue +321 -322
  147. package/dist/v3/components/Tag/index.vue +113 -113
  148. package/dist/v3/components/VirtualList/AutoSize.vue +40 -40
  149. package/dist/v3/components/VirtualList/index.vue +416 -416
  150. package/dist/v3/hooks/useBluetooth/index.ts +561 -561
  151. package/dist/v3/hooks/useContainerStyle.ts +95 -153
  152. package/dist/v3/hooks/useNFC/index.ts +107 -107
  153. package/dist/v3/hooks/useNFC/typing.d.ts +396 -396
  154. package/dist/v3/hooks/useNFC/useNFCAndroid.ts +966 -966
  155. package/dist/v3/hooks/useNFC/useNFCMpWeiXin.ts +812 -812
  156. package/dist/v3/hooks/useNFC/utils.ts +754 -754
  157. package/dist/v3/hooks/useRequest/index.ts +586 -586
  158. package/dist/v3/hooks/useRequest/utils.ts +267 -267
  159. package/dist/v3/hooks/useScanCode/index.ts +206 -206
  160. package/dist/v3/hooks/useWebsocket/index.ts +253 -253
  161. package/dist/v3/styles/theme.ts +12 -12
  162. package/package.json +70 -59
  163. package/dist/const.d.ts.map +0 -1
  164. package/dist/core-shared.d.ts.map +0 -1
  165. package/dist/core.d.ts.map +0 -1
  166. package/dist/i18n/index.d.ts.map +0 -1
  167. package/dist/i18n/instance.d.ts.map +0 -1
  168. package/dist/i18n/locales/en.d.ts.map +0 -1
  169. package/dist/i18n/locales/zh-Hans.d.ts.map +0 -1
  170. package/dist/index.d.ts.map +0 -1
  171. package/dist/modules/devConsole/index.d.ts.map +0 -1
  172. package/dist/modules/devEvent/index.d.ts.map +0 -1
  173. package/dist/modules/devIntercept/index.d.ts.map +0 -1
  174. package/dist/modules/devStore/index.d.ts.map +0 -1
  175. package/dist/modules/devToolInfo/index.d.ts.map +0 -1
  176. package/dist/plugins/uniDevTool/transform/transformApp.d.ts.map +0 -1
  177. package/dist/plugins/uniDevTool/transform/transformMain.d.ts.map +0 -1
  178. package/dist/plugins/uniDevTool/transform/transformVue.d.ts.map +0 -1
  179. package/dist/plugins/uniDevTool/uniDevTool.d.ts.map +0 -1
  180. package/dist/plugins/uniGlobalComponents/uniGlobalComponents.d.ts.map +0 -1
  181. package/dist/plugins/utils/index.d.ts.map +0 -1
  182. package/dist/type.d.ts.map +0 -1
  183. package/dist/utils/array.d.ts.map +0 -1
  184. package/dist/utils/date.d.ts.map +0 -1
  185. package/dist/utils/file.d.ts.map +0 -1
  186. package/dist/utils/function.d.ts.map +0 -1
  187. package/dist/utils/index.d.ts.map +0 -1
  188. package/dist/utils/ip.d.ts.map +0 -1
  189. package/dist/utils/language.d.ts.map +0 -1
  190. package/dist/utils/object.d.ts.map +0 -1
  191. package/dist/utils/openLink.d.ts.map +0 -1
  192. package/dist/utils/page.d.ts.map +0 -1
  193. package/dist/utils/platform.d.ts.map +0 -1
  194. package/dist/utils/string.d.ts.map +0 -1
  195. package/dist/utils/utils.d.ts.map +0 -1
@@ -1,812 +1,812 @@
1
- import { onMounted, onUnmounted, ref } from 'vue';
2
- import {
3
- arrayNumberToArrayBuffer,
4
- byteToString,
5
- createUriNdefRecord,
6
- formatCardInfo,
7
- generateWSCBytesForAndroid,
8
- getReadWriteStandard,
9
- getSakHex,
10
- getSakType,
11
- getTnfDescription,
12
- getTypeDescription,
13
- parseAtqa,
14
- parseUniversalTLV,
15
- parseVCardPayload,
16
- stringToArrayBuffer,
17
- transformArrayBuffer,
18
- wifiTLVConfig,
19
- } from './utils';
20
-
21
- export default function useNFCMpWeiXin(
22
- listener: NFC.Listener,
23
- _options?: NFC.NfcOption,
24
- ): NFC.NfcResult {
25
- /** 是否支持 nfc */
26
- const isSupportNFC = ref<boolean | undefined>(false);
27
- /** 是否监听中 */
28
- const isListening = ref<boolean>(false);
29
- /**
30
- * 是否已连接
31
- * 需要手动维护,调用connect()后连接 调用close()后断开 ,实际nfc 断开之后是无法监听到的, isConnected 已经被废弃掉了
32
- */
33
- const isConnected = ref<boolean>(false);
34
- /** nfc 数据 */
35
- const data = ref<NFC.Result>({
36
- id: new ArrayBuffer(0),
37
- techs: [],
38
- byteArray: [],
39
- hexArray: [],
40
- hexNumberArray: [],
41
- hexString: '',
42
- });
43
-
44
- /** nfc 适配器 */
45
- let nfcAdapter: NFC.Adapter;
46
-
47
- /** nfc 实例 */
48
- let nfcInstance: NFC.Instance | undefined;
49
-
50
- /** ndef 写入方式比较特殊,需要特殊处理 */
51
- const isNdef = ref(false);
52
-
53
- let maxTransceiveLength = 0;
54
-
55
- const _checkInterval: any = null;
56
-
57
- /**
58
- * 初始化 nfc adapter
59
- *
60
- * @return {*}
61
- */
62
- async function initNfcAdapter() {
63
- await checkHCEState();
64
-
65
- if (!isSupportNFC.value) return;
66
-
67
- nfcAdapter = wx.getNFCAdapter();
68
-
69
- nfcAdapter.onDiscovered(innerListener);
70
- }
71
-
72
- function getAtqa(nfcInstance: NFC.Instance): Promise<NFC.Atqa> {
73
- return new Promise((resolve, reject) => {
74
- if (!nfcInstance.getAtqa) {
75
- reject({ errMsg: '不支持获取 atqa' });
76
- }
77
- nfcInstance?.getAtqa?.({
78
- success: (res) => {
79
- resolve(res);
80
- },
81
- fail: (err) => {
82
- reject(err);
83
- },
84
- });
85
- });
86
- }
87
-
88
- function getMaxTransceiveLength(
89
- nfcInstance: NFC.Instance,
90
- ): Promise<NFC.MaxTransceiveLength> {
91
- return new Promise((resolve, reject) => {
92
- if (nfcInstance.getMaxTransceiveLength) {
93
- nfcInstance?.getMaxTransceiveLength?.({
94
- success: (res) => {
95
- resolve(res);
96
- },
97
- fail: (err) => {
98
- reject(err);
99
- },
100
- });
101
- } else {
102
- reject({ errMsg: '不支持获取 maxTransceiveLength' });
103
- }
104
- });
105
- }
106
-
107
- function getSak(nfcInstance: NFC.Instance): Promise<NFC.Sak> {
108
- return new Promise((resolve, reject) => {
109
- if (!nfcInstance.getMaxTransceiveLength) {
110
- reject({ errMsg: '不支持获取 sak' });
111
- }
112
-
113
- nfcInstance?.getSak?.({
114
- success: (res) => {
115
- resolve(res);
116
- },
117
- fail: (err) => {
118
- reject(err);
119
- },
120
- });
121
- });
122
- }
123
-
124
- /**
125
- * 检查HCE状态
126
- *
127
- * @return {*}
128
- */
129
- function checkHCEState() {
130
- return new Promise((resolve, reject) => {
131
- wx.getHCEState({
132
- success: (res: any) => {
133
- isSupportNFC.value = true;
134
- resolve(res);
135
- },
136
- fail: (err: any) => {
137
- isSupportNFC.value = false;
138
- reject(err);
139
- },
140
- });
141
- });
142
- }
143
-
144
- /**
145
- * 启用HCE
146
- *
147
- * @return {*}
148
- */
149
- function startHCE() {
150
- if (!isSupportNFC.value) {
151
- uni.showToast({
152
- title: '设备不支持 NFC',
153
- icon: 'none',
154
- });
155
- return Promise.reject({
156
- errMsg: '设备不支持 NFC',
157
- });
158
- }
159
-
160
- // 前置校验
161
- if (!nfcAdapter) {
162
- uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
163
- return Promise.reject({
164
- errMsg: '请先初始化 NFC 适配器',
165
- });
166
- }
167
-
168
- if (isListening.value) {
169
- uni.showToast({ title: 'NFC 监听已开启,无需重复操作', icon: 'none' });
170
- return Promise.reject({
171
- errMsg: 'NFC 监听已开启,无需重复操作',
172
- });
173
- }
174
- nfcAdapter.startDiscovery();
175
- isListening.value = true;
176
- uni.showToast({
177
- title: '开始监听NFC',
178
- icon: 'none',
179
- });
180
- return Promise.resolve({
181
- errMsg: '开始监听NFC',
182
- });
183
- }
184
-
185
- /**
186
- * 停用HCE
187
- *
188
- * @return {*}
189
- */
190
- function stopHCE() {
191
- // 前置校验
192
- if (!isSupportNFC.value) {
193
- uni.showToast({
194
- title: '设备不支持 NFC',
195
- icon: 'none',
196
- });
197
- return Promise.reject({
198
- errMsg: '设备不支持 NFC',
199
- });
200
- }
201
-
202
- // 前置校验
203
- if (!nfcAdapter) {
204
- uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
205
- return Promise.reject({
206
- errMsg: '请先初始化 NFC 适配器',
207
- });
208
- }
209
-
210
- if (!isListening.value) {
211
- uni.showToast({ title: 'NFC 监听已关闭,无需重复操作', icon: 'none' });
212
- return Promise.reject({
213
- errMsg: 'NFC 监听已关闭,无需重复操作',
214
- });
215
- }
216
-
217
- nfcAdapter.stopDiscovery();
218
- isListening.value = false;
219
- uni.showToast({
220
- title: '停止监听NFC',
221
- icon: 'none',
222
- });
223
- return Promise.resolve({
224
- errMsg: '停止监听NFC',
225
- });
226
- }
227
-
228
- function getInstance(techs: NFC.NfcType[], needNdef?: boolean) {
229
- let type = 'Ndef';
230
- if (needNdef) {
231
- type = 'Ndef';
232
- } else {
233
- type = techs.filter((tech) => tech != 'Ndef' && tech != 'NDEF')?.[0];
234
- }
235
-
236
- switch (type) {
237
- case 'NFC-A':
238
- return nfcAdapter.getNfcA();
239
- case 'NFC-B':
240
- return nfcAdapter.getNfcB();
241
- case 'NFC-F':
242
- return nfcAdapter.getNfcF();
243
- case 'NFC-V':
244
- return nfcAdapter.getNfcV();
245
- case 'MIFARE Classic':
246
- return nfcAdapter.getMifareClassic();
247
- case 'MIFARE Ultralight':
248
- return nfcAdapter.getMifareUltralight();
249
- case 'Ndef':
250
- isNdef.value = true;
251
- return nfcAdapter.getNdef();
252
- case 'ISO-DEP':
253
- return nfcAdapter.getIsoDep();
254
- default:
255
- return undefined;
256
- }
257
- }
258
-
259
- // function checkConnected() {
260
- // checkInterval = setInterval(async () => {
261
- // if (!nfcAdapter) {
262
- // isConnected.value = false;
263
- // clearInterval(checkInterval);
264
- // return;
265
- // }
266
-
267
- // if (!nfcInstance) {
268
- // isConnected.value = false;
269
- // clearInterval(checkInterval);
270
- // return;
271
- // }
272
- // try {
273
- // // TODO: 检测是否连接成功
274
- // // await connect();
275
-
276
- // isConnected.value = true;
277
- // } catch (error) {
278
- // console.log('error: ', error);
279
- // isConnected.value = false;
280
- // clearInterval(checkInterval);
281
- // }
282
- // }, options?.checkConnectedDelay ?? 500);
283
- // }
284
-
285
- /**
286
- * 读取监听
287
- *
288
- * @param {*} res
289
- */
290
- async function innerListener(res: NFC.Data) {
291
- const transform = transformArrayBuffer(res?.id);
292
-
293
- nfcInstance = getInstance(res.techs, true);
294
-
295
- if (res.techs.includes('NFC-A')) {
296
- const nfcA = nfcAdapter.getNfcA();
297
- try {
298
- const atqa = await getAtqa(nfcA);
299
- const atqaInfo = parseAtqa(atqa.atqa);
300
- data.value.atqa = atqa.atqa;
301
- data.value.uidType = atqaInfo?.uidType;
302
- data.value.storageSize = atqaInfo?.storageSize;
303
- data.value.manufacturer = atqaInfo?.manufacturer;
304
- data.value.cardFeatures = atqaInfo?.cardFeatures;
305
- data.value.reserved = atqaInfo?.reserved;
306
- } catch (_error) {
307
- // ignore error
308
- }
309
-
310
- try {
311
- const sak = await getSak(nfcA);
312
- const sakType = getSakType(sak.sak);
313
- const sakHex = getSakHex(sak.sak);
314
- data.value.sak = sak.sak;
315
- data.value.sakType = sakType;
316
- data.value.sakHex = sakHex;
317
- } catch (_error) {
318
- // ignore error
319
- }
320
- }
321
-
322
- if (nfcInstance) {
323
- await connect();
324
-
325
- data.value.readWriteStandard = getReadWriteStandard(res.techs);
326
- if (!isNdef.value) {
327
- const maxTransceive = await getMaxTransceiveLength(nfcInstance);
328
- maxTransceiveLength = maxTransceive.length;
329
- data.value.maxTransceiveLength = maxTransceiveLength;
330
- } else {
331
- const otherInstance = getInstance(res.techs);
332
- const maxTransceive = await getMaxTransceiveLength(otherInstance);
333
- maxTransceiveLength = maxTransceive.length;
334
- data.value.maxTransceiveLength = maxTransceiveLength;
335
- }
336
-
337
- const messages =
338
- res.messages?.map((message) => {
339
- const records = message.records.map((item) => {
340
- const typeByte = transformArrayBuffer(
341
- item.type as any as ArrayBuffer,
342
- ).byteArray;
343
- const type = byteToString(typeByte);
344
-
345
- const idByte = transformArrayBuffer(
346
- item.id as any as ArrayBuffer,
347
- ).byteArray;
348
- const id = byteToString(idByte);
349
- const tnf = item.tnf?.toString() as NFC.Tnf;
350
-
351
- const payloadByte = transformArrayBuffer(
352
- item.payload as any as ArrayBuffer,
353
- ).byteArray;
354
-
355
- const typeDescription = getTypeDescription(type, payloadByte);
356
-
357
- let payload: any = byteToString(payloadByte);
358
- if (type === 'application/vnd.wfa.wsc') {
359
- payload = parseUniversalTLV(payloadByte, wifiTLVConfig);
360
- } else if (type === 'text/vcard') {
361
- payload = parseVCardPayload(payload);
362
- }
363
-
364
- return {
365
- id,
366
- tnf,
367
- tnfDescription: getTnfDescription(tnf),
368
- type,
369
- typeDescription,
370
- payload,
371
- };
372
- });
373
-
374
- return {
375
- ...message,
376
- records,
377
- };
378
- }) ?? [];
379
-
380
- data.value = {
381
- ...data.value,
382
- ...res,
383
- ...transform,
384
- messages,
385
- };
386
-
387
- isConnected.value = true;
388
-
389
- listener?.(data.value);
390
- // checkConnected();
391
- // 可将该行去除
392
- uni?.__dev_tool_nfc_collection__?.(data.value);
393
- }
394
- }
395
-
396
- /**
397
- * 移除监听读取消息
398
- *
399
- * @return {*}
400
- */
401
- function offHCEMessage() {
402
- if (!isSupportNFC.value) {
403
- uni.showToast({ title: '设备不支持 NFC,无需移除监听', icon: 'none' });
404
- return { errMsg: 'success' };
405
- }
406
- isConnected.value = false;
407
- nfcAdapter.offDiscovered(innerListener);
408
-
409
- uni.showToast({ title: 'NFC 监听已移除', icon: 'none' });
410
- return { errMsg: 'success' };
411
- }
412
-
413
- /**
414
- * 连接 nfc
415
- *
416
- * @return {*}
417
- */
418
- function connect(): Promise<{ errMsg: string }> {
419
- return new Promise((resolve, reject) => {
420
- if (!isSupportNFC.value) {
421
- uni.showToast({ title: '设备不支持 NFC', icon: 'none' });
422
- reject({
423
- errMsg: '设备不支持 NFC',
424
- });
425
- }
426
-
427
- if (!isListening.value) {
428
- uni.showToast({ title: '请先开启前台调度监听', icon: 'none' });
429
- reject({
430
- errMsg: '请先开启前台调度监听',
431
- });
432
- }
433
-
434
- if (!nfcInstance) {
435
- uni.showToast({ title: '请先靠近 NFC 标签', icon: 'none' });
436
- reject({
437
- errMsg: '请先靠近 NFC 标签',
438
- });
439
- }
440
-
441
- nfcInstance?.connect?.({
442
- success: (res) => {
443
- resolve(res);
444
- isConnected.value = true;
445
- uni.showToast({
446
- title: 'NFC 连接成功',
447
- icon: 'none',
448
- });
449
- resolve({
450
- errMsg: 'NFC 连接成功',
451
- });
452
- },
453
- fail: (err) => {
454
- if (err.errMsg === 'connect:fail:Tech already connected') {
455
- resolve(err);
456
- isConnected.value = true;
457
- } else {
458
- reject(err);
459
- isConnected.value = false;
460
- nfcInstance = undefined;
461
- uni.showToast({
462
- title: 'NFC 连接失败',
463
- icon: 'none',
464
- });
465
- }
466
- },
467
- });
468
- });
469
- }
470
-
471
- /**
472
- * 断开 nfc
473
- *
474
- * @return {*}
475
- */
476
- function close(): Promise<{ errMsg: string }> {
477
- return new Promise((resolve, reject) => {
478
- if (!isSupportNFC.value) {
479
- reject({
480
- errMsg: '不支持NFC',
481
- });
482
- }
483
-
484
- if (!nfcInstance) {
485
- reject({
486
- errMsg: '未读取到NFC卡',
487
- });
488
- }
489
-
490
- nfcInstance?.close?.({
491
- success: (_res) => {
492
- isConnected.value = false;
493
- nfcInstance = undefined;
494
- resolve({
495
- errMsg: 'NFC 断开成功',
496
- });
497
-
498
- uni.showToast({ title: 'NFC 连接已关闭', icon: 'none' });
499
- },
500
- fail: (err) => {
501
- reject(err);
502
- uni.showToast({ title: 'NFC 连接关闭失败', icon: 'none' });
503
- },
504
- });
505
- });
506
- }
507
-
508
- async function transceive(data: ArrayBuffer) {
509
- return new Promise((resolve, reject) => {
510
- if (!isSupportNFC.value) {
511
- reject({
512
- errMsg: '不支持NFC',
513
- });
514
- return;
515
- }
516
-
517
- if (!nfcInstance) {
518
- reject({
519
- errMsg: '未读取到NFC卡',
520
- });
521
- return;
522
- }
523
- nfcInstance?.transceive?.({
524
- data,
525
- success: (res) => {
526
- resolve(res);
527
- },
528
- fail: (err) => {
529
- reject(err);
530
- },
531
- });
532
- });
533
- }
534
-
535
- async function writeNdefMessage(data: NFC.NdefData) {
536
- return new Promise((resolve, reject) => {
537
- if (!isSupportNFC.value) {
538
- reject({
539
- errMsg: '不支持NFC',
540
- });
541
- } else if (!nfcInstance) {
542
- reject({
543
- errMsg: '未读取到NFC卡',
544
- });
545
- } else {
546
- nfcInstance?.writeNdefMessage?.({
547
- ...data,
548
- success: (res) => {
549
- resolve(res);
550
- },
551
- fail: (err) => {
552
- reject(err);
553
- },
554
- });
555
- }
556
- });
557
- }
558
-
559
- /**
560
- * 写入数据
561
- *
562
- * 支持以以下类型
563
- * ISO-DEP
564
- * MIFARE Classic
565
- * MIFARE Ultralight
566
- * NFC-A
567
- * NFC-B
568
- * NFC-F
569
- * NFC-V
570
- *
571
- * @param {*} data
572
- * @return {*}
573
- */
574
- async function write(data: ArrayBuffer) {
575
- try {
576
- // 连接 nfc
577
- await connect();
578
- uni.showToast({
579
- title: '开始写入数据, 请勿断开连接',
580
- icon: 'none',
581
- });
582
- // 写入数据
583
-
584
- const result = await transceive(data);
585
-
586
- uni.showToast({
587
- title: '数据写入成功',
588
- icon: 'none',
589
- });
590
- // 断开 nfc
591
- await close();
592
- return Promise.resolve({
593
- errMsg: '数据写入成功',
594
- data: result,
595
- });
596
- } catch (error) {
597
- return Promise.reject({
598
- errMsg: '数据写入失败',
599
- error,
600
- });
601
- }
602
- }
603
-
604
- /**
605
- * 写入数据
606
- * 支持以以下类型
607
- * Ndef
608
- *
609
- * @param {NFC.NdefData} data
610
- */
611
- async function writeNdef(data: NFC.NdefRecord[]) {
612
- if (!isNdef.value) {
613
- uni.showToast({
614
- title: 'NFC 标签不支持 NDEF',
615
- icon: 'none',
616
- });
617
- return Promise.reject({
618
- errMsg: 'NFC 标签不支持 NDEF',
619
- });
620
- }
621
-
622
- if (!nfcInstance) {
623
- uni.showToast({
624
- title: '请先建立连接',
625
- icon: 'none',
626
- });
627
- return Promise.reject({
628
- errMsg: '请先建立连接',
629
- });
630
- }
631
-
632
- if (!isConnected.value) {
633
- uni.showToast({
634
- title: '请先建立连接',
635
- icon: 'none',
636
- });
637
- return Promise.reject({
638
- errMsg: '请先建立连接',
639
- });
640
- }
641
-
642
- uni.showToast({
643
- title: '开始写入数据,请勿断开连接',
644
- icon: 'none',
645
- duration: 3000,
646
- });
647
-
648
- try {
649
- const records = data?.map((item) => {
650
- // const tnf = stringToArrayBuffer(item.tnf);
651
- const id = item.id ? stringToArrayBuffer(item.id) : new ArrayBuffer(0);
652
- const type = stringToArrayBuffer(item.type);
653
-
654
- return {
655
- tnf: item.tnf,
656
- type,
657
- id,
658
- payload: item.payload,
659
- };
660
- });
661
-
662
- if (maxTransceiveLength && maxTransceiveLength < records.length) {
663
- uni.showToast({
664
- title: '写入数据超出标签容量',
665
- icon: 'none',
666
- duration: 3000,
667
- });
668
- nfcInstance.close();
669
-
670
- return Promise.reject({
671
- errMsg: '写入数据超出标签容量',
672
- });
673
- }
674
-
675
- // 连接 nfc
676
- await connect();
677
- uni.showToast({
678
- title: '开始写入数据, 请勿断开连接',
679
- icon: 'none',
680
- });
681
- // 写入数据
682
-
683
- const result = await writeNdefMessage({
684
- records,
685
- });
686
-
687
- await close();
688
- uni.showToast({
689
- title: '数据写入成功',
690
- icon: 'none',
691
- duration: 3000,
692
- });
693
- return Promise.resolve({
694
- errMsg: '数据写入成功',
695
- data: result,
696
- });
697
- } catch (error) {
698
- uni.showToast({
699
- title: '数据写入失败',
700
- icon: 'none',
701
- duration: 3000,
702
- });
703
-
704
- return Promise.reject({
705
- errMsg: '数据写入失败',
706
- error,
707
- });
708
- }
709
- }
710
-
711
- /**
712
- *
713
- *
714
- * @param {string} text
715
- * @param {string} [language='zh'] 微信小程序下无效
716
- * @return {*}
717
- */
718
- async function writeNdefText(
719
- text: string,
720
- _language = 'zh',
721
- ): Promise<{ errMsg: string }> {
722
- return writeNdef([
723
- {
724
- tnf: 1,
725
- type: 'T',
726
- payload: stringToArrayBuffer(text),
727
- },
728
- ]);
729
- }
730
-
731
- function writeNdefUri(uri: string): Promise<{ errMsg: string }> {
732
- const record = createUriNdefRecord(uri);
733
- return writeNdef([record]);
734
- }
735
-
736
- function writeNdefAndroidApp(
737
- packageName: string,
738
- ): Promise<{ errMsg: string }> {
739
- return writeNdef([
740
- {
741
- tnf: 4,
742
- type: 'android.com:pkg',
743
- payload: stringToArrayBuffer(packageName),
744
- },
745
- ]);
746
- }
747
-
748
- function writeNdefWifi({
749
- ssid,
750
- password,
751
- authType,
752
- }: NFC.WSCConfig): Promise<{ errMsg: string }> {
753
- const mimeType = 'application/vnd.wfa.wsc';
754
- const wifiData = generateWSCBytesForAndroid({
755
- ssid,
756
- password,
757
- authType,
758
- });
759
- return writeNdef([
760
- {
761
- tnf: 2,
762
- type: mimeType,
763
- payload: arrayNumberToArrayBuffer(wifiData),
764
- },
765
- ]);
766
- }
767
-
768
- function writeNdefVcard(
769
- cardInfo: NFC.VCardContactInfo,
770
- ): Promise<{ errMsg: string }> {
771
- const mimeType = 'text/vcard';
772
- const cardString = formatCardInfo(cardInfo);
773
-
774
- const cardData = stringToArrayBuffer(cardString);
775
- return writeNdef([
776
- {
777
- tnf: 2,
778
- type: mimeType,
779
- payload: cardData,
780
- },
781
- ]);
782
- }
783
-
784
- onMounted(() => {
785
- initNfcAdapter();
786
- });
787
-
788
- onUnmounted(() => {
789
- stopHCE();
790
- offHCEMessage();
791
- });
792
-
793
- return {
794
- data,
795
- isNdef,
796
- isSupportNFC,
797
- isListening,
798
- isConnected,
799
- nfcInstance,
800
- startHCE,
801
- stopHCE,
802
- connect,
803
- close,
804
- write,
805
- writeNdef,
806
- writeNdefText,
807
- writeNdefUri,
808
- writeNdefAndroidApp,
809
- writeNdefWifi,
810
- writeNdefVcard,
811
- };
812
- }
1
+ import { onMounted, onUnmounted, ref } from 'vue';
2
+ import {
3
+ arrayNumberToArrayBuffer,
4
+ byteToString,
5
+ createUriNdefRecord,
6
+ formatCardInfo,
7
+ generateWSCBytesForAndroid,
8
+ getReadWriteStandard,
9
+ getSakHex,
10
+ getSakType,
11
+ getTnfDescription,
12
+ getTypeDescription,
13
+ parseAtqa,
14
+ parseUniversalTLV,
15
+ parseVCardPayload,
16
+ stringToArrayBuffer,
17
+ transformArrayBuffer,
18
+ wifiTLVConfig,
19
+ } from './utils';
20
+
21
+ export default function useNFCMpWeiXin(
22
+ listener: NFC.Listener,
23
+ _options?: NFC.NfcOption,
24
+ ): NFC.NfcResult {
25
+ /** 是否支持 nfc */
26
+ const isSupportNFC = ref<boolean | undefined>(false);
27
+ /** 是否监听中 */
28
+ const isListening = ref<boolean>(false);
29
+ /**
30
+ * 是否已连接
31
+ * 需要手动维护,调用connect()后连接 调用close()后断开 ,实际nfc 断开之后是无法监听到的, isConnected 已经被废弃掉了
32
+ */
33
+ const isConnected = ref<boolean>(false);
34
+ /** nfc 数据 */
35
+ const data = ref<NFC.Result>({
36
+ id: new ArrayBuffer(0),
37
+ techs: [],
38
+ byteArray: [],
39
+ hexArray: [],
40
+ hexNumberArray: [],
41
+ hexString: '',
42
+ });
43
+
44
+ /** nfc 适配器 */
45
+ let nfcAdapter: NFC.Adapter;
46
+
47
+ /** nfc 实例 */
48
+ let nfcInstance: NFC.Instance | undefined;
49
+
50
+ /** ndef 写入方式比较特殊,需要特殊处理 */
51
+ const isNdef = ref(false);
52
+
53
+ let maxTransceiveLength = 0;
54
+
55
+ const _checkInterval: any = null;
56
+
57
+ /**
58
+ * 初始化 nfc adapter
59
+ *
60
+ * @return {*}
61
+ */
62
+ async function initNfcAdapter() {
63
+ await checkHCEState();
64
+
65
+ if (!isSupportNFC.value) return;
66
+
67
+ nfcAdapter = wx.getNFCAdapter();
68
+
69
+ nfcAdapter.onDiscovered(innerListener);
70
+ }
71
+
72
+ function getAtqa(nfcInstance: NFC.Instance): Promise<NFC.Atqa> {
73
+ return new Promise((resolve, reject) => {
74
+ if (!nfcInstance.getAtqa) {
75
+ reject({ errMsg: '不支持获取 atqa' });
76
+ }
77
+ nfcInstance?.getAtqa?.({
78
+ success: (res) => {
79
+ resolve(res);
80
+ },
81
+ fail: (err) => {
82
+ reject(err);
83
+ },
84
+ });
85
+ });
86
+ }
87
+
88
+ function getMaxTransceiveLength(
89
+ nfcInstance: NFC.Instance,
90
+ ): Promise<NFC.MaxTransceiveLength> {
91
+ return new Promise((resolve, reject) => {
92
+ if (nfcInstance.getMaxTransceiveLength) {
93
+ nfcInstance?.getMaxTransceiveLength?.({
94
+ success: (res) => {
95
+ resolve(res);
96
+ },
97
+ fail: (err) => {
98
+ reject(err);
99
+ },
100
+ });
101
+ } else {
102
+ reject({ errMsg: '不支持获取 maxTransceiveLength' });
103
+ }
104
+ });
105
+ }
106
+
107
+ function getSak(nfcInstance: NFC.Instance): Promise<NFC.Sak> {
108
+ return new Promise((resolve, reject) => {
109
+ if (!nfcInstance.getMaxTransceiveLength) {
110
+ reject({ errMsg: '不支持获取 sak' });
111
+ }
112
+
113
+ nfcInstance?.getSak?.({
114
+ success: (res) => {
115
+ resolve(res);
116
+ },
117
+ fail: (err) => {
118
+ reject(err);
119
+ },
120
+ });
121
+ });
122
+ }
123
+
124
+ /**
125
+ * 检查HCE状态
126
+ *
127
+ * @return {*}
128
+ */
129
+ function checkHCEState() {
130
+ return new Promise((resolve, reject) => {
131
+ wx.getHCEState({
132
+ success: (res: any) => {
133
+ isSupportNFC.value = true;
134
+ resolve(res);
135
+ },
136
+ fail: (err: any) => {
137
+ isSupportNFC.value = false;
138
+ reject(err);
139
+ },
140
+ });
141
+ });
142
+ }
143
+
144
+ /**
145
+ * 启用HCE
146
+ *
147
+ * @return {*}
148
+ */
149
+ function startHCE() {
150
+ if (!isSupportNFC.value) {
151
+ uni.showToast({
152
+ title: '设备不支持 NFC',
153
+ icon: 'none',
154
+ });
155
+ return Promise.reject({
156
+ errMsg: '设备不支持 NFC',
157
+ });
158
+ }
159
+
160
+ // 前置校验
161
+ if (!nfcAdapter) {
162
+ uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
163
+ return Promise.reject({
164
+ errMsg: '请先初始化 NFC 适配器',
165
+ });
166
+ }
167
+
168
+ if (isListening.value) {
169
+ uni.showToast({ title: 'NFC 监听已开启,无需重复操作', icon: 'none' });
170
+ return Promise.reject({
171
+ errMsg: 'NFC 监听已开启,无需重复操作',
172
+ });
173
+ }
174
+ nfcAdapter.startDiscovery();
175
+ isListening.value = true;
176
+ uni.showToast({
177
+ title: '开始监听NFC',
178
+ icon: 'none',
179
+ });
180
+ return Promise.resolve({
181
+ errMsg: '开始监听NFC',
182
+ });
183
+ }
184
+
185
+ /**
186
+ * 停用HCE
187
+ *
188
+ * @return {*}
189
+ */
190
+ function stopHCE() {
191
+ // 前置校验
192
+ if (!isSupportNFC.value) {
193
+ uni.showToast({
194
+ title: '设备不支持 NFC',
195
+ icon: 'none',
196
+ });
197
+ return Promise.reject({
198
+ errMsg: '设备不支持 NFC',
199
+ });
200
+ }
201
+
202
+ // 前置校验
203
+ if (!nfcAdapter) {
204
+ uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
205
+ return Promise.reject({
206
+ errMsg: '请先初始化 NFC 适配器',
207
+ });
208
+ }
209
+
210
+ if (!isListening.value) {
211
+ uni.showToast({ title: 'NFC 监听已关闭,无需重复操作', icon: 'none' });
212
+ return Promise.reject({
213
+ errMsg: 'NFC 监听已关闭,无需重复操作',
214
+ });
215
+ }
216
+
217
+ nfcAdapter.stopDiscovery();
218
+ isListening.value = false;
219
+ uni.showToast({
220
+ title: '停止监听NFC',
221
+ icon: 'none',
222
+ });
223
+ return Promise.resolve({
224
+ errMsg: '停止监听NFC',
225
+ });
226
+ }
227
+
228
+ function getInstance(techs: NFC.NfcType[], needNdef?: boolean) {
229
+ let type = 'Ndef';
230
+ if (needNdef) {
231
+ type = 'Ndef';
232
+ } else {
233
+ type = techs.filter((tech) => tech != 'Ndef' && tech != 'NDEF')?.[0];
234
+ }
235
+
236
+ switch (type) {
237
+ case 'NFC-A':
238
+ return nfcAdapter.getNfcA();
239
+ case 'NFC-B':
240
+ return nfcAdapter.getNfcB();
241
+ case 'NFC-F':
242
+ return nfcAdapter.getNfcF();
243
+ case 'NFC-V':
244
+ return nfcAdapter.getNfcV();
245
+ case 'MIFARE Classic':
246
+ return nfcAdapter.getMifareClassic();
247
+ case 'MIFARE Ultralight':
248
+ return nfcAdapter.getMifareUltralight();
249
+ case 'Ndef':
250
+ isNdef.value = true;
251
+ return nfcAdapter.getNdef();
252
+ case 'ISO-DEP':
253
+ return nfcAdapter.getIsoDep();
254
+ default:
255
+ return undefined;
256
+ }
257
+ }
258
+
259
+ // function checkConnected() {
260
+ // checkInterval = setInterval(async () => {
261
+ // if (!nfcAdapter) {
262
+ // isConnected.value = false;
263
+ // clearInterval(checkInterval);
264
+ // return;
265
+ // }
266
+
267
+ // if (!nfcInstance) {
268
+ // isConnected.value = false;
269
+ // clearInterval(checkInterval);
270
+ // return;
271
+ // }
272
+ // try {
273
+ // // TODO: 检测是否连接成功
274
+ // // await connect();
275
+
276
+ // isConnected.value = true;
277
+ // } catch (error) {
278
+ // console.log('error: ', error);
279
+ // isConnected.value = false;
280
+ // clearInterval(checkInterval);
281
+ // }
282
+ // }, options?.checkConnectedDelay ?? 500);
283
+ // }
284
+
285
+ /**
286
+ * 读取监听
287
+ *
288
+ * @param {*} res
289
+ */
290
+ async function innerListener(res: NFC.Data) {
291
+ const transform = transformArrayBuffer(res?.id);
292
+
293
+ nfcInstance = getInstance(res.techs, true);
294
+
295
+ if (res.techs.includes('NFC-A')) {
296
+ const nfcA = nfcAdapter.getNfcA();
297
+ try {
298
+ const atqa = await getAtqa(nfcA);
299
+ const atqaInfo = parseAtqa(atqa.atqa);
300
+ data.value.atqa = atqa.atqa;
301
+ data.value.uidType = atqaInfo?.uidType;
302
+ data.value.storageSize = atqaInfo?.storageSize;
303
+ data.value.manufacturer = atqaInfo?.manufacturer;
304
+ data.value.cardFeatures = atqaInfo?.cardFeatures;
305
+ data.value.reserved = atqaInfo?.reserved;
306
+ } catch (_error) {
307
+ // ignore error
308
+ }
309
+
310
+ try {
311
+ const sak = await getSak(nfcA);
312
+ const sakType = getSakType(sak.sak);
313
+ const sakHex = getSakHex(sak.sak);
314
+ data.value.sak = sak.sak;
315
+ data.value.sakType = sakType;
316
+ data.value.sakHex = sakHex;
317
+ } catch (_error) {
318
+ // ignore error
319
+ }
320
+ }
321
+
322
+ if (nfcInstance) {
323
+ await connect();
324
+
325
+ data.value.readWriteStandard = getReadWriteStandard(res.techs);
326
+ if (!isNdef.value) {
327
+ const maxTransceive = await getMaxTransceiveLength(nfcInstance);
328
+ maxTransceiveLength = maxTransceive.length;
329
+ data.value.maxTransceiveLength = maxTransceiveLength;
330
+ } else {
331
+ const otherInstance = getInstance(res.techs);
332
+ const maxTransceive = await getMaxTransceiveLength(otherInstance);
333
+ maxTransceiveLength = maxTransceive.length;
334
+ data.value.maxTransceiveLength = maxTransceiveLength;
335
+ }
336
+
337
+ const messages =
338
+ res.messages?.map((message) => {
339
+ const records = message.records.map((item) => {
340
+ const typeByte = transformArrayBuffer(
341
+ item.type as any as ArrayBuffer,
342
+ ).byteArray;
343
+ const type = byteToString(typeByte);
344
+
345
+ const idByte = transformArrayBuffer(
346
+ item.id as any as ArrayBuffer,
347
+ ).byteArray;
348
+ const id = byteToString(idByte);
349
+ const tnf = item.tnf?.toString() as NFC.Tnf;
350
+
351
+ const payloadByte = transformArrayBuffer(
352
+ item.payload as any as ArrayBuffer,
353
+ ).byteArray;
354
+
355
+ const typeDescription = getTypeDescription(type, payloadByte);
356
+
357
+ let payload: any = byteToString(payloadByte);
358
+ if (type === 'application/vnd.wfa.wsc') {
359
+ payload = parseUniversalTLV(payloadByte, wifiTLVConfig);
360
+ } else if (type === 'text/vcard') {
361
+ payload = parseVCardPayload(payload);
362
+ }
363
+
364
+ return {
365
+ id,
366
+ tnf,
367
+ tnfDescription: getTnfDescription(tnf),
368
+ type,
369
+ typeDescription,
370
+ payload,
371
+ };
372
+ });
373
+
374
+ return {
375
+ ...message,
376
+ records,
377
+ };
378
+ }) ?? [];
379
+
380
+ data.value = {
381
+ ...data.value,
382
+ ...res,
383
+ ...transform,
384
+ messages,
385
+ };
386
+
387
+ isConnected.value = true;
388
+
389
+ listener?.(data.value);
390
+ // checkConnected();
391
+ // 可将该行去除
392
+ uni?.__dev_tool_nfc_collection__?.(data.value);
393
+ }
394
+ }
395
+
396
+ /**
397
+ * 移除监听读取消息
398
+ *
399
+ * @return {*}
400
+ */
401
+ function offHCEMessage() {
402
+ if (!isSupportNFC.value) {
403
+ uni.showToast({ title: '设备不支持 NFC,无需移除监听', icon: 'none' });
404
+ return { errMsg: 'success' };
405
+ }
406
+ isConnected.value = false;
407
+ nfcAdapter.offDiscovered(innerListener);
408
+
409
+ uni.showToast({ title: 'NFC 监听已移除', icon: 'none' });
410
+ return { errMsg: 'success' };
411
+ }
412
+
413
+ /**
414
+ * 连接 nfc
415
+ *
416
+ * @return {*}
417
+ */
418
+ function connect(): Promise<{ errMsg: string }> {
419
+ return new Promise((resolve, reject) => {
420
+ if (!isSupportNFC.value) {
421
+ uni.showToast({ title: '设备不支持 NFC', icon: 'none' });
422
+ reject({
423
+ errMsg: '设备不支持 NFC',
424
+ });
425
+ }
426
+
427
+ if (!isListening.value) {
428
+ uni.showToast({ title: '请先开启前台调度监听', icon: 'none' });
429
+ reject({
430
+ errMsg: '请先开启前台调度监听',
431
+ });
432
+ }
433
+
434
+ if (!nfcInstance) {
435
+ uni.showToast({ title: '请先靠近 NFC 标签', icon: 'none' });
436
+ reject({
437
+ errMsg: '请先靠近 NFC 标签',
438
+ });
439
+ }
440
+
441
+ nfcInstance?.connect?.({
442
+ success: (res) => {
443
+ resolve(res);
444
+ isConnected.value = true;
445
+ uni.showToast({
446
+ title: 'NFC 连接成功',
447
+ icon: 'none',
448
+ });
449
+ resolve({
450
+ errMsg: 'NFC 连接成功',
451
+ });
452
+ },
453
+ fail: (err) => {
454
+ if (err.errMsg === 'connect:fail:Tech already connected') {
455
+ resolve(err);
456
+ isConnected.value = true;
457
+ } else {
458
+ reject(err);
459
+ isConnected.value = false;
460
+ nfcInstance = undefined;
461
+ uni.showToast({
462
+ title: 'NFC 连接失败',
463
+ icon: 'none',
464
+ });
465
+ }
466
+ },
467
+ });
468
+ });
469
+ }
470
+
471
+ /**
472
+ * 断开 nfc
473
+ *
474
+ * @return {*}
475
+ */
476
+ function close(): Promise<{ errMsg: string }> {
477
+ return new Promise((resolve, reject) => {
478
+ if (!isSupportNFC.value) {
479
+ reject({
480
+ errMsg: '不支持NFC',
481
+ });
482
+ }
483
+
484
+ if (!nfcInstance) {
485
+ reject({
486
+ errMsg: '未读取到NFC卡',
487
+ });
488
+ }
489
+
490
+ nfcInstance?.close?.({
491
+ success: (_res) => {
492
+ isConnected.value = false;
493
+ nfcInstance = undefined;
494
+ resolve({
495
+ errMsg: 'NFC 断开成功',
496
+ });
497
+
498
+ uni.showToast({ title: 'NFC 连接已关闭', icon: 'none' });
499
+ },
500
+ fail: (err) => {
501
+ reject(err);
502
+ uni.showToast({ title: 'NFC 连接关闭失败', icon: 'none' });
503
+ },
504
+ });
505
+ });
506
+ }
507
+
508
+ async function transceive(data: ArrayBuffer) {
509
+ return new Promise((resolve, reject) => {
510
+ if (!isSupportNFC.value) {
511
+ reject({
512
+ errMsg: '不支持NFC',
513
+ });
514
+ return;
515
+ }
516
+
517
+ if (!nfcInstance) {
518
+ reject({
519
+ errMsg: '未读取到NFC卡',
520
+ });
521
+ return;
522
+ }
523
+ nfcInstance?.transceive?.({
524
+ data,
525
+ success: (res) => {
526
+ resolve(res);
527
+ },
528
+ fail: (err) => {
529
+ reject(err);
530
+ },
531
+ });
532
+ });
533
+ }
534
+
535
+ async function writeNdefMessage(data: NFC.NdefData) {
536
+ return new Promise((resolve, reject) => {
537
+ if (!isSupportNFC.value) {
538
+ reject({
539
+ errMsg: '不支持NFC',
540
+ });
541
+ } else if (!nfcInstance) {
542
+ reject({
543
+ errMsg: '未读取到NFC卡',
544
+ });
545
+ } else {
546
+ nfcInstance?.writeNdefMessage?.({
547
+ ...data,
548
+ success: (res) => {
549
+ resolve(res);
550
+ },
551
+ fail: (err) => {
552
+ reject(err);
553
+ },
554
+ });
555
+ }
556
+ });
557
+ }
558
+
559
+ /**
560
+ * 写入数据
561
+ *
562
+ * 支持以以下类型
563
+ * ISO-DEP
564
+ * MIFARE Classic
565
+ * MIFARE Ultralight
566
+ * NFC-A
567
+ * NFC-B
568
+ * NFC-F
569
+ * NFC-V
570
+ *
571
+ * @param {*} data
572
+ * @return {*}
573
+ */
574
+ async function write(data: ArrayBuffer) {
575
+ try {
576
+ // 连接 nfc
577
+ await connect();
578
+ uni.showToast({
579
+ title: '开始写入数据, 请勿断开连接',
580
+ icon: 'none',
581
+ });
582
+ // 写入数据
583
+
584
+ const result = await transceive(data);
585
+
586
+ uni.showToast({
587
+ title: '数据写入成功',
588
+ icon: 'none',
589
+ });
590
+ // 断开 nfc
591
+ await close();
592
+ return Promise.resolve({
593
+ errMsg: '数据写入成功',
594
+ data: result,
595
+ });
596
+ } catch (error) {
597
+ return Promise.reject({
598
+ errMsg: '数据写入失败',
599
+ error,
600
+ });
601
+ }
602
+ }
603
+
604
+ /**
605
+ * 写入数据
606
+ * 支持以以下类型
607
+ * Ndef
608
+ *
609
+ * @param {NFC.NdefData} data
610
+ */
611
+ async function writeNdef(data: NFC.NdefRecord[]) {
612
+ if (!isNdef.value) {
613
+ uni.showToast({
614
+ title: 'NFC 标签不支持 NDEF',
615
+ icon: 'none',
616
+ });
617
+ return Promise.reject({
618
+ errMsg: 'NFC 标签不支持 NDEF',
619
+ });
620
+ }
621
+
622
+ if (!nfcInstance) {
623
+ uni.showToast({
624
+ title: '请先建立连接',
625
+ icon: 'none',
626
+ });
627
+ return Promise.reject({
628
+ errMsg: '请先建立连接',
629
+ });
630
+ }
631
+
632
+ if (!isConnected.value) {
633
+ uni.showToast({
634
+ title: '请先建立连接',
635
+ icon: 'none',
636
+ });
637
+ return Promise.reject({
638
+ errMsg: '请先建立连接',
639
+ });
640
+ }
641
+
642
+ uni.showToast({
643
+ title: '开始写入数据,请勿断开连接',
644
+ icon: 'none',
645
+ duration: 3000,
646
+ });
647
+
648
+ try {
649
+ const records = data?.map((item) => {
650
+ // const tnf = stringToArrayBuffer(item.tnf);
651
+ const id = item.id ? stringToArrayBuffer(item.id) : new ArrayBuffer(0);
652
+ const type = stringToArrayBuffer(item.type);
653
+
654
+ return {
655
+ tnf: item.tnf,
656
+ type,
657
+ id,
658
+ payload: item.payload,
659
+ };
660
+ });
661
+
662
+ if (maxTransceiveLength && maxTransceiveLength < records.length) {
663
+ uni.showToast({
664
+ title: '写入数据超出标签容量',
665
+ icon: 'none',
666
+ duration: 3000,
667
+ });
668
+ nfcInstance.close();
669
+
670
+ return Promise.reject({
671
+ errMsg: '写入数据超出标签容量',
672
+ });
673
+ }
674
+
675
+ // 连接 nfc
676
+ await connect();
677
+ uni.showToast({
678
+ title: '开始写入数据, 请勿断开连接',
679
+ icon: 'none',
680
+ });
681
+ // 写入数据
682
+
683
+ const result = await writeNdefMessage({
684
+ records,
685
+ });
686
+
687
+ await close();
688
+ uni.showToast({
689
+ title: '数据写入成功',
690
+ icon: 'none',
691
+ duration: 3000,
692
+ });
693
+ return Promise.resolve({
694
+ errMsg: '数据写入成功',
695
+ data: result,
696
+ });
697
+ } catch (error) {
698
+ uni.showToast({
699
+ title: '数据写入失败',
700
+ icon: 'none',
701
+ duration: 3000,
702
+ });
703
+
704
+ return Promise.reject({
705
+ errMsg: '数据写入失败',
706
+ error,
707
+ });
708
+ }
709
+ }
710
+
711
+ /**
712
+ *
713
+ *
714
+ * @param {string} text
715
+ * @param {string} [language='zh'] 微信小程序下无效
716
+ * @return {*}
717
+ */
718
+ async function writeNdefText(
719
+ text: string,
720
+ _language = 'zh',
721
+ ): Promise<{ errMsg: string }> {
722
+ return writeNdef([
723
+ {
724
+ tnf: 1,
725
+ type: 'T',
726
+ payload: stringToArrayBuffer(text),
727
+ },
728
+ ]);
729
+ }
730
+
731
+ function writeNdefUri(uri: string): Promise<{ errMsg: string }> {
732
+ const record = createUriNdefRecord(uri);
733
+ return writeNdef([record]);
734
+ }
735
+
736
+ function writeNdefAndroidApp(
737
+ packageName: string,
738
+ ): Promise<{ errMsg: string }> {
739
+ return writeNdef([
740
+ {
741
+ tnf: 4,
742
+ type: 'android.com:pkg',
743
+ payload: stringToArrayBuffer(packageName),
744
+ },
745
+ ]);
746
+ }
747
+
748
+ function writeNdefWifi({
749
+ ssid,
750
+ password,
751
+ authType,
752
+ }: NFC.WSCConfig): Promise<{ errMsg: string }> {
753
+ const mimeType = 'application/vnd.wfa.wsc';
754
+ const wifiData = generateWSCBytesForAndroid({
755
+ ssid,
756
+ password,
757
+ authType,
758
+ });
759
+ return writeNdef([
760
+ {
761
+ tnf: 2,
762
+ type: mimeType,
763
+ payload: arrayNumberToArrayBuffer(wifiData),
764
+ },
765
+ ]);
766
+ }
767
+
768
+ function writeNdefVcard(
769
+ cardInfo: NFC.VCardContactInfo,
770
+ ): Promise<{ errMsg: string }> {
771
+ const mimeType = 'text/vcard';
772
+ const cardString = formatCardInfo(cardInfo);
773
+
774
+ const cardData = stringToArrayBuffer(cardString);
775
+ return writeNdef([
776
+ {
777
+ tnf: 2,
778
+ type: mimeType,
779
+ payload: cardData,
780
+ },
781
+ ]);
782
+ }
783
+
784
+ onMounted(() => {
785
+ initNfcAdapter();
786
+ });
787
+
788
+ onUnmounted(() => {
789
+ stopHCE();
790
+ offHCEMessage();
791
+ });
792
+
793
+ return {
794
+ data,
795
+ isNdef,
796
+ isSupportNFC,
797
+ isListening,
798
+ isConnected,
799
+ nfcInstance,
800
+ startHCE,
801
+ stopHCE,
802
+ connect,
803
+ close,
804
+ write,
805
+ writeNdef,
806
+ writeNdefText,
807
+ writeNdefUri,
808
+ writeNdefAndroidApp,
809
+ writeNdefWifi,
810
+ writeNdefVcard,
811
+ };
812
+ }