@ninkch/dsh-infinite-canvas 0.17.7 → 0.17.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 +76 -40
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -356,6 +356,12 @@ window.__ModuleLoader__.load({
|
|
|
356
356
|
'dataRootOpen': '打开目录',
|
|
357
357
|
'dataRootMigrate': '迁移历史资产',
|
|
358
358
|
'dataRootMigrated': '已迁移 {n} 个资产到数据根目录',
|
|
359
|
+
'collapse': '折叠',
|
|
360
|
+
'foldOpen': '展开',
|
|
361
|
+
'craftReadyCount': '{r}/{n} 就绪',
|
|
362
|
+
'craftDirLabel': '当前项目后期目录',
|
|
363
|
+
'craftDataRootNeed': '请先在上方设置画布数据根目录:Craft 后期文件将存放于 数据根目录\\projects\\<项目>\\craft',
|
|
364
|
+
'craftRootMismatch': 'ArtCraft 自身数据目录与画布数据根目录不一致:请在 ArtCraft 设置里把数据目录改成同一根目录,否则后期文件会落到两处',
|
|
359
365
|
'dataRootImportBtn': '从数据目录导入',
|
|
360
366
|
'dataRootImported': '导入完成:合并 {n} 个项目、补入 {a} 条资产元数据',
|
|
361
367
|
'dataRootImportHint': '换电脑迁移:把整个数据目录拷到新机器 → 设置为数据根目录 → 点"从数据目录导入"即可恢复项目/节点/设定集/资产',
|
|
@@ -687,6 +693,12 @@ window.__ModuleLoader__.load({
|
|
|
687
693
|
'dataRootOpen': 'Open folder',
|
|
688
694
|
'dataRootMigrate': 'Migrate existing assets',
|
|
689
695
|
'dataRootMigrated': 'Migrated {n} assets to the data root',
|
|
696
|
+
'collapse': 'Collapse',
|
|
697
|
+
'foldOpen': 'Expand',
|
|
698
|
+
'craftReadyCount': '{r}/{n} ready',
|
|
699
|
+
'craftDirLabel': 'Project craft dir',
|
|
700
|
+
'craftDataRootNeed': 'Set the canvas data root above first: craft files go to <root>\\projects\\<project>\\craft',
|
|
701
|
+
'craftRootMismatch': "ArtCraft's own data root differs from the canvas data root — point ArtCraft at the same root or craft files will land in two places",
|
|
690
702
|
'dataRootImportBtn': 'Import from data root',
|
|
691
703
|
'dataRootImported': 'Imported: {n} projects merged, {a} asset records added',
|
|
692
704
|
'dataRootImportHint': 'Migration: copy the whole data folder to the new machine, set it as data root, then click "Import from data root" to restore projects/nodes/bible/assets',
|
|
@@ -1092,8 +1104,8 @@ window.__ModuleLoader__.load({
|
|
|
1092
1104
|
try { localStorage.setItem(key, JSON.stringify(value)); } catch { /* 忽略配额错误 */ }
|
|
1093
1105
|
}
|
|
1094
1106
|
const DEFAULT_SETTINGS = {
|
|
1095
|
-
//
|
|
1096
|
-
textLlm: { provider: '', model: ''
|
|
1107
|
+
// 文本模型全部用 Harness 的当前模型与默认参数:画布只选择模型,不单独配置生成参数
|
|
1108
|
+
textLlm: { provider: '', model: '' },
|
|
1097
1109
|
imageApis: [], // [{id, name, baseUrl, apiKey, model, mode, size?, responseFormat?}]
|
|
1098
1110
|
videoApis: [], // [{id, name, url, apiKey, model, protocol?, watermark?, generateAudio?}]
|
|
1099
1111
|
ttsApis: [], // [{id, name, baseUrl, apiKey, model, voice}]
|
|
@@ -1107,7 +1119,7 @@ window.__ModuleLoader__.load({
|
|
|
1107
1119
|
function loadSettings() {
|
|
1108
1120
|
const s = lsGet(LS_SETTINGS, {}) || {};
|
|
1109
1121
|
const out = {
|
|
1110
|
-
textLlm: {
|
|
1122
|
+
textLlm: { provider: (s.textLlm && s.textLlm.provider) || '', model: (s.textLlm && s.textLlm.model) || '' },
|
|
1111
1123
|
imageApis: Array.isArray(s.imageApis) ? s.imageApis : [],
|
|
1112
1124
|
videoApis: Array.isArray(s.videoApis) ? s.videoApis : [],
|
|
1113
1125
|
ttsApis: Array.isArray(s.ttsApis) ? s.ttsApis : [],
|
|
@@ -2302,7 +2314,9 @@ window.__ModuleLoader__.load({
|
|
|
2302
2314
|
const pid = S.activeId;
|
|
2303
2315
|
const map = craftMapLoad(pid);
|
|
2304
2316
|
if (!opts.force && map[rec.id]) return map[rec.id];
|
|
2305
|
-
|
|
2317
|
+
// Craft 后期数据统一放在**画布数据根目录**的项目目录下:projects/<项目>/<slug 前缀去掉>/craft/…
|
|
2318
|
+
// (ArtCraft 数据根目录 = 画布数据根目录时,即落在 <root>/projects/<项目>/craft/media/)
|
|
2319
|
+
const rel = 'projects/' + craftProjectSlug() + '/craft/media/' + assetFileBase(rec) + extForMime(rec.mime, rec.name);
|
|
2306
2320
|
const blob = rec.blob || await assetBlob(rec.id);
|
|
2307
2321
|
if (!blob) throw new Error('资产内容不可用: ' + rec.id);
|
|
2308
2322
|
await craft.write(rel, blob);
|
|
@@ -5331,12 +5345,12 @@ window.__ModuleLoader__.load({
|
|
|
5331
5345
|
width: dims.w, height: dims.h,
|
|
5332
5346
|
});
|
|
5333
5347
|
try {
|
|
5334
|
-
await craft.writeText(slug + '/craft/timeline.xml', xml);
|
|
5335
|
-
await craft.writeText(slug + '/craft/subs.srt', buildSrt(items));
|
|
5348
|
+
await craft.writeText('projects/' + slug + '/craft/timeline.xml', xml);
|
|
5349
|
+
await craft.writeText('projects/' + slug + '/craft/subs.srt', buildSrt(items));
|
|
5336
5350
|
} catch (e) { return; /* craftFetch 已提示 */ }
|
|
5337
5351
|
setFcDialog({
|
|
5338
|
-
args: JSON.stringify(['--project', slug + '/craft/drama.fcproj', '--import', slug + '/craft/timeline.xml', '--export', slug + '/out/final.mp4'], null, 1),
|
|
5339
|
-
outRel: slug + '/out/final.mp4',
|
|
5352
|
+
args: JSON.stringify(['--project', 'projects/' + slug + '/craft/drama.fcproj', '--import', 'projects/' + slug + '/craft/timeline.xml', '--export', 'projects/' + slug + '/craft/out/final.mp4'], null, 1),
|
|
5353
|
+
outRel: 'projects/' + slug + '/craft/out/final.mp4',
|
|
5340
5354
|
});
|
|
5341
5355
|
};
|
|
5342
5356
|
const submitFc = (args, outRel) => {
|
|
@@ -6131,13 +6145,12 @@ window.__ModuleLoader__.load({
|
|
|
6131
6145
|
// 默认项 = 内置专家 persona + 内置创作方法论 canvas-craft(自动叠加)
|
|
6132
6146
|
const options = [{ value: '', label: T('builtinExpert') }].concat((data.skills || []).map((x) => ({ value: x.name, label: x.name })));
|
|
6133
6147
|
return h('div', { className: 'dshic-field' },
|
|
6134
|
-
h('span', { className: 'dshic-field-label' }, label),
|
|
6148
|
+
h('span', { className: 'dshic-field-label' }, label, InfoTip(T('skillHint'))),
|
|
6135
6149
|
h('select', {
|
|
6136
6150
|
className: 'dshic-select', value: value || '',
|
|
6137
6151
|
onChange: (e) => onChange(e.target.value),
|
|
6138
6152
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6139
|
-
}, options.map((o) => h('option', { key: o.value, value: o.value }, o.label)))
|
|
6140
|
-
h('div', { className: 'dshic-hint' }, T('skillHint')));
|
|
6153
|
+
}, options.map((o) => h('option', { key: o.value, value: o.value }, o.label))));
|
|
6141
6154
|
}
|
|
6142
6155
|
|
|
6143
6156
|
function LlmModelSelect() {
|
|
@@ -6188,7 +6201,6 @@ window.__ModuleLoader__.load({
|
|
|
6188
6201
|
},
|
|
6189
6202
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6190
6203
|
}),
|
|
6191
|
-
h('div', { className: 'dshic-hint' }, T('llmHint')),
|
|
6192
6204
|
);
|
|
6193
6205
|
}
|
|
6194
6206
|
|
|
@@ -6202,6 +6214,13 @@ window.__ModuleLoader__.load({
|
|
|
6202
6214
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6203
6215
|
}));
|
|
6204
6216
|
}
|
|
6217
|
+
/** ⓘ 悬停说明:界面简洁化——长解释一律收进悬停提示(原生 title),不再平铺文字。 */
|
|
6218
|
+
function InfoTip(text) {
|
|
6219
|
+
return h('span', {
|
|
6220
|
+
title: String(text || ''), 'aria-label': String(text || ''),
|
|
6221
|
+
style: { flex: 'none', width: 14, height: 14, lineHeight: '13px', textAlign: 'center', fontSize: 10, borderRadius: '50%', border: '1px solid var(--dsw-alias-border-secondary, #777)', color: 'var(--dsw-alias-label-secondary, #999)', cursor: 'help', userSelect: 'none', opacity: 0.85 },
|
|
6222
|
+
}, 'i');
|
|
6223
|
+
}
|
|
6205
6224
|
function ApiListEditor({ kind }) {
|
|
6206
6225
|
const [s, setS] = useState(loadSettings);
|
|
6207
6226
|
const [openId, setOpenId] = useState(null);
|
|
@@ -6351,10 +6370,19 @@ window.__ModuleLoader__.load({
|
|
|
6351
6370
|
/** T2:设置面板 Craft 后期卡片(连接状态 / 工具灯 / 数据目录)。 */
|
|
6352
6371
|
function CraftCard() {
|
|
6353
6372
|
const [, force] = useState(0);
|
|
6373
|
+
const [open, setOpen] = useState(false); // 默认折叠:界面简洁,摘要常显
|
|
6354
6374
|
useEffect(() => { probeCraft().then(() => force((x) => x + 1)); }, []);
|
|
6355
6375
|
const cs = S.craftStatus;
|
|
6356
6376
|
const data = cs && cs.data;
|
|
6357
6377
|
const slug = craftProjectSlug();
|
|
6378
|
+
// Craft 后期目录 = **画布数据根目录** + 项目目录 + \craft(不再有 ArtCraft 独立数据目录的 second 口径)
|
|
6379
|
+
const craftDir = S.dataRoot ? (S.dataRoot.replace(/[\\/]+$/, '') + '\\projects\\' + slug + '\\craft') : '';
|
|
6380
|
+
// ArtCraft 自身的数据目录若与画布数据根目录不一致 → 后期文件会落到两处,必须提醒
|
|
6381
|
+
const artRoot = data && data.dataRoot ? data.dataRoot.path : '';
|
|
6382
|
+
const rootMismatch = !!(S.dataRoot && artRoot && artRoot.replace(/[\\/]+$/, '') !== S.dataRoot.replace(/[\\/]+$/, ''));
|
|
6383
|
+
// Craft 家族全量动态渲染:ArtCraft /status 返回几款 bins 就渲染几款(当前 12 款),不再写死
|
|
6384
|
+
const binKeys = (data && data.bins ? Object.keys(data.bins) : []).sort();
|
|
6385
|
+
const readyCount = binKeys.filter((k) => data.bins[k] && data.bins[k].found).length;
|
|
6358
6386
|
const binRow = (key) => {
|
|
6359
6387
|
const info = data && data.bins ? data.bins[key] : null;
|
|
6360
6388
|
const ok = !!(info && info.found);
|
|
@@ -6366,18 +6394,22 @@ window.__ModuleLoader__.load({
|
|
|
6366
6394
|
);
|
|
6367
6395
|
};
|
|
6368
6396
|
return h('div', { className: 'dshic-card' },
|
|
6369
|
-
h('div', {
|
|
6397
|
+
h('div', {
|
|
6398
|
+
className: 'dshic-row', style: { cursor: 'pointer' },
|
|
6399
|
+
onPointerDown: (e) => e.stopPropagation(), onClick: () => setOpen((x) => !x),
|
|
6400
|
+
title: open ? T('collapse') : T('foldOpen'),
|
|
6401
|
+
},
|
|
6370
6402
|
Ic('film', 12),
|
|
6371
6403
|
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('craftCard')),
|
|
6372
|
-
h('
|
|
6404
|
+
data ? h('span', { className: 'dshic-hint', style: { flex: 'none' } }, T('craftReadyCount').replace('{r}', String(readyCount)).replace('{n}', String(binKeys.length))) : null,
|
|
6405
|
+
h('button', { type: 'button', className: 'dshic-mini is-ghost', onPointerDown: (e) => e.stopPropagation(), onClick: (e) => { e.stopPropagation(); probeCraft().then(() => force((x) => x + 1)); } }, '↻'),
|
|
6406
|
+
h('span', { style: { flex: 'none', fontSize: 10, transition: 'transform .15s', transform: open ? 'rotate(90deg)' : 'rotate(0deg)' } }, '▶'),
|
|
6373
6407
|
),
|
|
6374
|
-
|
|
6375
|
-
? h('div', { className: 'dshic-hint' }, T('
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
data ? binRow('effectcraft') : null,
|
|
6380
|
-
data ? h('div', { className: 'dshic-hint' }, T('craftProjectDir') + ':' + slug + '/') : null,
|
|
6408
|
+
open ? [
|
|
6409
|
+
craftDir ? h('div', { className: 'dshic-hint' }, T('craftDirLabel') + ':' + craftDir) : h('div', { className: 'dshic-err' }, T('craftDataRootNeed')),
|
|
6410
|
+
rootMismatch ? h('div', { className: 'dshic-err' }, T('craftRootMismatch')) : null,
|
|
6411
|
+
...(data ? binKeys.map((k) => binRow(k)) : []),
|
|
6412
|
+
] : null,
|
|
6381
6413
|
);
|
|
6382
6414
|
}
|
|
6383
6415
|
|
|
@@ -6406,7 +6438,7 @@ window.__ModuleLoader__.load({
|
|
|
6406
6438
|
setRunning(true); setErr(null); setProgress('…');
|
|
6407
6439
|
try {
|
|
6408
6440
|
const mediaRel = await ensureAssetOnDisk(rec);
|
|
6409
|
-
const outRel = craftProjectSlug() + '/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
|
|
6441
|
+
const outRel = 'projects/' + craftProjectSlug() + '/craft/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
|
|
6410
6442
|
const job = await craft.jobStart({
|
|
6411
6443
|
bin: 'photocraft',
|
|
6412
6444
|
args: ['run', mediaRel, '--cmd', cmd, '--params', JSON.stringify(paramsObj), '--out', outRel],
|
|
@@ -6587,7 +6619,11 @@ window.__ModuleLoader__.load({
|
|
|
6587
6619
|
setBusy(false);
|
|
6588
6620
|
};
|
|
6589
6621
|
return h('div', { key: 'dataroot', className: 'dshic-card' },
|
|
6590
|
-
h('div', { className: 'dshic-row' },
|
|
6622
|
+
h('div', { className: 'dshic-row' },
|
|
6623
|
+
Ic('image', 12),
|
|
6624
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('dataRootLabel')),
|
|
6625
|
+
InfoTip(T('dataRootHint')),
|
|
6626
|
+
),
|
|
6591
6627
|
S.dataRootSupported === false
|
|
6592
6628
|
? h('div', { className: 'dshic-hint' }, T('dataRootUnsupported'))
|
|
6593
6629
|
: [
|
|
@@ -6600,7 +6636,6 @@ window.__ModuleLoader__.load({
|
|
|
6600
6636
|
h('button', { type: 'button', className: 'dshic-mini', disabled: busy || picking, onPointerDown: (e) => e.stopPropagation(), onClick: save }, T('dataRootSave')),
|
|
6601
6637
|
),
|
|
6602
6638
|
picking ? h('div', { className: 'dshic-hint', key: 'picking' }, T('dataRootPicking')) : null,
|
|
6603
|
-
h('div', { className: 'dshic-hint', key: 'hint' }, T('dataRootHint')),
|
|
6604
6639
|
h('div', { className: 'dshic-row', key: 'row2' },
|
|
6605
6640
|
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini', onPointerDown: (e) => e.stopPropagation(), onClick: openDir }, T('dataRootOpen')) : null,
|
|
6606
6641
|
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini', disabled: busy || picking || !!mig, onPointerDown: (e) => e.stopPropagation(), onClick: migrate }, mig === 'done' ? T('dataRootMigratedDone') : T('dataRootMigrate')) : null,
|
|
@@ -6608,9 +6643,9 @@ window.__ModuleLoader__.load({
|
|
|
6608
6643
|
),
|
|
6609
6644
|
h('div', { className: 'dshic-row', key: 'row3' },
|
|
6610
6645
|
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini is-ghost', disabled: busy || picking, onPointerDown: (e) => e.stopPropagation(), onClick: importFromRoot }, Ic('folder', 11), T('dataRootImportBtn')) : null,
|
|
6646
|
+
S.dataRoot ? InfoTip(T('dataRootImportHint')) : null,
|
|
6611
6647
|
h('div', { className: 'dshic-flex' }),
|
|
6612
6648
|
),
|
|
6613
|
-
S.dataRoot ? h('div', { className: 'dshic-hint', key: 'importHint' }, T('dataRootImportHint')) : null,
|
|
6614
6649
|
],
|
|
6615
6650
|
);
|
|
6616
6651
|
}
|
|
@@ -6626,8 +6661,6 @@ window.__ModuleLoader__.load({
|
|
|
6626
6661
|
};
|
|
6627
6662
|
const field = (label, value, onChange, placeholder, password) => h(Field, { label, value, onChange, placeholder, password });
|
|
6628
6663
|
return [
|
|
6629
|
-
h(CraftCard, { key: 'craft' }),
|
|
6630
|
-
h(DataRootCard, { key: 'dataroot' }),
|
|
6631
6664
|
h('div', { key: 'lang', className: 'dshic-card' },
|
|
6632
6665
|
h('div', { className: 'dshic-row' }, Ic('text', 12), h('strong', { style: { fontSize: 12 } }, T('langLabel'))),
|
|
6633
6666
|
h('select', {
|
|
@@ -6643,24 +6676,27 @@ window.__ModuleLoader__.load({
|
|
|
6643
6676
|
h('option', { value: 'zh' }, T('langZh')),
|
|
6644
6677
|
h('option', { value: 'en' }, T('langEn'))),
|
|
6645
6678
|
),
|
|
6646
|
-
h(
|
|
6647
|
-
|
|
6648
|
-
|
|
6679
|
+
h(DataRootCard, { key: 'dataroot' }),
|
|
6680
|
+
h(CraftCard, { key: 'craft' }),
|
|
6681
|
+
// 专家与技能卡:独立于模型选择
|
|
6682
|
+
h('div', { key: 'skills', className: 'dshic-card' },
|
|
6649
6683
|
h('div', { className: 'dshic-row' },
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
}),
|
|
6654
|
-
h(Field, {
|
|
6655
|
-
label: T('llmTemperature'), value: s.textLlm.temperature || '', placeholder: T('llmParamAuto'),
|
|
6656
|
-
onChange: (v) => apply((d) => { d.textLlm.temperature = v; }),
|
|
6657
|
-
}),
|
|
6684
|
+
Ic('spark', 12),
|
|
6685
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('skillEnhance')),
|
|
6686
|
+
InfoTip(T('skillHint')),
|
|
6658
6687
|
),
|
|
6659
|
-
h('div', { className: 'dshic-hint' }, T('llmParamHint')),
|
|
6660
|
-
h('div', { className: 'dshic-hint' }, T('skillEnhance')),
|
|
6661
6688
|
h(SkillSelect, { label: T('skillScript'), value: s.skillScript, onChange: (v) => apply((d) => { d.skillScript = v; }) }),
|
|
6662
6689
|
h(SkillSelect, { label: T('skillStoryboard'), value: s.skillStoryboard, onChange: (v) => apply((d) => { d.skillStoryboard = v; }) }),
|
|
6663
6690
|
),
|
|
6691
|
+
// 文本模型卡:只选模型,参数全用 Harness 默认;紧挨图片/视频/TTS 模型卡片
|
|
6692
|
+
h('div', { key: 'llm', className: 'dshic-card' },
|
|
6693
|
+
h('div', { className: 'dshic-row' },
|
|
6694
|
+
Ic('spark', 12),
|
|
6695
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('llmLabel')),
|
|
6696
|
+
InfoTip(T('llmHint')),
|
|
6697
|
+
),
|
|
6698
|
+
h(LlmModelSelect),
|
|
6699
|
+
),
|
|
6664
6700
|
h(ApiListEditor, { key: 'imglist', kind: 'image' }),
|
|
6665
6701
|
h(ApiListEditor, { key: 'vidlist', kind: 'video' }),
|
|
6666
6702
|
h(ApiListEditor, { key: 'ttslist', kind: 'tts' }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninkch/dsh-infinite-canvas",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.8",
|
|
4
4
|
"description": "Node-based short-drama studio for DeepSeek Harness: script → storyboard → assets → shots → voiced, subtitled final cut on an infinite canvas.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|