// 核心工具函数:将ArrayBuffer转换为十六进制字符串
export function arrayBufferToHex(buffer) {
// 将ArrayBuffer转为Uint8Array(便于遍历每个字节)
const uint8Array = new Uint8Array(buffer);
// 每个字节转为两位十六进制,不足两位补0,最后拼接成字符串
return Array.from(uint8Array)
.map(byte => byte.toString(16).padStart(2, '0')) // 确保每个字节占两位
.join('')
.toUpperCase(); // 转为大写(UID通常以大写展示)
}
export const stringToBuffer = function (str) {
// 首先将字符串转为16进制
if (!str) {
return new Uint8Array().buffer;
}
let val = ""
for (let i = 0; i < str.length; i++) {
if (val === '') {
val = str.charCodeAt(i).toString(16)
} else {
val += ',' + str.charCodeAt(i).toString(16)
}
}
// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})).buffer
}
const prepareSeal = async (seal, position) => {
// 调用拍照
const photoUrl = await takePhoto()
if (!photoUrl) return
try {
// 1. 获取 NFC 适配器
adapter.value = wx.getNFCAdapter()
toast.info('请使用手机触碰铅封')
// 2. 清理旧的监听,避免重复触发
if (discoveredListener.value) {
adapter.value.offDiscovered(discoveredListener.value)
discoveredListener.value = null
}
// 3. 开始发现 NFC 标签
adapter.value.startDiscovery({
success: () => {
console.log('NFC 监听已开启')
// 定义发现标签后的回调函数
discoveredListener.value = async (tagRes: any) => {
console.log('发现 NFC 标签:', tagRes)
// 3.1 获取 UID
const uidBuffer = tagRes.id
const uid = arrayBufferToHex(uidBuffer)
console.log('标签 UID:', uid)
try {
// 3.2 调用后端接口,提交 UID 及相关数据
const data = {
transportOrderId: transportOrderId.value,
vehicleNumber: vehicleNumber.value,
chipUid: uid,
applySealPosition: `${position}号口`,
applySealImage: photoUrl,
userId: uni.getStorageSync('userInfo').userId,
}
const res: any = await nfcSealApi(data)
if (res.code === 200) {
console.log('接口响应成功:', res)
// 3.3 获取 NDEF 实例
const ndef = adapter.value.getNdef(tagRes)
if (!ndef) {
toast.error('该标签不支持 NDEF 写入')
return
}
// 3.4 连接 NDEF
ndef.connect({
success: () => {
console.log('NDEF 连接成功')
// 3.5 写入 NDEF 文本记录
ndef.writeNdefMessage({
records: [{
id: stringToBuffer('1'),
payload: stringToBuffer(res.data),
type: stringToBuffer('T'), // 文本类型
tnf: 1 // NFC Forum Well Known Type
}],
success: async () => {
toast.success('写入成功')
console.log('写入成功:', res.data)
ndef.close()
await init(transportOrderId.value)
},
fail: (err: any) => {
toast.error('写入失败')
console.error('写入失败', err)
ndef.close()
},
})
},
fail: (err: any) => {
toast.error('NDEF 连接失败')
console.error('NDEF 连接失败:', err)
},
})
} else {
toast.error(res?.msg || '施封失败,请重新施封')
}
} catch (error: any) {
toast.error(error?.data?.msg || '施封失败,请重新施封')
console.error('接口调用异常:', error)
} finally {
// 3.6 清理监听和发现
if (discoveredListener.value) {
adapter.value.offDiscovered(discoveredListener.value)
discoveredListener.value = null
}
adapter.value.stopDiscovery()
console.log('NFC 监听已关闭')
}
}
// 注册标签监听
adapter.value.onDiscovered(discoveredListener.value)
},
fail: (err: any) => {
console.error('NFC 连接失败:', err)
toast.error('NFC 连接失败')
adapter.value.stopDiscovery()
},
})
} catch (err) {
console.error('NFC 初始化失败:', err)
toast.error('NFC 初始化失败')
}
}