# coding:utf-8 from django.shortcuts import render,redirect from django.http.response import JsonResponse,Http404,HttpResponseNotAllowed,HttpResponse from django.http import HttpResponseForbidden from django.contrib.auth.decorators import login_required # 登录需求装饰器 from django.views.decorators.http import require_http_methods,require_GET,require_POST # 视图请求方法装饰器 from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage,InvalidPage # 后端分页 from django.core.exceptions import PermissionDenied,ObjectDoesNotExist from app_doc.models import Project,Doc,DocTemp from django.contrib.auth.models import User from django.db.models import Q from django.db import transaction from loguru import logger import datetime import traceback import re from app_doc.report_utils import * from app_admin.decorators import check_headers,allow_report_file import os.path # 替换前端传来的非法字符 def validateTitle(title): rstr = r"[\/\\\:\*\?\"\<\>\|\[\]]" # '/ \ : * ? " < > |' new_title = re.sub(rstr, "_", title) # 替换为下划线 return new_title # 文集列表(首页) @logger.catch() def project_list(request): kw = request.GET.get('kw','') # 搜索词 sort = request.GET.get('sort',0) # 排序,0表示按时间升序排序,1表示按时间降序排序,默认为0 role = request.GET.get('role',-1) # 筛选文集权限,默认为显示所有可显示的文集 # 是否排序 if sort in ['',0,'0']: sort_str = '' else: sort_str = '-' # 是否搜索 if kw == '': is_kw = False else: is_kw = True # 是否认证 if request.user.is_authenticated: is_auth = True else: is_auth = False # 是否筛选 if role in ['',-1,'-1']: is_role = False role_list = [0,3] else: is_role = True # 没有搜索 and 认证用户 and 没有筛选 if (is_kw is False) and (is_auth) and (is_role is False): colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集列表 project_list = Project.objects.filter( Q(role__in=role_list) | \ Q(role=2,role_value__contains=str(request.user.username)) | \ Q(create_user=request.user) | \ Q(id__in=colla_list) ).order_by("{}create_time".format(sort_str)) # 没有搜索 and 认证用户 and 有筛选 elif (is_kw is False ) and (is_auth) and (is_role): if role in ['0',0]: project_list = Project.objects.filter(role=0).order_by("{}create_time".format(sort_str)) elif role in ['1',1]: project_list = Project.objects.filter(create_user=request.user,role=1).order_by("{}create_time".format(sort_str)) elif role in ['2',2]: project_list = Project.objects.filter(role=2,role_value__contains=str(request.user.username)).order_by("{}create_time".format(sort_str)) elif role in ['3',3]: project_list = Project.objects.filter(role=3).order_by("{}create_time".format(sort_str)) elif role in ['99',99]: colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集列表 project_list = Project.objects.filter(id__in=colla_list).order_by("{}create_time".format(sort_str)) else: return render(request,'404.html') # 没有搜索 and 游客 and 没有筛选 elif (is_kw is False) and (is_auth is False) and (is_role is False): project_list = Project.objects.filter(role__in=[0,3]).order_by("{}create_time".format(sort_str)) # 没有搜索 and 游客 and 有筛选 elif (is_kw is False) and (is_auth is False) and (is_role): if role in ['0',0]: project_list = Project.objects.filter(role=0).order_by("{}create_time".format(sort_str)) elif role in ['3',3]: project_list = Project.objects.filter(role=3).order_by("{}create_time".format(sort_str)) else: return render(request,'404.html') # 有搜索 and 认证用户 and 没有筛选 elif (is_kw) and (is_auth) and (is_role is False): colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集 # 查询所有可显示的文集 project_list = Project.objects.filter( Q(role__in=[0, 3]) | \ Q(role=2, role_value__contains=str(request.user.username)) | \ Q(create_user=request.user) | \ Q(id__in=colla_list), Q(name__icontains=kw) | Q(intro__icontains=kw) ).order_by('{}create_time'.format(sort_str)) # 有搜索 and 认证用户 and 有筛选 elif (is_kw) and (is_auth) and (is_role): if role in ['0',0]: project_list = Project.objects.filter( Q(name__icontains=kw)|Q(intro__icontains=kw), role=0 ).order_by("{}create_time".format(sort_str)) elif role in ['1',1]: project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), create_user=request.user ).order_by("{}create_time".format(sort_str)) elif role in ['2',2]: project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), role=2, role_value__contains=str(request.user.username) ).order_by("{}create_time".format(sort_str)) elif role in ['3',3]: project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), role=3 ).order_by("{}create_time".format(sort_str)) elif role in ['99',99]: colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集列表 project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), id__in=colla_list ).order_by("{}create_time".format(sort_str)) else: return render(request,'404.html') # 有搜索 and 游客 and 没有筛选 elif (is_kw) and (is_auth is False) and (is_role is False): project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), role__in=[0, 3] ).order_by("{}create_time".format(sort_str)) # 有搜索 and 游客 and 有筛选 elif (is_kw) and (is_auth is False) and (is_role): if role in ['0',0]: project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), role=0 ).order_by("{}create_time".format(sort_str)) elif role in ['3',3]: project_list = Project.objects.filter( Q(name__icontains=kw) | Q(intro__icontains=kw), role=3 ).order_by("{}create_time".format(sort_str)) else: return render(request,'404.html') # 分页处理 paginator = Paginator(project_list, 12) page = request.GET.get('page', 1) try: projects = paginator.page(page) except PageNotAnInteger: projects = paginator.page(1) except EmptyPage: projects = paginator.page(paginator.num_pages) return render(request, 'app_doc/pro_list.html', locals()) # 创建文集 @login_required() @require_http_methods(['POST']) def create_project(request): try: name = request.POST.get('pname','') name = validateTitle(name) desc = request.POST.get('desc','') role = request.POST.get('role',0) role_list = ['0','1','2','3',0,1,2,3] if name != '': project = Project.objects.create( name=validateTitle(name), intro=desc[:100], create_user=request.user, role = int(role) if role in role_list else 0 ) project.save() return JsonResponse({'status':True,'data':{'id':project.id,'name':project.name}}) else: return JsonResponse({'status':False,'data':'文集名称不能为空!'}) except Exception as e: logger.exception("创建文集出错") return JsonResponse({'status':False,'data':'出现异常,请检查输入值!'}) # 文集页 @require_http_methods(['GET']) @check_headers def project_index(request,pro_id): # 获取文集 try: # 获取文集信息 project = Project.objects.get(id=int(pro_id)) # 获取文集的协作用户信息 if request.user.is_authenticated: # 对登陆用户查询其协作文档信息 colla_user = ProjectCollaborator.objects.filter(project=project,user=request.user).count() else: colla_user = 0 # 获取文集前台下载权限 try: allow_download = ProjectReport.objects.get(project=project) except ObjectDoesNotExist: allow_download = False # 私密文集并且访问者非创建者非协作者 if (project.role == 1) and (request.user != project.create_user) and (colla_user == 0): return render(request,'404.html') # 指定用户可见文集 elif project.role == 2: user_list = project.role_value if request.user.is_authenticated: # 认证用户判断是否在许可用户列表中 if (request.user.username not in user_list) and \ (request.user != project.create_user) and \ (colla_user == 0): # 访问者不在指定用户之中 return render(request, '404.html') else:# 游客直接返回404 return render(request, '404.html') # 访问码可见 elif project.role == 3: # 浏览用户不为创建者、协作者 if request.user != project.create_user and colla_user == 0: viewcode = project.role_value viewcode_name = 'viewcode-{}'.format(project.id) r_viewcode = request.COOKIES[viewcode_name] if viewcode_name in request.COOKIES.keys() else 0 # 从cookie中获取访问码 if viewcode != r_viewcode: # cookie中的访问码不等于文集访问码,跳转到访问码认证界面 return redirect('/check_viewcode/?to={}'.format(request.path)) # 获取搜索词 kw = request.GET.get('kw','') # 获取文集下所有一级文档 # project_docs = Doc.objects.filter( # top_doc=int(pro_id), # parent_doc=0, # status=1 # ).values('id','name','top_doc').order_by('sort') if kw != '': search_result = Doc.objects.filter(top_doc=int(pro_id),pre_content__icontains=kw) return render(request,'app_doc/project_doc_search.html',locals()) return render(request, 'app_doc/project.html', locals()) except Exception as e: logger.exception("文集页访问异常") return render(request,'404.html') # 修改文集 @login_required() @require_http_methods(['POST']) def modify_project(request): try: pro_id = request.POST.get('pro_id',None) project = Project.objects.get(id=pro_id) # 验证用户有权限修改文集 if (request.user == project.create_user) or request.user.is_superuser: name = request.POST.get('name',None) content = request.POST.get('desc',None) project.name = validateTitle(name) project.intro = content project.save() return JsonResponse({'status':True,'data':'修改成功'}) else: return JsonResponse({'status':False,'data':'非法请求'}) except Exception as e: logger.exception("修改文集出错") return JsonResponse({'status':False,'data':'请求出错'}) # 修改文集权限 @login_required() @require_http_methods(['GET',"POST"]) @logger.catch() def modify_project_role(request,pro_id): try: pro = Project.objects.get(id=pro_id) except ObjectDoesNotExist: return Http404 if (pro.create_user != request.user) and (request.user.is_superuser is False): return render(request,'403.html') else: if request.method == 'GET': return render(request,'app_doc/manage_project_role.html',locals()) elif request.method == 'POST': role_type = request.POST.get('role','') if role_type != '': if int(role_type) in [0,1]:# 公开或私密 Project.objects.filter(id=int(pro_id)).update( role = role_type, modify_time = datetime.datetime.now() ) if int(role_type) == 2: # 指定用户可见 role_value = request.POST.get('tagsinput','') Project.objects.filter(id=int(pro_id)).update( role=role_type, role_value = role_value, modify_time = datetime.datetime.now() ) if int(role_type) == 3: # 访问码可见 role_value = request.POST.get('viewcode','') Project.objects.filter(id=int(pro_id)).update( role=role_type, role_value=role_value, modify_time=datetime.datetime.now() ) pro = Project.objects.get(id=int(pro_id)) return render(request, 'app_doc/manage_project_role.html', locals()) else: return Http404 # 验证文集访问码 @require_http_methods(['GET',"POST"]) def check_viewcode(request): try: if request.method == 'GET': project_id = request.GET.get('to','').split("/")[1].split('-')[1] project = Project.objects.get(id=int(project_id)) return render(request,'app_doc/check_viewcode.html',locals()) else: viewcode = request.POST.get('viewcode','') project_id = request.POST.get('project_id','') project = Project.objects.get(id=int(project_id)) if project.role == 3 and project.role_value == viewcode: obj = redirect("pro_index",pro_id=project_id) obj.set_cookie('viewcode-{}'.format(project_id),viewcode) return obj else: errormsg = "访问码错误" return render(request, 'app_doc/check_viewcode.html', locals()) except Exception as e: logger.exception("验证文集访问码出错") return render(request,'404.html') # 删除文集 @login_required() @require_http_methods(["POST"]) def del_project(request): try: pro_id = request.POST.get('pro_id','') if pro_id != '': pro = Project.objects.get(id=pro_id) if (request.user == pro.create_user) or request.user.is_superuser: # 删除文集下的文档 pro_doc_list = Doc.objects.filter(top_doc=int(pro_id)) pro_doc_list.delete() # 删除文集 pro.delete() return JsonResponse({'status':True}) else: return JsonResponse({'status':False,'data':'非法请求'}) else: return JsonResponse({'status':False,'data':'参数错误'}) except Exception as e: logger.exception("删除文集出错") return JsonResponse({'status':False,'data':'请求出错'}) # 管理文集 @login_required() @require_http_methods(['GET']) def manage_project(request): try: search_kw = request.GET.get('kw', None) if search_kw: pro_list = Project.objects.filter(create_user=request.user,intro__icontains=search_kw).order_by('-create_time') paginator = Paginator(pro_list, 15) page = request.GET.get('page', 1) try: pros = paginator.page(page) except PageNotAnInteger: pros = paginator.page(1) except EmptyPage: pros = paginator.page(paginator.num_pages) pros.kw = search_kw else: pro_list = Project.objects.filter(create_user=request.user).order_by('-create_time') paginator = Paginator(pro_list, 15) page = request.GET.get('page', 1) try: pros = paginator.page(page) except PageNotAnInteger: pros = paginator.page(1) except EmptyPage: pros = paginator.page(paginator.num_pages) return render(request,'app_doc/manage_project.html',locals()) except Exception as e: logger.exception("管理文集出错") return render(request,'404.html') # 修改文集前台下载权限 @login_required() @require_http_methods(['GET',"POST"]) @logger.catch() def modify_project_download(request,pro_id): try: pro = Project.objects.get(id=pro_id) except ObjectDoesNotExist: return Http404 if (pro.create_user != request.user) and (request.user.is_superuser is False): return render(request,'403.html') else: project_files = ProjectReportFile.objects.filter(project=pro) if request.method == 'GET': return render(request,'app_doc/manage_project_download.html',locals()) elif request.method == 'POST': download_epub = request.POST.get('download_epub',None) download_pdf = request.POST.get('download_pdf', None) # print("epub状态:",download_epub) # EPUB下载权限 if download_epub == 'on': epub_status = 1 else: epub_status = 0 # PDF下载权限 if download_pdf == 'on': pdf_status = 1 else: pdf_status = 0 # 写入数据库 ProjectReport.objects.update_or_create( project = pro,defaults={'allow_epub':epub_status} ) ProjectReport.objects.update_or_create( project=pro, defaults={'allow_pdf': pdf_status} ) return render(request,'app_doc/manage_project_download.html',locals()) # 文集协作管理 @login_required() @require_http_methods(['GET',"POST"]) @logger.catch() def manage_project_collaborator(request,pro_id): project = Project.objects.filter(id=pro_id, create_user=request.user) if project.exists() is False: return Http404 if request.method == 'GET': pro = project[0] collaborator = ProjectCollaborator.objects.filter(project=pro) return render(request, 'app_doc/manage_project_collaborator.html', locals()) elif request.method == 'POST': # type类型:0表示新增协作者、1表示删除协作者、2表示修改协作者 types = request.POST.get('types','') try: types = int(types) except: return JsonResponse({'status':False,'data':'参数错误'}) # 添加文集协作者 if int(types) == 0: colla_user = request.POST.get('username','') role = request.POST.get('role',0) user = User.objects.filter(username=colla_user) if user.exists(): if user[0] == project[0].create_user: # 用户为文集的创建者 return JsonResponse({'status':False,'data':'文集创建者无需添加'}) elif ProjectCollaborator.objects.filter(user=user[0],project=project[0]).exists(): return JsonResponse({'status':False,'data':'用户已存在'}) else: ProjectCollaborator.objects.create( project = project[0], user = user[0], role = role if role in ['1',1] else 0 ) return JsonResponse({'status':True,'data':'添加成功'}) else: return JsonResponse({'status':False,'data':'用户不存在'}) # 删除文集协作者 elif int(types) == 1: username = request.POST.get('username','') try: user = User.objects.get(username=username) pro_colla = ProjectCollaborator.objects.get(project=project[0],user=user) pro_colla.delete() return JsonResponse({'status':True,'data':'删除成功'}) except: logger.exception("删除协作者出错") return JsonResponse({'status':False,'data':'删除出错'}) # 修改协作权限 elif int(types) == 2: username = request.POST.get('username', '') role = request.POST.get('role','') try: user = User.objects.get(username=username) pro_colla = ProjectCollaborator.objects.filter(project=project[0], user=user) pro_colla.update(role=role) return JsonResponse({'status':True,'data':'修改成功'}) except: logger.exception("修改协作权限出错") return JsonResponse({'status':False,'data':'修改失败'}) else: return JsonResponse({'status':False,'data':'无效的类型'}) # 我协作的文集 @login_required() @logger.catch() def manage_pro_colla_self(request): colla_pros = ProjectCollaborator.objects.filter(user=request.user) return render(request,'app_doc/manage_project_self_colla.html',locals()) # 文档浏览页 @require_http_methods(['GET']) def doc(request,pro_id,doc_id): try: if pro_id != '' and doc_id != '': # 获取文集信息 project = Project.objects.get(id=int(pro_id)) # 获取文集的协作用户信息 if request.user.is_authenticated: colla_user = ProjectCollaborator.objects.filter(project=project,user=request.user) if colla_user.exists(): colla_user_role = colla_user[0].role colla_user = colla_user.count() else: colla_user = colla_user.count() else: colla_user = 0 # 私密文集且访问者非创建者、协作者 - 不能访问 if (project.role == 1) and (request.user != project.create_user) and (colla_user == 0): return render(request, '404.html') # 指定用户可见文集 elif project.role == 2: user_list = project.role_value if request.user.is_authenticated: # 认证用户判断是否在许可用户列表中 if (request.user.username not in user_list) and \ (request.user != project.create_user) and \ (colla_user == 0): # 访问者不在指定用户之中,也不是协作者 return render(request, '404.html') else: # 游客直接返回404 return render(request, '404.html') # 访问码可见 elif project.role == 3: # 浏览用户不为创建者和协作者 - 需要访问码 if (request.user != project.create_user) and (colla_user == 0): viewcode = project.role_value viewcode_name = 'viewcode-{}'.format(project.id) r_viewcode = request.COOKIES[ viewcode_name] if viewcode_name in request.COOKIES.keys() else 0 # 从cookie中获取访问码 if viewcode != r_viewcode: # cookie中的访问码不等于文集访问码,跳转到访问码认证界面 return redirect('/check_viewcode/?to={}'.format(request.path)) # 获取文档内容 try: doc = Doc.objects.get(id=int(doc_id),status=1) except ObjectDoesNotExist: return render(request, '404.html') # 获取文集下一级文档 # project_docs = Doc.objects.filter(top_doc=doc.top_doc, parent_doc=0, status=1).order_by('sort') return render(request,'app_doc/doc.html',locals()) else: return HttpResponse('参数错误') except Exception as e: logger.exception("文集浏览出错") return render(request,'404.html') # 创建文档 @login_required() @require_http_methods(['GET',"POST"]) @logger.catch() def create_doc(request): if request.method == 'GET': try: pid = request.GET.get('pid',-999) project_list = Project.objects.filter(create_user=request.user) # 自己创建的文集列表 colla_project_list = ProjectCollaborator.objects.filter(user=request.user) # 协作的文集列表 doctemp_list = DocTemp.objects.filter(create_user=request.user).values('id','name','create_time') return render(request,'app_doc/create_doc.html',locals()) except Exception as e: logger.exception("访问创建文档页面出错") return render(request,'404.html') elif request.method == 'POST': try: project = request.POST.get('project','') parent_doc = request.POST.get('parent_doc','') doc_name = request.POST.get('doc_name','') doc_content = request.POST.get('content','') pre_content = request.POST.get('pre_content','') sort = request.POST.get('sort','') status = request.POST.get('status',1) if project != '' and doc_name != '' and project != '-1': # 验证请求者是否有文集的权限 check_project = Project.objects.filter(id=project,create_user=request.user) colla_project = ProjectCollaborator.objects.filter(project=project,user=request.user) if check_project.count() > 0 or colla_project.count() > 0: # 创建文档 doc = Doc.objects.create( name=doc_name, content = doc_content, pre_content= pre_content, parent_doc= int(parent_doc) if parent_doc != '' else 0, top_doc= int(project), sort = sort if sort != '' else 99, create_user=request.user, status = status ) return JsonResponse({'status':True,'data':{'pro':project,'doc':doc.id}}) else: return JsonResponse({'status':False,'data':'无权操作此文集'}) else: return JsonResponse({'status':False,'data':'请确认文档标题、文集正确'}) except Exception as e: logger.exception("创建文档出错") return JsonResponse({'status':False,'data':'请求出错'}) else: return JsonResponse({'status':False,'data':'方法不允许'}) # 修改文档 @login_required() @require_http_methods(['GET',"POST"]) def modify_doc(request,doc_id): if request.method == 'GET': try: doc = Doc.objects.get(id=doc_id) # 查询文档信息 project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集信息 pro_colla = ProjectCollaborator.objects.filter(project=project,user=request.user) # 查询用户的协作文集信息 project_list = Project.objects.filter(create_user=request.user) # 自己创建的文集列表 colla_project_list = ProjectCollaborator.objects.filter(user=request.user) # 协作的文集列表 if (request.user == doc.create_user) or (pro_colla[0].role == 1): doc_list = Doc.objects.filter(top_doc=project.id) doctemp_list = DocTemp.objects.filter(create_user=request.user) history_list = DocHistory.objects.filter(doc=doc).order_by('-create_time') return render(request,'app_doc/modify_doc.html',locals()) else: return render(request,'403.html') except Exception as e: logger.exception("修改文档页面访问出错") return render(request,'404.html') elif request.method == 'POST': try: doc_id = request.POST.get('doc_id','') # 文档ID project = request.POST.get('project', '') # 文集ID parent_doc = request.POST.get('parent_doc', '') # 上级文档ID doc_name = request.POST.get('doc_name', '') # 文档名称 doc_content = request.POST.get('content', '') # 文档内容 pre_content = request.POST.get('pre_content', '') # 文档Markdown格式内容 sort = request.POST.get('sort', '') # 文档排序 status = request.POST.get('status',1) # 文档状态 if doc_id != '' and project != '' and doc_name != '' and project != '-1': doc = Doc.objects.get(id=doc_id) pro_colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # 验证用户有权限修改文档 - 文档的创建者或文集的高级协作者 if (request.user == doc.create_user) or (pro_colla[0].role == 1): # 将现有文档内容写入到文档历史中 DocHistory.objects.create( doc = doc, pre_content = doc.pre_content, create_user = request.user ) # 更新文档内容 Doc.objects.filter(id=int(doc_id)).update( name=doc_name, content=doc_content, pre_content=pre_content, parent_doc=int(parent_doc) if parent_doc != '' else 0, sort=sort if sort != '' else 99, modify_time = datetime.datetime.now(), status = status ) return JsonResponse({'status': True,'data':'修改成功'}) else: return JsonResponse({'status':False,'data':'未授权请求'}) else: return JsonResponse({'status': False,'data':'参数错误'}) except Exception as e: logger.exception("修改文档出错") return JsonResponse({'status':False,'data':'请求出错'}) # 删除文档 - 软删除 - 进入回收站 @login_required() @require_http_methods(["POST"]) def del_doc(request): try: # 获取文档ID doc_id = request.POST.get('doc_id',None) if doc_id: # 查询文档 try: doc = Doc.objects.get(id=doc_id) project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集 # 获取文档所属文集的协作信息 pro_colla = ProjectCollaborator.objects.filter(project=project,user=request.user) # if pro_colla.exists(): colla_user_role = pro_colla[0].role else: colla_user_role = 0 except ObjectDoesNotExist: return JsonResponse({'status': False, 'data': '文档不存在'}) # 如果请求用户为文档创建者、高级权限的协作者、文集的创建者,可以删除 if (request.user == doc.create_user) or (colla_user_role == 1) or (request.user == project.create_user): # 修改状态为删除 doc.status = 3 doc.modify_time = datetime.datetime.now() doc.save() # 修改其下级所有文档状态为删除 chr_doc = Doc.objects.filter(parent_doc=doc_id) # 获取下级文档 chr_doc_ids = chr_doc.values_list('id',flat=True) # 提取下级文档的ID chr_doc.update(status=3,modify_time=datetime.datetime.now()) # 修改下级文档的状态为删除 Doc.objects.filter(parent_doc__in=chr_doc_ids).update(status=3,modify_time=datetime.datetime.now()) # 修改下级文档的下级文档状态 return JsonResponse({'status': True, 'data': '删除完成'}) else: return JsonResponse({'status': False, 'data': '非法请求'}) else: return JsonResponse({'status':False,'data':'参数错误'}) except Exception as e: logger.exception("删除文档出错") return JsonResponse({'status':False,'data':'请求出错'}) # 管理文档 @login_required() @require_http_methods(['GET']) @logger.catch() def manage_doc(request): # 文档内容搜索参数 search_kw = request.GET.get('kw','') # 文档状态筛选参数 doc_status = request.GET.get('status', 'all') # 文档文集筛选参数 doc_pro_id = request.GET.get('pid','') is_search = True if search_kw != '' else False is_status = doc_status is_project = True if doc_pro_id != '' else False # 无搜索 - 无状态 - 无文集 if (is_search is False) and (is_status == 'all') and (is_project is False): doc_list = Doc.objects.filter(create_user=request.user,status__in=[0,1]).order_by('-modify_time') # 无搜索 - 无状态 - 有文集 elif (is_search is False) and (is_status == 'all') and (is_project): doc_list = Doc.objects.filter( create_user=request.user, top_doc=int(doc_pro_id), status__in=[0,1] ).order_by('-modify_time') # 无搜索 - 有状态 - 无文集 elif (is_search is False) and (is_status != 'all') and (is_project is False): # 返回已发布文档 if doc_status == 'published': doc_list = Doc.objects.filter(create_user=request.user, status=1).order_by('-modify_time') # 返回草稿文档 elif doc_status == 'draft': doc_list = Doc.objects.filter(create_user=request.user, status=0).order_by('-modify_time') else: doc_list = Doc.objects.filter(create_user=request.user, status__in=[0,1]).order_by('-modify_time') # 无搜索 - 有状态 - 有文集 elif (is_search is False) and (is_status != 'all') and (is_project): # 返回已发布文档 if doc_status == 'published': doc_list = Doc.objects.filter( create_user=request.user, status=1, top_doc=int(doc_pro_id) ).order_by('-modify_time') # 返回草稿文档 elif doc_status == 'draft': doc_list = Doc.objects.filter( create_user=request.user, status=0, top_doc = int(doc_pro_id) ).order_by('-modify_time') else: doc_list = Doc.objects.filter( create_user=request.user, top_doc=int(doc_pro_id), status__in=[0,1] ).order_by('-modify_time') # 有搜索 - 无状态 - 无文集 elif (is_search) and (is_status == 'all') and (is_project is False): doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user, status__in=[0,1] ).order_by('-modify_time') # 有搜索 - 无状态 - 有文集 elif (is_search) and (is_status == 'all') and (is_project): doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user,top_doc=int(doc_pro_id),status__in=[0,1] ).order_by('-modify_time') # 有搜索 - 有状态 - 无文集 elif (is_search) and (is_status != 'all') and (is_project is False): if doc_status == 'published': doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), create_user=request.user, status = 1 ).order_by('-modify_time') elif doc_status == 'draft': doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user, status = 0 ).order_by('-modify_time') else: doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user,status__in=[0,1] ).order_by('-modify_time') # 有搜索 - 有状态 - 有文集 elif (is_search) and (is_status != 'all') and (is_project): if doc_status == 'published': doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), create_user=request.user, status = 1, top_doc=int(doc_pro_id) ).order_by('-modify_time') elif doc_status == 'draft': doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user, status = 0, top_doc=int(doc_pro_id) ).order_by('-modify_time') else: doc_list = Doc.objects.filter( Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user, top_doc=int(doc_pro_id),status__in=[0,1] ).order_by('-modify_time') # 文集列表 project_list = Project.objects.filter(create_user=request.user) # 自己创建的文集列表 colla_project_list = ProjectCollaborator.objects.filter(user=request.user) # 协作的文集列表 # 文档数量 # 已发布文档数量 published_doc_cnt = Doc.objects.filter(create_user=request.user, status=1).count() # 草稿文档数量 draft_doc_cnt = Doc.objects.filter(create_user=request.user, status=0).count() # 所有文档数量 all_cnt = published_doc_cnt + draft_doc_cnt # 分页处理 paginator = Paginator(doc_list, 15) page = request.GET.get('page', 1) try: docs = paginator.page(page) except PageNotAnInteger: docs = paginator.page(1) except EmptyPage: docs = paginator.page(paginator.num_pages) docs.status = doc_status docs.pid = doc_pro_id docs.kw = search_kw return render(request,'app_doc/manage_doc.html',locals()) # 移动文档 @login_required() @require_http_methods(['POST']) def move_doc(request): doc_id = request.POST.get('doc_id','') # 文档ID pro_id = request.POST.get('pro_id','') # 移动的文集ID move_type = request.POST.get('move_type','') # 移动的类型 0复制 1移动 2连同下级文档移动 parent_id = request.POST.get('parent_id',0) # 判断文集是否存在且有权限 try: project = Project.objects.get(id=int(pro_id)) # 自己的文集 colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # 协作文集 if (project.create_user is not request.user) and (colla.count()): # 请求者不是文集创建者和协作者返回错误 return JsonResponse({'status':False,'data':'文集无权限'}) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'文集不存在'}) # 判断文档是否存在 try: doc = Doc.objects.get(id=int(doc_id),create_user=request.user) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'文档不存在'}) # 判断上级文档是否存在 try: if parent_id != '0': parent = Doc.objects.get(id=int(parent_id),create_user=request.user) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'上级文档不存在'}) # 复制文档 if move_type == '0': copy_doc = Doc.objects.create( name = doc.name, pre_content = doc.pre_content, content = doc.content, parent_doc = parent_id, top_doc = int(pro_id), create_user = request.user, create_time = datetime.datetime.now(), modify_time = datetime.datetime.now(), # 文档状态说明:0表示草稿状态,1表示发布状态 status = doc.status ) return JsonResponse({'status':True,'data':{'pro_id':pro_id,'doc_id':copy_doc.id}}) # 移动文档,下级文档更改到根目录 elif move_type == '1': try: # 修改文档的所属文集和上级文档实现移动文档 Doc.objects.filter(id=int(doc_id)).update(parent_doc=int(parent_id),top_doc=int(pro_id)) # 修改其子文档为顶级文档 Doc.objects.filter(parent_doc=doc_id).update(parent_doc=0) return JsonResponse({'status':True,'data':{'pro_id':pro_id,'doc_id':doc_id}}) except: logger.exception("移动文档异常") return JsonResponse({'status':False,'data':'移动文档失败'}) # 包含下级文档一起移动 elif move_type == '2': try: # 修改文档的所属文集和上级文档实现移动文档 Doc.objects.filter(id=int(doc_id)).update(parent_doc=int(parent_id), top_doc=int(pro_id)) # 修改其子文档的文集归属 child_doc = Doc.objects.filter(parent_doc=doc_id) child_doc.update(top_doc=int(pro_id)) # 遍历子文档,如果其存在下级文档,那么继续修改所属文集 for child in child_doc: Doc.objects.filter(parent_doc=child.id).update(top_doc=int(pro_id)) return JsonResponse({'status': True, 'data':{'pro_id':pro_id,'doc_id':doc_id}}) except: logger.exception("移动包含下级的文档异常") return JsonResponse({'status': False, 'data': '移动文档失败'}) else: return JsonResponse({'status':False,'data':'移动类型错误'}) # 查看对比文档历史版本 @login_required() @require_http_methods(['GET',"POST"]) def diff_doc(request,doc_id,his_id): if request.method == 'GET': try: doc = Doc.objects.get(id=doc_id) # 查询文档信息 project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集信息 pro_colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # 查询用户的协作文集信息 if (request.user == doc.create_user) or (pro_colla[0].role == 1): history = DocHistory.objects.get(id=his_id) history_list = DocHistory.objects.filter(doc=doc).order_by('-create_time') if history.doc == doc: return render(request, 'app_doc/diff_doc.html', locals()) else: return render(request, '403.html') else: return render(request, '403.html') except Exception as e: logger.exception("文档历史版本页面访问出错") return render(request, '404.html') elif request.method == 'POST': try: doc = Doc.objects.get(id=doc_id) # 查询文档信息 project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集信息 pro_colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # 查询用户的协作文集信息 if (request.user == doc.create_user) or (pro_colla[0].role == 1): history = DocHistory.objects.get(id=his_id) if history.doc == doc: return JsonResponse({'status':True,'data':history.pre_content}) else: return JsonResponse({'status': False, 'data': '非法请求'}) else: return JsonResponse({'status':False,'data':'非法请求'}) except Exception as e: logger.exception("文档历史版本获取出错") return JsonResponse({'status':False,'data':'获取异常'}) # 管理文档历史版本 @login_required() @require_http_methods(['GET',"POST"]) def manage_doc_history(request,doc_id): if request.method == 'GET': try: doc = Doc.objects.get(id=doc_id,create_user=request.user) history_list = DocHistory.objects.filter(create_user=request.user,doc=doc_id).order_by('-create_time') paginator = Paginator(history_list, 15) page = request.GET.get('page', 1) try: historys = paginator.page(page) except PageNotAnInteger: historys = paginator.page(1) except EmptyPage: historys = paginator.page(paginator.num_pages) return render(request, 'app_doc/manage_doc_history.html', locals()) except Exception as e: logger.exception("管理文档历史版本页面访问出错") return render(request, '404.html') elif request.method == 'POST': try: history_id = request.POST.get('history_id','') DocHistory.objects.filter(id=history_id,doc=doc_id,create_user=request.user).delete() return JsonResponse({'status':True,'data':'删除成功'}) except: logger.exception("操作文档历史版本出错") return JsonResponse({'status':False,'data':'出现异常'}) # 文档回收站 @login_required() @require_http_methods(['GET','POST']) def doc_recycle(request): if request.method == 'GET': # 获取状态为删除的文档 doc_list = Doc.objects.filter(status=3,create_user=request.user).order_by('-modify_time') # 分页处理 paginator = Paginator(doc_list, 15) page = request.GET.get('page', 1) try: docs = paginator.page(page) except PageNotAnInteger: docs = paginator.page(1) except EmptyPage: docs = paginator.page(paginator.num_pages) return render(request,'app_doc/manage_doc_recycle.html',locals()) elif request.method == 'POST': try: # 获取参数 doc_id = request.POST.get('doc_id', None) # 文档ID types = request.POST.get('type',None) # 操作类型 if doc_id: # 查询文档 try: doc = Doc.objects.get(id=doc_id) project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集 # 获取文档所属文集的协作信息 pro_colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # if pro_colla.exists(): colla_user_role = pro_colla[0].role else: colla_user_role = 0 except ObjectDoesNotExist: return JsonResponse({'status': False, 'data': '文档不存在'}) # 如果请求用户为文档创建者、高级权限的协作者、文集的创建者,可以操作 if (request.user == doc.create_user) or (colla_user_role == 1) or (request.user == project.create_user): # 还原文档 if types == 'restore': # 修改状态为草稿 doc.status = 0 doc.modify_time = datetime.datetime.now() doc.save() # 删除文档 elif types == 'del': # 删除文档 doc.delete() else: return JsonResponse({'status':False,'data':'无效请求'}) return JsonResponse({'status': True, 'data': '删除完成'}) else: return JsonResponse({'status': False, 'data': '非法请求'}) # 清空回收站 elif types == 'empty': docs = Doc.objects.filter(status=3,create_user=request.user) docs.delete() return JsonResponse({'status': True, 'data': '清空成功'}) # 还原回收站 elif types == 'restoreAll': Doc.objects.filter(status=3,create_user=request.user).update(status=0) return JsonResponse({'status': True, 'data': '还原成功'}) else: return JsonResponse({'status': False, 'data': '参数错误'}) except Exception as e: logger.exception("处理文档出错") return JsonResponse({'status': False, 'data': '请求出错'}) # 一键发布文档 @login_required() @require_http_methods(['POST']) def fast_publish_doc(request): doc_id = request.POST.get('doc_id',None) # 查询文档 try: doc = Doc.objects.get(id=doc_id) project = Project.objects.get(id=doc.top_doc) # 查询文档所属的文集 # 获取文档所属文集的协作信息 pro_colla = ProjectCollaborator.objects.filter(project=project, user=request.user) # if pro_colla.exists(): colla_user_role = pro_colla[0].role else: colla_user_role = 0 except ObjectDoesNotExist: return JsonResponse({'status': False, 'data': '文档不存在'}) # 判断请求者是否有权限(文档创建者、文集创建者、文集高级协作者) # 如果请求用户为文档创建者、高级权限的协作者、文集的创建者,可以删除 if (request.user == doc.create_user) or (colla_user_role == 1) or (request.user == project.create_user): try: doc.status = 1 doc.modify_time = datetime.datetime.now() doc.save() return JsonResponse({'status':True,'data':'发布成功'}) except: logger.exception("文档一键发布失败") return JsonResponse({'status':False,'data':'发布失败'}) else: return JsonResponse({'status':False,'data':'非法请求'}) # 创建文档模板 @login_required() @require_http_methods(['GET',"POST"]) def create_doctemp(request): if request.method == 'GET': doctemps = DocTemp.objects.filter(create_user=request.user) return render(request,'app_doc/create_doctemp.html',locals()) elif request.method == 'POST': try: name = request.POST.get('name','') content = request.POST.get('content','') if name != '': doctemp = DocTemp.objects.create( name = name, content = content, create_user=request.user ) doctemp.save() return JsonResponse({'status':True,'data':'创建成功'}) else: return JsonResponse({'status':False,'data':'模板标题不能为空'}) except Exception as e: logger.exception("创建文档模板出错") return JsonResponse({'status':False,'data':'请求出错'}) # 修改文档模板 @login_required() @require_http_methods(['GET',"POST"]) def modify_doctemp(request,doctemp_id): if request.method == 'GET': try: doctemp = DocTemp.objects.get(id=doctemp_id) if request.user.id == doctemp.create_user.id: doctemps = DocTemp.objects.filter(create_user=request.user) return render(request,'app_doc/modify_doctemp.html',locals()) else: return HttpResponse('非法请求') except Exception as e: logger.exception("访问文档模板修改页面出错") return render(request, '404.html') elif request.method == 'POST': try: doctemp_id = request.POST.get('doctemp_id','') name = request.POST.get('name','') content = request.POST.get('content','') if doctemp_id != '' and name !='': doctemp = DocTemp.objects.get(id=doctemp_id) if request.user.id == doctemp.create_user.id: doctemp.name = name doctemp.content = content doctemp.save() return JsonResponse({'status':True,'data':'修改成功'}) else: return JsonResponse({'status':False,'data':'非法操作'}) else: return JsonResponse({'status':False,'data':'参数错误'}) except Exception as e: logger.exception("修改文档模板出错") return JsonResponse({'status':False,'data':'请求出错'}) # 删除文档模板 @login_required() def del_doctemp(request): try: doctemp_id = request.POST.get('doctemp_id','') if doctemp_id != '': doctemp = DocTemp.objects.get(id=doctemp_id) if request.user.id == doctemp.create_user.id: doctemp.delete() return JsonResponse({'status':True,'data':'删除完成'}) else: return JsonResponse({'status':False,'data':'非法请求'}) else: return JsonResponse({'status': False, 'data': '参数错误'}) except Exception as e: logger.exception("删除文档模板出错") return JsonResponse({'status':False,'data':'请求出错'}) # 管理文档模板 @login_required() @require_http_methods(['GET']) def manage_doctemp(request): try: search_kw = request.GET.get('kw', None) if search_kw: doctemp_list = DocTemp.objects.filter( create_user=request.user, content__icontains=search_kw ).order_by('-modify_time') paginator = Paginator(doctemp_list, 10) page = request.GET.get('page', 1) try: doctemps = paginator.page(page) except PageNotAnInteger: doctemps = paginator.page(1) except EmptyPage: doctemps = paginator.page(paginator.num_pages) doctemps.kw = search_kw else: doctemp_list = DocTemp.objects.filter(create_user=request.user).order_by('-modify_time') paginator = Paginator(doctemp_list, 10) page = request.GET.get('page', 1) try: doctemps = paginator.page(page) except PageNotAnInteger: doctemps = paginator.page(1) except EmptyPage: doctemps = paginator.page(paginator.num_pages) return render(request, 'app_doc/manage_doctemp.html', locals()) except Exception as e: logger.exception("管理文档模板页面访问出错") return render(request, '404.html') # 获取指定文档模板 @login_required() @require_http_methods(["POST"]) def get_doctemp(request): try: doctemp_id = request.POST.get('doctemp_id','') if doctemp_id != '': content = DocTemp.objects.get(id=int(doctemp_id)).serializable_value('content') return JsonResponse({'status':True,'data':content}) else: return JsonResponse({'status':False,'data':'参数错误'}) except Exception as e: logger.exception("获取指定文档模板出错") return JsonResponse({'status':False,'data':'请求出错'}) # 获取指定文集的所有文档 @require_http_methods(["POST"]) @logger.catch() def get_pro_doc(request): pro_id = request.POST.get('pro_id','') if pro_id != '': # 获取文集所有文档的id、name和parent_doc3个字段 doc_list = Doc.objects.filter(top_doc=int(pro_id),status=1).values_list('id','name','parent_doc').order_by('parent_doc') item_list = [] # 遍历文档 for doc in doc_list: # 如果文档为顶级文档 if doc[2] == 0: # 将其数据添加到列表中 item = [ doc[0],doc[1],doc[2],'' ] item_list.append(item) # 如果文档不是顶级文档 else: # 查询文档的上级文档 try: parent = Doc.objects.get(id=doc[2]) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'文档id不存在'}) # 如果文档上级文档的上级是顶级文档,那么将其添加到列表 if parent.parent_doc == 0: # 只要二级目录 item = [ doc[0],doc[1],doc[2],parent.name+' --> ' ] item_list.append(item) return JsonResponse({'status':True,'data':list(item_list)}) else: return JsonResponse({'status':False,'data':'参数错误'}) # 获取指定文集的文档树数据 # @login_required() @require_http_methods(['POST']) @logger.catch() def get_pro_doc_tree(request): pro_id = request.POST.get('pro_id', None) if pro_id: # 获取一级文档 doc_list = [] top_docs = Doc.objects.filter(top_doc=pro_id,parent_doc=0,status=1).values('id','name').order_by('sort') for doc in top_docs: top_item = { 'id':doc['id'], 'field':doc['name'], 'title':doc['name'], 'href':'/project-{}/doc-{}/'.format(pro_id,doc['id']), 'spread':True, 'level':1 } # 获取二级文档 sec_docs = Doc.objects.filter(top_doc=pro_id,parent_doc=doc['id'],status=1).values('id','name').order_by('sort') if sec_docs.exists():# 二级文档 top_item['children'] = [] for doc in sec_docs: sec_item = { 'id': doc['id'], 'field': doc['name'], 'title': doc['name'], 'href': '/project-{}/doc-{}/'.format(pro_id, doc['id']), 'level':2 } # 获取三级文档 thr_docs = Doc.objects.filter(top_doc=pro_id,parent_doc=doc['id'],status=1).values('id','name').order_by('sort') if thr_docs.exists(): sec_item['children'] = [] for doc in thr_docs: item = { 'id': doc['id'], 'field': doc['name'], 'title': doc['name'], 'href': '/project-{}/doc-{}/'.format(pro_id, doc['id']), 'level': 3 } sec_item['children'].append(item) top_item['children'].append(sec_item) else: top_item['children'].append(sec_item) doc_list.append(top_item) else: doc_list.append(top_item) return JsonResponse({'status':True,'data':doc_list}) else: return JsonResponse({'status':False,'data':'参数错误'}) # 404页面 def handle_404(request): return render(request,'404.html') # 导出文集MD文件 @login_required() @require_http_methods(["POST"]) def report_md(request): pro_id = request.POST.get('project_id','') user = request.user try: project = Project.objects.get(id=int(pro_id)) if project.create_user == user: project_md = ReportMD( project_id=int(pro_id) ) md_file_path = project_md.work() # 生成并获取MD文件压缩包绝对路径 md_file_filename = os.path.split(md_file_path)[-1] # 提取文件名 md_file = "/media/reportmd_temp/"+ md_file_filename # 拼接相对链接 return JsonResponse({'status':True,'data':md_file}) else: return JsonResponse({'status':False,'data':'无权限'}) except Exception as e: logger.exception("导出文集MD文件出错") return JsonResponse({'status':False,'data':'文集不存在'}) # 生成文集文件 - 个人中心 - 文集管理 @login_required() @require_http_methods(["POST"]) def genera_project_file(request): report_type = request.POST.get('types',None) # 获取前端传入到导出文件类型参数 # 导出EPUB文件 pro_id = request.POST.get('pro_id') try: project = Project.objects.get(id=int(pro_id)) # 获取文集的协作用户信息 if request.user.is_authenticated: colla_user = ProjectCollaborator.objects.filter(project=project, user=request.user) if colla_user.exists(): colla_user_role = colla_user[0].role colla_user = colla_user.count() else: colla_user = colla_user.count() else: colla_user = 0 # 公开的文集 - 可以直接导出 if project.role == 0: allow_export = True # 私密文集 - 非创建者和协作者不可导出 elif (project.role == 1): if (request.user != project.create_user) and (colla_user == 0): allow_export = False else: allow_export = True # 指定用户可见文集 - 指定用户、文集创建者和协作者可导出 elif project.role == 2: user_list = project.role_value if request.user.is_authenticated: # 认证用户判断是否在许可用户列表中 if (request.user.username not in user_list) and \ (request.user != project.create_user) and \ (colla_user == 0): # 访问者不在指定用户之中,也不是协作者 allow_export = False else: allow_export = True else: # 游客直接返回404 allow_export = False # 访问码可见文集 - 文集创建者、协作者和通过验证即可导出 elif project.role == 3: # 浏览用户不为创建者和协作者 - 需要访问码 if (request.user != project.create_user) and (colla_user == 0): viewcode = project.role_value viewcode_name = 'viewcode-{}'.format(project.id) r_viewcode = request.COOKIES[ viewcode_name] if viewcode_name in request.COOKIES.keys() else 0 # 从cookie中获取访问码 if viewcode != r_viewcode: # cookie中的访问码不等于文集访问码,不可导出 allow_export = False else: allow_export = True else: allow_export = True else: allow_export = False # 允许被导出 if allow_export: # 导出EPUB if report_type in ['epub']: try: report_project = ReportEPUB( project_id=project.id ).work() # print(report_project) report_file_path = report_project.split('media', maxsplit=1)[-1] # 导出文件的路径 epub_file = '/media' + report_file_path + '.epub' # 文件相对路径 # 查询文集是否存在导出文件 report_cnt = ProjectReportFile.objects.filter(project=project,file_type='epub') # 存在文件删除 if report_cnt.count() != 0: for r in report_cnt: is_exist = os.path.exists(settings.BASE_DIR + r.file_path) if is_exist: os.remove(settings.BASE_DIR + r.file_path) report_cnt.delete() # 删除数据库记录 # 创建数据库记录 ProjectReportFile.objects.create( project=project, file_type='epub', file_name=epub_file, file_path=epub_file ) return JsonResponse({'status': True, 'data': epub_file}) except Exception as e: return JsonResponse({'status': False, 'data': '生成出错'}) # 导出PDF elif report_type in ['pdf']: try: report_project = ReportPDF( project_id=project.id ).work() if report_project is False: return JsonResponse({'status':False,'data':'生成出错'}) report_file_path = report_project.split('media', maxsplit=1)[-1] # 导出文件的路径 pdf_file = '/media' + report_file_path # 文件相对路径 # 查询文集是否存在导出文件 report_cnt = ProjectReportFile.objects.filter(project=project, file_type='pdf') # 存在文件删除 if report_cnt.count() != 0: for r in report_cnt: is_exist = os.path.exists(settings.BASE_DIR + r.file_path) if is_exist: os.remove(settings.BASE_DIR + r.file_path) report_cnt.delete() # 删除数据库记录 # 创建数据库记录 ProjectReportFile.objects.create( project=project, file_type='pdf', file_name=pdf_file, file_path=pdf_file ) return JsonResponse({'status': True, 'data': pdf_file}) except Exception as e: return JsonResponse({'status': False, 'data': '生成出错'}) else: return JsonResponse({'status': False, 'data': '不支持的类型'}) # 不允许被导出 else: return JsonResponse({'status':False,'data':'无权限导出'}) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'文集不存在'}) except Exception as e: logger.exception("生成文集文件出错") return JsonResponse({'status':False,'data':'系统异常'}) # 获取文集前台导出文件 @allow_report_file @require_http_methods(["POST"]) def report_file(request): report_type = request.POST.get('types',None) # 获取前端传入到导出文件类型参数 pro_id = request.POST.get('pro_id') try: project = Project.objects.get(id=int(pro_id)) # 获取文集的协作用户信息 if request.user.is_authenticated: colla_user = ProjectCollaborator.objects.filter(project=project, user=request.user) if colla_user.exists(): colla_user_role = colla_user[0].role colla_user = colla_user.count() else: colla_user = colla_user.count() else: colla_user = 0 # 公开的文集 - 可以直接导出 if project.role == 0: allow_export = True # 私密文集 - 非创建者和协作者不可导出 elif (project.role == 1): if (request.user != project.create_user) and (colla_user == 0): allow_export = False else: allow_export = True # 指定用户可见文集 - 指定用户、文集创建者和协作者可导出 elif project.role == 2: user_list = project.role_value if request.user.is_authenticated: # 认证用户判断是否在许可用户列表中 if (request.user.username not in user_list) and \ (request.user != project.create_user) and \ (colla_user == 0): # 访问者不在指定用户之中,也不是协作者 allow_export = False else: allow_export = True else: # 游客直接返回404 allow_export = False # 访问码可见文集 - 文集创建者、协作者和通过验证即可导出 elif project.role == 3: # 浏览用户不为创建者和协作者 - 需要访问码 if (request.user != project.create_user) and (colla_user == 0): viewcode = project.role_value viewcode_name = 'viewcode-{}'.format(project.id) r_viewcode = request.COOKIES[ viewcode_name] if viewcode_name in request.COOKIES.keys() else 0 # 从cookie中获取访问码 if viewcode != r_viewcode: # cookie中的访问码不等于文集访问码,不可导出 allow_export = False else: allow_export = True else: allow_export = True else: allow_export = False # return JsonResponse({'status':False,'data':'不存在的文集权限'}) if allow_export: # 导出EPUB文件 if report_type in ['epub']: try: try: report_project = ProjectReportFile.objects.get(project=project,file_type='epub') except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'无可用文件,请联系文集创建者'}) # print(report_project) return JsonResponse({'status': True, 'data': report_project.file_path}) except Exception as e: return JsonResponse({'status': False, 'data': '导出出错'}) # 导出PDF elif report_type in ['pdf']: try: try: report_project = ProjectReportFile.objects.get(project=project,file_type='pdf') except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'无可用文件,请联系文集创建者'}) # print(report_project) return JsonResponse({'status': True, 'data': report_project.file_path}) except Exception as e: return JsonResponse({'status': False, 'data': '导出出错'}) else: return JsonResponse({'status': False, 'data': '不支持的类型'}) else: return JsonResponse({'status':False,'data':'无权限导出'}) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'文集不存在'}) except Exception as e: logger.exception("获取文集前台导出文件出错") return JsonResponse({'status':False,'data':'系统异常'}) # 图片素材管理 @login_required() @require_http_methods(['GET',"POST"]) def manage_image(request): # 获取图片 if request.method == 'GET': try: groups = ImageGroup.objects.filter(user=request.user) # 获取所有分组 all_img_cnt = Image.objects.filter(user=request.user).count() no_group_cnt = Image.objects.filter(user=request.user,group_id=None).count() # 获取所有未分组的图片数量 g_id = int(request.GET.get('group', 0)) # 图片分组id if int(g_id) == 0: image_list = Image.objects.filter(user=request.user).order_by('-create_time') # 查询所有图片 elif int(g_id) == -1: image_list = Image.objects.filter(user=request.user,group_id=None).order_by('-create_time') # 查询指定分组的图片 else: image_list = Image.objects.filter(user=request.user,group_id=g_id).order_by('-create_time') # 查询指定分组的图片 paginator = Paginator(image_list, 18) page = request.GET.get('page', 1) try: images = paginator.page(page) except PageNotAnInteger: images = paginator.page(1) except EmptyPage: images = paginator.page(paginator.num_pages) images.group = g_id return render(request,'app_doc/manage_image.html',locals()) except: logger.exception("图片素材管理出错") return render(request,'404.html') elif request.method == 'POST': try: img_id = request.POST.get('img_id','') types = request.POST.get('types','') # 操作类型:0表示删除,1表示修改,2表示获取 # 删除图片 if int(types) == 0: img = Image.objects.get(id=img_id) if img.user != request.user: return JsonResponse({'status': False, 'data': '未授权请求'}) file_path = settings.BASE_DIR+img.file_path is_exist = os.path.exists(file_path) if is_exist: os.remove(file_path) img.delete() # 删除记录 return JsonResponse({'status':True,'data':'删除完成'}) # 移动图片分组 elif int(types) == 1: group_id = request.POST.get('group_id',None) if group_id is None: Image.objects.filter(id=img_id,user=request.user).update(group_id=None) else: group = ImageGroup.objects.get(id=group_id,user=request.user) Image.objects.filter(id=img_id,user=request.user).update(group_id=group) return JsonResponse({'status':True,'data':'移动完成'}) # 获取图片 elif int(types) == 2: group_id = request.POST.get('group_id', None) # 接受分组ID参数 if group_id is None: # return JsonResponse({'status':False,'data':'参数错误'}) elif int(group_id) == 0: imgs = Image.objects.filter(user=request.user).order_by('-create_time') elif int(group_id) == -1: imgs = Image.objects.filter(user=request.user,group_id=None).order_by('-create_time') else: imgs = Image.objects.filter(user=request.user,group_id=group_id).order_by('-create_time') img_list = [] for img in imgs: item = { 'path':img.file_path, 'name':img.file_name, } img_list.append(item) return JsonResponse({'status':True,'data':img_list}) else: return JsonResponse({'status':False,'data':'非法参数'}) except ObjectDoesNotExist: return JsonResponse({'status':False,'data':'图片不存在'}) except: logger.exception("操作图片素材出错") return JsonResponse({'status':False,'data':'程序异常'}) # 图片分组管理 @login_required() @require_http_methods(['GET',"POST"]) @logger.catch() def manage_img_group(request): if request.method == 'GET': groups = ImageGroup.objects.filter(user=request.user) return render(request,'app_doc/manage_image_group.html',locals()) # 操作分组 elif request.method == 'POST': types = request.POST.get('types',None) # 请求类型,0表示创建分组,1表示修改分组,2表示删除分组,3表示获取分组 # 创建分组 if int(types) == 0: group_name = request.POST.get('group_name', '') if group_name not in ['','默认分组','未分组']: ImageGroup.objects.create( user = request.user, group_name = group_name ) return JsonResponse({'status':True,'data':'ok'}) else: return JsonResponse({'status':False,'data':'名称无效'}) # 修改分组 elif int(types) == 1: group_name = request.POST.get("group_name",'') if group_name not in ['','默认分组','未分组']: group_id = request.POST.get('group_id', '') ImageGroup.objects.filter(id=group_id,user=request.user).update(group_name=group_name) return JsonResponse({'status':True,'data':'修改成功'}) else: return JsonResponse({'status':False,'data':'名称无效'}) # 删除分组 elif int(types) == 2: try: group_id = request.POST.get('group_id','') group = ImageGroup.objects.get(id=group_id,user=request.user) # 查询分组 images = Image.objects.filter(group_id=group_id,user=request.user).update(group_id=None) # 移动图片到未分组 group.delete() # 删除分组 return JsonResponse({'status':True,'data':'删除完成'}) except: logger.exception("删除图片分组出错") return JsonResponse({'status':False,'data':'删除错误'}) # 获取分组 elif int(types) == 3: try: group_list = [] all_cnt = Image.objects.filter(user=request.user).count() non_group_cnt = Image.objects.filter(group_id=None,user=request.user).count() group_list.append({'group_name':'全部图片','group_cnt':all_cnt,'group_id':0}) group_list.append({'group_name':'未分组','group_cnt':non_group_cnt,'group_id':-1}) groups = ImageGroup.objects.filter(user=request.user) # 查询所有分组 for group in groups: group_cnt = Image.objects.filter(group_id=group).count() item = { 'group_id':group.id, 'group_name':group.group_name, 'group_cnt':group_cnt } group_list.append(item) return JsonResponse({'status':True,'data':group_list}) except: logger.exception("获取图片分组出错") return JsonResponse({'status':False,'data':'出现错误'}) # 附件管理 @login_required() @require_http_methods(['GET',"POST"]) def manage_attachment(request): # 文件大小 字节转换 def sizeFormat(size, is_disk=False, precision=2): ''' size format for human. byte ---- (B) kilobyte ---- (KB) megabyte ---- (MB) gigabyte ---- (GB) terabyte ---- (TB) petabyte ---- (PB) exabyte ---- (EB) zettabyte ---- (ZB) yottabyte ---- (YB) ''' formats = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] unit = 1000.0 if is_disk else 1024.0 if not (isinstance(size, float) or isinstance(size, int)): raise TypeError('a float number or an integer number is required!') if size < 0: raise ValueError('number must be non-negative') for i in formats: size /= unit if size < unit: r = '{}{}'.format(round(size, precision),i) return r if request.method == 'GET': try: search_kw = request.GET.get('kw', None) if search_kw: attachment_list = Attachment.objects.filter( user=request.user, file_name__icontains=search_kw ).order_by('-create_time') paginator = Paginator(attachment_list, 15) page = request.GET.get('page', 1) try: attachments = paginator.page(page) except PageNotAnInteger: attachments = paginator.page(1) except EmptyPage: attachments = paginator.page(paginator.num_pages) attachments.kw = search_kw else: attachment_list = Attachment.objects.filter(user=request.user).order_by('-create_time') paginator = Paginator(attachment_list, 15) page = request.GET.get('page', 1) try: attachments = paginator.page(page) except PageNotAnInteger: attachments = paginator.page(1) except EmptyPage: attachments = paginator.page(paginator.num_pages) return render(request, 'app_doc/manage_attachment.html', locals()) except Exception as e: logger.exception("附件管理访问出错") return render(request,'404.html') elif request.method == 'POST': # types参数,0表示上传、1表示删除、2表示获取附件列表 types = request.POST.get('types','') if types in ['0',0]: attachment = request.FILES.get('attachment_upload',None) if attachment: attachment_name = attachment.name attachment_size = sizeFormat(attachment.size) # 限制附件大小在50mb以内 if attachment.size > 52428800: return JsonResponse({'status':False,'data':'文件大小超出限制'}) # 限制附件为ZIP格式文件 if attachment_name.endswith('.zip'): a = Attachment.objects.create( file_name = attachment_name, file_size = attachment_size, file_path = attachment, user = request.user ) return JsonResponse({'status':True,'data':{'name':attachment_name,'url':a.file_path.name}}) else: return JsonResponse({'status':False,'data':'不支持的格式'}) else: return JsonResponse({'status':False,'data':'无效文件'}) elif types in ['1',1]: attach_id = request.POST.get('attach_id','') attachment = Attachment.objects.filter(id=attach_id,user=request.user) # 查询附件 for a in attachment: # 遍历附件 a.file_path.delete() # 删除文件 attachment.delete() # 删除数据库记录 return JsonResponse({'status':True,'data':'删除成功'}) elif types in [2,'2']: attachment_list = [] attachments = Attachment.objects.filter(user=request.user) for a in attachments: item = { 'filename':a.file_name, 'filesize':a.file_size, 'filepath':a.file_path.name, 'filetime':a.create_time } attachment_list.append(item) return JsonResponse({'status':True,'data':attachment_list}) else: return JsonResponse({'status':False,'data':'无效参数'})