dsh-plugin-pack 1.0.6 → 1.0.8
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 +253 -72
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -113,11 +113,24 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
113
113
|
'import.checking': '正在检查冲突…',
|
|
114
114
|
'import.downloading': '正在从网络下载…',
|
|
115
115
|
'net.title': '从网络安装',
|
|
116
|
-
'net.desc': '
|
|
117
|
-
'net.placeholder': '
|
|
116
|
+
'net.desc': '输入插件整合包的来源:GitHub 仓库 / Release / 直链,或 npm 包名。下载后会校验它是不是整合包。',
|
|
117
|
+
'net.placeholder': '例如 dsh-plugin-pack 或 https://github.com/用户/仓库',
|
|
118
118
|
'net.go': '下载并安装',
|
|
119
119
|
'net.running': '正在处理…',
|
|
120
120
|
'net.notBundle': '下载到的不是整合包',
|
|
121
|
+
'net.button': '添加整合包',
|
|
122
|
+
'net.dialogTitle': '添加整合包',
|
|
123
|
+
'net.install': '下载并安装',
|
|
124
|
+
'net.close': '关闭',
|
|
125
|
+
'net.examples': '来源示例',
|
|
126
|
+
'net.ex1': '下载仓库归档',
|
|
127
|
+
'net.ex2': '取该 Release 里的 zip 附件',
|
|
128
|
+
'net.ex3': '任意直链',
|
|
129
|
+
'net.ex4': 'npm 包(单插件)',
|
|
130
|
+
'net.warnTitle': '安装前请确认来源可信',
|
|
131
|
+
'net.warnBody': '整合包会覆盖已装插件的文件与配置,来源不明的包可能损坏 DeepSeek Harness。安装前会先列出重名插件,由你逐个决定覆盖还是跳过。',
|
|
132
|
+
'net.done': '下载完成,已导入',
|
|
133
|
+
'import.pageTitle': '导入插件整合包',
|
|
121
134
|
'drop.title': '把 zip / tgz 或插件文件夹拖到这里',
|
|
122
135
|
'drop.release': '松手就导入',
|
|
123
136
|
'drop.running': '正在导入…',
|
|
@@ -282,11 +295,24 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
282
295
|
'import.checking': 'Checking for conflicts…',
|
|
283
296
|
'import.downloading': 'Downloading…',
|
|
284
297
|
'net.title': 'Install from network',
|
|
285
|
-
'net.desc': 'GitHub repo / release / direct link, or an npm package name. We verify it is a bundle after download.',
|
|
286
|
-
'net.placeholder': 'https://github.com/user/repo
|
|
298
|
+
'net.desc': 'Enter a bundle source: GitHub repo / release / direct link, or an npm package name. We verify it is a bundle after download.',
|
|
299
|
+
'net.placeholder': 'e.g. dsh-plugin-pack or https://github.com/user/repo',
|
|
287
300
|
'net.go': 'Download and install',
|
|
288
301
|
'net.running': 'Working…',
|
|
289
302
|
'net.notBundle': 'Downloaded file is not a bundle',
|
|
303
|
+
'net.button': 'Add bundle',
|
|
304
|
+
'net.dialogTitle': 'Add bundle',
|
|
305
|
+
'net.install': 'Download and install',
|
|
306
|
+
'net.close': 'Close',
|
|
307
|
+
'net.examples': 'Source examples',
|
|
308
|
+
'net.ex1': 'download repo archive',
|
|
309
|
+
'net.ex2': 'pick the zip asset of that release',
|
|
310
|
+
'net.ex3': 'any direct link',
|
|
311
|
+
'net.ex4': 'npm package (single plugin)',
|
|
312
|
+
'net.warnTitle': 'Verify the source before installing',
|
|
313
|
+
'net.warnBody': 'A bundle overwrites installed plugins and their config. Untrusted sources can damage DeepSeek Harness. You will be asked per-plugin whether to overwrite or skip.',
|
|
314
|
+
'net.done': 'Downloaded and imported',
|
|
315
|
+
'import.pageTitle': 'Import plugin bundle',
|
|
290
316
|
'drop.title': 'Drop a zip / tgz or plugin folder here',
|
|
291
317
|
'drop.release': 'Release to import',
|
|
292
318
|
'drop.running': 'Importing…',
|
|
@@ -1287,6 +1313,191 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
1287
1313
|
* @param {() => void} props.onCancel
|
|
1288
1314
|
* @param {(msg: string) => string} props.t
|
|
1289
1315
|
*/
|
|
1316
|
+
/**
|
|
1317
|
+
* 「添加整合包」弹窗。
|
|
1318
|
+
*
|
|
1319
|
+
* 布局对齐 DSH 自带的「添加插件」:
|
|
1320
|
+
* 标题 → 说明 → 输入框 → 折叠的示例 → 提示块 → 大按钮
|
|
1321
|
+
*
|
|
1322
|
+
* 下载后会校验是不是整合包;不是就当场用醒目样式报出来,
|
|
1323
|
+
* 不会让你以为"装上了"结果其实是普通压缩包。
|
|
1324
|
+
*
|
|
1325
|
+
* @param {object} props
|
|
1326
|
+
* @param {boolean} props.open
|
|
1327
|
+
* @param {string} props.value 输入框内容
|
|
1328
|
+
* @param {(v: string) => void} props.onChange
|
|
1329
|
+
* @param {object|null} props.result 上一次下载的结果或错误
|
|
1330
|
+
* @param {boolean} props.busy
|
|
1331
|
+
* @param {string} props.phase 进度文案
|
|
1332
|
+
* @param {() => void} props.onInstall
|
|
1333
|
+
* @param {() => void} props.onClose
|
|
1334
|
+
* @param {(key: string) => string} props.t
|
|
1335
|
+
*/
|
|
1336
|
+
function AddBundleDialog({ open, value, onChange, result, busy, phase, onInstall, onClose, t }) {
|
|
1337
|
+
const [showExamples, setShowExamples] = useState(false);
|
|
1338
|
+
|
|
1339
|
+
// Esc 关闭
|
|
1340
|
+
useEffect(() => {
|
|
1341
|
+
if (!open) return;
|
|
1342
|
+
const onKey = (event) => {
|
|
1343
|
+
if (event.key === 'Escape' && !busy) onClose();
|
|
1344
|
+
};
|
|
1345
|
+
window.addEventListener('keydown', onKey);
|
|
1346
|
+
return () => window.removeEventListener('keydown', onKey);
|
|
1347
|
+
}, [open, busy, onClose]);
|
|
1348
|
+
|
|
1349
|
+
if (!open) return null;
|
|
1350
|
+
|
|
1351
|
+
const isNotBundle =
|
|
1352
|
+
['NOT_A_BUNDLE', 'NOT_A_ZIP', 'BAD_FORMAT', 'BAD_MANIFEST', 'BAD_PACK'].includes(String(result?.code ?? '')) ||
|
|
1353
|
+
/不是整合包|没有 manifest|不是插件包/i.test(String(result?.error ?? ''));
|
|
1354
|
+
|
|
1355
|
+
return h(
|
|
1356
|
+
'div',
|
|
1357
|
+
{
|
|
1358
|
+
style: {
|
|
1359
|
+
position: 'fixed',
|
|
1360
|
+
inset: 0,
|
|
1361
|
+
zIndex: 10070,
|
|
1362
|
+
background: 'rgba(0,0,0,.45)',
|
|
1363
|
+
display: 'flex',
|
|
1364
|
+
alignItems: 'center',
|
|
1365
|
+
justifyContent: 'center',
|
|
1366
|
+
padding: 16,
|
|
1367
|
+
},
|
|
1368
|
+
// 点遮罩关闭(跑的时候不关,避免误触中断)
|
|
1369
|
+
onClick: () => !busy && onClose(),
|
|
1370
|
+
},
|
|
1371
|
+
h(
|
|
1372
|
+
'div',
|
|
1373
|
+
{
|
|
1374
|
+
style: {
|
|
1375
|
+
width: 'min(560px, 100%)',
|
|
1376
|
+
background: 'var(--dsw-alias-bg-layer-1,#fff)',
|
|
1377
|
+
borderRadius: 14,
|
|
1378
|
+
padding: '20px 20px 16px',
|
|
1379
|
+
boxShadow: '0 12px 40px rgba(0,0,0,.22)',
|
|
1380
|
+
border: '.5px solid var(--dsw-alias-border-l1,#e6e6e6)',
|
|
1381
|
+
},
|
|
1382
|
+
onClick: (event) => event.stopPropagation(),
|
|
1383
|
+
},
|
|
1384
|
+
// 标题行 + 关闭
|
|
1385
|
+
h(
|
|
1386
|
+
'div',
|
|
1387
|
+
{ style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 } },
|
|
1388
|
+
h('h2', { style: { margin: 0, fontSize: 17, fontWeight: 600, flex: 1 } }, t('net.dialogTitle')),
|
|
1389
|
+
h(
|
|
1390
|
+
'button',
|
|
1391
|
+
{
|
|
1392
|
+
className: 'pp-btn sm',
|
|
1393
|
+
style: { flex: 'none', padding: '2px 8px' },
|
|
1394
|
+
disabled: busy,
|
|
1395
|
+
onClick: onClose,
|
|
1396
|
+
title: t('net.close'),
|
|
1397
|
+
},
|
|
1398
|
+
'✕',
|
|
1399
|
+
),
|
|
1400
|
+
),
|
|
1401
|
+
h('p', { className: 'pp-hint', style: { margin: '0 0 12px' } }, t('net.desc')),
|
|
1402
|
+
|
|
1403
|
+
// 输入框(自动聚焦,回车即安装)
|
|
1404
|
+
h('input', {
|
|
1405
|
+
className: 'pp-input pp-mono',
|
|
1406
|
+
type: 'text',
|
|
1407
|
+
autoFocus: true,
|
|
1408
|
+
value,
|
|
1409
|
+
placeholder: t('net.placeholder'),
|
|
1410
|
+
disabled: busy,
|
|
1411
|
+
onInput: (event) => onChange(event.target.value),
|
|
1412
|
+
onKeyDown: (event) => {
|
|
1413
|
+
if (event.key === 'Enter' && !busy && value.trim()) onInstall();
|
|
1414
|
+
},
|
|
1415
|
+
style: { width: '100%', boxSizing: 'border-box', fontSize: 12.5, padding: '9px 11px' },
|
|
1416
|
+
}),
|
|
1417
|
+
|
|
1418
|
+
// 折叠的示例(对齐自带弹窗的「安装引导和示例」)
|
|
1419
|
+
h(
|
|
1420
|
+
'div',
|
|
1421
|
+
{ style: { margin: '10px 0 0' } },
|
|
1422
|
+
h(
|
|
1423
|
+
'button',
|
|
1424
|
+
{
|
|
1425
|
+
className: 'pp-btn sm',
|
|
1426
|
+
style: { padding: '2px 0', background: 'none', border: 'none', color: 'var(--dsw-alias-label-secondary,#6b7280)' },
|
|
1427
|
+
onClick: () => setShowExamples((v) => !v),
|
|
1428
|
+
},
|
|
1429
|
+
`${showExamples ? '▾' : '▸'} ${t('net.examples')}`,
|
|
1430
|
+
),
|
|
1431
|
+
showExamples
|
|
1432
|
+
? h(
|
|
1433
|
+
'div',
|
|
1434
|
+
{ className: 'pp-hint', style: { marginTop: 6, lineHeight: 1.9 } },
|
|
1435
|
+
h('div', null, h('code', null, 'https://github.com/用户/仓库'), ` ${t('net.ex1')}`),
|
|
1436
|
+
h('div', null, h('code', null, 'https://github.com/用户/仓库/releases/tag/v1.0.0'), ` ${t('net.ex2')}`),
|
|
1437
|
+
h('div', null, h('code', null, 'https://example.com/backup.zip'), ` ${t('net.ex3')}`),
|
|
1438
|
+
h('div', null, h('code', null, 'dsh-plugin-pack'), ` ${t('net.ex4')}`),
|
|
1439
|
+
)
|
|
1440
|
+
: null,
|
|
1441
|
+
),
|
|
1442
|
+
|
|
1443
|
+
// 提示块(对齐自带的黄色提示)
|
|
1444
|
+
h(
|
|
1445
|
+
'div',
|
|
1446
|
+
{
|
|
1447
|
+
style: {
|
|
1448
|
+
marginTop: 12,
|
|
1449
|
+
padding: '10px 12px',
|
|
1450
|
+
borderRadius: 10,
|
|
1451
|
+
background: 'color-mix(in srgb,var(--dsw-alias-state-warning-primary,#d97706) 8%,transparent)',
|
|
1452
|
+
border: '.5px solid color-mix(in srgb,var(--dsw-alias-state-warning-primary,#d97706) 35%,transparent)',
|
|
1453
|
+
fontSize: 12,
|
|
1454
|
+
lineHeight: 1.7,
|
|
1455
|
+
color: 'var(--dsw-alias-label-secondary,#6b7280)',
|
|
1456
|
+
},
|
|
1457
|
+
},
|
|
1458
|
+
h('div', { style: { fontWeight: 600, marginBottom: 2 } }, `⚠ ${t('net.warnTitle')}`),
|
|
1459
|
+
h('div', null, t('net.warnBody')),
|
|
1460
|
+
),
|
|
1461
|
+
|
|
1462
|
+
// 结果区:成功 / 不是整合包 / 其它错误
|
|
1463
|
+
result
|
|
1464
|
+
? h(
|
|
1465
|
+
'div',
|
|
1466
|
+
{ style: { marginTop: 12 } },
|
|
1467
|
+
result.error
|
|
1468
|
+
? isNotBundle
|
|
1469
|
+
? h(
|
|
1470
|
+
'div',
|
|
1471
|
+
{ className: 'pp-not-bundle' },
|
|
1472
|
+
h('div', { className: 'pp-not-bundle-title' }, t('net.notBundle')),
|
|
1473
|
+
h('div', { className: 'pp-not-bundle-detail' }, String(result.error)),
|
|
1474
|
+
)
|
|
1475
|
+
: h(Alert, { kind: 'err' }, String(result.error))
|
|
1476
|
+
: h(
|
|
1477
|
+
'div',
|
|
1478
|
+
{ className: 'pp-hint' },
|
|
1479
|
+
`✓ ${t('net.done')} · ${result.from ?? ''} · ${result.name ?? ''} · ${
|
|
1480
|
+
result.bytes ? (result.bytes / 1048576).toFixed(1) + ' MiB' : ''
|
|
1481
|
+
} · ${result.plugins?.length ?? 0} ${t('plugins')}`,
|
|
1482
|
+
),
|
|
1483
|
+
)
|
|
1484
|
+
: null,
|
|
1485
|
+
|
|
1486
|
+
// 大按钮(对齐自带的整宽「安装」)
|
|
1487
|
+
h(
|
|
1488
|
+
'button',
|
|
1489
|
+
{
|
|
1490
|
+
className: 'pp-btn primary',
|
|
1491
|
+
style: { width: '100%', marginTop: 14, padding: '10px 12px', boxSizing: 'border-box' },
|
|
1492
|
+
disabled: busy || !value.trim(),
|
|
1493
|
+
onClick: onInstall,
|
|
1494
|
+
},
|
|
1495
|
+
busy ? h(Spinner, { label: phase || t('net.running') }) : t('net.install'),
|
|
1496
|
+
),
|
|
1497
|
+
),
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1290
1501
|
function ConflictDialog({ pending, onConfirm, onCancel, t }) {
|
|
1291
1502
|
const conflicts = pending?.conflicts ?? [];
|
|
1292
1503
|
/** 初始全部选「覆盖」——多数人是想升级到新版本。 */
|
|
@@ -1611,6 +1822,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
1611
1822
|
const [netSource, setNetSource] = useState('');
|
|
1612
1823
|
/** 网络安装的结果/错误。 */
|
|
1613
1824
|
const [netResult, setNetResult] = useState(null);
|
|
1825
|
+
/** 「添加整合包」弹窗是否打开。 */
|
|
1826
|
+
const [netOpen, setNetOpen] = useState(false);
|
|
1614
1827
|
/** 后台任务列表:切走画面回来靠它恢复 */
|
|
1615
1828
|
const [jobs, setJobs] = useState([]);
|
|
1616
1829
|
/** 体积上限(MiB),0 = 不限制。默认跟着服务端配置走。 */
|
|
@@ -1941,6 +2154,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
1941
2154
|
setImportResult(result);
|
|
1942
2155
|
await load();
|
|
1943
2156
|
await refreshJobs();
|
|
2157
|
+
// 装完关掉弹窗,回到列表看结果
|
|
2158
|
+
setNetOpen(false);
|
|
1944
2159
|
return;
|
|
1945
2160
|
}
|
|
1946
2161
|
|
|
@@ -1956,15 +2171,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
1956
2171
|
conflicts,
|
|
1957
2172
|
plugins: preview.plugins ?? [],
|
|
1958
2173
|
});
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
downloaded: true,
|
|
1962
|
-
file: fetched.file,
|
|
1963
|
-
from: fetched.from,
|
|
1964
|
-
name: fetched.name,
|
|
1965
|
-
bytes: fetched.bytes,
|
|
1966
|
-
plugins: fetched.plugins,
|
|
1967
|
-
});
|
|
2174
|
+
// 交给冲突弹窗接管,先关掉来源弹窗
|
|
2175
|
+
setNetOpen(false);
|
|
1968
2176
|
return;
|
|
1969
2177
|
}
|
|
1970
2178
|
|
|
@@ -2117,6 +2325,25 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
2117
2325
|
hotBusy ? h(Spinner, { label: t('hotload.running') }) : t('hotload'),
|
|
2118
2326
|
),
|
|
2119
2327
|
h('button', { className: 'pp-btn sm', disabled: busy, onClick: load }, busy ? h(Spinner, { label: t('loading') }) : t('refresh')),
|
|
2328
|
+
/* 「添加整合包」放在这一行最右,对齐 DSH 自带的「添加插件」位置
|
|
2329
|
+
* (页面标题行右上角),而不是沉到「导入插件整合包」小标题旁边。
|
|
2330
|
+
* 只在导入页出现,其它子页不占位。 */
|
|
2331
|
+
onlyTab === 'import' || tab === 'import'
|
|
2332
|
+
? h(
|
|
2333
|
+
'button',
|
|
2334
|
+
{
|
|
2335
|
+
className: 'pp-btn sm',
|
|
2336
|
+
style: { display: 'inline-flex', alignItems: 'center', gap: 5 },
|
|
2337
|
+
disabled: busy,
|
|
2338
|
+
onClick: () => {
|
|
2339
|
+
setNetResult(null);
|
|
2340
|
+
setNetOpen(true);
|
|
2341
|
+
},
|
|
2342
|
+
},
|
|
2343
|
+
h('span', { style: { fontSize: 14, lineHeight: 1 } }, '+'),
|
|
2344
|
+
t('net.button'),
|
|
2345
|
+
)
|
|
2346
|
+
: null,
|
|
2120
2347
|
),
|
|
2121
2348
|
error ? h(Alert, { kind: 'err' }, `${t('failed')}: ${error}`) : null,
|
|
2122
2349
|
hotResult
|
|
@@ -2344,65 +2571,6 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
2344
2571
|
null,
|
|
2345
2572
|
h(DropZone, { onFile: runDrop, busy, dropRef: lastDrop, phase }),
|
|
2346
2573
|
|
|
2347
|
-
/* 从网络安装:GitHub / npm / 直链。
|
|
2348
|
-
* 下载后服务端会校验它真的是整合包(inspectBundle),
|
|
2349
|
-
* 不是就明确报「下载到的不是整合包」,不会硬导进去。 */
|
|
2350
|
-
h(
|
|
2351
|
-
'div',
|
|
2352
|
-
{ className: 'pp-card', style: { marginTop: 14 } },
|
|
2353
|
-
h('h3', { style: { margin: '0 0 4px', fontSize: 14, fontWeight: 600 } }, t('net.title')),
|
|
2354
|
-
h('p', { className: 'pp-hint', style: { margin: '0 0 10px' } }, t('net.desc')),
|
|
2355
|
-
h(
|
|
2356
|
-
'div',
|
|
2357
|
-
{ style: { display: 'flex', gap: 8, alignItems: 'flex-start', flexWrap: 'wrap' } },
|
|
2358
|
-
h('input', {
|
|
2359
|
-
className: 'pp-input pp-mono',
|
|
2360
|
-
type: 'text',
|
|
2361
|
-
value: netSource,
|
|
2362
|
-
placeholder: t('net.placeholder'),
|
|
2363
|
-
disabled: busy,
|
|
2364
|
-
onInput: (event) => setNetSource(event.target.value),
|
|
2365
|
-
onKeyDown: (event) => {
|
|
2366
|
-
if (event.key === 'Enter' && !busy) runNetworkInstall();
|
|
2367
|
-
},
|
|
2368
|
-
style: { flex: '1 1 260px', minWidth: 0, fontSize: 12 },
|
|
2369
|
-
}),
|
|
2370
|
-
h(
|
|
2371
|
-
'button',
|
|
2372
|
-
{
|
|
2373
|
-
className: 'pp-btn',
|
|
2374
|
-
disabled: busy || !netSource.trim(),
|
|
2375
|
-
onClick: runNetworkInstall,
|
|
2376
|
-
},
|
|
2377
|
-
busy ? t('net.running') : t('net.go'),
|
|
2378
|
-
),
|
|
2379
|
-
),
|
|
2380
|
-
// 结果:下载成功 / 不是整合包 / 其它错误
|
|
2381
|
-
netResult?.error
|
|
2382
|
-
? h(
|
|
2383
|
-
'div',
|
|
2384
|
-
{ style: { marginTop: 10 } },
|
|
2385
|
-
['NOT_A_BUNDLE', 'NOT_A_ZIP', 'BAD_FORMAT', 'BAD_MANIFEST', 'BAD_PACK'].includes(String(netResult.code ?? '')) ||
|
|
2386
|
-
/不是整合包|没有 manifest/i.test(String(netResult.error))
|
|
2387
|
-
? h(
|
|
2388
|
-
'div',
|
|
2389
|
-
{ className: 'pp-not-bundle' },
|
|
2390
|
-
h('div', { className: 'pp-not-bundle-title' }, t('net.notBundle')),
|
|
2391
|
-
h('div', { className: 'pp-not-bundle-detail' }, String(netResult.error)),
|
|
2392
|
-
)
|
|
2393
|
-
: h(Alert, { kind: 'err' }, netResult.error),
|
|
2394
|
-
)
|
|
2395
|
-
: netResult?.ok
|
|
2396
|
-
? h(
|
|
2397
|
-
'div',
|
|
2398
|
-
{ className: 'pp-hint', style: { marginTop: 8 } },
|
|
2399
|
-
`✓ ${netResult.from} · ${netResult.name ?? ''} · ${
|
|
2400
|
-
netResult.bytes ? (netResult.bytes / 1048576).toFixed(1) + ' MiB' : ''
|
|
2401
|
-
} · ${netResult.plugins?.length ?? 0} ${t('plugins')}`,
|
|
2402
|
-
)
|
|
2403
|
-
: null,
|
|
2404
|
-
),
|
|
2405
|
-
|
|
2406
2574
|
// 后台任务:切走画面回来能看到刚才那次导入的结果
|
|
2407
2575
|
h(JobList, { jobs, onClear: clearJobHistory, t }),
|
|
2408
2576
|
|
|
@@ -2693,6 +2861,19 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
|
|
|
2693
2861
|
setOut(looksLikeFile || picked.endsWith('\\') || picked.endsWith('/') ? picked : `${picked}\\`);
|
|
2694
2862
|
},
|
|
2695
2863
|
}),
|
|
2864
|
+
/* 「添加整合包」弹窗:带来源输入 + 校验提示 + 整宽安装按钮,
|
|
2865
|
+
* 布局对齐 DSH 自带的「添加插件」弹窗。 */
|
|
2866
|
+
h(AddBundleDialog, {
|
|
2867
|
+
open: netOpen,
|
|
2868
|
+
value: netSource,
|
|
2869
|
+
onChange: setNetSource,
|
|
2870
|
+
result: netResult,
|
|
2871
|
+
busy,
|
|
2872
|
+
phase,
|
|
2873
|
+
onInstall: runNetworkInstall,
|
|
2874
|
+
onClose: () => setNetOpen(false),
|
|
2875
|
+
t,
|
|
2876
|
+
}),
|
|
2696
2877
|
// 重名冲突弹窗:叠在最上层
|
|
2697
2878
|
h(ConflictDialog, {
|
|
2698
2879
|
pending: pendingImport,
|