feat: Enhance AI suggestion functionality in ImportClient and improve compactLine handling
Build and Push Reader Image / docker (push) Successful in 42s

This commit is contained in:
2026-05-04 20:59:30 +07:00
parent 350c4dfa18
commit 9005cfa5ef
2 changed files with 10 additions and 5 deletions
+8 -3
View File
@@ -56,6 +56,7 @@ export function ImportClient() {
const [parseError, setParseError] = useState("") const [parseError, setParseError] = useState("")
const [aiLoading, setAiLoading] = useState(false) const [aiLoading, setAiLoading] = useState(false)
const [aiModel, setAiModel] = useState("")
const [importing, setImporting] = useState(false) const [importing, setImporting] = useState(false)
const [result, setResult] = useState<Record<string, unknown> | null>(null) const [result, setResult] = useState<Record<string, unknown> | null>(null)
@@ -237,16 +238,19 @@ export function ImportClient() {
form.append("preview", "true") form.append("preview", "true")
form.append("splitMode", splitMode) form.append("splitMode", splitMode)
if (splitMode === "regex") form.append("chapterRegex", chapterStartPattern) if (splitMode === "regex") form.append("chapterRegex", chapterStartPattern)
const res = await fetch("/api/mod/epub", { method: "POST", credentials: "include", body: form }) form.append("title", title)
form.append("authorName", author)
const res = await fetch("/api/mod/epub/ai-suggest", { method: "POST", credentials: "include", body: form })
const data = await res.json() const data = await res.json()
if (!res.ok) throw new Error(data?.detail || "AI suggest failed") if (!res.ok) throw new Error(data?.detail || "AI suggest failed")
const suggestedGenres: string[] = (data?.novel?.detectedGenres || []).slice(0, 6) const suggestedGenres: string[] = (data?.suggestedGenres || []).slice(0, 6)
setAiModel(String(data?.model || data?.source || ""))
setGenreQuery("") setGenreQuery("")
if (suggestedGenres.length > 0) { if (suggestedGenres.length > 0) {
const ensuredIds = await ensureGenreIdsByNames(suggestedGenres) const ensuredIds = await ensureGenreIdsByNames(suggestedGenres)
setSelectedGenreIds(ensuredIds) setSelectedGenreIds(ensuredIds)
} }
if (!shortDescription) setShortDescription(data?.novel?.description || "") setShortDescription(data?.shortDescription || "")
toast.success("Đã áp dụng gợi ý AI") toast.success("Đã áp dụng gợi ý AI")
} catch (error) { } catch (error) {
toast.error(error instanceof Error ? error.message : "AI suggest lỗi") toast.error(error instanceof Error ? error.message : "AI suggest lỗi")
@@ -480,6 +484,7 @@ export function ImportClient() {
<Button variant="outline" onClick={onAiSuggest} disabled={aiLoading}>{aiLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Sparkles className="h-4 w-4" />} AI gợi ý</Button> <Button variant="outline" onClick={onAiSuggest} disabled={aiLoading}>{aiLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Sparkles className="h-4 w-4" />} AI gợi ý</Button>
<Button onClick={onSaveReview}>Lưu & sang bước 3</Button> <Button onClick={onSaveReview}>Lưu & sang bước 3</Button>
</div> </div>
{aiModel && <p className="text-xs text-muted-foreground">AI model: {aiModel}</p>}
</section> </section>
)} )}
+2 -2
View File
@@ -32,8 +32,8 @@ function sourceClass(source: HotCarouselItem["hotSource"]) {
return "border-primary/30 bg-primary/20 text-primary" return "border-primary/30 bg-primary/20 text-primary"
} }
function compactLine(text: string, max = 180) { function compactLine(text: string | null | undefined, max = 180) {
const normalized = text.replace(/\s+/g, " ").trim() const normalized = String(text || "").replace(/\s+/g, " ").trim()
if (normalized.length <= max) return normalized if (normalized.length <= max) return normalized
return `${normalized.slice(0, max).trim()}...` return `${normalized.slice(0, max).trim()}...`
} }