1.0.6
This commit is contained in:
parent
887aa55930
commit
ebdc516a55
@ -1,3 +1,9 @@
|
||||
# 1.0.6
|
||||
|
||||
1. 增加远程扫码入库功能
|
||||
2. 修改 README 文档
|
||||
3. 修复已知问题
|
||||
|
||||
# 1.0.5
|
||||
|
||||
1. 新增扫码入库功能
|
||||
|
||||
@ -68,8 +68,10 @@ V2.2 用户菜单栏将直接出现“LEYE”选项;V3 用户若未开启“
|
||||
## 开源许可
|
||||
|
||||
本扩展使用以下开源软件:
|
||||
- [jsQR](https://www.jsdelivr.com/package/npm/jsqr):二维码解析库,使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 许可协议授权
|
||||
- [xlsx](https://www.jsdelivr.com/package/npm/xlsx):Excel 解析库,使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 许可协议授权
|
||||
- [Tailwind CSS](https://www.jsdelivr.com/package/npm/tailwindcss):CSS 框架,使用 [MIT License](https://choosealicense.com/licenses/mit/) 许可协议授权
|
||||
- [SheetJS](https://www.npmjs.com/package/xlsx):Excel 解析库,使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 许可协议授权
|
||||
- [jsQR](https://www.npmjs.com/package/jsqr):二维码解析库,使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 许可协议授权
|
||||
- [node-qrcode](https://www.npmjs.com/package/qrcode):二维码生成库,使用 [MIT License](https://choosealicense.com/licenses/mit/) 许可协议授权
|
||||
- [MQTT.js](https://www.npmjs.com/package/mqtt):MQTT 客户端库,使用 [MIT License](https://choosealicense.com/licenses/mit/) 许可协议授权
|
||||
- [Tailwind CSS](https://www.npmjs.com/package/tailwindcss):CSS 框架,使用 [MIT License](https://choosealicense.com/licenses/mit/) 许可协议授权
|
||||
|
||||
本扩展使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 开源许可协议,商业/教育用途请考虑联系开发者获取常规版。
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"uuid": "944f7c94a8ca485e848f1118effcbb9a",
|
||||
"displayName": "LEYE",
|
||||
"description": "LEYE 电子元器件库存管理系统 EDA 联动扩展",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"publisher": "Mr_Fang",
|
||||
"engines": {
|
||||
"eda": "^3.2.80"
|
||||
|
||||
@ -596,6 +596,10 @@ video {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
.static {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
@ -644,6 +648,10 @@ video {
|
||||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.m-auto {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
@ -1086,6 +1094,11 @@ video {
|
||||
border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
|
||||
}
|
||||
|
||||
.border-blue-300 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(147 197 253 / var(--tw-border-opacity, 1));
|
||||
}
|
||||
|
||||
.border-blue-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
</style>
|
||||
<script src="/iframe/js/xlsx.full.min.js" language="JavaScript"></script>
|
||||
<script src="/iframe/js/jsQR.min.js" language="JavaScript"></script>
|
||||
<script src="/iframe/js/qrcode.min.js" language="JavaScript"></script>
|
||||
<script src="/iframe/js/mqtt.min.js" language="JavaScript"></script>
|
||||
</head>
|
||||
<body class="bg-gray-100 font-sans text-sm">
|
||||
<div id="fixed-window" class="bg-gray-50 flex flex-col overflow-hidden mx-auto">
|
||||
@ -124,6 +126,8 @@
|
||||
let importList = [];
|
||||
let videoStream = null;
|
||||
let currentScanData = null;
|
||||
let mqttClient = null;
|
||||
const myDeviceId = Math.random().toString(36).substring(2, 10);
|
||||
|
||||
function renderList() {
|
||||
if (importList.length === 0) {
|
||||
@ -156,9 +160,12 @@
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const videoDevices = devices.filter(device => device.kind === 'videoinput');
|
||||
cameraSelect.innerHTML = videoDevices.map(d =>
|
||||
let options = videoDevices.map(d =>
|
||||
`<option value="${d.deviceId}">${d.label || '摄像头 ' + d.deviceId.slice(0, 5)}</option>`
|
||||
).join('');
|
||||
|
||||
options += `<option value="WEBSOCKET_MODE">WebSocket 远程扫码</option>`;
|
||||
cameraSelect.innerHTML = options;
|
||||
} catch (e) {
|
||||
eda.sys_Message.showToastMessage('无法获取摄像头列表: ' + e.message, ESYS_ToastMessageType.ERROR);
|
||||
}
|
||||
@ -168,11 +175,12 @@
|
||||
stopCamera();
|
||||
qrDialog.classList.add('hidden');
|
||||
|
||||
document.getElementById('res-cid').textContent = currentScanData.lcscId;
|
||||
document.getElementById('res-pm').textContent = currentScanData.name;
|
||||
document.getElementById('res-qty').textContent = currentScanData.quantity;
|
||||
|
||||
currentScanData = null;
|
||||
if (currentScanData) {
|
||||
document.getElementById('res-cid').textContent = currentScanData.lcscId;
|
||||
document.getElementById('res-pm').textContent = currentScanData.name;
|
||||
document.getElementById('res-qty').textContent = currentScanData.quantity;
|
||||
currentScanData = null;
|
||||
}
|
||||
};
|
||||
|
||||
function stopCamera() {
|
||||
@ -180,16 +188,68 @@
|
||||
videoStream.getTracks().forEach(track => track.stop());
|
||||
videoStream = null;
|
||||
}
|
||||
qrVideo.parentElement.classList.remove('scanning');
|
||||
|
||||
if (mqttClient) {
|
||||
console.log("正在断开 MQTT 远程连接...");
|
||||
mqttClient.end(true); // 强制关闭连接
|
||||
mqttClient = null;
|
||||
}
|
||||
|
||||
qrVideo.style.display = 'block';
|
||||
const oldQr = document.getElementById('remote-qr-canvas');
|
||||
if (oldQr) oldQr.remove();
|
||||
|
||||
if(qrVideo.parentElement) {
|
||||
qrVideo.parentElement.classList.remove('scanning');
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('btn-start-camera').onclick = async () => {
|
||||
stopCamera();
|
||||
const deviceId = cameraSelect.value;
|
||||
async function startRemoteMode() {
|
||||
if (mqttClient) {
|
||||
mqttClient.end(true);
|
||||
}
|
||||
|
||||
const broker = 'wss://test.mosquitto.org:8081';
|
||||
const topic = `leye/scan/${myDeviceId}`;
|
||||
|
||||
mqttClient = mqtt.connect(broker);
|
||||
|
||||
mqttClient.on('connect', () => {
|
||||
mqttClient.subscribe(topic);
|
||||
eda.sys_Message.showToastMessage('MQTT 远程模式启动', ESYS_ToastMessageType.SUCCESS);
|
||||
|
||||
const scanUrl = `https://leye.dragon.edu.kg/scan.html?id=${myDeviceId}`;
|
||||
|
||||
qrVideo.style.display = 'none';
|
||||
let qrCanvas = document.getElementById('remote-qr-canvas') || createQrCanvas();
|
||||
QRCode.toCanvas(qrCanvas, scanUrl, { width: 250 });
|
||||
});
|
||||
|
||||
mqttClient.on('message', (t, message) => {
|
||||
try {
|
||||
const msg = JSON.parse(message.toString());
|
||||
if (msg.type === 'SCAN_RESULT') {
|
||||
parseQrData(msg.content);
|
||||
eda.sys_Message.showToastMessage('远程扫码成功', ESYS_ToastMessageType.INFO);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("MQTT数据解析失败", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createQrCanvas() {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.id = 'remote-qr-canvas';
|
||||
canvas.className = "absolute inset-0 w-full h-full p-4 bg-white";
|
||||
qrVideo.parentElement.appendChild(canvas);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
async function startLocalCamera(deviceId) {
|
||||
const constraints = {
|
||||
video: deviceId ? { deviceId: { exact: deviceId } } : { facingMode: 'environment' }
|
||||
};
|
||||
|
||||
try {
|
||||
videoStream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||
qrVideo.srcObject = videoStream;
|
||||
@ -199,6 +259,17 @@
|
||||
} catch (e) {
|
||||
eda.sys_Message.showToastMessage('启动摄像头失败', ESYS_ToastMessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('btn-start-camera').onclick = async () => {
|
||||
stopCamera();
|
||||
const mode = cameraSelect.value;
|
||||
|
||||
if (mode === "WEBSOCKET_MODE") {
|
||||
startRemoteMode();
|
||||
} else {
|
||||
startLocalCamera(mode);
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('btn-scan').onclick = () => {
|
||||
@ -429,7 +500,6 @@
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
const SERVER = await eda.sys_Storage.getExtensionUserConfig('server-host') || 'http://localhost:21816';
|
||||
|
||||
for (const item of toSave) {
|
||||
try {
|
||||
|
||||
19
iframe/js/mqtt.min.js
vendored
Normal file
19
iframe/js/mqtt.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
iframe/js/qrcode.min.js
vendored
Normal file
7
iframe/js/qrcode.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user