from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status from .models import LobsterMemory from .serializers import LobsterMemorySerializer, FileDiffSerializer from .services import FileScanner, DiffChecker import json @api_view(['GET']) def scan_files(request): """ 扫描本地文件 """ lobster_id = request.query_params.get('lobster_id', 'daotong') scanner = FileScanner() files = scanner.scan_directory(lobster_id) return Response({ 'success': True, 'data': files, 'total': len(files) }) @api_view(['GET']) def get_file_tree(request): """ 获取文件树 """ lobster_id = request.query_params.get('lobster_id', 'daotong') scanner = FileScanner() tree = scanner.get_file_tree(lobster_id) return Response({ 'success': True, 'data': tree }) @api_view(['GET']) def check_sync_status(request): """ 检查同步状态 """ lobster_id = request.query_params.get('lobster_id', 'daotong') # 获取本地文件 scanner = FileScanner() local_files = scanner.scan_directory(lobster_id) # 获取数据库文件 db_files = list(LobsterMemory.objects.filter( lobster_id=lobster_id ).values('file_path', 'hash', 'version', 'updated_at')) # 检查同步状态 checker = DiffChecker() sync_status = checker.check_sync_status(local_files, db_files) return Response({ 'success': True, 'data': sync_status }) @api_view(['GET']) def get_file_diff(request): """ 获取文件差异 """ file_path = request.query_params.get('file_path') lobster_id = request.query_params.get('lobster_id', 'daotong') if not file_path: return Response({ 'success': False, 'error': 'file_path is required' }, status=status.HTTP_400_BAD_REQUEST) scanner = FileScanner() # 获取本地内容 try: local_content, local_hash = scanner.get_file_content(file_path) except FileNotFoundError: local_content = None local_hash = None # 获取数据库内容 try: db_record = LobsterMemory.objects.filter( lobster_id=lobster_id, file_path=file_path ).order_by('-version').first() if db_record: db_content = db_record.content db_hash = db_record.hash else: db_content = None db_hash = None except Exception as e: return Response({ 'success': False, 'error': str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # 获取差异 checker = DiffChecker() if local_content and db_content: diff = checker.get_file_diff(local_content, db_content) else: diff = { 'local_lines': local_content.split('\n') if local_content else [], 'db_lines': db_content.split('\n') if db_content else [], 'has_diff': local_content != db_content } # 确定状态 if local_hash == db_hash: status = 'consistent' elif local_hash and not db_hash: status = 'local_newer' elif not local_hash and db_hash: status = 'db_newer' else: status = 'conflict' return Response({ 'success': True, 'data': { 'file_path': file_path, 'lobster_id': lobster_id, 'local_content': local_content, 'db_content': db_content, 'local_hash': local_hash, 'db_hash': db_hash, 'status': status, 'diff': diff } }) @api_view(['POST']) def sync_to_db(request): """ 同步到数据库 """ lobster_id = request.data.get('lobster_id', 'daotong') file_path = request.data.get('file_path') if not file_path: return Response({ 'success': False, 'error': 'file_path is required' }, status=status.HTTP_400_BAD_REQUEST) scanner = FileScanner() try: # 读取本地文件 content, file_hash = scanner.get_file_content(file_path) # 查找现有记录 existing = LobsterMemory.objects.filter( lobster_id=lobster_id, file_path=file_path ).order_by('-version').first() if existing: # 创建新版本 new_version = existing.version + 1 else: new_version = 1 # 创建新记录 record = LobsterMemory.objects.create( lobster_id=lobster_id, file_path=file_path, content=content, hash=file_hash, status='consistent', version=new_version, ) return Response({ 'success': True, 'message': '已同步到数据库', 'data': LobsterMemorySerializer(record).data }) except Exception as e: return Response({ 'success': False, 'error': str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @api_view(['POST']) def sync_to_local(request): """ 同步到本地 """ lobster_id = request.data.get('lobster_id', 'daotong') file_path = request.data.get('file_path') if not file_path: return Response({ 'success': False, 'error': 'file_path is required' }, status=status.HTTP_400_BAD_REQUEST) scanner = FileScanner() try: # 从数据库获取最新版本 db_record = LobsterMemory.objects.filter( lobster_id=lobster_id, file_path=file_path ).order_by('-version').first() if not db_record: return Response({ 'success': False, 'error': 'File not found in database' }, status=status.HTTP_404_NOT_FOUND) # 写入本地文件 scanner.write_file(file_path, db_record.content) return Response({ 'success': True, 'message': '已同步到本地', 'data': LobsterMemorySerializer(db_record).data }) except Exception as e: return Response({ 'success': False, 'error': str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @api_view(['GET']) def get_versions(request): """ 获取文件的所有版本 """ file_path = request.query_params.get('file_path') lobster_id = request.query_params.get('lobster_id', 'daotong') if not file_path: return Response({ 'success': False, 'error': 'file_path is required' }, status=status.HTTP_400_BAD_REQUEST) versions = LobsterMemory.objects.filter( lobster_id=lobster_id, file_path=file_path ).order_by('-version') return Response({ 'success': True, 'data': LobsterMemorySerializer(versions, many=True).data }) @api_view(['GET']) def get_stats(request): """ 获取统计信息 """ lobster_id = request.query_params.get('lobster_id', 'daotong') total_files = LobsterMemory.objects.filter(lobster_id=lobster_id).count() status_counts = {} for status_choice, _ in LobsterMemory.STATUS_CHOICES: count = LobsterMemory.objects.filter( lobster_id=lobster_id, status=status_choice ).count() status_counts[status_choice] = count # 获取总大小 from django.db.models import Sum total_size = LobsterMemory.objects.filter( lobster_id=lobster_id ).aggregate(total=Sum('size'))['total'] or 0 return Response({ 'success': True, 'data': { 'total_files': total_files, 'status_counts': status_counts, 'total_size': total_size, 'total_size_mb': round(total_size / 1024 / 1024, 2) } })