scan-ipp-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/scan-ipp-sdk.es.js +351 -0
- package/dist/scan-ipp-sdk.umd.js +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## 订单处理 SDK
|
|
2
|
+
|
|
3
|
+
轻量级、零依赖的订单金额计算 & 购物车处理 SDK,支持四舍五入、向上取整、抹零、五舍六入、零元筐、押筐、附加费、反推单价/重量等业务逻辑,即插即用。
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
npm i order-processing-sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import OrderProcessingSDK from 'order-processing-sdk'
|
|
11
|
+
|
|
12
|
+
const cart = [
|
|
13
|
+
{ calAmount: 12.34, borrowAmount: 0, borrowNum: 0, originalBorrowPrice: 2 }
|
|
14
|
+
]
|
|
15
|
+
const billing = { customerId: '1001', customerName: '张三', freeBasket: false }
|
|
16
|
+
|
|
17
|
+
const detail = await OrderProcessingSDK.handleShopCar(cart, billing, 0)
|
|
18
|
+
// 0=四舍五入 1=向上取整 2=不处理 3=抹零 4=五舍六入
|
|
19
|
+
console.log(detail.totalCalAmount) // 12
|
|
20
|
+
console.log(detail.totalChangeDiff) // -0.34
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
| 方法 | 说明 |
|
|
26
|
+
| ------------------------------------------------ | -------------------- |
|
|
27
|
+
| `handleShopCar(items, billing, roundType)` | 单订单处理(核心) |
|
|
28
|
+
| `batchProcessOrders(orders, billing, roundType)` | 批量处理 |
|
|
29
|
+
| `calculateOrderStats(items)` | 统计:总数/总额/均值/最大/最小 |
|
|
30
|
+
| `syncProductCheckStatus(...)` | 购物车与货品勾选状态同步 |
|
|
31
|
+
| `handleBillingData(row, opts)` | 行级开单计算(金额/重量/附加费/押筐) |
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
MIT © qinxingxing
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
const E = "_ipp._tcp";
|
|
2
|
+
let P = !1, y = null, T = null, W = null, b = [], D = !1, C = null, O = null, $ = null, k = [], I = null;
|
|
3
|
+
function q(o, e) {
|
|
4
|
+
h();
|
|
5
|
+
const n = uni.getSystemInfoSync().platform;
|
|
6
|
+
console.log(`[LAN-SCAN] Starting discovery on ${n} for ${E}`), P = !0, b = [], D = !1, I = setTimeout(() => {
|
|
7
|
+
P && (console.warn("[LAN-SCAN] Discovery timeout, no devices found"), h(), I = null, clearTimeout(I));
|
|
8
|
+
}, 15e3), n === "android" ? j(o, e) : n === "ios" ? H(o, e) : (e && e("Unsupported platform"), h());
|
|
9
|
+
}
|
|
10
|
+
function h() {
|
|
11
|
+
if (I && (clearTimeout(I), I = null), !(!P && !C && !y && !O)) {
|
|
12
|
+
console.log("[LAN-SCAN] Stopping discovery");
|
|
13
|
+
try {
|
|
14
|
+
if (C) {
|
|
15
|
+
try {
|
|
16
|
+
C.release(), console.log("[Android] Multicast lock released");
|
|
17
|
+
} catch (t) {
|
|
18
|
+
console.warn("[Android] Release multicast lock warning:", t);
|
|
19
|
+
}
|
|
20
|
+
C = null;
|
|
21
|
+
}
|
|
22
|
+
const e = uni.getSystemInfoSync().platform;
|
|
23
|
+
if (e === "android") {
|
|
24
|
+
if (y && T)
|
|
25
|
+
try {
|
|
26
|
+
y.stopServiceDiscovery(T);
|
|
27
|
+
} catch (t) {
|
|
28
|
+
console.warn("[Android] Stop discovery warning: ", t);
|
|
29
|
+
}
|
|
30
|
+
T = null, W = null, y = null, b = [], D = !1;
|
|
31
|
+
} else e === "ios" && (k && k.length > 0 && k.forEach((t) => {
|
|
32
|
+
if (t.service)
|
|
33
|
+
try {
|
|
34
|
+
t.service.stop(), t.service.setDelegate(null);
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}), k = [], O && (O.stop(), O.setDelegate(null)), O = null, $ = null);
|
|
38
|
+
} catch (o) {
|
|
39
|
+
console.error("[LAN-SCAN] Error stopping discovery:", o);
|
|
40
|
+
}
|
|
41
|
+
P = !1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function j(o, e) {
|
|
45
|
+
let t = null;
|
|
46
|
+
try {
|
|
47
|
+
const n = plus.android.importClass("android.content.Context"), s = plus.android.importClass("android.net.nsd.NsdManager"), c = plus.android.importClass("android.net.nsd.NsdServiceInfo"), i = plus.android.runtimeMainActivity();
|
|
48
|
+
if (y = i.getSystemService(n.NSD_SERVICE), !y) {
|
|
49
|
+
e && e("Failed to get NsdManager"), h();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const r = plus.android.importClass("android.net.wifi.WifiManager");
|
|
53
|
+
t = i.getSystemService(n.WIFI_SERVICE).createMulticastLock("ipp-discovery"), t.setReferenceCounted(!0), t.acquire(), console.log("[Android] Multicast lock acquired"), C = t, T = plus.android.implements("android.net.nsd.NsdManager$DiscoveryListener", {
|
|
54
|
+
onDiscoveryStarted: function(a) {
|
|
55
|
+
console.log("[Android] Discovery started: " + a);
|
|
56
|
+
},
|
|
57
|
+
onDiscoveryStopped: function(a) {
|
|
58
|
+
console.log("[Android] Discovery stopped: " + a);
|
|
59
|
+
},
|
|
60
|
+
onServiceFound: function(a) {
|
|
61
|
+
console.log("[Android] Service found: " + a.getServiceName(), a), _(a, o);
|
|
62
|
+
},
|
|
63
|
+
onServiceLost: function(a) {
|
|
64
|
+
console.log("[Android] Service lost: " + a.getServiceName());
|
|
65
|
+
},
|
|
66
|
+
onStartDiscoveryFailed: function(a, d) {
|
|
67
|
+
console.error("[Android] Discovery failed: Error code:" + d), e && e("Start discovery failed code: " + d), h();
|
|
68
|
+
},
|
|
69
|
+
onStopDiscoveryFailed: function(a, d) {
|
|
70
|
+
console.error("[Android] Stop discovery failed: Error code:" + d);
|
|
71
|
+
}
|
|
72
|
+
}), y.discoverServices("_ipp._tcp", s.PROTOCOL_DNS_SD, T);
|
|
73
|
+
} catch (n) {
|
|
74
|
+
if (console.error("[Android] Exception in startAndroidScan:", n), t) {
|
|
75
|
+
try {
|
|
76
|
+
t.release();
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
t = null;
|
|
80
|
+
}
|
|
81
|
+
C = null, e && e(n.message), h();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function _(o, e) {
|
|
85
|
+
b.push(o), R(e);
|
|
86
|
+
}
|
|
87
|
+
function R(o) {
|
|
88
|
+
if (D || b.length === 0 || !y)
|
|
89
|
+
return;
|
|
90
|
+
const e = b.shift();
|
|
91
|
+
D = !0, console.log("[Android] Processing resolve for: " + e.getServiceName());
|
|
92
|
+
const t = plus.android.implements("android.net.nsd.NsdManager$ResolveListener", {
|
|
93
|
+
onResolveFailed: function(n, s) {
|
|
94
|
+
console.error("[Android] Resolve failed: " + s), D = !1, setTimeout(() => R(o), 100);
|
|
95
|
+
},
|
|
96
|
+
onServiceResolved: function(n) {
|
|
97
|
+
const s = plus.android.invoke(n, "toString");
|
|
98
|
+
console.log("[Android] Service resolved raw: " + s);
|
|
99
|
+
const c = n.getHost();
|
|
100
|
+
let i = "";
|
|
101
|
+
if (c) {
|
|
102
|
+
const l = plus.android.invoke(c, "getHostAddress");
|
|
103
|
+
l && l.indexOf(":") === -1 && (i = l, console.log("[Android] Got IP from getHostAddress: " + i));
|
|
104
|
+
}
|
|
105
|
+
if (!i && s) {
|
|
106
|
+
const l = /(?:\/)?((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/g;
|
|
107
|
+
let p;
|
|
108
|
+
for (; (p = l.exec(s)) !== null; ) {
|
|
109
|
+
const g = p[1];
|
|
110
|
+
if (g !== "127.0.0.1" && g !== "0.0.0.0") {
|
|
111
|
+
i = g, console.log("[Android] Extracted IPv4 from string: " + i);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
!i && c && (i = plus.android.invoke(c, "getHostAddress"));
|
|
116
|
+
}
|
|
117
|
+
let r = n.getPort();
|
|
118
|
+
if ((!r || r <= 0) && s) {
|
|
119
|
+
const l = /port:\s*(\d+)/, p = s.match(l);
|
|
120
|
+
p && p[1] && (r = parseInt(p[1]), console.log("[Android] Extracted Port from string: " + r));
|
|
121
|
+
}
|
|
122
|
+
console.log("Port:", r);
|
|
123
|
+
const f = {};
|
|
124
|
+
try {
|
|
125
|
+
const l = plus.android.invoke(n, "getAttributes");
|
|
126
|
+
if (l) {
|
|
127
|
+
const p = plus.android.importClass("java.lang.String"), g = plus.android.invoke(l, "keySet"), m = plus.android.invoke(g, "iterator");
|
|
128
|
+
for (; plus.android.invoke(m, "hasNext"); ) {
|
|
129
|
+
const v = plus.android.invoke(m, "next"), A = plus.android.invoke(l, "get", v);
|
|
130
|
+
let x = "";
|
|
131
|
+
if (A)
|
|
132
|
+
try {
|
|
133
|
+
x = new p(A, "UTF-8").toString();
|
|
134
|
+
} catch {
|
|
135
|
+
console.warn("Failed to convert TXT value for key: " + v);
|
|
136
|
+
}
|
|
137
|
+
f[v] = x;
|
|
138
|
+
}
|
|
139
|
+
console.log("[Android] TXT Records: " + JSON.stringify(f));
|
|
140
|
+
}
|
|
141
|
+
} catch (l) {
|
|
142
|
+
console.warn("[Android] Failed to get attributes: " + l.message);
|
|
143
|
+
}
|
|
144
|
+
i && i.startsWith("/") && (i = i.substring(1));
|
|
145
|
+
const a = plus.android.invoke(n, "getServiceName");
|
|
146
|
+
let d = "";
|
|
147
|
+
c && (d = plus.android.invoke(c, "getHostName"));
|
|
148
|
+
let S = f.rp || "ipp/print";
|
|
149
|
+
S.startsWith("/") && (S = S.substring(1));
|
|
150
|
+
let N = "";
|
|
151
|
+
i && r ? N = `ipp://${i}:${r}/${S}` : d && r && (N = `ipp://${d}:${r}/${S}`);
|
|
152
|
+
const u = {
|
|
153
|
+
name: a,
|
|
154
|
+
ip: i,
|
|
155
|
+
port: r,
|
|
156
|
+
hostName: d,
|
|
157
|
+
attributes: f,
|
|
158
|
+
ippUrl: N,
|
|
159
|
+
// 添加 IPP URL
|
|
160
|
+
paper: B(f)
|
|
161
|
+
// 支持的纸张规格
|
|
162
|
+
};
|
|
163
|
+
console.log("Device Object Constructed: " + JSON.stringify(u)), typeof o == "function" ? o(u) : console.error("[Android] onDeviceFound callback is not a function!"), D = !1, setTimeout(() => R(o), 100);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
y.resolveService(e, t);
|
|
168
|
+
} catch (n) {
|
|
169
|
+
console.error("[Android] resolveService exception", n), D = !1, R(o);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function H(o, e) {
|
|
173
|
+
try {
|
|
174
|
+
const t = plus.ios.importClass("NSNetServiceBrowser"), n = plus.ios.importClass("NSNetService");
|
|
175
|
+
if (!t || !n) {
|
|
176
|
+
const s = "Failed to import iOS classes: NSNetServiceBrowser/NSNetService";
|
|
177
|
+
console.error("[iOS] " + s), e && e(s), h();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
O = new t(), console.log("[iOS] Browser created"), $ = plus.ios.implements("NSNetServiceBrowserDelegate", {
|
|
181
|
+
"netServiceBrowserWillSearch:": function(s) {
|
|
182
|
+
console.log("[iOS] Search started successfully");
|
|
183
|
+
},
|
|
184
|
+
"netServiceBrowser:didFindService:moreComing:": function(s, c, i) {
|
|
185
|
+
let r = "Unknown";
|
|
186
|
+
try {
|
|
187
|
+
r = plus.ios.invoke(c, "name");
|
|
188
|
+
} catch (f) {
|
|
189
|
+
console.error("[iOS] Error getting service name: " + f.message);
|
|
190
|
+
}
|
|
191
|
+
console.log("[iOS] Service found: " + r), X(c, o);
|
|
192
|
+
},
|
|
193
|
+
"netServiceBrowser:didRemoveService:moreComing:": function(s, c, i) {
|
|
194
|
+
let r = "Unknown";
|
|
195
|
+
try {
|
|
196
|
+
r = plus.ios.invoke(c, "name");
|
|
197
|
+
} catch {
|
|
198
|
+
}
|
|
199
|
+
console.log("[iOS] Service removed: " + r);
|
|
200
|
+
},
|
|
201
|
+
"netServiceBrowserDidStopSearch:": function(s) {
|
|
202
|
+
console.log("[iOS] Search stopped");
|
|
203
|
+
},
|
|
204
|
+
"netServiceBrowser:didNotSearch:": function(s, c) {
|
|
205
|
+
console.error("[iOS] Search failed", c), e && e("iOS Search failed, check permissions in manifest.json"), h();
|
|
206
|
+
}
|
|
207
|
+
}), plus.ios.invoke(O, "setDelegate:", $), console.log("[iOS] Invoking searchForServicesOfType:inDomain: with " + E), plus.ios.invoke(O, "searchForServicesOfType:inDomain:", E, "local.");
|
|
208
|
+
} catch (t) {
|
|
209
|
+
console.error("[iOS] Exception in startIOSScan:", t), e && e(t.message), h();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function X(o, e) {
|
|
213
|
+
console.log("[iOS] Starting resolution for service object");
|
|
214
|
+
const t = plus.ios.implements("NSNetServiceDelegate", {
|
|
215
|
+
"netServiceDidResolveAddress:": function(n) {
|
|
216
|
+
console.log("[iOS] netServiceDidResolveAddress triggered");
|
|
217
|
+
let s = "", c = 0, i = "";
|
|
218
|
+
try {
|
|
219
|
+
s = plus.ios.invoke(n, "name"), c = plus.ios.invoke(n, "port"), i = plus.ios.invoke(n, "hostName"), console.log(`[iOS] Basic Info - Name: ${s}, Port: ${c}, HostName: ${i}`);
|
|
220
|
+
} catch (u) {
|
|
221
|
+
console.error("[iOS] Failed to get basic info: " + u.message);
|
|
222
|
+
}
|
|
223
|
+
let r = "";
|
|
224
|
+
try {
|
|
225
|
+
const u = plus.ios.invoke(n, "addresses");
|
|
226
|
+
if (u) {
|
|
227
|
+
const l = plus.ios.invoke(u, "count");
|
|
228
|
+
console.log("[iOS] Found " + l + " addresses");
|
|
229
|
+
for (let p = 0; p < l; p++) {
|
|
230
|
+
const g = plus.ios.invoke(u, "objectAtIndex:", p);
|
|
231
|
+
if (!g) continue;
|
|
232
|
+
const m = plus.ios.invoke(g, "base64EncodedStringWithOptions:", 0);
|
|
233
|
+
if (m) {
|
|
234
|
+
const v = L(m);
|
|
235
|
+
if (!v || v.length < 4) continue;
|
|
236
|
+
if (v.length >= 8 && v[1] === 2) {
|
|
237
|
+
r = `${v[4]}.${v[5]}.${v[6]}.${v[7]}`, console.log("[iOS] Parsed IPv4: " + r);
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} else
|
|
243
|
+
console.warn("[iOS] addresses is null");
|
|
244
|
+
} catch (u) {
|
|
245
|
+
console.error("[iOS] Error parsing addresses: " + u.message);
|
|
246
|
+
}
|
|
247
|
+
r || (r = i, console.log("[iOS] No IPv4 found, using hostName: " + r));
|
|
248
|
+
let f = {};
|
|
249
|
+
try {
|
|
250
|
+
const u = plus.ios.invoke(n, "TXTRecordData");
|
|
251
|
+
if (u) {
|
|
252
|
+
const l = plus.ios.invoke(u, "base64EncodedStringWithOptions:", 0);
|
|
253
|
+
if (l) {
|
|
254
|
+
const p = L(l);
|
|
255
|
+
if (p) {
|
|
256
|
+
let g = 0;
|
|
257
|
+
for (; g < p.length; ) {
|
|
258
|
+
const m = p[g];
|
|
259
|
+
if (g++, g + m > p.length) break;
|
|
260
|
+
if (m > 0) {
|
|
261
|
+
const v = p.subarray(g, g + m);
|
|
262
|
+
let A = "";
|
|
263
|
+
for (let w = 0; w < m; w++) A += String.fromCharCode(v[w]);
|
|
264
|
+
const x = A.indexOf("=");
|
|
265
|
+
if (x > 0) {
|
|
266
|
+
const w = A.substring(0, x), U = A.substring(x + 1);
|
|
267
|
+
f[w] = U;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
g += m;
|
|
271
|
+
}
|
|
272
|
+
console.log("[iOS] Parsed TXT Records: " + JSON.stringify(f));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} catch (u) {
|
|
277
|
+
console.warn("[iOS] Failed to parse TXT record: " + u.message);
|
|
278
|
+
}
|
|
279
|
+
let a = f.rp || "ipp/print";
|
|
280
|
+
a.startsWith("/") && (a = a.substring(1));
|
|
281
|
+
let d = r;
|
|
282
|
+
!d && i && (d = i), !d && s && (d = s.replace(/\s+/g, "-") + ".local", console.log("[iOS] Constructed hostTarget from name: " + d));
|
|
283
|
+
let S = "";
|
|
284
|
+
d && c ? (S = `ipp://${d}:${c}/${a}`, console.log("[iOS] Generated IPP URL: " + S)) : console.warn("[iOS] Cannot generate IPP URL, missing host or port");
|
|
285
|
+
const N = {
|
|
286
|
+
name: s,
|
|
287
|
+
ip: r,
|
|
288
|
+
// 这里可能是 IP 地址,也可能是 hostName
|
|
289
|
+
port: c,
|
|
290
|
+
hostName: i,
|
|
291
|
+
isIOS: !0,
|
|
292
|
+
attributes: f,
|
|
293
|
+
ippUrl: S,
|
|
294
|
+
paper: B(f)
|
|
295
|
+
};
|
|
296
|
+
typeof e == "function" && e(N), M(t);
|
|
297
|
+
},
|
|
298
|
+
"netService:didNotResolve:": function(n, s) {
|
|
299
|
+
console.error("[iOS] Resolve failed for " + (plus.ios.invoke(n, "name") || "Unknown"), s), M(t);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
k.push({
|
|
303
|
+
delegate: t,
|
|
304
|
+
service: o
|
|
305
|
+
}), console.log("[iOS] Setting delegate for resolution"), plus.ios.invoke(o, "setDelegate:", t), console.log("[iOS] Invoking resolveWithTimeout"), plus.ios.invoke(o, "resolveWithTimeout:", 5);
|
|
306
|
+
}
|
|
307
|
+
function M(o) {
|
|
308
|
+
const e = k.findIndex((t) => t.delegate === o);
|
|
309
|
+
if (e > -1) {
|
|
310
|
+
const t = k[e];
|
|
311
|
+
if (t.service)
|
|
312
|
+
try {
|
|
313
|
+
t.service.setDelegate(null), t.service.stop();
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
k.splice(e, 1);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function L(o) {
|
|
320
|
+
if (!o) return null;
|
|
321
|
+
if (typeof atob == "function")
|
|
322
|
+
try {
|
|
323
|
+
const S = atob(o), N = S.length, u = new Uint8Array(N);
|
|
324
|
+
for (let l = 0; l < N; l++)
|
|
325
|
+
u[l] = S.charCodeAt(l);
|
|
326
|
+
return u;
|
|
327
|
+
} catch (S) {
|
|
328
|
+
return console.error("atob failed", S), null;
|
|
329
|
+
}
|
|
330
|
+
const e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
331
|
+
let t = o.length * 0.75;
|
|
332
|
+
const n = o.length;
|
|
333
|
+
let s, c = 0, i, r, f, a;
|
|
334
|
+
o[o.length - 1] === "=" && (t--, o[o.length - 2] === "=" && t--);
|
|
335
|
+
const d = new Uint8Array(t);
|
|
336
|
+
for (s = 0; s < n; s += 4)
|
|
337
|
+
i = e.indexOf(o[s]), r = e.indexOf(o[s + 1]), f = e.indexOf(o[s + 2]), a = e.indexOf(o[s + 3]), d[c++] = i << 2 | r >> 4, f != 64 && (d[c++] = (r & 15) << 4 | f >> 2), a != 64 && (d[c++] = (f & 3) << 6 | a);
|
|
338
|
+
return d;
|
|
339
|
+
}
|
|
340
|
+
function B(o) {
|
|
341
|
+
let e = [];
|
|
342
|
+
if (!o) return e;
|
|
343
|
+
const t = (o.PaperMax || "").toLowerCase(), n = (o.ty || o.product || "").toLowerCase();
|
|
344
|
+
return (t.includes("a3") || n.includes("a3")) && e.push("A3"), e;
|
|
345
|
+
}
|
|
346
|
+
const J = ScanIPPPSDK;
|
|
347
|
+
export {
|
|
348
|
+
J as default,
|
|
349
|
+
q as startDiscovery,
|
|
350
|
+
h as stopDiscovery
|
|
351
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(N,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(N=typeof globalThis<"u"?globalThis:N||self,w(N.ScanIPPPSDK={}))})(this,function(N){"use strict";const w="_ipp._tcp";let M=!1,h=null,x=null,W=null,R=[],D=!1,b=null,O=null,$=null,k=[],C=null;function j(o,e){y();const n=uni.getSystemInfoSync().platform;console.log(`[LAN-SCAN] Starting discovery on ${n} for ${w}`),M=!0,R=[],D=!1,C=setTimeout(()=>{M&&(console.warn("[LAN-SCAN] Discovery timeout, no devices found"),y(),C=null,clearTimeout(C))},15e3),n==="android"?_(o,e):n==="ios"?X(o,e):(e&&e("Unsupported platform"),y())}function y(){if(C&&(clearTimeout(C),C=null),!(!M&&!b&&!h&&!O)){console.log("[LAN-SCAN] Stopping discovery");try{if(b){try{b.release(),console.log("[Android] Multicast lock released")}catch(t){console.warn("[Android] Release multicast lock warning:",t)}b=null}const e=uni.getSystemInfoSync().platform;if(e==="android"){if(h&&x)try{h.stopServiceDiscovery(x)}catch(t){console.warn("[Android] Stop discovery warning: ",t)}x=null,W=null,h=null,R=[],D=!1}else e==="ios"&&(k&&k.length>0&&k.forEach(t=>{if(t.service)try{t.service.stop(),t.service.setDelegate(null)}catch{}}),k=[],O&&(O.stop(),O.setDelegate(null)),O=null,$=null)}catch(o){console.error("[LAN-SCAN] Error stopping discovery:",o)}M=!1}}function _(o,e){let t=null;try{const n=plus.android.importClass("android.content.Context"),i=plus.android.importClass("android.net.nsd.NsdManager"),c=plus.android.importClass("android.net.nsd.NsdServiceInfo"),s=plus.android.runtimeMainActivity();if(h=s.getSystemService(n.NSD_SERVICE),!h){e&&e("Failed to get NsdManager"),y();return}const r=plus.android.importClass("android.net.wifi.WifiManager");t=s.getSystemService(n.WIFI_SERVICE).createMulticastLock("ipp-discovery"),t.setReferenceCounted(!0),t.acquire(),console.log("[Android] Multicast lock acquired"),b=t,x=plus.android.implements("android.net.nsd.NsdManager$DiscoveryListener",{onDiscoveryStarted:function(a){console.log("[Android] Discovery started: "+a)},onDiscoveryStopped:function(a){console.log("[Android] Discovery stopped: "+a)},onServiceFound:function(a){console.log("[Android] Service found: "+a.getServiceName(),a),H(a,o)},onServiceLost:function(a){console.log("[Android] Service lost: "+a.getServiceName())},onStartDiscoveryFailed:function(a,d){console.error("[Android] Discovery failed: Error code:"+d),e&&e("Start discovery failed code: "+d),y()},onStopDiscoveryFailed:function(a,d){console.error("[Android] Stop discovery failed: Error code:"+d)}}),h.discoverServices("_ipp._tcp",i.PROTOCOL_DNS_SD,x)}catch(n){if(console.error("[Android] Exception in startAndroidScan:",n),t){try{t.release()}catch{}t=null}b=null,e&&e(n.message),y()}}function H(o,e){R.push(o),E(e)}function E(o){if(D||R.length===0||!h)return;const e=R.shift();D=!0,console.log("[Android] Processing resolve for: "+e.getServiceName());const t=plus.android.implements("android.net.nsd.NsdManager$ResolveListener",{onResolveFailed:function(n,i){console.error("[Android] Resolve failed: "+i),D=!1,setTimeout(()=>E(o),100)},onServiceResolved:function(n){const i=plus.android.invoke(n,"toString");console.log("[Android] Service resolved raw: "+i);const c=n.getHost();let s="";if(c){const l=plus.android.invoke(c,"getHostAddress");l&&l.indexOf(":")===-1&&(s=l,console.log("[Android] Got IP from getHostAddress: "+s))}if(!s&&i){const l=/(?:\/)?((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/g;let p;for(;(p=l.exec(i))!==null;){const g=p[1];if(g!=="127.0.0.1"&&g!=="0.0.0.0"){s=g,console.log("[Android] Extracted IPv4 from string: "+s);break}}!s&&c&&(s=plus.android.invoke(c,"getHostAddress"))}let r=n.getPort();if((!r||r<=0)&&i){const l=/port:\s*(\d+)/,p=i.match(l);p&&p[1]&&(r=parseInt(p[1]),console.log("[Android] Extracted Port from string: "+r))}console.log("Port:",r);const f={};try{const l=plus.android.invoke(n,"getAttributes");if(l){const p=plus.android.importClass("java.lang.String"),g=plus.android.invoke(l,"keySet"),m=plus.android.invoke(g,"iterator");for(;plus.android.invoke(m,"hasNext");){const v=plus.android.invoke(m,"next"),T=plus.android.invoke(l,"get",v);let P="";if(T)try{P=new p(T,"UTF-8").toString()}catch{console.warn("Failed to convert TXT value for key: "+v)}f[v]=P}console.log("[Android] TXT Records: "+JSON.stringify(f))}}catch(l){console.warn("[Android] Failed to get attributes: "+l.message)}s&&s.startsWith("/")&&(s=s.substring(1));const a=plus.android.invoke(n,"getServiceName");let d="";c&&(d=plus.android.invoke(c,"getHostName"));let S=f.rp||"ipp/print";S.startsWith("/")&&(S=S.substring(1));let A="";s&&r?A=`ipp://${s}:${r}/${S}`:d&&r&&(A=`ipp://${d}:${r}/${S}`);const u={name:a,ip:s,port:r,hostName:d,attributes:f,ippUrl:A,paper:U(f)};console.log("Device Object Constructed: "+JSON.stringify(u)),typeof o=="function"?o(u):console.error("[Android] onDeviceFound callback is not a function!"),D=!1,setTimeout(()=>E(o),100)}});try{h.resolveService(e,t)}catch(n){console.error("[Android] resolveService exception",n),D=!1,E(o)}}function X(o,e){try{const t=plus.ios.importClass("NSNetServiceBrowser"),n=plus.ios.importClass("NSNetService");if(!t||!n){const i="Failed to import iOS classes: NSNetServiceBrowser/NSNetService";console.error("[iOS] "+i),e&&e(i),y();return}O=new t,console.log("[iOS] Browser created"),$=plus.ios.implements("NSNetServiceBrowserDelegate",{"netServiceBrowserWillSearch:":function(i){console.log("[iOS] Search started successfully")},"netServiceBrowser:didFindService:moreComing:":function(i,c,s){let r="Unknown";try{r=plus.ios.invoke(c,"name")}catch(f){console.error("[iOS] Error getting service name: "+f.message)}console.log("[iOS] Service found: "+r),q(c,o)},"netServiceBrowser:didRemoveService:moreComing:":function(i,c,s){let r="Unknown";try{r=plus.ios.invoke(c,"name")}catch{}console.log("[iOS] Service removed: "+r)},"netServiceBrowserDidStopSearch:":function(i){console.log("[iOS] Search stopped")},"netServiceBrowser:didNotSearch:":function(i,c){console.error("[iOS] Search failed",c),e&&e("iOS Search failed, check permissions in manifest.json"),y()}}),plus.ios.invoke(O,"setDelegate:",$),console.log("[iOS] Invoking searchForServicesOfType:inDomain: with "+w),plus.ios.invoke(O,"searchForServicesOfType:inDomain:",w,"local.")}catch(t){console.error("[iOS] Exception in startIOSScan:",t),e&&e(t.message),y()}}function q(o,e){console.log("[iOS] Starting resolution for service object");const t=plus.ios.implements("NSNetServiceDelegate",{"netServiceDidResolveAddress:":function(n){console.log("[iOS] netServiceDidResolveAddress triggered");let i="",c=0,s="";try{i=plus.ios.invoke(n,"name"),c=plus.ios.invoke(n,"port"),s=plus.ios.invoke(n,"hostName"),console.log(`[iOS] Basic Info - Name: ${i}, Port: ${c}, HostName: ${s}`)}catch(u){console.error("[iOS] Failed to get basic info: "+u.message)}let r="";try{const u=plus.ios.invoke(n,"addresses");if(u){const l=plus.ios.invoke(u,"count");console.log("[iOS] Found "+l+" addresses");for(let p=0;p<l;p++){const g=plus.ios.invoke(u,"objectAtIndex:",p);if(!g)continue;const m=plus.ios.invoke(g,"base64EncodedStringWithOptions:",0);if(m){const v=B(m);if(!v||v.length<4)continue;if(v.length>=8&&v[1]===2){r=`${v[4]}.${v[5]}.${v[6]}.${v[7]}`,console.log("[iOS] Parsed IPv4: "+r);break}}}}else console.warn("[iOS] addresses is null")}catch(u){console.error("[iOS] Error parsing addresses: "+u.message)}r||(r=s,console.log("[iOS] No IPv4 found, using hostName: "+r));let f={};try{const u=plus.ios.invoke(n,"TXTRecordData");if(u){const l=plus.ios.invoke(u,"base64EncodedStringWithOptions:",0);if(l){const p=B(l);if(p){let g=0;for(;g<p.length;){const m=p[g];if(g++,g+m>p.length)break;if(m>0){const v=p.subarray(g,g+m);let T="";for(let I=0;I<m;I++)T+=String.fromCharCode(v[I]);const P=T.indexOf("=");if(P>0){const I=T.substring(0,P),K=T.substring(P+1);f[I]=K}}g+=m}console.log("[iOS] Parsed TXT Records: "+JSON.stringify(f))}}}}catch(u){console.warn("[iOS] Failed to parse TXT record: "+u.message)}let a=f.rp||"ipp/print";a.startsWith("/")&&(a=a.substring(1));let d=r;!d&&s&&(d=s),!d&&i&&(d=i.replace(/\s+/g,"-")+".local",console.log("[iOS] Constructed hostTarget from name: "+d));let S="";d&&c?(S=`ipp://${d}:${c}/${a}`,console.log("[iOS] Generated IPP URL: "+S)):console.warn("[iOS] Cannot generate IPP URL, missing host or port");const A={name:i,ip:r,port:c,hostName:s,isIOS:!0,attributes:f,ippUrl:S,paper:U(f)};typeof e=="function"&&e(A),L(t)},"netService:didNotResolve:":function(n,i){console.error("[iOS] Resolve failed for "+(plus.ios.invoke(n,"name")||"Unknown"),i),L(t)}});k.push({delegate:t,service:o}),console.log("[iOS] Setting delegate for resolution"),plus.ios.invoke(o,"setDelegate:",t),console.log("[iOS] Invoking resolveWithTimeout"),plus.ios.invoke(o,"resolveWithTimeout:",5)}function L(o){const e=k.findIndex(t=>t.delegate===o);if(e>-1){const t=k[e];if(t.service)try{t.service.setDelegate(null),t.service.stop()}catch{}k.splice(e,1)}}function B(o){if(!o)return null;if(typeof atob=="function")try{const S=atob(o),A=S.length,u=new Uint8Array(A);for(let l=0;l<A;l++)u[l]=S.charCodeAt(l);return u}catch(S){return console.error("atob failed",S),null}const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";let t=o.length*.75;const n=o.length;let i,c=0,s,r,f,a;o[o.length-1]==="="&&(t--,o[o.length-2]==="="&&t--);const d=new Uint8Array(t);for(i=0;i<n;i+=4)s=e.indexOf(o[i]),r=e.indexOf(o[i+1]),f=e.indexOf(o[i+2]),a=e.indexOf(o[i+3]),d[c++]=s<<2|r>>4,f!=64&&(d[c++]=(r&15)<<4|f>>2),a!=64&&(d[c++]=(f&3)<<6|a);return d}function U(o){let e=[];if(!o)return e;const t=(o.PaperMax||"").toLowerCase(),n=(o.ty||o.product||"").toLowerCase();return(t.includes("a3")||n.includes("a3"))&&e.push("A3"),e}const J=ScanIPPPSDK;N.default=J,N.startDiscovery=j,N.stopDiscovery=y,Object.defineProperties(N,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "scan-ipp-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "扫描IPPP码SDK(Vite 打包)",
|
|
5
|
+
"main": "dist/scan-ipp-sdk.umd.js",
|
|
6
|
+
"module": "dist/scan-ipp-sdk.es.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"order",
|
|
13
|
+
"cart",
|
|
14
|
+
"round",
|
|
15
|
+
"money",
|
|
16
|
+
"sdk",
|
|
17
|
+
"vite"
|
|
18
|
+
],
|
|
19
|
+
"author": "your-name <your-email>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/yourname/scan-ipp-sdk.git"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite",
|
|
27
|
+
"build": "vite build",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"vite": "^5.0.0",
|
|
32
|
+
"vite-plugin-dts": "^3.6.0"
|
|
33
|
+
}
|
|
34
|
+
}
|