import { initNFC, startRead, closeNFC } from '@/utils/nfc.js';
const prepareSeal = async (seal, position) => {
const photoUrl = await takePhoto()
if (!photoUrl) return
initNFC(async (e) => {
if (!e.uid || !e.text) {
toast.error('NFC 读取失败')
return
}
try {
const data = {
transportOrderId: info.value.transportOrderId,
vehicleNumber: info.value.selfPickupVehicle,
unsealImage: photoUrl,
chipUid: e.uid.replace(/:/g, '').toUpperCase(),
encryptedDataHash: e.text,
unsealPosition: `${position}号口`,
userId: uni.getStorageSync('userInfo').userId,
}
const res = await getNfcUnlockApi(data)
if (res.code === 200) {
await refresh()
toast.success('解封成功')
} else {
toast.error( res.msg || '解封失败')
}
} catch (error) {
console.log(error)
} finally {
closeNFC()
}
})
startRead();
}
onUnmounted(() => {
closeNFC()
})
// 全局变量(与你原代码保持一致)
let NfcAdapter = null
let NdefRecord = null
let NdefMessage = null
let nfcAdapter = null
let mainActivity = null
let waiting = null
let readyRead = false
let readCallback = null
/**
* 初始化NFC监听
* @param {Function} cb - 读取结果回调函数
*/
export function initNFC(cb) {
if (uni.getSystemInfoSync().platform !== 'android') {
plus.nativeUI.toast('仅支持安卓设备')
return
}
readCallback = cb
try {
// 获取UniApp主Activity(App端关键)
mainActivity = plus.android.runtimeMainActivity()
const Intent = plus.android.importClass('android.content.Intent')
const PendingIntent = plus.android.importClass('android.app.PendingIntent')
const IntentFilter = plus.android.importClass('android.content.IntentFilter')
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter')
// 初始化NFC适配器
nfcAdapter = NfcAdapter.getDefaultAdapter(mainActivity)
if (!nfcAdapter) {
plus.nativeUI.toast('设备不支持NFC')
return
}
if (!nfcAdapter.isEnabled()) {
plus.nativeUI.toast('请在系统设置中开启NFC')
return
}
// 配置Intent
const intent = new Intent(mainActivity, mainActivity.getClass())
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
const pendingIntent = PendingIntent.getActivity(mainActivity, 0, intent, PendingIntent.FLAG_MUTABLE)
// 配置过滤器
const ndefFilter = new IntentFilter("android.nfc.action.TECH_DISCOVERED")
ndefFilter.addDataType("*/*")
const intentFiltersArray = [ndefFilter]
// 支持的NFC技术类型
const techListsArray = [
["android.nfc.tech.IsoDep"],
["android.nfc.tech.NfcA"],
["android.nfc.tech.NfcB"],
["android.nfc.tech.NfcF"],
["android.nfc.tech.Nfcf"],
["android.nfc.tech.NfcV"],
["android.nfc.tech.NdefFormatable"],
["android.nfc.tech.MifareClassi"],
["android.nfc.tech.MifareUltralight"]
]
// 移除旧的事件监听,避免重复注册
plus.globalEvent.removeEventListener("newintent", handleNfcData)
// 注册新的事件监听
plus.globalEvent.addEventListener("newintent", handleNfcData, false)
// 页面生命周期
plus.globalEvent.addEventListener("pause", function () {
if (nfcAdapter) {
nfcAdapter.disableForegroundDispatch(mainActivity)
console.log('pause: 关闭NFC前台调度')
}
}, false)
plus.globalEvent.addEventListener("resume", function () {
if (nfcAdapter) {
nfcAdapter.enableForegroundDispatch(mainActivity, pendingIntent, intentFiltersArray, techListsArray)
console.log('resume: 重启NFC前台调度')
}
}, false)
// 初始启用前台调度
nfcAdapter.enableForegroundDispatch(mainActivity, pendingIntent, intentFiltersArray, techListsArray)
console.log('NFC初始化完成,等待标签')
} catch (e) {
console.error('NFC初始化失败:', e)
plus.nativeUI.toast('NFC初始化失败')
}
}
/**
* 处理NFC数据
*/
function handleNfcData() {
if (!readyRead || !readCallback) return
try {
NdefRecord = plus.android.importClass("android.nfc.NdefRecord")
NdefMessage = plus.android.importClass("android.nfc.NdefMessage")
const intent = mainActivity.getIntent()
console.log("action type:" + intent.getAction())
if ("android.nfc.action.TECH_DISCOVERED" === intent.getAction()) {
__read(intent)
}
} catch (e) {
console.error('处理NFC数据失败:', e)
plus.nativeUI.toast('读取失败')
if (waiting) waiting.close()
readyRead = false
readCallback({ error: '处理数据失败: ' + e.message })
// 出错时也关闭NFC
closeNFC()
}
}
/**
* 读取NFC内容(增加UID获取)
*/
function __read(intent) {
waiting.setTitle('请勿移开标签\n正在读取数据...')
try {
// 获取标签对象,用于读取UID
const tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
plus.android.importClass(tag)
// 获取并转换UID
let uid = ''
if (tag && tag.getId) {
const uidBytes = tag.getId()
uid = bytesToHex(uidBytes)
}
// 读取NDEF内容
const Parcelable = plus.android.importClass("android.os.Parcelable")
const rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES")
if (!rawmsgs || rawmsgs.length === 0) {
plus.nativeUI.toast('未检测到NDEF数据')
// 即使没有文本数据,也返回UID
readCallback({ uid, error: '未检测到NDEF数据' })
waiting.close()
readyRead = false
closeNFC()
return
}
const records = rawmsgs[0].getRecords()
if (!records || records.length === 0) {
plus.nativeUI.toast('未找到NDEF记录')
readCallback({ uid, error: '未找到NDEF记录' })
waiting.close()
readyRead = false
closeNFC()
return
}
const result = records[0].getPayload()
const text = plus.android.newObject("java.lang.String", result)
// 读取成功,返回UID和文本
readCallback({ uid, text })
plus.nativeUI.toast('读取成功')
} catch (e) {
console.error('读取NFC失败:', e)
plus.nativeUI.toast('读取失败')
readCallback({ error: '读取失败: ' + e.message })
} finally {
waiting.close()
readyRead = false
closeNFC()
}
}
/**
* 字节数组转16进制字符串(用于UID转换)
*/
function bytesToHex(bytes) {
if (!bytes) return ''
const hexChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
let hex = ''
for (let i = 0
const value = bytes[i] & 0xFF
hex += hexChars[value >> 4] + hexChars[value & 0x0F]
if (i < bytes.length - 1) hex += ':'
}
return hex
}
/**
* 开始读取
*/
export function startRead() {
if (!nfcAdapter) {
plus.nativeUI.toast('请先初始化NFC')
return
}
readyRead = true
waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!")
}
/**
* 关闭NFC(清理资源)
*/
export function closeNFC() {
if (nfcAdapter && mainActivity) {
nfcAdapter.disableForegroundDispatch(mainActivity)
plus.globalEvent.removeEventListener("newintent", handleNfcData)
}
if (waiting) waiting.close()
readyRead = false
// 不清除回调,以便接收最后一次结果
console.log('NFC已关闭')
}
// UniApp plusready后自动初始化(可选)
plus.globalEvent.addEventListener('plusready', function () {
console.log('plusready: NFC模块准备就绪')
}, false)