@waterwx/dsh-novel-forge 0.1.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/LICENSE +202 -0
- package/README.md +180 -0
- package/cordis.patch.yml +13 -0
- package/lib/client.js +3924 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +3120 -0
- package/lib/index.js.map +1 -0
- package/lib/types/assets.d.ts +35 -0
- package/lib/types/assistant.d.ts +43 -0
- package/lib/types/bookshelf.d.ts +35 -0
- package/lib/types/client/api.d.ts +68 -0
- package/lib/types/client/docx.d.ts +15 -0
- package/lib/types/client/index.d.ts +14 -0
- package/lib/types/client/locales.d.ts +139 -0
- package/lib/types/client/mount.d.ts +9 -0
- package/lib/types/client/panel/AssetsTab.d.ts +7 -0
- package/lib/types/client/panel/AssistantTab.d.ts +7 -0
- package/lib/types/client/panel/BookshelfBar.d.ts +11 -0
- package/lib/types/client/panel/NovelPanel.d.ts +13 -0
- package/lib/types/client/panel/controller.d.ts +19 -0
- package/lib/types/client/panel/helpers.d.ts +8 -0
- package/lib/types/client/sidebar-entry.d.ts +13 -0
- package/lib/types/docx.d.ts +19 -0
- package/lib/types/engine.d.ts +95 -0
- package/lib/types/index.d.ts +55 -0
- package/lib/types/protocol.d.ts +521 -0
- package/lib/types/routes.d.ts +29 -0
- package/package.json +105 -0
- package/src/assets.ts +518 -0
- package/src/assistant.ts +547 -0
- package/src/bookshelf.ts +137 -0
- package/src/client/api.ts +254 -0
- package/src/client/css-modules.d.ts +8 -0
- package/src/client/docx.ts +69 -0
- package/src/client/index.ts +34 -0
- package/src/client/locales.ts +271 -0
- package/src/client/mount.tsx +97 -0
- package/src/client/panel/AssetsTab.tsx +341 -0
- package/src/client/panel/AssistantTab.tsx +188 -0
- package/src/client/panel/BookshelfBar.tsx +116 -0
- package/src/client/panel/NovelPanel.tsx +990 -0
- package/src/client/panel/controller.ts +45 -0
- package/src/client/panel/helpers.ts +17 -0
- package/src/client/panel/panel.module.css +894 -0
- package/src/client/sidebar-entry.ts +122 -0
- package/src/docx.ts +83 -0
- package/src/engine.ts +1019 -0
- package/src/index.ts +184 -0
- package/src/protocol.ts +539 -0
- package/src/routes.ts +955 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 书架条:显示所有书,点击切换当前书(继续编译),+ 新建。
|
|
3
|
+
*/
|
|
4
|
+
import { useState } from 'react'
|
|
5
|
+
import type { NovelApi } from '../api.ts'
|
|
6
|
+
import type { BookshelfSnapshot } from '../../protocol.ts'
|
|
7
|
+
import css from './panel.module.css'
|
|
8
|
+
|
|
9
|
+
/** Props. */
|
|
10
|
+
export interface BookshelfBarProps {
|
|
11
|
+
api: NovelApi
|
|
12
|
+
shelf: BookshelfSnapshot
|
|
13
|
+
/** 刷新整个面板(切换书后重新拉状态)。 */
|
|
14
|
+
onSwitch: () => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** 书架条。 */
|
|
18
|
+
export function BookshelfBar({ api, shelf, onSwitch }: BookshelfBarProps) {
|
|
19
|
+
const [creating, setCreating] = useState(false)
|
|
20
|
+
const [name, setName] = useState('')
|
|
21
|
+
const [busy, setBusy] = useState(false)
|
|
22
|
+
const [error, setError] = useState('')
|
|
23
|
+
|
|
24
|
+
const handleCreate = async (): Promise<void> => {
|
|
25
|
+
const bookName = name.trim()
|
|
26
|
+
if (bookName === '') return
|
|
27
|
+
setBusy(true)
|
|
28
|
+
setError('')
|
|
29
|
+
try {
|
|
30
|
+
await api.bookCreate(bookName)
|
|
31
|
+
setCreating(false)
|
|
32
|
+
setName('')
|
|
33
|
+
onSwitch()
|
|
34
|
+
} catch (err) {
|
|
35
|
+
setError((err as Error).message)
|
|
36
|
+
} finally {
|
|
37
|
+
setBusy(false)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const handleActivate = async (id: string): Promise<void> => {
|
|
42
|
+
if (id === shelf.activeBookId) return
|
|
43
|
+
setBusy(true)
|
|
44
|
+
try {
|
|
45
|
+
await api.bookActivate(id)
|
|
46
|
+
onSwitch()
|
|
47
|
+
} catch (err) {
|
|
48
|
+
setError((err as Error).message)
|
|
49
|
+
} finally {
|
|
50
|
+
setBusy(false)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleRemove = async (id: string): Promise<void> => {
|
|
55
|
+
setBusy(true)
|
|
56
|
+
try {
|
|
57
|
+
await api.bookRemove(id)
|
|
58
|
+
onSwitch()
|
|
59
|
+
} catch (err) {
|
|
60
|
+
setError((err as Error).message)
|
|
61
|
+
} finally {
|
|
62
|
+
setBusy(false)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className={css.bookshelf}>
|
|
68
|
+
<span className={css.bookshelfLabel}>书架</span>
|
|
69
|
+
<div className={css.bookshelfList}>
|
|
70
|
+
{shelf.books.map(book => (
|
|
71
|
+
<div
|
|
72
|
+
key={book.id}
|
|
73
|
+
className={`${css.bookChip} ${book.id === shelf.activeBookId ? css.bookChipActive : ''}`}
|
|
74
|
+
onClick={() => { void handleActivate(book.id) }}
|
|
75
|
+
title={book.outputDir}
|
|
76
|
+
>
|
|
77
|
+
<span className={css.bookChipName}>{book.bookName}</span>
|
|
78
|
+
<span className={css.bookChipMeta}>{book.hasProject ? `${book.done}/${book.total} 章` : '未开书'}</span>
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
className={css.bookChipRemove}
|
|
82
|
+
title="从书架移除"
|
|
83
|
+
onClick={(e) => { e.stopPropagation(); void handleRemove(book.id) }}
|
|
84
|
+
>
|
|
85
|
+
×
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
))}
|
|
89
|
+
{!creating ? (
|
|
90
|
+
<button type="button" className={css.bookAdd} onClick={() => { setCreating(true) }}>
|
|
91
|
+
+ 新书
|
|
92
|
+
</button>
|
|
93
|
+
) : (
|
|
94
|
+
<div className={css.bookCreateForm}>
|
|
95
|
+
<input
|
|
96
|
+
className={css.input}
|
|
97
|
+
style={{ width: 140 }}
|
|
98
|
+
placeholder="书名"
|
|
99
|
+
value={name}
|
|
100
|
+
onChange={e => { setName(e.target.value) }}
|
|
101
|
+
onKeyDown={e => { if (e.key === 'Enter') void handleCreate() }}
|
|
102
|
+
autoFocus
|
|
103
|
+
/>
|
|
104
|
+
<button type="button" className={`${css.button} ${css.buttonSmall} ${css.buttonPrimary}`} disabled={busy || name.trim() === ''} onClick={() => { void handleCreate() }}>
|
|
105
|
+
创建
|
|
106
|
+
</button>
|
|
107
|
+
<button type="button" className={`${css.button} ${css.buttonSmall}`} onClick={() => { setCreating(false) }}>
|
|
108
|
+
取消
|
|
109
|
+
</button>
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
{error !== '' && <span style={{ color: 'var(--nf-error)', fontSize: 12 }}>{error}</span>}
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
}
|