脱敏
This commit is contained in:
1 parent
2f7f07467e
commit
ca1d7e77ba
18 files changed
+53
-76
No files matched your search
@@ -1,7 +1,5 @@
|
||||
import { FileText, PenLine } from 'lucide-react';
|
||||
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
|
||||
import { useCanvasGraphContext } from '../../contexts/CanvasGraphContext';
|
||||
import { getCurrentArtifactContent, isCodeArtifact } from '../../utils/artifact';
|
||||
import { TextArtifactRenderer } from '../artifact/TextArtifactRenderer';
|
||||
@@ -47,7 +45,7 @@ export function AIWritingDraftPanel() {
|
||||
<div className="h-10 border-b flex items-center gap-2 px-4 shrink-0 bg-muted/20">
|
||||
<FileText className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
|
||||
<span className="text-sm font-medium truncate flex-1">
|
||||
{content?.title ? desensitize(content.title) : '草稿预览'}
|
||||
{content?.title ?? '草稿预览'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { CheckCircle2, ChevronRight, FileText, Search, PenLine, ClipboardEdit, Star } from 'lucide-react';
|
||||
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
|
||||
import type { AIWritingSessionSummary, CompletedInterventionRecord } from '../../api/ai-writing-sessions';
|
||||
import { AIWritingTimeline } from './AIWritingTimeline';
|
||||
|
||||
@@ -81,10 +79,10 @@ export function AIWritingHistoryView({ session }: AIWritingHistoryViewProps) {
|
||||
{/* 元信息 */}
|
||||
<div className="px-4 pt-3">
|
||||
<div className="rounded-lg border bg-muted/30 px-3 py-2.5 space-y-1">
|
||||
<p className="text-xs font-semibold truncate">{desensitize(session.draft_title ?? session.title ?? "")}</p>
|
||||
<p className="text-xs font-semibold truncate">{session.draft_title ?? session.title}</p>
|
||||
{session.user_intent && (
|
||||
<p className="text-[11px] text-muted-foreground leading-relaxed line-clamp-2">
|
||||
{desensitize(session.user_intent)}
|
||||
{session.user_intent}
|
||||
</p>
|
||||
)}
|
||||
{createdAt && (
|
||||
|
||||
@@ -4,7 +4,6 @@ import { ChevronsDown, Play, Plus, RotateCcw, Settings2, Square, Trash2 } from '
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
Dialog,
|
||||
@@ -252,7 +251,7 @@ export function AIWritingPanel({
|
||||
<div className="flex flex-col h-full overflow-hidden bg-background">
|
||||
<div className="flex items-center justify-between px-4 py-2.5 border-b shrink-0">
|
||||
<span className="text-sm font-semibold truncate flex-1 min-w-0 mr-2">
|
||||
{desensitize(historySession.draft_title ?? historySession.title)}
|
||||
{historySession.draft_title ?? historySession.title}
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5 shrink-0">
|
||||
<Button
|
||||
@@ -502,7 +501,7 @@ export function AIWritingPanel({
|
||||
<span className="inline-block size-1.5 rounded-full bg-blue-500 animate-pulse" />
|
||||
)}
|
||||
{state.status === 'researching' && state.researchProgress
|
||||
? desensitize(state.researchProgress)
|
||||
? state.researchProgress
|
||||
: STATUS_LABEL[state.status] ?? state.status}
|
||||
</>
|
||||
)}
|
||||
@@ -518,16 +517,16 @@ export function AIWritingPanel({
|
||||
</DialogHeader>
|
||||
<div className="space-y-3 py-1 text-sm">
|
||||
<ReqRow label="写作意图">
|
||||
<p className="text-muted-foreground whitespace-pre-wrap leading-relaxed">{desensitize(state.request.userIntent ?? "")}</p>
|
||||
<p className="text-muted-foreground whitespace-pre-wrap leading-relaxed">{state.request.userIntent}</p>
|
||||
</ReqRow>
|
||||
<ReqRow label="文章类型">
|
||||
<span className="text-muted-foreground">
|
||||
{desensitize(articleTypes.find((t) => t.key === state.request!.articleType)?.label ?? state.request.articleType ?? "")}
|
||||
{articleTypes.find((t) => t.key === state.request!.articleType)?.label ?? state.request.articleType}
|
||||
</span>
|
||||
</ReqRow>
|
||||
{!hideAdvancedFields && (
|
||||
<ReqRow label="目标读者">
|
||||
<span className="text-muted-foreground">{desensitize(state.request.targetAudience ?? "")}</span>
|
||||
<span className="text-muted-foreground">{state.request.targetAudience}</span>
|
||||
</ReqRow>
|
||||
)}
|
||||
<ReqRow label="目标字数">
|
||||
@@ -547,7 +546,7 @@ export function AIWritingPanel({
|
||||
)}
|
||||
{state.request.modelName && (
|
||||
<ReqRow label="写作模型">
|
||||
<span className="text-muted-foreground">{desensitize(state.request.modelName)}</span>
|
||||
<span className="text-muted-foreground">{state.request.modelName}</span>
|
||||
</ReqRow>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
ExternalLink, ListTree, FileText,
|
||||
} from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import { buildIntranetSourceUrl } from '@/core/config';
|
||||
import type { AIMaterial, CompletedIntervention } from '../../types/ai-writing';
|
||||
import { OutlineCard } from './OutlineCard';
|
||||
@@ -105,7 +104,7 @@ function CompletedMaterialItem({ material }: { material: AIMaterial }) {
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start gap-1.5">
|
||||
<span className="flex-1 font-medium leading-snug line-clamp-2">{desensitize(material.title ?? "")}</span>
|
||||
<span className="flex-1 font-medium leading-snug line-clamp-2">{material.title}</span>
|
||||
{hasDetail && (
|
||||
<ChevronRight
|
||||
className={cn(
|
||||
@@ -116,8 +115,8 @@ function CompletedMaterialItem({ material }: { material: AIMaterial }) {
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<span className="truncate max-w-[100px]">{desensitize(material.source ?? "")}</span>
|
||||
{material.publishedAt && <><span className="text-muted-foreground/40">·</span><span>{desensitize(material.publishedAt)}</span></>}
|
||||
<span className="truncate max-w-[100px]">{material.source}</span>
|
||||
{material.publishedAt && <><span className="text-muted-foreground/40">·</span><span>{material.publishedAt}</span></>}
|
||||
<div className="flex flex-1 items-center gap-1 min-w-0">
|
||||
<div className="flex-1 h-1 rounded-full bg-muted overflow-hidden min-w-[40px]">
|
||||
<div className={cn('h-full rounded-full', barColor)} style={{ width: `${pct}%` }} />
|
||||
@@ -132,7 +131,7 @@ function CompletedMaterialItem({ material }: { material: AIMaterial }) {
|
||||
<div className="px-2.5 pb-2 pt-1.5 space-y-1.5 border-t border-border/40">
|
||||
{material.content && (
|
||||
<p className="text-muted-foreground leading-relaxed line-clamp-6">
|
||||
{desensitize(material.content.slice(0, 300))}
|
||||
{material.content.slice(0, 300)}
|
||||
{material.content.length > 300 && '…'}
|
||||
</p>
|
||||
)}
|
||||
@@ -170,7 +169,7 @@ function OutlineCompleted({ record, expanded, onToggle }: { record: CompletedInt
|
||||
已确认大纲
|
||||
{record.outline?.title && (
|
||||
<span className="ml-1 text-muted-foreground font-normal">
|
||||
《{desensitize(record.outline.title)}》
|
||||
《{record.outline.title}》
|
||||
</span>
|
||||
)}
|
||||
<span className="ml-1 text-muted-foreground font-normal">共 {sectionCount} 章节</span>
|
||||
@@ -197,7 +196,7 @@ function OutlineCompleted({ record, expanded, onToggle }: { record: CompletedInt
|
||||
// ── 草稿确认历史卡 ────────────────────────────────────────────────────────────
|
||||
|
||||
function DraftCompleted({ record, expanded, onToggle }: { record: CompletedIntervention; expanded: boolean; onToggle: () => void }) {
|
||||
const title = record.draftTitle ? `《${desensitize(record.draftTitle)}》` : '草稿';
|
||||
const title = record.draftTitle ? `《${record.draftTitle}》` : '草稿';
|
||||
const wordCount = record.draftWordCount ?? 0;
|
||||
const hasReview = !!record.reviewResult;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Brain, ChevronRight } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { StreamingDraftSection } from '../../types/ai-writing';
|
||||
import { CollapseTransition } from './CollapseTransition';
|
||||
|
||||
@@ -50,7 +49,7 @@ function SectionThinking({ thinkingText, isDone }: { thinkingText: string; isDon
|
||||
ref={preRef}
|
||||
className="text-[10px] font-mono leading-relaxed px-2.5 py-2 text-amber-700/70 dark:text-amber-300/60 whitespace-pre-wrap max-h-32 overflow-y-auto italic"
|
||||
>
|
||||
{desensitize(thinkingText)}
|
||||
{thinkingText}
|
||||
{!isDone && (
|
||||
<span className="inline-block w-0.5 h-3 bg-amber-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
)}
|
||||
@@ -72,7 +71,7 @@ function SectionBody({ text, showCursor }: { text: string; showCursor: boolean }
|
||||
if (heading) {
|
||||
return (
|
||||
<p key={i} className="text-xs font-semibold text-foreground mt-2 mb-1">
|
||||
{desensitize(line.slice(heading[0].length))}
|
||||
{line.slice(heading[0].length)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
@@ -82,7 +81,7 @@ function SectionBody({ text, showCursor }: { text: string; showCursor: boolean }
|
||||
key={i}
|
||||
className="text-xs leading-relaxed text-foreground/90 whitespace-pre-wrap m-0 mb-1"
|
||||
>
|
||||
{desensitize(line)}
|
||||
{line}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
@@ -109,7 +108,7 @@ export function DraftStreamingView({ title, sections }: DraftStreamingViewProps)
|
||||
<div className="px-4 pb-4">
|
||||
<div className="rounded-xl border bg-card shadow-sm p-4 prose prose-sm dark:prose-invert max-w-none">
|
||||
{title && (
|
||||
<h1 className="text-base font-bold text-center mb-4 text-foreground">{desensitize(title)}</h1>
|
||||
<h1 className="text-base font-bold text-center mb-4 text-foreground">{title}</h1>
|
||||
)}
|
||||
|
||||
{sections.map((sec) => (
|
||||
@@ -118,7 +117,7 @@ export function DraftStreamingView({ title, sections }: DraftStreamingViewProps)
|
||||
'text-sm font-semibold mb-1.5',
|
||||
sec.isDone ? 'text-foreground' : 'text-purple-500',
|
||||
)}>
|
||||
{desensitize(sec.sectionTitle ?? "")}
|
||||
{sec.sectionTitle}
|
||||
</h2>
|
||||
|
||||
{/* 该章节的思考过程(可折叠) */}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Sparkles } from 'lucide-react';
|
||||
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
|
||||
import type { ParsedIntent } from '../../types/ai-writing';
|
||||
import type { ArticleType } from '../../api/ai-writing-article-types';
|
||||
|
||||
@@ -34,13 +32,13 @@ export function IntentResultCard({
|
||||
</span>
|
||||
</div>
|
||||
<div className="px-3 py-2.5 space-y-1.5 text-xs">
|
||||
<Row label="文章类型" value={desensitize(typeLabel ?? "")} />
|
||||
<Row label="文章类型" value={typeLabel} />
|
||||
{!hideTargetAudience && (
|
||||
<Row label="目标读者" value={desensitize(intent.targetAudience ?? "")} />
|
||||
<Row label="目标读者" value={intent.targetAudience} />
|
||||
)}
|
||||
<Row label="字数目标" value={`${intent.wordCountTarget} 字`} />
|
||||
{intent.refinedIntent && (
|
||||
<Row label="精炼意图" value={desensitize(intent.refinedIntent)} multiline />
|
||||
<Row label="精炼意图" value={intent.refinedIntent} multiline />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Sparkles, ChevronDown, ChevronRight, Brain } from 'lucide-react';
|
||||
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
|
||||
interface IntentStreamingViewProps {
|
||||
text: string;
|
||||
thinkingText?: string;
|
||||
@@ -56,7 +54,7 @@ export function IntentStreamingView({ text, thinkingText }: IntentStreamingViewP
|
||||
ref={thinkRef}
|
||||
className="text-[11px] font-mono leading-relaxed p-3 text-amber-700/70 dark:text-amber-300/60 whitespace-pre-wrap max-h-40 overflow-y-auto italic"
|
||||
>
|
||||
{desensitize(thinkingText)}
|
||||
{thinkingText}
|
||||
{!text && (
|
||||
<span className="inline-block w-0.5 h-3.5 bg-amber-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
)}
|
||||
@@ -86,7 +84,7 @@ export function IntentStreamingView({ text, thinkingText }: IntentStreamingViewP
|
||||
ref={preRef}
|
||||
className="text-[11px] font-mono leading-relaxed p-3 text-muted-foreground whitespace-pre-wrap max-h-52 overflow-y-auto"
|
||||
>
|
||||
{desensitize(text)}
|
||||
{text}
|
||||
<span className="inline-block w-0.5 h-3.5 bg-blue-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type {
|
||||
AIMaterial, AIOutline, ReviewResult, ReviewIssue,
|
||||
ProgressEvent, UserInterventionPayload,
|
||||
@@ -381,7 +380,7 @@ function DraftConfirmCard({ draftTitle, revisionCount, reviewResult, onSubmit, d
|
||||
<div>
|
||||
<p className="text-xs font-medium">草稿已完成,请确认后继续</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
{draftTitle ? `《${desensitize(draftTitle)}》` : '草稿'}
|
||||
{draftTitle ? `《${draftTitle}》` : '草稿'}
|
||||
{revisionCount > 0 ? `(第 ${revisionCount} 次修改稿)` : '(初稿)'}
|
||||
· 右侧可预览完整内容
|
||||
</p>
|
||||
@@ -617,8 +616,8 @@ function SectionHelpCard({ blockedSections, onSubmit, disabled }: SectionHelpCar
|
||||
{blockedSections.map((b) => (
|
||||
<div key={b.sectionTitle} className="rounded-md border bg-background p-2.5 space-y-2">
|
||||
<div>
|
||||
<p className="text-xs font-medium">{desensitize(b.sectionTitle ?? "")}</p>
|
||||
<p className="text-[11px] text-muted-foreground mt-0.5">{desensitize(b.reason ?? "")}</p>
|
||||
<p className="text-xs font-medium">{b.sectionTitle}</p>
|
||||
<p className="text-[11px] text-muted-foreground mt-0.5">{b.reason}</p>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
{DECISION_OPTIONS.map((opt) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { ReviewIssue } from '../../types/ai-writing';
|
||||
|
||||
interface IssueListProps {
|
||||
@@ -94,14 +93,14 @@ function IssueGroup({ label, labelClass, items, selectable, selectedIndices, onT
|
||||
<span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium', CATEGORY_COLOR[issue.category] ?? 'bg-muted text-muted-foreground')}>
|
||||
{CATEGORY_LABEL[issue.category] ?? issue.category}
|
||||
</span>
|
||||
<span className="text-muted-foreground truncate">{desensitize(issue.location ?? "")}</span>
|
||||
<span className="text-muted-foreground truncate">{issue.location}</span>
|
||||
</div>
|
||||
<p className={cn('text-foreground leading-snug', selectable ? 'pl-5' : '')}>
|
||||
{desensitize(issue.issue ?? "")}
|
||||
{issue.issue}
|
||||
</p>
|
||||
<p className={cn('text-muted-foreground leading-snug', selectable ? 'pl-5' : '')}>
|
||||
<span className="text-primary mr-1">→</span>
|
||||
{desensitize(issue.suggestion ?? "")}
|
||||
{issue.suggestion}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { ChevronRight, ExternalLink } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import { buildIntranetSourceUrl } from '@/core/config';
|
||||
import type { AIMaterial } from '../../types/ai-writing';
|
||||
import { CollapseTransition } from './CollapseTransition';
|
||||
@@ -52,7 +51,7 @@ export function MaterialItem({ material, checked, onToggle }: MaterialItemProps)
|
||||
className="flex flex-1 items-start gap-1.5 text-left"
|
||||
>
|
||||
<span className={cn('flex-1 font-medium leading-snug line-clamp-2', !checked && 'text-muted-foreground')}>
|
||||
{desensitize(material.title ?? "")}
|
||||
{material.title}
|
||||
</span>
|
||||
<ChevronRight
|
||||
className={cn(
|
||||
@@ -65,11 +64,11 @@ export function MaterialItem({ material, checked, onToggle }: MaterialItemProps)
|
||||
|
||||
{/* 元信息行 */}
|
||||
<div className="flex items-center gap-2 px-2.5 pb-2 pl-8">
|
||||
<span className="text-muted-foreground truncate max-w-[120px]">{desensitize(material.source ?? "")}</span>
|
||||
<span className="text-muted-foreground truncate max-w-[120px]">{material.source}</span>
|
||||
{material.publishedAt && (
|
||||
<>
|
||||
<span className="text-muted-foreground/40">·</span>
|
||||
<span className="text-muted-foreground shrink-0">{desensitize(material.publishedAt)}</span>
|
||||
<span className="text-muted-foreground shrink-0">{material.publishedAt}</span>
|
||||
</>
|
||||
)}
|
||||
{/* 相关度色条 */}
|
||||
@@ -91,7 +90,7 @@ export function MaterialItem({ material, checked, onToggle }: MaterialItemProps)
|
||||
<CollapseTransition open={expanded}>
|
||||
<div className="px-2.5 pb-2.5 pl-8 space-y-1.5 border-t">
|
||||
<p className="text-muted-foreground leading-relaxed pt-2 line-clamp-6">
|
||||
{desensitize(material.content.slice(0, 300))}
|
||||
{material.content.slice(0, 300)}
|
||||
{material.content.length > 300 && '…'}
|
||||
</p>
|
||||
{material.recUuid && (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { ListTree, Plus } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { AIOutline, OutlineSection as OutlineSectionType } from '../../types/ai-writing';
|
||||
import { OutlineSection } from './OutlineSection';
|
||||
import { CollapseTransition } from './CollapseTransition';
|
||||
@@ -93,7 +92,7 @@ export function OutlineCard({ outline, onChange, readOnly = false }: OutlineCard
|
||||
className={editable ? 'flex-1 font-semibold cursor-text hover:text-primary' : 'flex-1 font-semibold'}
|
||||
onClick={() => editable && setEditingTitle(true)}
|
||||
>
|
||||
{outline.title ? desensitize(outline.title) : <span className="text-muted-foreground italic font-normal">(未设置标题)</span>}
|
||||
{outline.title || <span className="text-muted-foreground italic font-normal">(未设置标题)</span>}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { ChevronRight, Plus, X, GripVertical } from 'lucide-react';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { OutlineSection as OutlineSectionType } from '../../types/ai-writing';
|
||||
import { CollapseTransition } from './CollapseTransition';
|
||||
@@ -101,7 +100,7 @@ export function OutlineSection({
|
||||
className={cn('flex-1 font-medium', !readOnly && 'cursor-text hover:text-primary')}
|
||||
onClick={() => !readOnly && setEditingTitle(true)}
|
||||
>
|
||||
{section.sectionTitle ? desensitize(section.sectionTitle) : <span className="text-muted-foreground italic">(未命名)</span>}
|
||||
{section.sectionTitle || <span className="text-muted-foreground italic">(未命名)</span>}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -120,7 +119,7 @@ export function OutlineSection({
|
||||
<div key={i} className="flex items-center gap-1.5 pt-1.5">
|
||||
<span className="text-muted-foreground/40 shrink-0">•</span>
|
||||
{readOnly ? (
|
||||
<span className="flex-1 text-muted-foreground">{desensitize(kp)}</span>
|
||||
<span className="flex-1 text-muted-foreground">{kp}</span>
|
||||
) : (
|
||||
<input
|
||||
value={kp}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { FileText, ChevronDown, ChevronRight, Brain } from 'lucide-react';
|
||||
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
|
||||
interface OutlineStreamingViewProps {
|
||||
text: string;
|
||||
thinkingText?: string;
|
||||
@@ -52,7 +50,7 @@ export function OutlineStreamingView({ text, thinkingText }: OutlineStreamingVie
|
||||
ref={thinkRef}
|
||||
className="text-[11px] font-mono leading-relaxed p-3 text-amber-700/70 dark:text-amber-300/60 whitespace-pre-wrap max-h-40 overflow-y-auto italic"
|
||||
>
|
||||
{desensitize(thinkingText)}
|
||||
{thinkingText}
|
||||
{/* 思考仍在进行时显示光标 */}
|
||||
{!text && (
|
||||
<span className="inline-block w-0.5 h-3.5 bg-amber-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
@@ -84,7 +82,7 @@ export function OutlineStreamingView({ text, thinkingText }: OutlineStreamingVie
|
||||
ref={preRef}
|
||||
className="text-[11px] font-mono leading-relaxed p-3 text-muted-foreground whitespace-pre-wrap max-h-52 overflow-y-auto"
|
||||
>
|
||||
{desensitize(text)}
|
||||
{text}
|
||||
<span className="inline-block w-0.5 h-3.5 bg-purple-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { CheckCircle2, Loader2 } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { StreamingReviewItem, ReviewIssue } from '../../types/ai-writing';
|
||||
|
||||
const CATEGORY_META: Record<
|
||||
@@ -42,9 +41,9 @@ function IssueRow({ issue }: { issue: ReviewIssue }) {
|
||||
)}>
|
||||
{issue.severity === 'major' ? '严重' : '轻微'}
|
||||
</span>
|
||||
<span className="text-muted-foreground">{desensitize(issue.issue ?? "")}</span>
|
||||
<span className="text-muted-foreground">{issue.issue}</span>
|
||||
{issue.suggestion && (
|
||||
<span className="text-orange-600 dark:text-orange-400"> → {desensitize(issue.suggestion)}</span>
|
||||
<span className="text-orange-600 dark:text-orange-400"> → {issue.suggestion}</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -74,10 +73,10 @@ function StreamingText({ item }: { item: StreamingReviewItem }) {
|
||||
>
|
||||
{item.thinkingText && (
|
||||
<span className="italic text-amber-600/70 dark:text-amber-400/60">
|
||||
{desensitize(item.thinkingText)}
|
||||
{item.thinkingText}
|
||||
</span>
|
||||
)}
|
||||
{desensitize(item.streamingText ?? "")}
|
||||
{item.streamingText}
|
||||
<span className="inline-block w-0.5 h-3 bg-orange-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
|
||||
</pre>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { CheckCircle2, XCircle } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { RevisionSummary } from '../../types/ai-writing';
|
||||
|
||||
interface RevisionSummaryCardProps {
|
||||
@@ -50,7 +49,7 @@ export function RevisionSummaryCard({ summary }: RevisionSummaryCardProps) {
|
||||
)}>
|
||||
{CATEGORY_LABEL[iss.category] ?? iss.category}
|
||||
</span>
|
||||
<span>{desensitize(iss.issue ?? "")}</span>
|
||||
<span>{iss.issue}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -65,7 +64,7 @@ export function RevisionSummaryCard({ summary }: RevisionSummaryCardProps) {
|
||||
</p>
|
||||
{skippedIssues.map((iss, i) => (
|
||||
<div key={i} className="flex items-start gap-1.5 pl-5 text-muted-foreground/60 leading-snug line-through">
|
||||
<span>{desensitize(iss.issue ?? "")}</span>
|
||||
<span>{iss.issue}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { AlertCircle, AlertTriangle, CheckCircle2, Circle, Loader2, PauseCircle } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { ProgressEvent } from '../../types/ai-writing';
|
||||
|
||||
type StepStatus = 'done' | 'running' | 'paused' | 'waiting' | 'error' | 'warning';
|
||||
@@ -50,7 +49,7 @@ export function TimelineStep({ event, isLast, children }: TimelineStepProps) {
|
||||
AGENT_COLOR[event.agentName] ?? 'text-muted-foreground',
|
||||
)}
|
||||
>
|
||||
{desensitize(event.agentName)}
|
||||
{event.agentName}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -71,11 +70,11 @@ export function TimelineStep({ event, isLast, children }: TimelineStepProps) {
|
||||
: 'text-amber-600 dark:text-amber-500',
|
||||
)}
|
||||
>
|
||||
{desensitize(event.title || event.message || (isError ? '出错了' : '提示'))}
|
||||
{event.title || event.message || (isError ? '出错了' : '提示')}
|
||||
</p>
|
||||
{event.detail && (
|
||||
<p className="mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words">
|
||||
{desensitize(event.detail)}
|
||||
{event.detail}
|
||||
</p>
|
||||
)}
|
||||
{/* 接口解析失败时的原始错误响应体,默认折叠,点击展开 */}
|
||||
@@ -85,13 +84,13 @@ export function TimelineStep({ event, isLast, children }: TimelineStepProps) {
|
||||
错误返回结果(点击展开)
|
||||
</summary>
|
||||
<pre className="mt-1 max-h-60 overflow-auto whitespace-pre-wrap break-all rounded bg-muted/60 p-2 text-[10px] leading-relaxed text-muted-foreground">
|
||||
{desensitize(event.raw)}
|
||||
{event.raw}
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span className="ml-1.5 text-xs text-muted-foreground">{desensitize(event.message ?? "")}</span>
|
||||
<span className="ml-1.5 text-xs text-muted-foreground">{event.message}</span>
|
||||
)}
|
||||
|
||||
{children}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { desensitize } from '@/lib/desensitize';
|
||||
import type { WritingStatus } from '../../types/ai-writing';
|
||||
|
||||
interface WritingSkeletonCardProps {
|
||||
@@ -38,7 +37,7 @@ function MaterialsSkeleton({ researchProgress }: { researchProgress?: string })
|
||||
{/* 标题行:展示素材收集专家的实时进度 */}
|
||||
<div className="flex items-center gap-2 text-xs text-blue-500 font-medium">
|
||||
<ThinkingDots color="bg-blue-400" />
|
||||
<span>{researchProgress ? desensitize(researchProgress) : '素材收集专家搜索中…'}</span>
|
||||
<span>{researchProgress || '素材收集专家搜索中…'}</span>
|
||||
</div>
|
||||
|
||||
{/* 关键词标签占位 */}
|
||||
|
||||
@@ -4,7 +4,6 @@ import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import type { CanvasArtifactText } from "../../types/artifact";
|
||||
import { TiptapEditor } from "../../editor/TiptapEditor";
|
||||
import { useWritingEditor } from "../../hooks/useWritingEditor";
|
||||
@@ -248,7 +247,7 @@ export function TextArtifactRenderer({ content, isStreaming }: TextArtifactRende
|
||||
},
|
||||
}}
|
||||
>
|
||||
{desensitize(content.fullMarkdown)}
|
||||
{content.fullMarkdown}
|
||||
</ReactMarkdown>
|
||||
<span className="inline-block w-0.5 h-4 bg-primary animate-pulse align-middle ml-0.5" />
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user