diff --git a/CHANGES.md b/CHANGES.md index b10d43f..caaf5e4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,16 @@ ## 版本更新记录 +### v0.5.6 2020-07-31 + +- 修复Markdown编辑器插入图片、表格、音视频等内容时光标丢失的问题; +- 优化重构搜索功能,支持在搜索界面进行文集和文档搜索; +- 优化文档页面排版显示; +- 优化文档页面代码块超长超宽代码样式; +- 优化移动复制文档弹出框大纲超长的样式; +- 优化epub和PDF格式文件导出; +- 优化编辑器界面排版布局; +- 优化文档三级目录渲染错误的问题; + ### v0.5.5 2020-07-20 - 禁用编辑器页面的列表目录和下拉目录语法解析 diff --git a/MrDoc/settings.py b/MrDoc/settings.py index 9c5a2b9..094dd5c 100644 --- a/MrDoc/settings.py +++ b/MrDoc/settings.py @@ -40,7 +40,7 @@ SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = CONFIG.getboolean('site','debug') -VERSIONS = '0.5.5' +VERSIONS = '0.5.6' ALLOWED_HOSTS = ['*'] diff --git a/README.md b/README.md index 4d661d9..bf707c0 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,16 @@ ## MrDoc觅道文档 - 记录文档,汇聚思想 - [English](./README_ENG.md) -![mrdoc](https://img.shields.io/badge/MrDoc-v0.5.5-brightgreen.svg) ![python](https://img.shields.io/badge/Python-3.5+-blue.svg) ![mrdoc](https://img.shields.io/badge/Django-v2.2-important.svg) +![mrdoc](https://img.shields.io/badge/MrDoc-v0.5.6-brightgreen.svg) ![python](https://img.shields.io/badge/Python-3.5+-blue.svg) ![mrdoc](https://img.shields.io/badge/Django-v2.2-important.svg) ![Mrdoc首页](./captrue/mrdoc-index.png) +

打赏项目: +微信| +支付宝| +QQ| +PayPal| +

+ ### 介绍 `MrDoc` 是基于`Python`开发的在线文档系统,适合作为个人和小型团队的文档、知识和笔记管理工具。致力于成为全平台(Web端、桌面端、移动端)的私有化在线文档部署方案。 diff --git a/README_ENG.md b/README_ENG.md index f833c0c..905c446 100644 --- a/README_ENG.md +++ b/README_ENG.md @@ -1,10 +1,17 @@ ## MrDoc - Writing documents, gathering ideas -![mrdoc](https://img.shields.io/badge/MrDoc-v0.5.5-brightgreen.svg) ![python](https://img.shields.io/badge/Python-3.5+-blue.svg) ![mrdoc](https://img.shields.io/badge/Django-v2.2-important.svg) +![mrdoc](https://img.shields.io/badge/MrDoc-v0.5.6-brightgreen.svg) ![python](https://img.shields.io/badge/Python-3.5+-blue.svg) ![mrdoc](https://img.shields.io/badge/Django-v2.2-important.svg) ![Mrdoc首页](./captrue/mrdoc-index.png) +

Sponsor: +WeChat| +AliPay| +QQ| +PayPal| +

+ ### Introduce `Mrdoc` is an online document system developed based on python. It is suitable for individuals and small teams to manage documents, knowledge and notes. It is committed to become a private online document deployment solution for the whole platform (web, desktop, mobile). diff --git a/app_admin/views.py b/app_admin/views.py index f224f04..d372d0a 100644 --- a/app_admin/views.py +++ b/app_admin/views.py @@ -317,7 +317,7 @@ def admin_project(request): if request.method == 'GET': search_kw = request.GET.get('kw','') if search_kw == '': - project_list = Project.objects.all() + project_list = Project.objects.all().order_by('-create_time') paginator = Paginator(project_list,20) page = request.GET.get('page',1) try: diff --git a/app_doc/report_utils.py b/app_doc/report_utils.py index 89df28c..9120ba5 100644 --- a/app_doc/report_utils.py +++ b/app_doc/report_utils.py @@ -275,6 +275,7 @@ class ReportEPUB(): seque_tag = html_soup.select('.sequence-diagram') # 查找所有时序图标签 echart_tag = html_soup.select('.echart') # 查找所有echart图表标签 code_tag = html_soup.find_all(name="code") # 查找code代码标签 + iframe_tag = html_soup.find_all(name='iframe') # 查找iframe # 添加css样式标签 style_link = html_soup.new_tag(name='link',href="../Styles/style.css",rel="stylesheet",type="text/css") @@ -290,6 +291,12 @@ class ReportEPUB(): # 添加html标签的xmlns属性 html_soup.html['xmlns'] = "http://www.w3.org/1999/xhtml" + # 替换iframe视频为视频URL链接文本 + for iframe in iframe_tag: + iframe_src = iframe.get('src') + iframe.name = 'p' + iframe.string = "本格式不支持iframe视频显示,视频地址为:{}".format(iframe_src) + # 替换HTML文本中静态文件的相对链接为绝对链接 for src in src_tag: if src['src'].startswith("/"): @@ -908,7 +915,7 @@ class ReportPDF():
- 本文档由觅道文档(MrDoc)生成 + 本文档由MrDoc觅道文档生成

{project_name}

diff --git a/app_doc/templatetags/doc_filter.py b/app_doc/templatetags/doc_filter.py index 4cafdd6..a631bd0 100644 --- a/app_doc/templatetags/doc_filter.py +++ b/app_doc/templatetags/doc_filter.py @@ -2,6 +2,7 @@ # 文档自定义模板过滤器 from app_doc.models import * from django import template +import re register = template.Library() @@ -129,4 +130,32 @@ def get_doc_previous(value): return previous.id except Exception as e: import traceback - print(traceback.print_exc()) \ No newline at end of file + print(traceback.print_exc()) + + +# 获取内容的关键词上下文 +@register.filter(name='get_key_context') +def get_key_context(value,args): + # print(value,args) + # re_result = re.findall(args, value, flags=re.IGNORECASE) + value = value.replace('\n','') + p = re.compile(args,flags=re.IGNORECASE) + value_list = [] + for m in p.finditer(value): + # print(value,m,m.start(),m.group(),) + # print( m.start(), m.group()) + start_point = m.start() - 20 + if start_point < 0: + start_point = 0 + end_point = m.end()+20 + # print(start_point,end_point) + # print(value[start_point:end_point]) + value_list.append(value[start_point:end_point]) + # print(value_list) + if len(value_list) > 0: + r = "…".join(value_list) + if len(r) > 200: + r = r[0:200] + else: + r = value[0:200] + return r \ No newline at end of file diff --git a/app_doc/urls.py b/app_doc/urls.py index 8725f4b..c00f9dd 100644 --- a/app_doc/urls.py +++ b/app_doc/urls.py @@ -32,6 +32,7 @@ urlpatterns = [ path('move_doc/', views.move_doc, name='move_doc'), # 移动文档 path('doc_recycle/', views.doc_recycle,name='doc_recycle'), # 文档回收站 path('fast_pub_doc/',views.fast_publish_doc,name='fast_pub_doc'), # 一键发布文档 + path('download_doc_md//',views.download_doc_md,name='download_doc_md'), # 下载文档Markdown文件 #################文档模板相关 path('manage_doctemp/',views.manage_doctemp,name='manage_doctemp'), # 文档模板列表 path('create_doctemp/',views.create_doctemp,name="create_doctemp"), # 创建文档模板 @@ -44,4 +45,5 @@ urlpatterns = [ path('manage_attachment/',views.manage_attachment,name='manage_attachment'), # 附件管理 ################其他功能相关 path('upload_doc_img/',util_upload_img.upload_img,name="upload_doc_img"), # 上传图片 + path('search/',views.search,name="search"), # 搜索功能 ] \ No newline at end of file diff --git a/app_doc/views.py b/app_doc/views.py index 3ecbb6e..dda562c 100644 --- a/app_doc/views.py +++ b/app_doc/views.py @@ -1339,7 +1339,7 @@ def get_pro_doc_tree(request): 'level': 3 } sec_item['children'].append(item) - top_item['children'].append(sec_item) + top_item['children'].append(sec_item) else: top_item['children'].append(sec_item) doc_list.append(top_item) @@ -1471,6 +1471,7 @@ def genera_project_file(request): return JsonResponse({'status': True, 'data': epub_file}) except Exception as e: + logger.exception("生成EPUB出错") return JsonResponse({'status': False, 'data': '生成出错'}) # 导出PDF elif report_type in ['pdf']: @@ -1865,4 +1866,135 @@ def manage_attachment(request): attachment_list.append(item) return JsonResponse({'status':True,'data':attachment_list}) else: - return JsonResponse({'status':False,'data':'无效参数'}) \ No newline at end of file + return JsonResponse({'status':False,'data':'无效参数'}) + + +# 搜索 +def search(request): + kw = request.GET.get('kw', None) + search_type = request.GET.get('type', 'doc') # 搜索类型,默认文档doc + date_type = request.GET.get('d_type', 'recent') + date_range = request.GET.get('d_range', 'all') # 时间范围,默认不限,all + project_range = request.GET.get('p_range', 0) # 文集范围,默认不限,all + + # 处理时间范围 + if date_type == 'recent': + if date_range == 'recent1': # 最近1天 + start_date = datetime.datetime.now() - datetime.timedelta(days=1) + elif date_range == 'recent7': # 最近7天 + start_date = datetime.datetime.now() - datetime.timedelta(days=7) + elif date_range == 'recent30': # 最近30天 + start_date = datetime.datetime.now() - datetime.timedelta(days=30) + elif date_range == 'recent365': # 最近一年 + start_date = datetime.datetime.now() - datetime.timedelta(days=365) + else: + start_date = datetime.datetime.strptime('1900-01-01', '%Y-%m-%d') + end_date = datetime.datetime.now() + elif date_type == 'day': + try: + date_list = date_range.split('|') + start_date = datetime.datetime.strptime(date_list[0], '%Y-%m-%d') + end_date = datetime.datetime.strptime(date_list[1], '%Y-%m-%d') + except: + start_date = datetime.datetime.now() - datetime.timedelta(days=1) + end_date = datetime.datetime.now() + + # 是否时间筛选 + if date_range == 'all': + is_date_range = False + else: + is_date_range = True + + # 是否认证 + if request.user.is_authenticated: + is_auth = True + else: + is_auth = False + + # 存在搜索关键词 + if kw: + # 搜索文档 + if search_type == 'doc': + if is_auth: + colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集 + open_list = [i.id for i in Project.objects.filter(role=0)] # 公开文集 + view_list = list(set(open_list).union(set(colla_list))) # 合并上述两个文集ID列表 + + data_list = Doc.objects.filter( + Q(top_doc__in=view_list), # 包含用户可浏览到的文集 + Q(create_time__gte=start_date, create_time__lte=end_date), # 筛选创建时间 + Q(name__icontains=kw) | Q(content__icontains=kw) # 筛选文档标题和内容中包含搜索词 + ).order_by('-create_time') + else: + view_list = [i.id for i in Project.objects.filter(role=0)] + data_list = Doc.objects.filter( + Q(top_doc__in=view_list), + Q(create_time__gte=start_date, create_time__lte=end_date), # 筛选创建时间 + Q(name__icontains=kw) | Q(content__icontains=kw) # 筛选文档标题和内容中包含搜索词 + ).order_by('-create_time') + + # 搜索文集 + elif search_type == 'pro': + # 认证用户 + if is_auth: + colla_list = [i.project.id for i in ProjectCollaborator.objects.filter(user=request.user)] # 用户的协作文集 + # 查询所有可显示的文集 + data_list = Project.objects.filter( + Q(role=0) | \ + Q(role=2, role_value__contains=str(request.user.username)) | \ + Q(create_user=request.user) | \ + Q(id__in=colla_list), + Q(create_time__gte=start_date, create_time__lte=end_date), # 筛选创建时间 + Q(name__icontains=kw) | Q(intro__icontains=kw) # 筛选文集名称和简介包含搜索词 + ).order_by('-create_time') + # 游客 + else: + data_list = Project.objects.filter( + Q(role=0), + Q(name__icontains=kw) | Q(intro__icontains=kw), + Q(create_time__gte=start_date, create_time__lte=end_date), # 筛选创建时间 + ).order_by("-create_time") + + # 搜索标签 + # elif search_type == 'tag': + # pass + else: + return render(request, 'app_doc/search.html') + + # 分页处理 + paginator = Paginator(data_list, 12) + page = request.GET.get('page', 1) + try: + datas = paginator.page(page) + except PageNotAnInteger: + datas = paginator.page(1) + except EmptyPage: + datas = paginator.page(paginator.num_pages) + return render(request, 'app_doc/search_result.html', locals()) + + # 否则跳转到搜索首页 + else: + return render(request,'app_doc/search.html') + +# 文档Markdown文件下载 +@require_http_methods(['GET',"POST"]) +def download_doc_md(request,doc_id): + if request.user.is_authenticated: + if request.user.is_superuser: + try: + doc = Doc.objects.get(id=doc_id) + except ObjectDoesNotExist: + return JsonResponse({'status':False,'data':'文档不存在'}) + else: + try: + doc = Doc.objects.get(id=doc_id,create_user = request.user) + except ObjectDoesNotExist: + return JsonResponse({'status':False,'data':'文档不存在'}) + else: + return render(request,'404.html') + + response = HttpResponse(content_type='text/plain') + response['Content-Disposition'] = 'attachment; filename={}.md'.format(doc.name) + response.write(doc.pre_content) + + return response diff --git a/static/mrdoc.css b/static/mrdoc.css index 399ca5c..9d2efe3 100644 --- a/static/mrdoc.css +++ b/static/mrdoc.css @@ -188,7 +188,7 @@ body, html { .project-title{ font-size: 20px; font-weight: 700; - margin:20px; + margin:0 20px; text-align: center; } .doc-summary { @@ -356,12 +356,12 @@ li.active > a,li.active > div > a{ } /* 返回顶部 */ .toTop { - width: 70px; - height: 70px; + width: 50px; + height: 50px; border-radius: 50%; background: #f6f6f6; text-align: center; - line-height: 70px; + line-height: 50px; /*返回顶部标签固定定位*/ position: fixed; right: 35px; diff --git a/static/search/home_btn.svg b/static/search/home_btn.svg new file mode 100644 index 0000000..7d76bff --- /dev/null +++ b/static/search/home_btn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/search/mrdoc_logo_300.png b/static/search/mrdoc_logo_300.png new file mode 100644 index 0000000..b54dd90 Binary files /dev/null and b/static/search/mrdoc_logo_300.png differ diff --git a/static/search/mrdoc_search_logo.svg b/static/search/mrdoc_search_logo.svg new file mode 100644 index 0000000..94de7d3 --- /dev/null +++ b/static/search/mrdoc_search_logo.svg @@ -0,0 +1,39 @@ + + + + + background + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/search/mrdoc_search_logo_2.svg b/static/search/mrdoc_search_logo_2.svg new file mode 100644 index 0000000..52b858f --- /dev/null +++ b/static/search/mrdoc_search_logo_2.svg @@ -0,0 +1,17 @@ + + + + background + + + + + + + Layer 1 + + + + + + \ No newline at end of file diff --git a/static/search/search.svg b/static/search/search.svg new file mode 100644 index 0000000..c370075 --- /dev/null +++ b/static/search/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/search/search_btn.svg b/static/search/search_btn.svg new file mode 100644 index 0000000..7e8e55b --- /dev/null +++ b/static/search/search_btn.svg @@ -0,0 +1 @@ + Search Icon of a magnifying glass \ No newline at end of file diff --git a/template/app_admin/admin_project.html b/template/app_admin/admin_project.html index 9d63e00..4b1770d 100644 --- a/template/app_admin/admin_project.html +++ b/template/app_admin/admin_project.html @@ -44,7 +44,7 @@ {% for pro in projects %} - {{ pro.name }} + {{ pro.name }} {{ pro.intro }} {% load project_filter %} {{ pro.id | get_doc_count }} @@ -64,9 +64,9 @@ {{ pro.create_time }} {{ pro.create_user }} - + 修改 diff --git a/template/app_doc/create_base_2.html b/template/app_doc/create_base_2.html index e86f720..eb41624 100644 --- a/template/app_doc/create_base_2.html +++ b/template/app_doc/create_base_2.html @@ -112,6 +112,13 @@ .layui-colla-content{ padding: 0px; } + /* 预览代码宽度 */ + ol.linenums li{ + width: max-content; + } + #doc-tree{ + margin-bottom: 5px; + } + + diff --git a/template/app_doc/docs_base.html b/template/app_doc/docs_base.html index 2132631..b85dc18 100644 --- a/template/app_doc/docs_base.html +++ b/template/app_doc/docs_base.html @@ -79,12 +79,26 @@ .markdown-body h6{ font-size: .85em; } + .markdown-body p img{ + max-width: 350px; + } #url_qrcode img{ margin: auto; } #share{ background-color: #333; } + /* 文档代码块样式 */ + ol.linenums li{ + width: max-content; + } + pre.linenums{ + max-height: 400px; + } + li.L1, li.L3, li.L5, li.L7, li.L9 { + background: none !important; + } + /* layui弹出框颜色 */ .layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after{ border-bottom: 2px solid #333; @@ -136,7 +150,7 @@ @@ -156,11 +170,9 @@
+ + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + +
+ + + + + +{% block custom_script %} + + + + {% if debug %} + {% else %} + {{ static_code | safe }} + {% endif %} + +{% endblock %} + + \ No newline at end of file