vite-uni-dev-tool 1.0.0 → 1.1.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.
Files changed (168) hide show
  1. package/README.md +46 -0
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +12 -0
  4. package/dist/const.d.ts.map +1 -1
  5. package/dist/const.js +1 -1
  6. package/dist/core-shared.d.ts +1 -1
  7. package/dist/core-shared.d.ts.map +1 -1
  8. package/dist/core-shared.js +1 -1
  9. package/dist/core.d.ts +10 -3
  10. package/dist/core.d.ts.map +1 -1
  11. package/dist/core.js +2 -2
  12. package/dist/i18n/locales/en.cjs +1 -1
  13. package/dist/i18n/locales/en.d.ts +81 -0
  14. package/dist/i18n/locales/en.d.ts.map +1 -1
  15. package/dist/i18n/locales/en.js +1 -1
  16. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  17. package/dist/i18n/locales/zh-Hans.d.ts +82 -1
  18. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -1
  19. package/dist/i18n/locales/zh-Hans.js +1 -1
  20. package/dist/modules/devConsole/index.cjs +1 -1
  21. package/dist/modules/devConsole/index.js +3 -3
  22. package/dist/modules/devEvent/index.cjs +3 -3
  23. package/dist/modules/devEvent/index.d.ts +1 -0
  24. package/dist/modules/devEvent/index.d.ts.map +1 -1
  25. package/dist/modules/devEvent/index.js +3 -3
  26. package/dist/modules/devIntercept/index.cjs +14 -13
  27. package/dist/modules/devIntercept/index.d.ts +19 -0
  28. package/dist/modules/devIntercept/index.d.ts.map +1 -1
  29. package/dist/modules/devIntercept/index.js +14 -13
  30. package/dist/modules/devStore/index.cjs +1 -1
  31. package/dist/modules/devStore/index.d.ts +21 -0
  32. package/dist/modules/devStore/index.d.ts.map +1 -1
  33. package/dist/modules/devStore/index.js +1 -1
  34. package/dist/plugins/uniDevTool/transform/transformMain.cjs +1 -1
  35. package/dist/plugins/uniDevTool/transform/transformMain.js +1 -1
  36. package/dist/type.d.ts +47 -2
  37. package/dist/type.d.ts.map +1 -1
  38. package/dist/utils/language.cjs +1 -1
  39. package/dist/utils/language.d.ts.map +1 -1
  40. package/dist/utils/language.js +1 -1
  41. package/dist/utils/object.cjs +1 -1
  42. package/dist/utils/object.d.ts.map +1 -1
  43. package/dist/utils/object.js +1 -1
  44. package/dist/v3/DevTool/components/BluetoothList/BluetoothItem.vue +199 -0
  45. package/dist/v3/DevTool/components/BluetoothList/BluetoothTool.vue +730 -0
  46. package/dist/v3/DevTool/components/BluetoothList/index.vue +167 -0
  47. package/dist/v3/{CaptureScreen → DevTool/components/CaptureScreen}/index.vue +109 -109
  48. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/ConsoleItem.vue +225 -224
  49. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/RunJSInput.vue +247 -249
  50. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/index.vue +171 -160
  51. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/staticTips.ts +1145 -1145
  52. package/dist/v3/{DevToolButton → DevTool/components/DevToolButton}/index.vue +7 -4
  53. package/dist/v3/{DevToolTitle → DevTool/components/DevToolTitle}/index.vue +24 -24
  54. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/DevToolOverlay.vue +197 -182
  55. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/const.ts +28 -5
  56. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/dataUtils.ts +48 -48
  57. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolData.ts +387 -338
  58. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolHandlers.ts +629 -549
  59. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolOverlay.ts +197 -184
  60. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/index.vue +67 -16
  61. package/dist/v3/{ElEvent → DevTool/components/ElEvent}/ElEventItem.vue +105 -105
  62. package/dist/v3/{ElEvent → DevTool/components/ElEvent}/index.vue +106 -109
  63. package/dist/v3/{Instance → DevTool/components/Instance}/components/InstanceTreeNode.vue +265 -265
  64. package/dist/v3/{Instance → DevTool/components/Instance}/flatten.ts +226 -226
  65. package/dist/v3/{Instance → DevTool/components/Instance}/index.vue +94 -94
  66. package/dist/v3/{Instance → DevTool/components/Instance}/registry.ts +49 -49
  67. package/dist/v3/{Instance → DevTool/components/Instance}/transformTree.ts +375 -375
  68. package/dist/v3/{Instance → DevTool/components/Instance}/transformTreeCtx.ts +268 -268
  69. package/dist/v3/{Instance → DevTool/components/Instance}/typing.d.ts +43 -43
  70. package/dist/v3/{InstanceDetail → DevTool/components/InstanceDetail}/index.vue +485 -485
  71. package/dist/v3/{JsonDetail → DevTool/components/JsonDetail}/index.vue +70 -70
  72. package/dist/v3/{NFCList → DevTool/components/NFCList}/NFCItem.vue +112 -113
  73. package/dist/v3/{NFCList → DevTool/components/NFCList}/NFCTool.vue +454 -478
  74. package/dist/v3/{NFCList → DevTool/components/NFCList}/const.ts +56 -56
  75. package/dist/v3/{NFCList → DevTool/components/NFCList}/index.vue +94 -98
  76. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/InterceptConfig.vue +624 -608
  77. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/InterceptItem.vue +140 -140
  78. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkDetail.vue +287 -296
  79. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkIntercept.vue +88 -93
  80. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkItem.vue +163 -167
  81. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkSend.vue +589 -556
  82. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/const.ts +4 -4
  83. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/hooks/useNetworkForm.ts +86 -86
  84. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/index.vue +160 -160
  85. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/utils.ts +101 -101
  86. package/dist/v3/{Performance → DevTool/components/Performance}/index.vue +498 -495
  87. package/dist/v3/{Performance → DevTool/components/Performance}/modules/PerformanceMetrics.vue +153 -153
  88. package/dist/v3/{Performance → DevTool/components/Performance}/modules/PerformanceWidget.vue +12 -9
  89. package/dist/v3/{Performance → DevTool/components/Performance}/modules/usePerformanceChart.ts +460 -460
  90. package/dist/v3/{Performance → DevTool/components/Performance}/modules/usePerformanceData.ts +258 -258
  91. package/dist/v3/{PiniaList → DevTool/components/PiniaList}/index.vue +93 -94
  92. package/dist/v3/{RouteList → DevTool/components/RouteList}/index.vue +21 -24
  93. package/dist/v3/{RunJS → DevTool/components/RunJS}/index.vue +148 -148
  94. package/dist/v3/{ScanCodeList → DevTool/components/ScanCodeList}/ScanCodeItem.vue +97 -98
  95. package/dist/v3/{ScanCodeList → DevTool/components/ScanCodeList}/index.vue +100 -104
  96. package/dist/v3/{SettingButton → DevTool/components/SettingButton}/index.vue +45 -45
  97. package/dist/v3/{SettingList → DevTool/components/SettingList}/index.vue +218 -150
  98. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +304 -0
  99. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingDevTool.vue +212 -208
  100. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingInfo.vue +157 -119
  101. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingLanguage.vue +74 -74
  102. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingLog.vue +230 -230
  103. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingNetwork.vue +3 -3
  104. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingTheme.vue +37 -7
  105. package/dist/v3/{SettingList → DevTool/components/SettingList}/typing.d.ts +2 -2
  106. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/Line.vue +127 -116
  107. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/index.vue +8 -8
  108. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/parseCode.ts +609 -701
  109. package/dist/v3/{StorageList → DevTool/components/StorageList}/index.vue +174 -174
  110. package/dist/v3/{TransferList → DevTool/components/TransferList}/TransferDetail.vue +268 -268
  111. package/dist/v3/{TransferList → DevTool/components/TransferList}/TransferItem.vue +4 -4
  112. package/dist/v3/{TransferList → DevTool/components/TransferList}/index.vue +8 -8
  113. package/dist/v3/{UniEvent → DevTool/components/UniEvent}/UniEventItem.vue +6 -7
  114. package/dist/v3/{UniEvent → DevTool/components/UniEvent}/index.vue +6 -6
  115. package/dist/v3/{VuexList → DevTool/components/VuexList}/index.vue +84 -84
  116. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/WebSocketDetail.vue +8 -8
  117. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/WebSocketItem.vue +4 -4
  118. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/index.vue +8 -8
  119. package/dist/v3/DevTool/index.vue +179 -5
  120. package/dist/v3/{AppTransition → components/AppTransition}/index.vue +176 -170
  121. package/dist/v3/{AutoSizer → components/AutoSizer}/index.vue +192 -192
  122. package/dist/v3/{AutoSizer → components/AutoSizer}/index1.vue +184 -184
  123. package/dist/v3/{AutoSizer → components/AutoSizer}/utils.ts +49 -49
  124. package/dist/v3/components/Barrage/BarrageItem.vue +137 -0
  125. package/dist/v3/components/Barrage/index.vue +202 -0
  126. package/dist/v3/{CircularButton → components/CircularButton}/index.vue +84 -84
  127. package/dist/v3/{CustomSwiper → components/CustomSwiper}/CustomSwiperItem.vue +49 -49
  128. package/dist/v3/{CustomSwiper → components/CustomSwiper}/index.vue +104 -104
  129. package/dist/v3/{DraggableContainer → components/DraggableContainer}/index.vue +1 -1
  130. package/dist/v3/{Empty → components/Empty}/index.vue +29 -29
  131. package/dist/v3/{FilterInput → components/FilterInput}/index.vue +1 -1
  132. package/dist/v3/{FilterSelect → components/FilterSelect}/index.vue +179 -179
  133. package/dist/v3/{JsonPretty → components/JsonPretty}/components/Brackets/index.vue +27 -27
  134. package/dist/v3/{JsonPretty → components/JsonPretty}/components/Carets/index.vue +59 -59
  135. package/dist/v3/{JsonPretty → components/JsonPretty}/components/CheckController/index.vue +136 -136
  136. package/dist/v3/{JsonPretty → components/JsonPretty}/components/TreeNode/index.vue +387 -381
  137. package/dist/v3/{JsonPretty → components/JsonPretty}/hooks/useClipboard.ts +21 -21
  138. package/dist/v3/{JsonPretty → components/JsonPretty}/hooks/useError.ts +21 -21
  139. package/dist/v3/{JsonPretty → components/JsonPretty}/index.vue +16 -13
  140. package/dist/v3/{JsonPretty → components/JsonPretty}/type.ts +127 -126
  141. package/dist/v3/{JsonPretty → components/JsonPretty}/utils/index.ts +169 -169
  142. package/dist/v3/{MovableContainer → components/MovableContainer}/index.vue +1 -1
  143. package/dist/v3/{Pick → components/Pick}/index.vue +322 -322
  144. package/dist/v3/{Tabs → components/Tabs}/index.vue +30 -4
  145. package/dist/v3/{Tag → components/Tag}/index.vue +113 -113
  146. package/dist/v3/{VirtualList → components/VirtualList}/AutoSize.vue +40 -40
  147. package/dist/v3/{VirtualList → components/VirtualList}/index.vue +416 -412
  148. package/dist/v3/hooks/useBluetooth/index.ts +561 -0
  149. package/dist/v3/hooks/useContainerStyle.ts +153 -153
  150. package/dist/v3/hooks/useNFC/index.ts +107 -107
  151. package/dist/v3/hooks/useNFC/typing.d.ts +396 -396
  152. package/dist/v3/hooks/useNFC/useNFCAndroid.ts +966 -966
  153. package/dist/v3/hooks/useNFC/useNFCMpWeiXin.ts +812 -812
  154. package/dist/v3/hooks/useNFC/utils.ts +754 -754
  155. package/dist/v3/hooks/useRequest/index.ts +586 -573
  156. package/dist/v3/hooks/useRequest/utils.ts +267 -267
  157. package/dist/v3/hooks/useScanCode/index.ts +206 -206
  158. package/dist/v3/hooks/useWebsocket/README.md +79 -0
  159. package/dist/v3/hooks/useWebsocket/index.ts +253 -0
  160. package/dist/v3/styles/theme.css +17 -10
  161. package/dist/v3/styles/theme.ts +12 -12
  162. package/package.json +59 -64
  163. package/dist/plugins/uniParseStock/index.d.ts +0 -10
  164. package/dist/plugins/uniParseStock/index.d.ts.map +0 -1
  165. /package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/index.css +0 -0
  166. /package/dist/v3/{SettingList → DevTool/components/SettingList}/index.css +0 -0
  167. /package/dist/v3/{Empty → components/Empty}/empty.png +0 -0
  168. /package/dist/v3/{VirtualList → components/VirtualList}/readme.md +0 -0
@@ -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
+ }