duqing2026 commited on
Commit
7844eee
·
1 Parent(s): 517964f

demo 效果展示,方便 hf 部署浏览

Browse files
src/app/api/documents/[id]/route.ts CHANGED
@@ -1,17 +1,19 @@
1
- import { NextResponse } from 'next/server';
2
  import db from '@/lib/db';
3
 
4
  export async function GET(
5
- request: Request,
6
  { params }: { params: Promise<{ id: string }> }
7
  ) {
8
  try {
9
  const resolvedParams = await params;
10
  const { id } = resolvedParams;
 
11
 
12
  // DEMO DATA HANDLER
13
- if (id.startsWith('demo/')) {
14
  // Return static content for demo docs
 
15
  const demoDocs: Record<string, any> = {
16
  'demo/kb1/doc1': {
17
  id: 'demo/kb1/doc1',
 
1
+ import { NextRequest, NextResponse } from 'next/server';
2
  import db from '@/lib/db';
3
 
4
  export async function GET(
5
+ request: NextRequest,
6
  { params }: { params: Promise<{ id: string }> }
7
  ) {
8
  try {
9
  const resolvedParams = await params;
10
  const { id } = resolvedParams;
11
+ const isDemoMode = request.nextUrl.searchParams.get('mode') === 'demo';
12
 
13
  // DEMO DATA HANDLER
14
+ if (isDemoMode || id.startsWith('demo/')) {
15
  // Return static content for demo docs
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
  const demoDocs: Record<string, any> = {
18
  'demo/kb1/doc1': {
19
  id: 'demo/kb1/doc1',
src/app/api/documents/route.ts CHANGED
@@ -1,10 +1,12 @@
1
 
2
- import { NextResponse } from 'next/server';
3
  import db from '@/lib/db';
4
  import { startYuqueSync, getSyncStatus } from '@/lib/yuque-service';
5
 
6
- export async function GET() {
7
  try {
 
 
8
  // Select all columns EXCEPT content_preview to reduce payload size, but include length for stats
9
  // Use word_count if available (more accurate), otherwise fallback to 0 (will be updated on next sync)
10
  const docs = db.prepare(`
@@ -21,7 +23,7 @@ export async function GET() {
21
 
22
  // DEMO DATA FALLBACK
23
  // If database is empty or connection fails, return static demo data for HuggingFace/Demo purposes
24
- if (docs.length === 0 && kbs.length === 0) {
25
  return NextResponse.json({
26
  documents: [
27
  {
 
1
 
2
+ import { NextRequest, NextResponse } from 'next/server';
3
  import db from '@/lib/db';
4
  import { startYuqueSync, getSyncStatus } from '@/lib/yuque-service';
5
 
6
+ export async function GET(req: NextRequest) {
7
  try {
8
+ const isDemoMode = req.nextUrl.searchParams.get('mode') === 'demo';
9
+
10
  // Select all columns EXCEPT content_preview to reduce payload size, but include length for stats
11
  // Use word_count if available (more accurate), otherwise fallback to 0 (will be updated on next sync)
12
  const docs = db.prepare(`
 
23
 
24
  // DEMO DATA FALLBACK
25
  // If database is empty or connection fails, return static demo data for HuggingFace/Demo purposes
26
+ if (isDemoMode || (docs.length === 0 && kbs.length === 0)) {
27
  return NextResponse.json({
28
  documents: [
29
  {
src/app/api/history/sessions/route.ts CHANGED
@@ -2,12 +2,13 @@ import { NextRequest, NextResponse } from 'next/server';
2
  import db from '@/lib/db';
3
 
4
  // GET: List all sessions
5
- export async function GET() {
6
  try {
 
7
  const sessions = db.prepare('SELECT * FROM sessions ORDER BY created_at DESC').all();
8
 
9
  // DEMO DATA FALLBACK
10
- if (sessions.length === 0) {
11
  return NextResponse.json([
12
  {
13
  id: 'demo-session-1',
 
2
  import db from '@/lib/db';
3
 
4
  // GET: List all sessions
5
+ export async function GET(req: NextRequest) {
6
  try {
7
+ const isDemoMode = req.nextUrl.searchParams.get('mode') === 'demo';
8
  const sessions = db.prepare('SELECT * FROM sessions ORDER BY created_at DESC').all();
9
 
10
  // DEMO DATA FALLBACK
11
+ if (isDemoMode || sessions.length === 0) {
12
  return NextResponse.json([
13
  {
14
  id: 'demo-session-1',
src/app/knowledge/page.tsx CHANGED
@@ -325,19 +325,27 @@ function KnowledgePageContent() {
325
 
326
  const fetchDocuments = async () => {
327
  try {
328
- const res = await fetch('/api/documents');
 
 
 
 
329
  const data = await res.json();
330
  setDocuments(data.documents || []);
331
  setKnowledgeBases(data.knowledgeBases || []);
332
  setSyncStatus(data.status);
333
 
334
- // Initial KB selection logic (only if not already set via URL)
335
- if (!currentKbNamespace && data.knowledgeBases && data.knowledgeBases.length > 0) {
336
  // Check URL first
337
  const kbParam = searchParams.get('kb');
338
- if (kbParam && data.knowledgeBases.some((k: KnowledgeBase) => k.namespace === kbParam)) {
339
- setCurrentKbNamespace(kbParam);
 
 
 
340
  } else {
 
341
  setCurrentKbNamespace(data.knowledgeBases[0].namespace);
342
  }
343
  }
@@ -430,7 +438,11 @@ function KnowledgePageContent() {
430
  if (selectedNode && !selectedNode.doc.content_preview && selectedNode.doc.id) {
431
  setIsLoadingContent(true);
432
  try {
433
- const res = await fetch(`/api/documents/${encodeURIComponent(selectedNode.doc.id)}`);
 
 
 
 
434
  if (res.ok) {
435
  const data = await res.json();
436
  if (data.content_preview) {
@@ -461,7 +473,7 @@ function KnowledgePageContent() {
461
  }, 2000);
462
 
463
  return () => clearInterval(interval);
464
- }, [syncStatus.status]);
465
 
466
  const handleSync = async () => {
467
  try {
@@ -494,6 +506,11 @@ function KnowledgePageContent() {
494
  </div>
495
 
496
  <div className="flex items-center gap-4">
 
 
 
 
 
497
  <button
498
  onClick={handleSync}
499
  disabled={syncStatus.status === 'running'}
 
325
 
326
  const fetchDocuments = async () => {
327
  try {
328
+ const isDemoEnv = process.env.NEXT_PUBLIC_DEMO_MODE === 'true';
329
+ const isDemoParam = searchParams.get('demo') === 'true';
330
+ const isDemo = isDemoEnv || isDemoParam;
331
+
332
+ const res = await fetch(`/api/documents${isDemo ? '?mode=demo' : ''}`);
333
  const data = await res.json();
334
  setDocuments(data.documents || []);
335
  setKnowledgeBases(data.knowledgeBases || []);
336
  setSyncStatus(data.status);
337
 
338
+ // Initial KB selection logic
339
+ if (data.knowledgeBases && data.knowledgeBases.length > 0) {
340
  // Check URL first
341
  const kbParam = searchParams.get('kb');
342
+ // Verify if the kbParam actually exists in the fetched knowledge bases
343
+ const kbExists = kbParam && data.knowledgeBases.some((k: KnowledgeBase) => k.namespace === kbParam);
344
+
345
+ if (kbExists) {
346
+ if (!currentKbNamespace) setCurrentKbNamespace(kbParam);
347
  } else {
348
+ // If no KB selected, or selected KB doesn't exist (e.g. switching modes), select the first one
349
  setCurrentKbNamespace(data.knowledgeBases[0].namespace);
350
  }
351
  }
 
438
  if (selectedNode && !selectedNode.doc.content_preview && selectedNode.doc.id) {
439
  setIsLoadingContent(true);
440
  try {
441
+ const isDemoEnv = process.env.NEXT_PUBLIC_DEMO_MODE === 'true';
442
+ const isDemoParam = searchParams.get('demo') === 'true';
443
+ const isDemo = isDemoEnv || isDemoParam;
444
+
445
+ const res = await fetch(`/api/documents/${encodeURIComponent(selectedNode.doc.id)}${isDemo ? '?mode=demo' : ''}`);
446
  if (res.ok) {
447
  const data = await res.json();
448
  if (data.content_preview) {
 
473
  }, 2000);
474
 
475
  return () => clearInterval(interval);
476
+ }, [syncStatus.status, searchParams.get('demo')]);
477
 
478
  const handleSync = async () => {
479
  try {
 
506
  </div>
507
 
508
  <div className="flex items-center gap-4">
509
+ {(process.env.NEXT_PUBLIC_DEMO_MODE === 'true' || searchParams.get('demo') === 'true') && (
510
+ <div className="px-2 py-1 bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 text-xs font-medium rounded border border-amber-200 dark:border-amber-800">
511
+ Demo Mode
512
+ </div>
513
+ )}
514
  <button
515
  onClick={handleSync}
516
  disabled={syncStatus.status === 'running'}
src/hooks/useChatHistory.ts CHANGED
@@ -110,7 +110,8 @@ export function useChatHistory() {
110
  useEffect(() => {
111
  async function fetchSessions() {
112
  try {
113
- const res = await fetch('/api/history/sessions');
 
114
  if (!res.ok) throw new Error('Failed to fetch sessions');
115
  const data = await res.json();
116
  setSessions(data);
 
110
  useEffect(() => {
111
  async function fetchSessions() {
112
  try {
113
+ const isDemo = process.env.NEXT_PUBLIC_DEMO_MODE === 'true';
114
+ const res = await fetch(`/api/history/sessions${isDemo ? '?mode=demo' : ''}`);
115
  if (!res.ok) throw new Error('Failed to fetch sessions');
116
  const data = await res.json();
117
  setSessions(data);
备注.md CHANGED
@@ -1,9 +0,0 @@
1
-
2
- 你实现的demo 功能,上传之后没有啊,能不能在本地看一下,或者用什么方式检查一下,确定可以再上传。或者是你确保代码没问题,也可以直接更新,告诉,我再上传试一下
3
- - 知识库管理页面 :
4
- - 将显示 2 个演示知识库:“产品手册”和“技术文档”。
5
- - 包含 3 篇演示文档:“RAG 系统介绍”、“快速开始指南”和“API 接口文档”。
6
- - 文档列表会显示字数、同步时间等模拟数据。
7
- - 历史对话记录 :
8
- - 侧边栏会显示 2 个历史会话:“什么是 RAG 架构?”和“DeepSeek V3 性能评估”。
9
- - 点击这些会话,可以查看预设的对话内容(问答详情)。