1.0.5
This commit is contained in:
parent
45fe4e70b6
commit
887aa55930
@ -1,3 +1,10 @@
|
|||||||
|
# 1.0.5
|
||||||
|
|
||||||
|
1. 新增扫码入库功能
|
||||||
|
2. 修改 README 文档
|
||||||
|
3. 新增检查更新功能
|
||||||
|
4. 修复已知问题
|
||||||
|
|
||||||
# 1.0.3
|
# 1.0.3
|
||||||
|
|
||||||
1. 由于可能存在的安全原因,移除了使用 Cookie 获取立创商城订单的功能,相关功能已被废弃
|
1. 由于可能存在的安全原因,移除了使用 Cookie 获取立创商城订单的功能,相关功能已被废弃
|
||||||
|
|||||||
12
README.md
12
README.md
@ -37,10 +37,15 @@ V2.2 用户菜单栏将直接出现“LEYE”选项;V3 用户若未开启“
|
|||||||
|
|
||||||
## 器件入库
|
## 器件入库
|
||||||
|
|
||||||
扩展支持从立创商城单 Excel 文档以及 CID 导入器件。
|
扩展支持从立创商城单 Excel 文档、立创商城物料二维码以及 CID 导入器件。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
> **Tip: 扫描立创商城二维码导入器件**
|
||||||
|
>
|
||||||
|
> 在 V1.0.5 版本以上,可以通过扫描立创商城物料包装上的二维码导入器件,扫描后会自动识别 CID 并导入对应器件。
|
||||||
|
> 
|
||||||
|
|
||||||
### 批量出库
|
### 批量出库
|
||||||
|
|
||||||
打开本页面后将自动整理 BOM 与 LEYE 库存相比较,非立创商城器件(无 CID)显示为红底,不在 LEYE 库存内的器件显示为黄底,在 LEYE 库存内的器件显示为绿底。
|
打开本页面后将自动整理 BOM 与 LEYE 库存相比较,非立创商城器件(无 CID)显示为红底,不在 LEYE 库存内的器件显示为黄底,在 LEYE 库存内的器件显示为绿底。
|
||||||
@ -62,4 +67,9 @@ 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/) 许可协议授权
|
||||||
|
|
||||||
本扩展使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 开源许可协议,商业/教育用途请考虑联系开发者获取常规版。
|
本扩展使用 [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) 开源许可协议,商业/教育用途请考虑联系开发者获取常规版。
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"uuid": "944f7c94a8ca485e848f1118effcbb9a",
|
"uuid": "944f7c94a8ca485e848f1118effcbb9a",
|
||||||
"displayName": "LEYE",
|
"displayName": "LEYE",
|
||||||
"description": "LEYE 电子元器件库存管理系统 EDA 联动扩展",
|
"description": "LEYE 电子元器件库存管理系统 EDA 联动扩展",
|
||||||
"version": "1.0.3",
|
"version": "1.0.5",
|
||||||
"publisher": "Mr_Fang",
|
"publisher": "Mr_Fang",
|
||||||
"engines": {
|
"engines": {
|
||||||
"eda": "^3.2.80"
|
"eda": "^3.2.80"
|
||||||
|
|||||||
@ -221,18 +221,13 @@
|
|||||||
document.getElementById('check').addEventListener('click', function (event) {
|
document.getElementById('check').addEventListener('click', function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
eda.sys_Message.showToastMessage(
|
eda.sys_ClientUrl
|
||||||
'🥺 暂不支持',
|
.request('https://leye.dragon.edu.kg/release/eext.ver.json', 'GET')
|
||||||
ESYS_ToastMessageType.ERROR
|
|
||||||
);
|
|
||||||
|
|
||||||
/* eda.sys_ClientUrl
|
|
||||||
.request('https://ext.lceda.cn/api/v1/extensions/his_version_list?bizKey=', 'GET')
|
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data && data.code === 0) {
|
if (data) {
|
||||||
const his_list = data.result;
|
const his_list = data.versions;
|
||||||
const latestVersion = his_list[0].version;
|
const latestVersion = his_list[0].ver;
|
||||||
const currentVersion = document.getElementById('version').textContent.replace('V', '');
|
const currentVersion = document.getElementById('version').textContent.replace('V', '');
|
||||||
// 比较版本号,latestVersion 和 currentVersion
|
// 比较版本号,latestVersion 和 currentVersion
|
||||||
const latestParts = latestVersion.split('.').map(Number);
|
const latestParts = latestVersion.split('.').map(Number);
|
||||||
@ -251,7 +246,7 @@
|
|||||||
if (isNewVersionAvailable) {
|
if (isNewVersionAvailable) {
|
||||||
eda.sys_Message.showToastMessage(`😋 有新版本可用: V${latestVersion}`, ESYS_ToastMessageType.INFO);
|
eda.sys_Message.showToastMessage(`😋 有新版本可用: V${latestVersion}`, ESYS_ToastMessageType.INFO);
|
||||||
document.getElementById('tip').innerHTML =
|
document.getElementById('tip').innerHTML =
|
||||||
`<a href="https://ext.lceda.cn/item/fangs233/fangs-hyper-export" target="_blank" class="text-blue-600 hover:text-blue-800">前往更新新版本</a>`;
|
`<a href="https://lrurl.top/LeyeEEXT" target="_blank" class="text-blue-600 hover:text-blue-800">前往更新新版本</a>`;
|
||||||
} else {
|
} else {
|
||||||
eda.sys_Message.showToastMessage('👍 当前已是最新版本', ESYS_ToastMessageType.SUCCESS);
|
eda.sys_Message.showToastMessage('👍 当前已是最新版本', ESYS_ToastMessageType.SUCCESS);
|
||||||
}
|
}
|
||||||
@ -262,7 +257,7 @@
|
|||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
'去瞅一眼',
|
'去瞅一眼',
|
||||||
"eda.sys_Window.open('https://ext.lceda.cn/item/fangs233/fangs-hyper-export')",
|
"eda.sys_Window.open('https://lrurl.top/LeyeEEXT')",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -274,9 +269,9 @@
|
|||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
'去瞅一眼',
|
'去瞅一眼',
|
||||||
"eda.sys_Window.open('https://ext.lceda.cn/item/fangs233/fangs-hyper-export')",
|
"eda.sys_Window.open('https://lrurl.top/LeyeEEXT')",
|
||||||
);
|
);
|
||||||
}); */
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('afdian').addEventListener('click', function (event) {
|
document.getElementById('afdian').addEventListener('click', function (event) {
|
||||||
|
|||||||
@ -709,6 +709,10 @@ video {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline-flex {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
@ -745,6 +749,19 @@ video {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.size-1 {
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-0 {
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-0\.5 {
|
||||||
|
height: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-1 {
|
.h-1 {
|
||||||
height: 0.25rem;
|
height: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -757,10 +774,22 @@ video {
|
|||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-\[250px\] {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.min-h-screen {
|
.min-h-screen {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-1 {
|
||||||
|
width: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-12 {
|
.w-12 {
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
}
|
}
|
||||||
@ -813,10 +842,18 @@ video {
|
|||||||
width: 24rem;
|
width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-\[250px\] {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
.w-\[400px\] {
|
.w-\[400px\] {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-\[450px\] {
|
||||||
|
width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
.w-\[5\%\] {
|
.w-\[5\%\] {
|
||||||
width: 5%;
|
width: 5%;
|
||||||
}
|
}
|
||||||
@ -879,6 +916,10 @@ video {
|
|||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.flex-col {
|
.flex-col {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@ -903,6 +944,10 @@ video {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-2 {
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.gap-3 {
|
.gap-3 {
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
@ -943,6 +988,12 @@ video {
|
|||||||
margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));
|
margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-y-reverse: 0;
|
||||||
|
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
||||||
|
}
|
||||||
|
|
||||||
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-y-reverse: 0;
|
--tw-space-y-reverse: 0;
|
||||||
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
@ -1010,6 +1061,10 @@ video {
|
|||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-2 {
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-b {
|
.border-b {
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
}
|
}
|
||||||
@ -1022,6 +1077,15 @@ video {
|
|||||||
border-top-width: 1px;
|
border-top-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-dashed {
|
||||||
|
border-style: dashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-blue-100 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.border-blue-600 {
|
.border-blue-600 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));
|
border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));
|
||||||
@ -1087,6 +1151,11 @@ video {
|
|||||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-gray-600 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-green-600 {
|
.bg-green-600 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
|
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
|
||||||
@ -1115,6 +1184,11 @@ video {
|
|||||||
--tw-bg-opacity: 0.5;
|
--tw-bg-opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.object-cover {
|
||||||
|
-o-object-fit: cover;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
.p-1 {
|
.p-1 {
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -1346,6 +1420,11 @@ video {
|
|||||||
color: rgb(22 163 74 / var(--tw-text-opacity, 1));
|
color: rgb(22 163 74 / var(--tw-text-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-orange-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(234 88 12 / var(--tw-text-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.text-red-500 {
|
.text-red-500 {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
|
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
|
||||||
@ -1375,12 +1454,22 @@ video {
|
|||||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
|
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opacity-50 {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
.shadow {
|
.shadow {
|
||||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadow-\[0_0_8px_rgba\(59\2c 130\2c 246\2c 0\.8\)\] {
|
||||||
|
--tw-shadow: 0 0 8px rgba(59,130,246,0.8);
|
||||||
|
--tw-shadow-colored: 0 0 8px var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
.shadow-inner {
|
.shadow-inner {
|
||||||
--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
|
--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
|
||||||
--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);
|
--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);
|
||||||
@ -1429,6 +1518,11 @@ video {
|
|||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invert {
|
||||||
|
--tw-invert: invert(100%);
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
@ -1483,6 +1577,11 @@ video {
|
|||||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-gray-700:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-green-700:hover {
|
.hover\:bg-green-700:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
|
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
|
||||||
@ -1508,6 +1607,11 @@ video {
|
|||||||
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
|
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:text-gray-600:hover {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:text-red-700:hover {
|
.hover\:text-red-700:hover {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
|
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
|
||||||
|
|||||||
@ -11,8 +11,11 @@
|
|||||||
#fixed-window { width: 1280px; height: 680px; border: 1px solid #e5e7eb; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
|
#fixed-window { width: 1280px; height: 680px; border: 1px solid #e5e7eb; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
|
||||||
.table-container { height: calc(680px - 160px - 64px); overflow-y: auto; }
|
.table-container { height: calc(680px - 160px - 64px); overflow-y: auto; }
|
||||||
.sticky-header { position: sticky; top: 0; z-index: 10; }
|
.sticky-header { position: sticky; top: 0; z-index: 10; }
|
||||||
|
@keyframes scan { 0% { top: 0; } 100% { top: 100%; } }
|
||||||
|
.scanning #scan-line { display: block; animation: scan 2s linear infinite; }
|
||||||
</style>
|
</style>
|
||||||
<script src="/iframe/js/xlsx.full.min.js" language="JavaScript"></script>
|
<script src="/iframe/js/xlsx.full.min.js" language="JavaScript"></script>
|
||||||
|
<script src="/iframe/js/jsQR.min.js" language="JavaScript"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-100 font-sans text-sm">
|
<body class="bg-gray-100 font-sans text-sm">
|
||||||
<div id="fixed-window" class="bg-gray-50 flex flex-col overflow-hidden mx-auto">
|
<div id="fixed-window" class="bg-gray-50 flex flex-col overflow-hidden mx-auto">
|
||||||
@ -22,6 +25,7 @@
|
|||||||
<input id="order-uuid" type="text" placeholder="UUID 或者 订单链接" disabled class="flex-grow px-3 py-1.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 outline-none" />
|
<input id="order-uuid" type="text" placeholder="UUID 或者 订单链接" disabled class="flex-grow px-3 py-1.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 outline-none" />
|
||||||
<button id="import-order-btn" class="px-6 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">添加订单</button>
|
<button id="import-order-btn" class="px-6 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">添加订单</button>
|
||||||
<button id="import-order-file-btn" class="px-6 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">添加订单详情 Excel 文档</button>
|
<button id="import-order-file-btn" class="px-6 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">添加订单详情 Excel 文档</button>
|
||||||
|
<button id="open-qr-btn" class="px-6 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">扫描二维码</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-3">
|
<div class="flex items-center space-x-3">
|
||||||
<span class="font-medium text-gray-700 w-32">立创商城编号导入</span>
|
<span class="font-medium text-gray-700 w-32">立创商城编号导入</span>
|
||||||
@ -68,15 +72,58 @@
|
|||||||
<button id="clear-list-btn" class="px-6 py-2 border border-red-300 text-red-600 rounded-md hover:bg-red-50">清空列表</button>
|
<button id="clear-list-btn" class="px-6 py-2 border border-red-300 text-red-600 rounded-md hover:bg-red-50">清空列表</button>
|
||||||
<button id="batch-save-btn" class="px-8 py-2 bg-blue-600 text-white font-bold rounded-md hover:bg-blue-700 shadow-md">批量入库</button>
|
<button id="batch-save-btn" class="px-8 py-2 bg-blue-600 text-white font-bold rounded-md hover:bg-blue-700 shadow-md">批量入库</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="qr-dialog" class="fixed inset-0 z-50 hidden flex items-center justify-center bg-black bg-opacity-50">
|
||||||
|
<div class="bg-white rounded-lg shadow-xl w-[450px] overflow-hidden">
|
||||||
|
<div class="px-4 py-3 border-b flex justify-between items-center bg-gray-50">
|
||||||
|
<h3 class="font-bold text-gray-700">扫码入库</h3>
|
||||||
|
<button onclick="closeQrDialog()" class="text-gray-400 hover:text-gray-600">×</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<select id="camera-select" class="w-full px-3 py-2 border rounded-md text-sm outline-none focus:ring-2 focus:ring-blue-500">
|
||||||
|
<option value="">正在检测摄像头...</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div class="relative w-[250px] h-[250px] mx-auto bg-black rounded-lg overflow-hidden border-2 border-gray-300">
|
||||||
|
<video id="qr-video" class="absolute inset-0 w-full h-full object-cover shadow-inner" playsinline></video>
|
||||||
|
<canvas id="qr-canvas" class="hidden"></canvas>
|
||||||
|
<div id="scan-line" class="absolute left-0 right-0 h-0.5 bg-blue-500 opacity-50 shadow-[0_0_8px_rgba(59,130,246,0.8)] hidden"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="scan-result" class="p-3 bg-blue-50 rounded-md border border-blue-100">
|
||||||
|
<div class="text-sm space-y-1">
|
||||||
|
<p>CID: <span id="res-cid"></span></p>
|
||||||
|
<p>型号: <span id="res-pm"></span></p>
|
||||||
|
<p>数量: <span id="res-qty"></span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-3 gap-2">
|
||||||
|
<button id="btn-start-camera" class="py-2 bg-gray-600 text-white rounded hover:bg-gray-700 text-sm">打开摄像头</button>
|
||||||
|
<button id="btn-scan" class="py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm disabled:opacity-50" disabled>扫描二维码</button>
|
||||||
|
<button id="btn-add-to-list" class="py-2 bg-green-600 text-white rounded hover:bg-green-700 text-sm disabled:opacity-50" disabled>加入列表</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const SERVER = eda.sys_Storage.getExtensionUserConfig('server-host') || 'http://localhost:21816/api';
|
const SERVER = eda.sys_Storage.getExtensionUserConfig('server-host') || 'http://localhost:21816/api';
|
||||||
const AUTO_RUN = eda.sys_Storage.getExtensionUserConfig('server-auto-run') || true;
|
const AUTO_RUN = eda.sys_Storage.getExtensionUserConfig('server-auto-run') || true;
|
||||||
|
|
||||||
const tableBody = document.getElementById('import-table-body');
|
const tableBody = document.getElementById('import-table-body');
|
||||||
const listCount = document.getElementById('list-count');
|
const listCount = document.getElementById('list-count');
|
||||||
|
const qrDialog = document.getElementById('qr-dialog');
|
||||||
|
const qrVideo = document.getElementById('qr-video');
|
||||||
|
const qrCanvas = document.getElementById('qr-canvas');
|
||||||
|
const cameraSelect = document.getElementById('camera-select');
|
||||||
|
|
||||||
let importList = [];
|
let importList = [];
|
||||||
|
let videoStream = null;
|
||||||
|
let currentScanData = null;
|
||||||
|
|
||||||
function renderList() {
|
function renderList() {
|
||||||
if (importList.length === 0) {
|
if (importList.length === 0) {
|
||||||
@ -105,6 +152,127 @@
|
|||||||
listCount.textContent = importList.length;
|
listCount.textContent = importList.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateCameraList() {
|
||||||
|
try {
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
const videoDevices = devices.filter(device => device.kind === 'videoinput');
|
||||||
|
cameraSelect.innerHTML = videoDevices.map(d =>
|
||||||
|
`<option value="${d.deviceId}">${d.label || '摄像头 ' + d.deviceId.slice(0, 5)}</option>`
|
||||||
|
).join('');
|
||||||
|
} catch (e) {
|
||||||
|
eda.sys_Message.showToastMessage('无法获取摄像头列表: ' + e.message, ESYS_ToastMessageType.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.closeQrDialog = () => {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
function stopCamera() {
|
||||||
|
if (videoStream) {
|
||||||
|
videoStream.getTracks().forEach(track => track.stop());
|
||||||
|
videoStream = null;
|
||||||
|
}
|
||||||
|
qrVideo.parentElement.classList.remove('scanning');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('btn-start-camera').onclick = async () => {
|
||||||
|
stopCamera();
|
||||||
|
const deviceId = cameraSelect.value;
|
||||||
|
const constraints = {
|
||||||
|
video: deviceId ? { deviceId: { exact: deviceId } } : { facingMode: 'environment' }
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
videoStream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
|
qrVideo.srcObject = videoStream;
|
||||||
|
qrVideo.play();
|
||||||
|
document.getElementById('btn-scan').disabled = false;
|
||||||
|
qrVideo.parentElement.classList.add('scanning');
|
||||||
|
} catch (e) {
|
||||||
|
eda.sys_Message.showToastMessage('启动摄像头失败', ESYS_ToastMessageType.ERROR);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('btn-scan').onclick = () => {
|
||||||
|
if (!videoStream) return;
|
||||||
|
|
||||||
|
const ctx = qrCanvas.getContext('2d', { willReadFrequently: true });
|
||||||
|
qrCanvas.width = qrVideo.videoWidth;
|
||||||
|
qrCanvas.height = qrVideo.videoHeight;
|
||||||
|
ctx.drawImage(qrVideo, 0, 0, qrCanvas.width, qrCanvas.height);
|
||||||
|
|
||||||
|
const imageData = ctx.getImageData(0, 0, qrCanvas.width, qrCanvas.height);
|
||||||
|
const code = jsQR(imageData.data, imageData.width, imageData.height);
|
||||||
|
|
||||||
|
if (code) {
|
||||||
|
eda.sys_Log.add(code.data);
|
||||||
|
parseQrData(code.data);
|
||||||
|
} else {
|
||||||
|
eda.sys_Message.showToastMessage('未扫描到有效二维码,请重试', ESYS_ToastMessageType.WARNING);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseQrData(data) {
|
||||||
|
try {
|
||||||
|
// 使用正则提取 pc, pm, qty
|
||||||
|
const pcMatch = data.match(/pc:([^,}]+)/);
|
||||||
|
const pmMatch = data.match(/pm:([^,}]+)/);
|
||||||
|
const qtyMatch = data.match(/qty:(\d+)/);
|
||||||
|
|
||||||
|
if (pcMatch) {
|
||||||
|
currentScanData = {
|
||||||
|
lcscId: pcMatch[1].trim().toUpperCase(),
|
||||||
|
name: pmMatch ? pmMatch[1].trim() : '未知型号',
|
||||||
|
quantity: qtyMatch ? parseInt(qtyMatch[1]) : 1,
|
||||||
|
selected: true
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('res-cid').textContent = currentScanData.lcscId;
|
||||||
|
document.getElementById('res-pm').textContent = currentScanData.name;
|
||||||
|
document.getElementById('res-qty').textContent = currentScanData.quantity;
|
||||||
|
document.getElementById('btn-add-to-list').disabled = false;
|
||||||
|
} else {
|
||||||
|
throw new Error("无效的二维码格式");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
eda.sys_Message.showToastMessage('解析失败: ' + e.message, ESYS_ToastMessageType.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('btn-add-to-list').onclick = async () => {
|
||||||
|
if (!currentScanData) return;
|
||||||
|
|
||||||
|
const btn = document.getElementById('btn-add-to-list');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = '处理中...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const item = { ...currentScanData };
|
||||||
|
await enrichData([item]);
|
||||||
|
importList.push(item);
|
||||||
|
renderList();
|
||||||
|
|
||||||
|
eda.sys_Message.showToastMessage('已加入待入库列表', ESYS_ToastMessageType.SUCCESS);
|
||||||
|
document.getElementById('res-cid').textContent = '等待扫描...';
|
||||||
|
document.getElementById('res-pm').textContent = '等待扫描...';
|
||||||
|
document.getElementById('res-qty').textContent = '等待扫描...';
|
||||||
|
currentScanData = null;
|
||||||
|
} catch (e) {
|
||||||
|
eda.sys_Message.showToastMessage('获取详情失败', ESYS_ToastMessageType.ERROR);
|
||||||
|
} finally {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = '加入列表';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window.updateQty = (index, val) => { importList[index].quantity = parseInt(val) || 0; };
|
window.updateQty = (index, val) => { importList[index].quantity = parseInt(val) || 0; };
|
||||||
window.removeItem = (index) => { importList.splice(index, 1); renderList(); };
|
window.removeItem = (index) => { importList.splice(index, 1); renderList(); };
|
||||||
|
|
||||||
@ -114,6 +282,11 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
document.getElementById('open-qr-btn').onclick = async () => {
|
||||||
|
qrDialog.classList.remove('hidden');
|
||||||
|
await updateCameraList();
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById('import-order-file-btn').onclick = async () => {
|
document.getElementById('import-order-file-btn').onclick = async () => {
|
||||||
try {
|
try {
|
||||||
const file = await eda.sys_FileSystem.openReadFileDialog(['xls', ['xlsx']], false);
|
const file = await eda.sys_FileSystem.openReadFileDialog(['xls', ['xlsx']], false);
|
||||||
|
|||||||
8
iframe/js/jsQR.min.js
vendored
Normal file
8
iframe/js/jsQR.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
images/img_07.png
Normal file
BIN
images/img_07.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
7
src/global.d.ts
vendored
7
src/global.d.ts
vendored
@ -1,7 +0,0 @@
|
|||||||
export {};
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface GlobalThis {
|
|
||||||
__LEYE_INIT_FLAG__?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
25
src/index.ts
25
src/index.ts
@ -10,12 +10,13 @@
|
|||||||
* 如需了解更多开发细节,请阅读:
|
* 如需了解更多开发细节,请阅读:
|
||||||
* https://prodocs.lceda.cn/cn/api/guide/
|
* https://prodocs.lceda.cn/cn/api/guide/
|
||||||
*/
|
*/
|
||||||
|
import * as extensionConfig from '../extension.json';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export function activate(status?: 'onStartupFinished', arg?: string): void {}
|
export function activate(status?: 'onStartupFinished', arg?: string): void {}
|
||||||
|
|
||||||
export function about(): void {
|
export async function about(): Promise<void> {
|
||||||
eda.sys_IFrame.openIFrame('/iframe/about.html', 400, 200);
|
await eda.sys_IFrame.openIFrame('/iframe/about.html', 400, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openLeyeIFrame(): Promise<void> {
|
export async function openLeyeIFrame(): Promise<void> {
|
||||||
@ -34,8 +35,8 @@ export async function openExportIFrame(): Promise<void> {
|
|||||||
await eda.sys_IFrame.openIFrame('/iframe/export.html', 1000, 600, 'leye-export', { minimizeButton: true, grayscaleMask: true });
|
await eda.sys_IFrame.openIFrame('/iframe/export.html', 1000, 600, 'leye-export', { minimizeButton: true, grayscaleMask: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openSettings(): void {
|
export async function openSettings(): Promise<void> {
|
||||||
eda.sys_IFrame.openIFrame('/iframe/settings.html', 400, 600);
|
await eda.sys_IFrame.openIFrame('/iframe/settings.html', 400, 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -62,4 +63,20 @@ if (!globalThis['__LEYE_INIT_FLAG__']) {
|
|||||||
}).catch((err: any) => {
|
}).catch((err: any) => {
|
||||||
console.error('[LEYE] 获取公告和更新失败: ', err);
|
console.error('[LEYE] 获取公告和更新失败: ', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 获取最新版本
|
||||||
|
console.log('[LEYE] 获取最新版本');
|
||||||
|
eda.sys_ClientUrl.request('https://leye.dragon.edu.kg/release/eext.ver.json').then(async (res: any) => {
|
||||||
|
const data = await res.json();
|
||||||
|
console.log('[LEYE] 获取最新版本: ', data);
|
||||||
|
if (extensionConfig.version !== data.versions[0].ver) {
|
||||||
|
eda.sys_Dialog.showConfirmationMessage(data.versions[0].changelog, `LEYE 有新版本 ${data.versions[0].ver} 可用,是否前往下载?`, '前往下载', '算了', async (r) => {
|
||||||
|
if (r) {
|
||||||
|
eda.sys_Window.open('https://lrurl.top/LeyeEEXT', ESYS_WindowOpenTarget.BLANK);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch((err: any) => {
|
||||||
|
console.error('[LEYE] 获取最新版本: ', err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user