Files
AIclinicalresearch/docs/02-通用能力层/快速引用卡片.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

4.9 KiB
Raw Blame History

通用能力层 - 快速引用卡片

一页纸速查表,快速找到需要的通用能力


🎯 我需要...

💬 AI 对话功能

前端:

import { AIStreamChat } from '@/shared/components/Chat';
<AIStreamChat apiEndpoint="/api/v1/xxx/chat/stream" enableDeepThinking={true} />

后端:

import { createStreamingService } from '../../../common/streaming';
const service = createStreamingService(reply);
await service.streamGenerate(messages);

📚 详细文档


🤖 调用 LLM

import { LLMFactory } from '../../../common/llm/adapters/LLMFactory';

const llm = LLMFactory.getAdapter('deepseek-v3');
const response = await llm.chat(messages);

// 流式
for await (const chunk of llm.chatStream(messages)) {
  console.log(chunk.content);
}

📚 详细文档


📁 文件存储

import { storage } from '../../../common/storage';

// 上传
const url = await storage.upload('path/file.pdf', buffer);

// 下载
const buffer = await storage.download('path/file.pdf');

📚 详细文档


异步任务

import { JobFactory } from '../../../common/jobs';

const queue = JobFactory.getQueue();

// 创建任务
await queue.createJob('job-name', { taskId: 'xxx' });

// 注册Worker
queue.registerWorker('job-name', async (job) => {
  // 处理逻辑
});

📚 详细文档


📄 文档处理

import { ExtractionClient } from '../../../common/document/ExtractionClient';

const client = new ExtractionClient();
const text = await client.extractText(buffer, 'pdf');

📚 详细文档


🔍 知识库检索RAG

import { DifyClient } from '../../../common/rag/DifyClient';

const dify = new DifyClient(apiKey, baseURL);
const results = await dify.retrievalSearch(query, options);

📚 详细文档


💾 缓存服务

import { cache } from '../../../common/cache';

await cache.set('key', value, 3600);  // TTL: 3600秒
const value = await cache.get('key');
await cache.delete('key');

📚 详细文档


📝 日志记录

import { logger } from '../../../common/logging';

logger.info('[Module] 操作描述', { userId: 'xxx', detail: 'xxx' });
logger.error('[Module] 错误', { error, stack: error.stack });

📚 详细文档


🔐 认证授权

后端:

import { authenticate, getUserId } from '../../../common/auth';

// 路由
fastify.get('/api', { preHandler: [authenticate] }, handler);

// 控制器
const userId = getUserId(request);

前端:

import { getAccessToken } from '@/framework/auth/api';
const token = getAccessToken();

// 或使用 apiClient自动携带token
import apiClient from '@/common/api/axios';
await apiClient.get('/api/xxx');

📚 详细文档


📋 Prompt 管理

import { PromptService } from '../../../common/prompt/prompt.service';

const promptService = new PromptService();
const prompt = await promptService.getActivePrompt('template_code');
const rendered = promptService.renderPrompt(template, variables);

📚 详细文档


🏗️ 架构原则

正确做法

// 1. 使用通用能力,不要重复造轮子
import { createStreamingService } from '../../../common/streaming';

// 2. 遵循云原生规范
await storage.upload();  // 不要用 fs.writeFileSync()

// 3. 使用结构化日志
logger.info('[Module] 操作', { detail });  // 不要用 console.log()

// 4. 统一认证
fastify.get('/api', { preHandler: [authenticate] });

// 5. 标准化API格式
// OpenAI Compatible, not 自定义格式

错误做法

// 1. 自己实现已有的能力
reply.raw.write('data: ...');  // ❌ 应该用 StreamingService

// 2. 直接操作本地文件
fs.writeFileSync('/tmp/file');  // ❌ 应该用 storage

// 3. 使用 console.log
console.log('debug');  // ❌ 应该用 logger

// 4. 硬编码用户ID
const userId = 'test';  // ❌ 应该用 getUserId(request)

// 5. 自定义格式
{ type: 'delta', content: 'xxx' }  // ❌ 应该用 OpenAI Compatible

📚 完整文档


更新时间: 2026-01-14