dsh-ponlay-erp 1.8.0 → 1.8.1
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/client.js +32 -4
- package/index.js +16 -6
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -26,6 +26,11 @@ window.__ModuleLoader__.load({
|
|
|
26
26
|
|
|
27
27
|
const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms))
|
|
28
28
|
|
|
29
|
+
function activeLang(localeFace) {
|
|
30
|
+
const id = String(localeFace.getSnapshot().active || '').toLowerCase()
|
|
31
|
+
return id.startsWith('zh') ? 'zh' : 'en'
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
// ---------------------------------------------------------------
|
|
30
35
|
// Dictionaries
|
|
31
36
|
// ---------------------------------------------------------------
|
|
@@ -36,6 +41,7 @@ window.__ModuleLoader__.load({
|
|
|
36
41
|
'status.loading': 'Connecting…',
|
|
37
42
|
'action.retry': 'Retry',
|
|
38
43
|
'action.openExternal': 'Open in new tab',
|
|
44
|
+
'action.expandSidebar': 'Expand sidebar',
|
|
39
45
|
'error.proxyTitle': 'Embedded mode is unavailable',
|
|
40
46
|
'error.proxyBody': 'The local ERP proxy did not start, so the system cannot be embedded here. You can still open the original site in a new tab.',
|
|
41
47
|
'error.httpsTitle': 'Embedded mode needs the local http address',
|
|
@@ -63,6 +69,7 @@ window.__ModuleLoader__.load({
|
|
|
63
69
|
'status.loading': '正在连接…',
|
|
64
70
|
'action.retry': '重试',
|
|
65
71
|
'action.openExternal': '在新窗口打开',
|
|
72
|
+
'action.expandSidebar': '展开侧边栏',
|
|
66
73
|
'error.proxyTitle': '内嵌模式不可用',
|
|
67
74
|
'error.proxyBody': '本地 ERP 代理未启动,无法在此页面内嵌;你仍然可以在新窗口打开原站。',
|
|
68
75
|
'error.httpsTitle': '内嵌模式需要本地 http 地址',
|
|
@@ -95,6 +102,7 @@ window.__ModuleLoader__.load({
|
|
|
95
102
|
'M6.5 12.5v3M10 12.5v2M13.5 12.5v3M17 12.5v2',
|
|
96
103
|
],
|
|
97
104
|
alert: ['M12 3.2 2.9 19.8h18.2L12 3.2Z', 'M12 9.4v4.4', 'M12 16.6v.2'],
|
|
105
|
+
panelLeft: ['M3.5 5.5h17a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1h-17a1 1 0 0 1-1-1v-11a1 1 0 0 1 1-1Z', 'M9 5.5v13'],
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
function Icon({ name, size = 16 }) {
|
|
@@ -199,11 +207,12 @@ window.__ModuleLoader__.load({
|
|
|
199
207
|
// Persistent ERP surface
|
|
200
208
|
// ---------------------------------------------------------------
|
|
201
209
|
|
|
202
|
-
function ErpSurface({ t, localeFace, store, usePanelInfo }) {
|
|
210
|
+
function ErpSurface({ t, localeFace, store, usePanelInfo, layout }) {
|
|
203
211
|
const active = usePanelInfo((info) => info.activePanelId === PANEL_KEY)
|
|
204
212
|
const rect = useSyncExternalStore(store.subscribe, store.getRect, store.getRect)
|
|
205
213
|
useSyncExternalStore(localeFace.subscribe, localeFace.getSnapshot, localeFace.getSnapshot)
|
|
206
214
|
|
|
215
|
+
const lang = activeLang(localeFace)
|
|
207
216
|
const [started, setStarted] = useState(false)
|
|
208
217
|
const [attempt, setAttempt] = useState(0)
|
|
209
218
|
const [proxy, setProxy] = useState({ phase: 'loading', port: 0, target: DEFAULT_TARGET })
|
|
@@ -294,9 +303,10 @@ window.__ModuleLoader__.load({
|
|
|
294
303
|
const ready = proxy.phase === 'ready'
|
|
295
304
|
// A stale browser token must not outlive the server-side session: the
|
|
296
305
|
// reset page clears the proxy origin's storage and forwards to /login.
|
|
297
|
-
const targetPath = judged && !loggedIn ?
|
|
306
|
+
const targetPath = judged && !loggedIn ? `/_ponlay/reset?ponlay_lang=${lang}` : '/'
|
|
298
307
|
const src = ready && judged ? `http://${PROXY_HOST}:${proxy.port}${targetPath}` : ''
|
|
299
308
|
const visible = active && Boolean(rect) && rect.width > 0 && rect.height > 0
|
|
309
|
+
const collapsed = Boolean(rect) && rect.left < 120
|
|
300
310
|
const style = {
|
|
301
311
|
top: `${rect ? rect.top : 0}px`,
|
|
302
312
|
left: `${rect ? rect.left : 0}px`,
|
|
@@ -344,17 +354,30 @@ window.__ModuleLoader__.load({
|
|
|
344
354
|
'div',
|
|
345
355
|
{ className: 'erp-surface', style, 'data-hidden': visible ? 'false' : 'true' },
|
|
346
356
|
face,
|
|
357
|
+
visible && collapsed
|
|
358
|
+
? h(
|
|
359
|
+
'button',
|
|
360
|
+
{
|
|
361
|
+
type: 'button',
|
|
362
|
+
className: 'erp-expand',
|
|
363
|
+
title: t('action.expandSidebar'),
|
|
364
|
+
'aria-label': t('action.expandSidebar'),
|
|
365
|
+
onClick: () => layout?.toggleSidebar(),
|
|
366
|
+
},
|
|
367
|
+
h(Icon, { name: 'panelLeft', size: 16 }),
|
|
368
|
+
)
|
|
369
|
+
: null,
|
|
347
370
|
showLoading
|
|
348
371
|
? h('div', { className: 'erp-loading', 'aria-hidden': true }, h('span', { className: 'erp-spinner' }), t('status.loading'))
|
|
349
372
|
: null,
|
|
350
373
|
)
|
|
351
374
|
}
|
|
352
375
|
|
|
353
|
-
function ErpSurfaceHost({ t, localeFace, store, usePanelInfo }) {
|
|
376
|
+
function ErpSurfaceHost({ t, localeFace, store, usePanelInfo, layout }) {
|
|
354
377
|
// A slot entry that throws blanks its registration; degrade to "off"
|
|
355
378
|
// instead if the standard kit ever stops providing the panel hook.
|
|
356
379
|
if (typeof usePanelInfo !== 'function') return null
|
|
357
|
-
return h(ErpSurface, { t, localeFace, store, usePanelInfo })
|
|
380
|
+
return h(ErpSurface, { t, localeFace, store, usePanelInfo, layout })
|
|
358
381
|
}
|
|
359
382
|
|
|
360
383
|
// ---------------------------------------------------------------
|
|
@@ -560,6 +583,9 @@ window.__ModuleLoader__.load({
|
|
|
560
583
|
.erp-cfg-notice-pending{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 45%,transparent);color:var(--dsw-alias-state-warn-primary)}
|
|
561
584
|
.erp-cfg-notice-error{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);color:var(--dsw-alias-state-error-primary)}
|
|
562
585
|
.erp-cfg-summary{font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
|
|
586
|
+
.erp-expand{position:absolute;top:calc(var(--dsh-frame-top-clearance,0px) + 10px);left:12px;z-index:5;display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--dsw-alias-border-l1);border-radius:9px;background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-secondary);box-shadow:0 6px 18px color-mix(in srgb,var(--dsw-alias-label-primary) 16%,transparent);cursor:pointer;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
|
|
587
|
+
.erp-expand:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}
|
|
588
|
+
.erp-expand:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
563
589
|
@keyframes erp-spin{to{transform:rotate(360deg)}}
|
|
564
590
|
@media (prefers-reduced-motion:reduce){.erp-spinner{animation-duration:1.6s}}
|
|
565
591
|
`
|
|
@@ -573,6 +599,7 @@ window.__ModuleLoader__.load({
|
|
|
573
599
|
inject: ['slots', 'locale'],
|
|
574
600
|
apply(ctx) {
|
|
575
601
|
const locale = ctx.get('locale')
|
|
602
|
+
const layout = ctx.get('layout')
|
|
576
603
|
const store = createRectStore()
|
|
577
604
|
const dicts = [locale.register('ponlay-erp', 'en', EN), locale.register('ponlay-erp', 'zh', ZH)]
|
|
578
605
|
ctx.effect(() => () => {
|
|
@@ -607,6 +634,7 @@ window.__ModuleLoader__.load({
|
|
|
607
634
|
t,
|
|
608
635
|
localeFace,
|
|
609
636
|
store,
|
|
637
|
+
layout,
|
|
610
638
|
usePanelInfo: props.usePanelInfo,
|
|
611
639
|
}),
|
|
612
640
|
),
|
package/index.js
CHANGED
|
@@ -24,12 +24,20 @@ const INFO_PATH = '/plugin/ponlay-erp/info'
|
|
|
24
24
|
const STATE_PATH = '/plugin/ponlay-erp/state'
|
|
25
25
|
const CONFIG_PATH = '/plugin/ponlay-erp/config'
|
|
26
26
|
const RESET_PATH = '/_ponlay/reset'
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
/** Reset page: clear the stale ERP session but seed the UI language. */
|
|
28
|
+
function resetHtml(lang) {
|
|
29
|
+
const locale = lang === 'en' ? 'en' : 'zh'
|
|
30
|
+
return `<!doctype html>
|
|
31
|
+
<html lang="${locale}"><head><meta charset="utf-8"><title>Ponlay ERP</title></head>
|
|
29
32
|
<body><script>
|
|
30
|
-
try {
|
|
33
|
+
try {
|
|
34
|
+
localStorage.clear();
|
|
35
|
+
sessionStorage.clear();
|
|
36
|
+
localStorage.setItem('GlobalState', JSON.stringify({ language: '${locale}' }));
|
|
37
|
+
} catch (error) {}
|
|
31
38
|
location.replace('/login');
|
|
32
39
|
</script></body></html>`
|
|
40
|
+
}
|
|
33
41
|
const PORT_CANDIDATES = [4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326]
|
|
34
42
|
const MAX_UPSTREAM_BYTES = 8 * 1024 * 1024
|
|
35
43
|
const MAX_CONFIG_BODY_BYTES = 64 * 1024
|
|
@@ -248,13 +256,15 @@ function createProxyHandler(jar, port, target) {
|
|
|
248
256
|
|
|
249
257
|
// A stale browser token must not outlive the server-side session: clear the
|
|
250
258
|
// proxy origin's storage, then let the ERP show its own login page.
|
|
251
|
-
|
|
259
|
+
const requestUrl = new URL(req.url || '/', 'http://127.0.0.1')
|
|
260
|
+
if (requestUrl.pathname === RESET_PATH) {
|
|
261
|
+
const html = resetHtml(requestUrl.searchParams.get('ponlay_lang') === 'en' ? 'en' : 'zh')
|
|
252
262
|
res.writeHead(200, {
|
|
253
263
|
'content-type': 'text/html; charset=utf-8',
|
|
254
264
|
'cache-control': 'no-store',
|
|
255
|
-
'content-length': Buffer.byteLength(
|
|
265
|
+
'content-length': Buffer.byteLength(html),
|
|
256
266
|
})
|
|
257
|
-
res.end(req.method === 'HEAD' ? undefined :
|
|
267
|
+
res.end(req.method === 'HEAD' ? undefined : html)
|
|
258
268
|
return
|
|
259
269
|
}
|
|
260
270
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ponlay-erp",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Ponlay ERP system embedded in DeepSeek Harness: the ERP login page or signed-in layout fills the main area, with a configurable system address.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|