-
-
-
diff --git a/src/services/booksApi.ts b/src/services/booksApi.ts
index c897a42..046aaa5 100644
--- a/src/services/booksApi.ts
+++ b/src/services/booksApi.ts
@@ -70,3 +70,7 @@ export function deleteBook(id: string): Promise<{ ok: true }> {
export function generateLesson(topic: string): Promise
{
return request('/api/generate', { method: 'POST', body: JSON.stringify({ topic }) })
}
+
+export function generateOutline(theme: string): Promise<{ titles: string[] }> {
+ return request('/api/generate/outline', { method: 'POST', body: JSON.stringify({ theme }) })
+}
diff --git a/src/services/markdownParser.ts b/src/services/markdownParser.ts
index c12e1f1..82c68e5 100644
--- a/src/services/markdownParser.ts
+++ b/src/services/markdownParser.ts
@@ -247,7 +247,7 @@ export function parseTeachingDesign(filename: string, markdown: string): Teachin
if (!reflectionTable) {
warnings.push({ code: 'missing-reflection', message: '教学成效与反思表格格式不正确。' })
} else {
- for (const row of reflectionTable.rows) {
+ for (const row of [reflectionTable.header, ...reflectionTable.rows]) {
const label = cleanLabel(row[0] ?? '')
const value = normalizeMultiline(row[1] ?? '')
if (label === '教学成效') design.effectiveness = value
diff --git a/src/services/markdownTable.ts b/src/services/markdownTable.ts
index a835d67..f10dad7 100644
--- a/src/services/markdownTable.ts
+++ b/src/services/markdownTable.ts
@@ -166,6 +166,24 @@ export function extractMarkdownTable(
const header = splitMarkdownRow(headerLine)
const divider = splitMarkdownRow(dividerLine)
+ // Handle separator-first tables (no header row: starts with |:---|:---|)
+ if (header.length > 0 && header.every((cell) => dividerCellPattern.test(cell))) {
+ const rows: string[][] = []
+ let end = start
+
+ while (end + 1 < lines.length && !insideFence[end + 1] && isTableRow(lines[end + 1]!)) {
+ end++
+ const row = splitMarkdownRow(lines[end]!)
+ if (!row.every((cell) => dividerCellPattern.test(cell))) {
+ rows.push(row)
+ }
+ }
+
+ if (rows.length > 0) {
+ return { start, end, header: [], rows }
+ }
+ }
+
if (
header.length === 0 ||
divider.length !== header.length ||
diff --git a/src/style.css b/src/style.css
index 82c73e7..08bbf4c 100644
--- a/src/style.css
+++ b/src/style.css
@@ -604,6 +604,7 @@ table {
margin-bottom: 16px;
}
+.dialog input,
.book-list-create input,
.book-list-item input {
flex: 1 1 auto;
@@ -652,3 +653,58 @@ table {
color: var(--muted);
font-size: 14px;
}
+
+/* Batch generate dialog */
+.batch-dialog {
+ width: 480px;
+}
+
+.batch-topics-input {
+ display: block;
+ width: 100%;
+ border: 1px solid var(--line);
+ border-radius: 6px;
+ padding: 8px 12px;
+ resize: vertical;
+ margin-top: 8px;
+}
+
+.batch-topics-input:focus {
+ outline: none;
+ border-color: var(--green-600);
+}
+
+.batch-topics-count {
+ font-size: 13px;
+ color: var(--muted);
+ margin: 6px 0 0;
+}
+
+.batch-progress-label {
+ font-size: 16px;
+ margin: 8px 0 4px;
+}
+
+.batch-current-topic {
+ color: var(--muted);
+ font-size: 14px;
+ margin: 0 0 12px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.batch-progress-bar {
+ height: 6px;
+ background: var(--line);
+ border-radius: 3px;
+ overflow: hidden;
+ margin-bottom: 4px;
+}
+
+.batch-progress-fill {
+ height: 100%;
+ background: var(--green-600);
+ border-radius: 3px;
+ transition: width 0.3s ease;
+}