@waterwx/dsh-novel-forge 1.6.0 → 1.7.2
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/lib/client.js +37690 -2269
- package/lib/client.js.map +1 -1
- package/lib/index.js +767 -56
- package/lib/index.js.map +1 -1
- package/lib/types/client/api.d.ts +3 -0
- package/lib/types/client/locales.d.ts +0 -1
- package/lib/types/client/panel/FlowGuide.d.ts +21 -0
- package/lib/types/client/panel/MangaRoleLibrary.d.ts +18 -0
- package/lib/types/client/panel/MangaWorkspace.d.ts +6 -4
- package/lib/types/client/panel/RoleVisualPanel.d.ts +5 -3
- package/lib/types/client/panel/SceneLibrary.d.ts +1 -1
- package/lib/types/client/panel/StoryboardTab.d.ts +6 -2
- package/lib/types/engine.d.ts +23 -9
- package/lib/types/index.d.ts +6 -4
- package/lib/types/protocol.d.ts +171 -3
- package/package.json +100 -98
- package/src/client/api.ts +9 -0
- package/src/client/locales.ts +0 -1
- package/src/client/panel/AssetsTab.tsx +22 -22
- package/src/client/panel/AssistantTab.tsx +3 -3
- package/src/client/panel/BookshelfBar.tsx +1 -1
- package/src/client/panel/CreateBookView.tsx +10 -10
- package/src/client/panel/FlowGuide.tsx +83 -0
- package/src/client/panel/MangaRoleLibrary.tsx +810 -0
- package/src/client/panel/MangaWorkspace.tsx +359 -293
- package/src/client/panel/NovelPanel.tsx +465 -307
- package/src/client/panel/ReaderView.tsx +4 -4
- package/src/client/panel/RunPanel.tsx +9 -9
- package/src/client/panel/SceneLibrary.tsx +69 -68
- package/src/client/panel/ShelfView.tsx +28 -35
- package/src/client/panel/StoryboardTab.tsx +106 -42
- package/src/client/panel/StyleCard.tsx +13 -13
- package/src/client/panel/StyleGallery.tsx +2 -2
- package/src/client/panel/WorldTab.tsx +5 -5
- package/src/client/panel/panel.module.css +1189 -454
- package/src/client/panel/views.tsx +24 -24
- package/src/engine.ts +530 -59
- package/src/index.ts +37 -6
- package/src/protocol.ts +175 -3
- package/src/routes.ts +229 -1
- package/src/client/panel/RoleVisualPanel.tsx +0 -468
|
@@ -86,14 +86,14 @@ export function PlotlineCard(props: {
|
|
|
86
86
|
}): ReactElement {
|
|
87
87
|
const { line } = props
|
|
88
88
|
return (
|
|
89
|
-
<div key={line.id} style={{ border: '1px solid var(--nf-border)', borderRadius: 10, padding: '
|
|
89
|
+
<div key={line.id} style={{ border: '1px solid var(--nf-border)', borderRadius: 'var(--nf-radius-10)', padding: 'var(--nf-space-8) var(--nf-space-12)', fontSize: 'var(--nf-fs-12)', display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-4)' }}>
|
|
90
90
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
91
|
-
<span style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
91
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: 'var(--nf-space-6)', flexWrap: 'wrap' }}>
|
|
92
92
|
<b>{line.name}</b>
|
|
93
93
|
<span className={css.badge} style={{ borderColor: 'var(--nf-accent)', color: 'var(--nf-accent)' }}>{kindLabel(line.kind)}</span>
|
|
94
94
|
<span className={css.badge} style={{ borderColor: plotlineStatusColor(line.status), color: plotlineStatusColor(line.status) }}>{plotlineStatusLabel(line.status)}</span>
|
|
95
95
|
</span>
|
|
96
|
-
<span style={{ display: 'flex', gap: 6 }}>
|
|
96
|
+
<span style={{ display: 'flex', gap: 'var(--nf-space-6)' }}>
|
|
97
97
|
<button
|
|
98
98
|
type="button"
|
|
99
99
|
className={`${css.button} ${css.buttonSmall}`}
|
|
@@ -131,14 +131,14 @@ export function RoleCandidateRow(props: {
|
|
|
131
131
|
const label = ROLE_LABELS[r.roleLabel] ?? r.roleLabel
|
|
132
132
|
const color = roleColor(r.roleLabel)
|
|
133
133
|
return (
|
|
134
|
-
<div key={r.name} style={{ border: '1px solid var(--nf-border)', borderRadius: 8, padding: '
|
|
134
|
+
<div key={r.name} style={{ border: '1px solid var(--nf-border)', borderRadius: 'var(--nf-radius-8)', padding: 'var(--nf-space-6) var(--nf-space-10)', fontSize: 'var(--nf-fs-12)' }}>
|
|
135
135
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
136
|
-
<span style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
136
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: 'var(--nf-space-6)', flexWrap: 'wrap' }}>
|
|
137
137
|
<b>{r.name}</b>
|
|
138
138
|
<span className={css.badge} style={{ borderColor: color, color }}>{label}</span>
|
|
139
139
|
{r.identity !== '' && <span className={css.meta}>{r.identity}</span>}
|
|
140
140
|
</span>
|
|
141
|
-
<span style={{ display: 'flex', gap: 6 }}>
|
|
141
|
+
<span style={{ display: 'flex', gap: 'var(--nf-space-6)' }}>
|
|
142
142
|
<button type="button" className={`${css.button} ${css.buttonSmall} ${css.buttonPrimary}`} disabled={props.disabled} onClick={props.onAdopt}>
|
|
143
143
|
+ 采纳
|
|
144
144
|
</button>
|
|
@@ -165,14 +165,14 @@ export function RoleCard(props: {
|
|
|
165
165
|
const label = ROLE_LABELS[r.roleLabel] ?? r.roleLabel
|
|
166
166
|
const color = roleColor(r.roleLabel)
|
|
167
167
|
return (
|
|
168
|
-
<div key={r.name} style={{ border: '1px solid var(--nf-border)', borderRadius: 8, padding: '
|
|
168
|
+
<div key={r.name} style={{ border: '1px solid var(--nf-border)', borderRadius: 'var(--nf-radius-8)', padding: 'var(--nf-space-6) var(--nf-space-10)', fontSize: 'var(--nf-fs-12)' }}>
|
|
169
169
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
170
|
-
<span style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
170
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: 'var(--nf-space-6)', flexWrap: 'wrap' }}>
|
|
171
171
|
<b>{r.name}</b>
|
|
172
172
|
<span className={css.badge} style={{ borderColor: color, color }}>{label}</span>
|
|
173
173
|
{r.identity !== '' && <span className={css.meta}>{r.identity}</span>}
|
|
174
174
|
</span>
|
|
175
|
-
<span style={{ display: 'flex', gap: 6 }}>
|
|
175
|
+
<span style={{ display: 'flex', gap: 'var(--nf-space-6)' }}>
|
|
176
176
|
<button type="button" className={`${css.button} ${css.buttonSmall}`} disabled={props.disabled} onClick={props.onEdit}>编辑</button>
|
|
177
177
|
<button type="button" className={`${css.button} ${css.buttonSmall}`} disabled={props.disabled} onClick={props.onRemove}>删除</button>
|
|
178
178
|
</span>
|
|
@@ -200,10 +200,10 @@ export function PlotlineHealthPanel(props: {
|
|
|
200
200
|
}): ReactElement {
|
|
201
201
|
const { report } = props
|
|
202
202
|
return (
|
|
203
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, border: '1px solid var(--nf-info)', borderRadius: 12, padding: 10 }}>
|
|
203
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-6)', border: '1px solid var(--nf-info)', borderRadius: 'var(--nf-radius-12)', padding: 'var(--nf-space-10)' }}>
|
|
204
204
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
205
205
|
<b>🩺 剧情健康检查</b>
|
|
206
|
-
<span style={{ display: 'flex', gap: 8 }}>
|
|
206
|
+
<span style={{ display: 'flex', gap: 'var(--nf-space-8)' }}>
|
|
207
207
|
<button
|
|
208
208
|
type="button"
|
|
209
209
|
className={`${css.button} ${css.buttonSmall}`}
|
|
@@ -216,21 +216,21 @@ export function PlotlineHealthPanel(props: {
|
|
|
216
216
|
<button type="button" className={`${css.button} ${css.buttonSmall}`} onClick={props.onClose}>收起</button>
|
|
217
217
|
</span>
|
|
218
218
|
</div>
|
|
219
|
-
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--nf-accent)' }}>判定:{report.verdict}</div>
|
|
219
|
+
<div style={{ fontSize: 'var(--nf-fs-12)', fontWeight: 700, color: 'var(--nf-accent)' }}>判定:{report.verdict}</div>
|
|
220
220
|
{report.timing !== '' && <div className={css.meta}><b>建议时机:</b>{report.timing}</div>}
|
|
221
221
|
{report.reasons.length > 0 && (
|
|
222
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 2, fontSize: 12 }}>
|
|
222
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-2)', fontSize: 'var(--nf-fs-12)' }}>
|
|
223
223
|
{report.reasons.map((r, i) => <div key={i} className={css.meta}>· {r}</div>)}
|
|
224
224
|
</div>
|
|
225
225
|
)}
|
|
226
226
|
{report.lines.length > 0 && (
|
|
227
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
|
|
227
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-4)', fontSize: 'var(--nf-fs-12)' }}>
|
|
228
228
|
{report.lines.map((l, i) => {
|
|
229
229
|
const color = l.health === 'ok' ? 'var(--nf-success)' : l.health === 'warning' ? 'var(--nf-warn)' : 'var(--nf-error)'
|
|
230
230
|
const label = l.health === 'ok' ? '健康' : l.health === 'warning' ? '预警' : '搁置过久'
|
|
231
231
|
return (
|
|
232
|
-
<div key={i} style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
|
|
233
|
-
<span className={css.badge} style={{ borderColor: color, color, flex: 'none', marginTop:
|
|
232
|
+
<div key={i} style={{ display: 'flex', gap: 'var(--nf-space-8)', alignItems: 'flex-start' }}>
|
|
233
|
+
<span className={css.badge} style={{ borderColor: color, color, flex: 'none', marginTop: 'var(--nf-space-2)' }}>{label}</span>
|
|
234
234
|
<span className={css.meta}><b>{l.name}</b>:{l.note}</span>
|
|
235
235
|
</div>
|
|
236
236
|
)
|
|
@@ -250,20 +250,20 @@ export function PlotlinePlanPanel(props: {
|
|
|
250
250
|
}): ReactElement {
|
|
251
251
|
const { plan } = props
|
|
252
252
|
return (
|
|
253
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, border: '1px solid var(--nf-accent)', borderRadius: 12, padding: 10 }}>
|
|
253
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-6)', border: '1px solid var(--nf-accent)', borderRadius: 'var(--nf-radius-12)', padding: 'var(--nf-space-10)' }}>
|
|
254
254
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
255
255
|
<b>✨ AI 剧情方案</b>
|
|
256
256
|
<button type="button" className={`${css.button} ${css.buttonSmall}`} onClick={props.onClose}>收起</button>
|
|
257
257
|
</div>
|
|
258
258
|
{plan.direction !== '' && (
|
|
259
|
-
<div className={css.meta} style={{ fontSize: 12 }}><b>下一阶段方向:</b>{plan.direction}</div>
|
|
259
|
+
<div className={css.meta} style={{ fontSize: 'var(--nf-fs-12)' }}><b>下一阶段方向:</b>{plan.direction}</div>
|
|
260
260
|
)}
|
|
261
261
|
{plan.suggestions.length > 0 && (
|
|
262
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
|
|
262
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-4)', fontSize: 'var(--nf-fs-12)' }}>
|
|
263
263
|
{plan.suggestions.map((s, i) => (
|
|
264
|
-
<div key={i} style={{ border: '1px solid var(--nf-border)', borderRadius: 8, padding: '
|
|
264
|
+
<div key={i} style={{ border: '1px solid var(--nf-border)', borderRadius: 'var(--nf-radius-8)', padding: 'var(--nf-space-6) var(--nf-space-10)' }}>
|
|
265
265
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
266
|
-
<span style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
266
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: 'var(--nf-space-6)', flexWrap: 'wrap' }}>
|
|
267
267
|
<b>{s.name}</b>
|
|
268
268
|
<span className={css.badge} style={{ borderColor: 'var(--nf-accent)', color: 'var(--nf-accent)' }}>{kindLabel(s.kind)}</span>
|
|
269
269
|
</span>
|
|
@@ -289,16 +289,16 @@ export function PlotlineSuggestionPanel(props: {
|
|
|
289
289
|
onClose: () => void
|
|
290
290
|
}): ReactElement {
|
|
291
291
|
return (
|
|
292
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, border: '1px solid var(--nf-info)', borderRadius: 12, padding: 10 }}>
|
|
292
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--nf-space-6)', border: '1px solid var(--nf-info)', borderRadius: 'var(--nf-radius-12)', padding: 'var(--nf-space-10)' }}>
|
|
293
293
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
294
294
|
<b>✨ AI 建议({props.suggestions.length} 条)</b>
|
|
295
295
|
<button type="button" className={`${css.button} ${css.buttonSmall}`} onClick={props.onClose}>收起</button>
|
|
296
296
|
</div>
|
|
297
297
|
{props.suggestions.length === 0 && <span className={css.meta}>没有候选线。</span>}
|
|
298
298
|
{props.suggestions.map((s, i) => (
|
|
299
|
-
<div key={i} style={{ border: '1px solid var(--nf-border)', borderRadius: 8, padding: '
|
|
299
|
+
<div key={i} style={{ border: '1px solid var(--nf-border)', borderRadius: 'var(--nf-radius-8)', padding: 'var(--nf-space-6) var(--nf-space-10)', fontSize: 'var(--nf-fs-12)' }}>
|
|
300
300
|
<div className={css.row} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
|
|
301
|
-
<span style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
301
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: 'var(--nf-space-6)', flexWrap: 'wrap' }}>
|
|
302
302
|
<b>{s.name}</b>
|
|
303
303
|
<span className={css.badge} style={{ borderColor: 'var(--nf-accent)', color: 'var(--nf-accent)' }}>{kindLabel(s.kind)}</span>
|
|
304
304
|
</span>
|