手机获取nfc中的数据
This commit is contained in:
parent
2fcaa764c8
commit
b51f87790f
|
|
@ -11,9 +11,23 @@
|
||||||
/>
|
/>
|
||||||
<text class="status-title">{{ connectionText }}</text>
|
<text class="status-title">{{ connectionText }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="status-desc">
|
<view class="status-desc">
|
||||||
请保持手机在线,等待刷卡设备将NFC卡号传递到本页面。
|
<text>请保持手机在线,等待刷卡设备将NFC卡号传递到本页面。</text>
|
||||||
</text>
|
<text v-if="nfcSupported" class="nfc-hint">
|
||||||
|
<text class="nfc-hint-text">或使用手机 NFC 功能直接读取卡片</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="nfcSupported" class="nfc-status">
|
||||||
|
<view class="nfc-status-header">
|
||||||
|
<view
|
||||||
|
:class="['status-dot', nfcEnabled ? 'online' : 'offline']"
|
||||||
|
/>
|
||||||
|
<text class="nfc-status-title">{{ nfcStatusText }}</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="nfcError" class="nfc-error-text">
|
||||||
|
<text class="error-content">{{ nfcError }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view :class="{ ready: !!cardNo }" class="card-box">
|
<view :class="{ ready: !!cardNo }" class="card-box">
|
||||||
<text class="card-label">NFC卡号</text>
|
<text class="card-label">NFC卡号</text>
|
||||||
<text class="card-value">{{ cardNo || "等待刷卡..." }}</text>
|
<text class="card-value">{{ cardNo || "等待刷卡..." }}</text>
|
||||||
|
|
@ -101,6 +115,11 @@ export default {
|
||||||
usingGlobalSocketEvents: false,
|
usingGlobalSocketEvents: false,
|
||||||
globalSocketHandlers: null,
|
globalSocketHandlers: null,
|
||||||
connectTimeout: null,
|
connectTimeout: null,
|
||||||
|
// NFC 相关状态
|
||||||
|
nfcAdapter: null,
|
||||||
|
nfcSupported: false,
|
||||||
|
nfcEnabled: false,
|
||||||
|
nfcError: "",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -113,6 +132,15 @@ export default {
|
||||||
}
|
}
|
||||||
return this.socketConnected ? "已连接,等待刷卡" : "连接中...";
|
return this.socketConnected ? "已连接,等待刷卡" : "连接中...";
|
||||||
},
|
},
|
||||||
|
nfcStatusText() {
|
||||||
|
if (!this.nfcSupported) {
|
||||||
|
return "设备不支持 NFC";
|
||||||
|
}
|
||||||
|
if (this.nfcError) {
|
||||||
|
return `NFC 错误: ${this.nfcError}`;
|
||||||
|
}
|
||||||
|
return this.nfcEnabled ? "NFC 已开启,请将卡片贴近手机" : "NFC 未开启";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onLoad(options = {}) {
|
onLoad(options = {}) {
|
||||||
if (options.unitId) {
|
if (options.unitId) {
|
||||||
|
|
@ -122,9 +150,11 @@ export default {
|
||||||
this.deviceMac = options.mac;
|
this.deviceMac = options.mac;
|
||||||
}
|
}
|
||||||
this.initSocket();
|
this.initSocket();
|
||||||
|
this.initNFC();
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.cleanupSocket();
|
this.cleanupSocket();
|
||||||
|
this.cleanupNFC();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
buildSocketUrl() {
|
buildSocketUrl() {
|
||||||
|
|
@ -366,7 +396,6 @@ export default {
|
||||||
} else if (errorMsg.includes("fail")) {
|
} else if (errorMsg.includes("fail")) {
|
||||||
userFriendlyMsg = "网络连接失败,请检查网络和服务器地址";
|
userFriendlyMsg = "网络连接失败,请检查网络和服务器地址";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connectionError = userFriendlyMsg;
|
this.connectionError = userFriendlyMsg;
|
||||||
this.socketConnected = false;
|
this.socketConnected = false;
|
||||||
},
|
},
|
||||||
|
|
@ -550,6 +579,203 @@ export default {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// NFC 相关方法
|
||||||
|
initNFC() {
|
||||||
|
// 检查是否支持 NFC(微信小程序环境)
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
if (typeof wx === "undefined" || !wx.getNFCAdapter) {
|
||||||
|
console.warn("当前环境不支持 NFC 功能");
|
||||||
|
this.nfcSupported = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取 NFC 适配器
|
||||||
|
const nfcAdapter = wx.getNFCAdapter();
|
||||||
|
if (!nfcAdapter) {
|
||||||
|
console.warn("无法获取 NFC 适配器");
|
||||||
|
this.nfcSupported = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nfcAdapter = nfcAdapter;
|
||||||
|
this.nfcSupported = true;
|
||||||
|
|
||||||
|
// 开始发现 NFC 标签
|
||||||
|
this.startNFCDiscovery();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("初始化 NFC 失败:", error);
|
||||||
|
this.nfcSupported = false;
|
||||||
|
this.nfcError = error.message || "初始化失败";
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
// 非微信小程序环境,不支持 NFC
|
||||||
|
console.warn("NFC 功能仅在微信小程序中支持");
|
||||||
|
this.nfcSupported = false;
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
startNFCDiscovery() {
|
||||||
|
if (!this.nfcAdapter) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 监听 NFC 标签发现事件
|
||||||
|
this.nfcAdapter.onDiscovered((res) => {
|
||||||
|
this.handleNfcDiscovered(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 开始发现 NFC 标签
|
||||||
|
this.nfcAdapter.startDiscovery({
|
||||||
|
success: () => {
|
||||||
|
console.log("NFC 发现已启动");
|
||||||
|
this.nfcEnabled = true;
|
||||||
|
this.nfcError = "";
|
||||||
|
this.lastMessage = "NFC 已开启,请将卡片贴近手机";
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error("启动 NFC 发现失败:", err);
|
||||||
|
this.nfcEnabled = false;
|
||||||
|
this.nfcError = err.errMsg || "启动失败";
|
||||||
|
|
||||||
|
// 如果是权限问题,给出提示
|
||||||
|
if (err.errMsg && err.errMsg.includes("permission")) {
|
||||||
|
this.nfcError = "需要 NFC 权限,请在设置中开启";
|
||||||
|
} else if (err.errMsg && err.errMsg.includes("not support")) {
|
||||||
|
this.nfcError = "设备不支持 NFC 功能";
|
||||||
|
this.nfcSupported = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("启动 NFC 发现异常:", error);
|
||||||
|
this.nfcEnabled = false;
|
||||||
|
this.nfcError = error.message || "启动异常";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleNfcDiscovered(res) {
|
||||||
|
console.log("发现 NFC 标签:", res);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let cardNo = "";
|
||||||
|
|
||||||
|
console.log("移动号获取NFC:res", res);
|
||||||
|
console.log("res.id 类型:", typeof res.id, res.id);
|
||||||
|
console.log("res.techs:", res.techs);
|
||||||
|
|
||||||
|
// NFC 卡号主要存储在 res.id 中,格式为 ArrayBuffer
|
||||||
|
// 对于 MIFARE Classic 等卡片,UID 就存储在 id 字段
|
||||||
|
// 根据调试信息:[[ArrayBufferData]]: 1312 表示4字节的数值
|
||||||
|
if (res.id) {
|
||||||
|
// id 通常是 ArrayBuffer,需要转换为字符串
|
||||||
|
if (res.id instanceof ArrayBuffer) {
|
||||||
|
// 将 ArrayBuffer 转换为十六进制字符串
|
||||||
|
const uint8Array = new Uint8Array(res.id);
|
||||||
|
const bytes = Array.from(uint8Array);
|
||||||
|
|
||||||
|
console.log("=== NFC 卡号提取详情 ===");
|
||||||
|
console.log("ArrayBuffer 字节长度:", res.id.byteLength);
|
||||||
|
console.log("ArrayBuffer 字节数组(十进制):", bytes);
|
||||||
|
console.log("ArrayBuffer 字节数组(十六进制):", bytes.map(b => "0x" + b.toString(16).padStart(2, "0").toUpperCase()));
|
||||||
|
|
||||||
|
// 转换为十六进制字符串(每字节两位,不足补0)
|
||||||
|
// NFC 卡号通常按照字节顺序(大端序)存储
|
||||||
|
cardNo = bytes
|
||||||
|
.join("")
|
||||||
|
.toUpperCase();
|
||||||
|
|
||||||
|
// 如果字节数组是 [0, 0, 5, 32],则卡号为 "00000520"
|
||||||
|
// 如果字节数组是 [32, 5, 0, 0],则卡号为 "20050000"
|
||||||
|
console.log("转换后的卡号(十六进制字符串):", cardNo);
|
||||||
|
console.log("卡号长度:", cardNo.length, "字符");
|
||||||
|
console.log("========================");
|
||||||
|
} else if (typeof res.id === "string") {
|
||||||
|
cardNo = res.id;
|
||||||
|
console.log("卡号(字符串):", cardNo);
|
||||||
|
} else {
|
||||||
|
console.warn("res.id 格式未知:", res.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 id 字段没有值,尝试从 techs 中获取
|
||||||
|
if (!cardNo && res.techs && res.techs.length > 0) {
|
||||||
|
// 尝试从 techs 中读取数据
|
||||||
|
for (const tech of res.techs) {
|
||||||
|
if (tech.id) {
|
||||||
|
if (tech.id instanceof ArrayBuffer) {
|
||||||
|
const uint8Array = new Uint8Array(tech.id);
|
||||||
|
cardNo = Array.from(uint8Array)
|
||||||
|
.map((b) => b.toString(16).padStart(2, "0"))
|
||||||
|
.join("")
|
||||||
|
.toUpperCase();
|
||||||
|
break;
|
||||||
|
} else if (typeof tech.id === "string") {
|
||||||
|
cardNo = tech.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果还是没有获取到,尝试从其他字段获取
|
||||||
|
if (!cardNo) {
|
||||||
|
// 尝试从 res 的其他字段获取
|
||||||
|
if (res.serialNumber) {
|
||||||
|
cardNo = res.serialNumber;
|
||||||
|
} else if (res.uid) {
|
||||||
|
cardNo = res.uid;
|
||||||
|
} else if (res.cardId) {
|
||||||
|
cardNo = res.cardId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cardNo) {
|
||||||
|
// 清理卡号格式(去除空格、冒号等)
|
||||||
|
cardNo = cardNo.replace(/[\s:]/g, "").toUpperCase();
|
||||||
|
this.cardNo = cardNo;
|
||||||
|
this.lastMessage = "已通过 NFC 读取卡号";
|
||||||
|
uni.showToast({
|
||||||
|
title: "读取成功",
|
||||||
|
icon: "success",
|
||||||
|
duration: 1500,
|
||||||
|
});
|
||||||
|
console.log("NFC 读取到的卡号:", cardNo);
|
||||||
|
} else {
|
||||||
|
console.warn("无法从 NFC 标签中提取卡号:", res);
|
||||||
|
uni.showToast({
|
||||||
|
title: "无法读取卡号",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("处理 NFC 标签数据失败:", error);
|
||||||
|
uni.showToast({
|
||||||
|
title: "读取失败",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cleanupNFC() {
|
||||||
|
if (this.nfcAdapter) {
|
||||||
|
try {
|
||||||
|
// 停止 NFC 发现
|
||||||
|
this.nfcAdapter.stopDiscovery({
|
||||||
|
success: () => {
|
||||||
|
console.log("NFC 发现已停止");
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.warn("停止 NFC 发现失败:", err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("清理 NFC 资源失败:", error);
|
||||||
|
}
|
||||||
|
this.nfcAdapter = null;
|
||||||
|
}
|
||||||
|
this.nfcEnabled = false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -610,6 +836,43 @@ export default {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nfc-hint {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nfc-hint-text {
|
||||||
|
color: #4a90e2;
|
||||||
|
font-size: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nfc-status {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
background: rgba(74, 144, 226, 0.08);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
border-left: 4rpx solid #4a90e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nfc-status-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nfc-status-title {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nfc-error-text {
|
||||||
|
margin-top: 12rpx;
|
||||||
|
padding: 12rpx;
|
||||||
|
background: #fef0f0;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.card-box {
|
.card-box {
|
||||||
margin-top: 24rpx;
|
margin-top: 24rpx;
|
||||||
border: 2rpx dashed #f0b400;
|
border: 2rpx dashed #f0b400;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user