系统框架文档

系统框架文档

一、项目结构

``

bossagents/

├── app/

│ ├── (auth)/

│ │ ├── auth.ts # 认证配置

│ │ ├── login/

│ │ │ └── page.tsx # 登录页

│ │ └── register/

│ │ └── page.tsx # 注册页

│ ├── (chat)/

│ │ ├── chat/

│ │ │ └── [id]/

│ │ │ └── page.tsx # 聊天页

│ │ ├── api/

│ │ │ └── chat/

│ │ │ └── route.ts # 聊天API

│ │ └── layout.tsx # 聊天布局

│ ├── api/

│ │ ├── auth/

│ │ │ ├── login/route.ts # 登录API

│ │ │ ├── logout/route.ts # 登出API

│ │ │ ├── register/route.ts # 注册API

│ │ │ └── session/route.ts # 会话API

│ │ ├── objects/

│ │ │ └── route.ts # 统一对象API

│ │ ├── models/

│ │ │ └── route.ts # 模型配置API

│ │ └── ai-proxy/

│ │ └── route.ts # AI代理API

│ ├── change-management/

│ │ ├── page.tsx # 变更管理页

│ │ └── layout.tsx # 变更管理布局

│ ├── layout.tsx # 根布局

│ ├── page.tsx # 首页

│ └── globals.css # 全局样式

├── components/

│ ├── ui/ # UI组件

│ ├── sidebar.tsx # 侧边栏

│ └── ...

├── lib/

│ ├── SCSAI/ # SCSAI相关

│ │ ├── client.ts # SCSAI客户端

│ │ ├── aml.ts # AML执行

│ │ └── fallback.ts # 降级策略

│ ├── db/ # 数据库相关

│ │ ├── index.ts # 数据库初始化

│ │ ├── auth.ts # 认证数据库操作

│ │ └── local-data.ts # 本地数据

│ ├── llm/ # 大模型相关

│ │ ├── index.ts # 大模型配置

│ │ └── providers.ts # 模型提供商

│ └── aml/ # AML模板

│ ├── queries.ts # 查询模板

│ ├── creates.ts # 创建模板

│ ├── edits.ts # 编辑模板

│ └── deletes.ts # 删除模板

├── docs/ # 文档

└── data/ # 数据目录

└── chatbot.db # SQLite数据库

`

二、数据库设计

2.1 数据库初始化

文件位置/app/lib/db/index.ts

`typescript

import Database from 'better-sqlite3';

import path from 'path';

const dbPath = path.join(process.cwd(), 'data', 'chatbot.db');

let db: Database.Database | null = null;

export function getDatabase(): Database.Database {

if (!db) {

db = new Database(dbPath);

db.pragma('journal_mode = WAL');

initDatabase(db);

}

return db;

}

function initDatabase(database: Database.Database) {

// 用户表

database.exec(

CREATE TABLE IF NOT EXISTS "User" (

id INTEGER PRIMARY KEY AUTOINCREMENT,

email TEXT UNIQUE NOT NULL,

password TEXT NOT NULL,

name TEXT,

type TEXT DEFAULT 'regular',

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

updated_at TEXT DEFAULT CURRENT_TIMESTAMP

)

);

// 会话表

database.exec(

CREATE TABLE IF NOT EXISTS "Session" (

id TEXT PRIMARY KEY,

user_id INTEGER NOT NULL,

expires_at TEXT NOT NULL,

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

FOREIGN KEY (user_id) REFERENCES "User"(id)

)

);

// 模型配置表

database.exec(

CREATE TABLE IF NOT EXISTS "ModelConfig" (

id INTEGER PRIMARY KEY AUTOINCREMENT,

name TEXT UNIQUE NOT NULL,

provider TEXT NOT NULL,

model TEXT NOT NULL,

api_key TEXT,

base_url TEXT,

temperature REAL DEFAULT 0.7,

max_tokens INTEGER DEFAULT 2000,

is_default INTEGER DEFAULT 0,

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

updated_at TEXT DEFAULT CURRENT_TIMESTAMP

)

);

// 聊天历史表

database.exec(

CREATE TABLE IF NOT EXISTS "ChatHistory" (

id INTEGER PRIMARY KEY AUTOINCREMENT,

user_id INTEGER NOT NULL,

message TEXT NOT NULL,

response TEXT,

model TEXT,

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

FOREIGN KEY (user_id) REFERENCES "User"(id)

)

);

// AML模板表

database.exec(

CREATE TABLE IF NOT EXISTS "AmlTemplate" (

id INTEGER PRIMARY KEY AUTOINCREMENT,

name TEXT UNIQUE NOT NULL,

type TEXT NOT NULL,

item_type TEXT NOT NULL,

template TEXT NOT NULL,

description TEXT,

parameters TEXT,

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

updated_at TEXT DEFAULT CURRENT_TIMESTAMP

)

);

// AML对象表

database.exec(

CREATE TABLE IF NOT EXISTS "AmlObject" (

id INTEGER PRIMARY KEY AUTOINCREMENT,

item_type TEXT NOT NULL,

name TEXT,

aml TEXT NOT NULL,

schema TEXT,

created_at TEXT DEFAULT CURRENT_TIMESTAMP,

updated_at TEXT DEFAULT CURRENT_TIMESTAMP

)

);

// 初始化默认模型配置

initDefaultModels(database);

}

function initDefaultModels(database: Database.Database) {

const existingModels = database.prepare('SELECT COUNT(*) as count FROM "ModelConfig"').get() as { count: number };

if (existingModels.count === 0) {

// 插入星火模型

database.prepare(

INSERT INTO "ModelConfig" (name, provider, model, api_key, base_url, temperature, max_tokens, is_default)

VALUES (?, ?, ?, ?, ?, ?, ?, ?)

).run(

'讯飞星火',

'spark',

'astron-code-latest',

process.env.SPARK_API_KEY || '',

'https://maas-coding-api.cn-huabei-1.xf-yun.com/v2',

0.7,

2000,

1

);

// 插入DeepSeek模型

database.prepare(

INSERT INTO "ModelConfig" (name, provider, model, api_key, base_url, temperature, max_tokens, is_default)

VALUES (?, ?, ?, ?, ?, ?, ?, ?)

).run(

'DeepSeek',

'deepseek',

'deepseek-chat',

process.env.DEEPSEEK_API_KEY || '',

'https://api.deepseek.com/v1',

0.7,

2000,

0

);

console.log('Default models initialized');

}

}

`

2.2 数据库表结构

用户表 (User)

| 字段 | 类型 | 说明 |

|------|------|------|

| id | INTEGER | 主键 |

| email | TEXT | 邮箱(唯一) |

| password | TEXT | 密码(MD5) |

| name | TEXT | 用户名 |

| type | TEXT | 用户类型 |

| created_at | TEXT | 创建时间 |

| updated_at | TEXT | 更新时间 |

会话表 (Session)

| 字段 | 类型 | 说明 |

|------|------|------|

| id | TEXT | 会话ID(UUID) |

| user_id | INTEGER | 用户ID |

| expires_at | TEXT | 过期时间 |

| created_at | TEXT | 创建时间 |

模型配置表 (ModelConfig)

| 字段 | 类型 | 说明 |

|------|------|------|

| id | INTEGER | 主键 |

| name | TEXT | 模型名称 |

| provider | TEXT | 提供商 |

| model | TEXT | 模型标识 |

| api_key | TEXT | API密钥 |

| base_url | TEXT | 基础URL |

| temperature | REAL | 温度参数 |

| max_tokens | INTEGER | 最大tokens |

| is_default | INTEGER | 是否默认 |

三、认证系统

3.1 认证配置

文件位置/app/(auth)/auth.ts

`typescript

import { getDatabase } from '@/app/lib/db';

import { cookies } from 'next/headers';

export type UserType = 'admin' | 'regular';

export interface SessionUser {

id: number;

email: string;

name: string;

type: UserType;

}

export async function auth(): Promise<{ user: SessionUser } | null> {

const cookieStore = await cookies();

const sessionId = cookieStore.get('sessionId')?.value;

if (!sessionId) {

return null;

}

const db = getDatabase();

const session = db.prepare(

SELECT s.*, u.id as user_id, u.email, u.name, u.type

FROM "Session" s

JOIN "User" u ON s.user_id = u.id

WHERE s.id = ? AND s.expires_at > datetime('now')

).get(sessionId) as any;

if (!session) {

return null;

}

return {

user: {

id: session.user_id,

email: session.email,

name: session.name,

type: session.type as UserType

}

};

}

`

3.2 登录API

文件位置/app/api/auth/login/route.ts

`typescript

import { NextRequest, NextResponse } from 'next/server';

import { getDatabase } from '@/app/lib/db';

import crypto from 'crypto';

function md5(str: string): string {

return crypto.createHash('md5').update(str).digest('hex');

}

export async function POST(request: NextRequest) {

try {

const { email, password } = await request.json();

if (!email || !password) {

return NextResponse.json(

{ success: false, message: 'Email and password are required' },

{ status: 400 }

);

}

const db = getDatabase();

const user = db.prepare('SELECT * FROM "User" WHERE email = ?').get(email) as any;

if (!user) {

return NextResponse.json(

{ success: false, message: 'Invalid email or password' },

{ status: 401 }

);

}

// 开发环境允许任意密码

const isPasswordValid = process.env.NODE_ENV === 'development' || user.password === md5(password);

if (!isPasswordValid) {

return NextResponse.json(

{ success: false, message: 'Invalid email or password' },

{ status: 401 }

);

}

// 创建会话

const sessionId = crypto.randomUUID();

const expiresAt = new Date(Date.now() + 24 60 60 * 1000).toISOString();

db.prepare(

INSERT INTO "Session" (id, user_id, expires_at)

VALUES (?, ?, ?)

).run(sessionId, user.id, expiresAt);

const response = NextResponse.json({

success: true,

message: 'Login successful',

data: {

id: user.id,

email: user.email,

name: user.name,

type: user.type

}

});

response.cookies.set('sessionId', sessionId, {

httpOnly: true,

secure: process.env.NODE_ENV === 'production',

sameSite: 'lax',

expires: new Date(Date.now() + 24 60 60 * 1000)

});

return response;

} catch (error: any) {

console.error('Login error:', error);

return NextResponse.json(

{ success: false, message: 'Internal server error' },

{ status: 500 }

);

}

}

`

3.3 注册API

文件位置/app/api/auth/register/route.ts

`typescript

import { NextRequest, NextResponse } from 'next/server';

import { getDatabase } from '@/app/lib/db';

import crypto from 'crypto';

function md5(str: string): string {

return crypto.createHash('md5').update(str).digest('hex');

}

export async function POST(request: NextRequest) {

try {

const { email, password, name } = await request.json();

if (!email || !password) {

return NextResponse.json(

{ success: false, message: 'Email and password are required' },

{ status: 400 }

);

}

const db = getDatabase();

// 检查邮箱是否已存在

const existingUser = db.prepare('SELECT id FROM "User" WHERE email = ?').get(email);

if (existingUser) {

return NextResponse.json(

{ success: false, message: 'Email already exists' },

{ status: 400 }

);

}

// 创建用户

const hashedPassword = md5(password);

const result = db.prepare(

INSERT INTO "User" (email, password, name, type)

VALUES (?, ?, ?, ?)

).run(email, hashedPassword, name || '', 'regular');

return NextResponse.json({

success: true,

message: 'Registration successful',

data: {

id: result.lastInsertRowid,

email,

name: name || ''

}

});

} catch (error: any) {

console.error('Registration error:', error);

return NextResponse.json(

{ success: false, message: 'Internal server error' },

{ status: 500 }

);

}

}

`

四、大模型配置

4.1 默认模型配置

文件位置/app/lib/llm/providers.ts

`typescript

// 默认模型配置

export const defaultModels = [

{

name: '讯飞星火',

provider: 'spark',

model: 'astron-code-latest',

apiKey: process.env.SPARK_API_KEY || 'your-spark-api-key',

baseURL: 'https://maas-coding-api.cn-huabei-1.xf-yun.com/v2',

temperature: 0.7,

maxTokens: 2000,

isDefault: true

},

{

name: 'DeepSeek',

provider: 'deepseek',

model: 'deepseek-chat',

apiKey: process.env.DEEPSEEK_API_KEY || 'your-deepseek-api-key',

baseURL: 'https://api.deepseek.com/v1',

temperature: 0.7,

maxTokens: 2000,

isDefault: false

}

];

// 模型提供商配置

export const modelProviders = {

spark: {

name: '讯飞星火',

baseURL: 'https://maas-coding-api.cn-huabei-1.xf-yun.com/v2',

apiKeyEnv: 'SPARK_API_KEY'

},

deepseek: {

name: 'DeepSeek',

baseURL: 'https://api.deepseek.com/v1',

apiKeyEnv: 'DEEPSEEK_API_KEY'

},

openai: {

name: 'OpenAI',

baseURL: 'https://api.openai.com/v1',

apiKeyEnv: 'OPENAI_API_KEY'

},

anthropic: {

name: 'Claude',

baseURL: 'https://api.anthropic.com/v1',

apiKeyEnv: 'ANTHROPIC_API_KEY'

},

qianwen: {

name: '通义千问',

baseURL: 'https://dashscope.aliyuncs.com/api/v1',

apiKeyEnv: 'DASHSCOPE_API_KEY'

},

moonshotai: {

name: '月之暗面',

baseURL: 'https://api.moonshot.cn/v1',

apiKeyEnv: 'MOONSHOTAI_API_KEY'

}

};

`

4.2 大模型调用

文件位置/app/lib/llm/index.ts

`typescript

import { getDatabase } from '@/app/lib/db';

import { defaultModels } from './providers';

export interface LLMConfig {

provider: string;

model: string;

apiKey: string;

baseURL: string;

temperature: number;

maxTokens: number;

}

// 获取默认模型

export function getDefaultModel(): LLMConfig | null {

const db = getDatabase();

// 先从数据库获取

const dbModel = db.prepare(

'SELECT * FROM "ModelConfig" WHERE is_default = 1 LIMIT 1'

).get() as any;

if (dbModel) {

return {

provider: dbModel.provider,

model: dbModel.model,

apiKey: dbModel.api_key || '',

baseURL: dbModel.base_url || '',

temperature: dbModel.temperature,

maxTokens: dbModel.max_tokens

};

}

// 如果数据库没有,返回默认配置

const defaultModel = defaultModels.find(m => m.isDefault);

if (defaultModel) {

return {

provider: defaultModel.provider,

model: defaultModel.model,

apiKey: defaultModel.apiKey,

baseURL: defaultModel.baseURL,

temperature: defaultModel.temperature,

maxTokens: defaultModel.maxTokens

};

}

return null;

}

// 获取所有模型

export function getAllModels() {

const db = getDatabase();

const dbModels = db.prepare('SELECT * FROM "ModelConfig"').get() as any[];

if (dbModels && dbModels.length > 0) {

return dbModels.map(m => ({

id: m.id,

name: m.name,

provider: m.provider,

model: m.model,

apiKey: m.api_key,

baseURL: m.base_url,

temperature: m.temperature,

maxTokens: m.max_tokens,

isDefault: m.is_default === 1

}));

}

return defaultModels;

}

`

4.3 AI代理API

文件位置/app/api/ai-proxy/route.ts

`typescript

import { NextRequest, NextResponse } from 'next/server';

import { getDefaultModel } from '@/app/lib/llm';

export async function POST(request: NextRequest) {

try {

const body = await request.json();

const { messages, provider, model: modelName, apiKey, baseURL } = body;

// 使用传入的配置或默认模型

let config;

if (provider && modelName) {

config = {

provider,

model: modelName,

apiKey: apiKey || '',

baseURL: baseURL || ''

};

} else {

config = getDefaultModel();

if (!config) {

return NextResponse.json(

{ success: false, error: 'No model configured' },

{ status: 400 }

);

}

}

let apiEndpoint = '';

const headers: Record = {

'Content-Type': 'application/json'

};

// 根据提供商设置API端点和认证

switch (config.provider) {

case 'spark':

apiEndpoint = config.baseURL || 'https://maas-coding-api.cn-huabei-1.xf-yun.com/v2';

headers['Authorization'] = Bearer ${config.apiKey};

break;

case 'deepseek':

apiEndpoint = config.baseURL || 'https://api.deepseek.com/v1/chat/completions';

headers['Authorization'] = Bearer ${config.apiKey};

break;

case 'openai':

apiEndpoint = (config.baseURL || 'https://api.openai.com/v1') + '/chat/completions';

headers['Authorization'] = Bearer ${config.apiKey};

break;

default:

return NextResponse.json(

{ success: false, error: Unsupported provider: ${config.provider} },

{ status: 400 }

);

}

// 调用大模型API

const response = await fetch(apiEndpoint, {

method: 'POST',

headers,

body: JSON.stringify({

model: config.model,

messages,

temperature: 0.7,

max_tokens: 2000

})

});

if (!response.ok) {

const errorText = await response.text();

console.error('AI API error:', errorText);

return NextResponse.json(

{ success: false, error: AI API error: ${response.status} },

{ status: response.status }

);

}

const data = await response.json();

return NextResponse.json({

success: true,

data: {

content: data.choices?.[0]?.message?.content || '',

usage: data.usage

}

});

} catch (error: any) {

console.error('AI proxy error:', error);

return NextResponse.json(

{ success: false, error: error.message },

{ status: 500 }

);

}

}

`

五、环境变量配置

文件位置/app/.env.local

`env

SCSAI配置

SCSAI_SERVER=http://114.113.153.234/scplm

SCSAI_DATABASE=agent

大模型API密钥(默认配置)

SPARK_API_KEY=0508e2d155d689743f9fef6e9fd20400:MDlkZDI1YTU0ZTkyZDMyOTllOWMwMzQ5

DEEPSEEK_API_KEY=your-deepseek-api-key

OPENAI_API_KEY=your-openai-api-key

应用配置

NEXT_PUBLIC_APP_NAME=老板智能体工作台

NEXT_PUBLIC_APP_VERSION=1.0.0

``

六、关键文件位置总结

功能文件位置
数据库初始化/app/lib/db/index.ts
认证配置/app/(auth)/auth.ts
登录API/app/api/auth/login/route.ts
注册API/app/api/auth/register/route.ts
大模型配置/app/lib/llm/providers.ts
大模型调用/app/lib/llm/index.ts
AI代理API/app/api/ai-proxy/route.ts
SCSAI客户端/app/lib/SCSAI/client.ts
AML操作/app/lib/aml/index.ts
对象API/app/api/objects/route.ts
← 返回案例列表
分享:
🤖 Try Now →
🤖
🎁