diff --git a/CHANGES.md b/CHANGES.md index fe8982a..380dca6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,15 @@ ## 版本更新记录 -### v0.3.4 +### v0.4 2020-04-06 + +- 新增附件功能,可在个人中心管理附件,在文档编辑器中上传和添加附件; +- 重构文档编辑页面布局,界面排版更加友好,涉及新建文档页面、修改文档页面、新建文档模板页面、修改文档模板页面; +- 添加首页文集搜索功能和分页功能; +- 优化文档编辑器,重写表格组件,文档表格可以先填写内容在插入到Markdown编辑器中,预览界面a标签链接以新窗口的方式打开;; +- 优化个人中心和后台管理文档搜索,支持文档内容和标题搜索; +- 优化个人中心和后台管理页面、首页和文集、文档浏览页面移动端样式; + +### v0.3.4 2020-04-03 - 添加基于用户的API模块,支持通过用户Token获取文集、新建文档和上传图片; - 优化文档编辑页面布局; diff --git a/MrDoc/settings.py b/MrDoc/settings.py index 031a0d6..442a201 100644 --- a/MrDoc/settings.py +++ b/MrDoc/settings.py @@ -25,7 +25,7 @@ SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False -VERSIONS = '0.3.4' +VERSIONS = '0.4' ALLOWED_HOSTS = ['*'] diff --git a/README.md b/README.md index f5514f0..aff9c33 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,12 @@ ## MrDoc - 记录文档,汇聚思想 -![Mrdoc首页](./docs/mrdoc_2019080101.gif) +![Mrdoc首页](./captrue/mrdoc-index.png) ## 介绍 -基于Python编写的文档写作系统,适合作为文档、知识和笔记管理工具。 +`MrDoc`是基于`Python`开发的在线文档系统,适合作为个人和小型团队的文档、知识和笔记管理工具。 -MarkDown快速书写,两栏式阅读布局,清晰高效浏览。 - -当前版本为:**v0.3.4**,版本发布时间为**2020-04-03** - -完整更新记录详见:[CHANGES.md](./CHANGES.md) - -MrDoc拥有以下特点: +### 特性: - 简洁的站点与用户系统 - 支持用户注册、用户登录、用户管理、管理员等控制等功能; @@ -23,14 +17,19 @@ MrDoc拥有以下特点: - 结构清晰地文档系统 - 基于文集的文档撰写和阅读; - - 基于Editormd的Markdown编辑器,支持Markdown语法的文档写作,支持图片粘贴上传,支持从本地MD文件中插入内容; + - 使用基于`Editormd`的`Markdown`编辑器并扩展,以`Markdown`语法进行文档写作; - 提供文档模板功能,支持文档模板的创建、修改; - - 仿GitBook文档阅读页面,支持文档阅读页面的字体缩放,字体类型修改,页面社交分享,良好的移动端阅读体验; + - 两栏式文档阅读页面,支持文档阅读页面的字体缩放,字体类型修改,页面社交分享,良好的移动端阅读体验; - 支持三级目录层级显示; - - 支持文集后台导出为markdown文本格式.md文件、前台导出为EPUB电子书; + - 支持文集后台导出为`markdown`文本格式`.md`文件、前台导出为`EPUB`等格式文件; - 基于文集进行权限控制,提供公开、私密、指定用户可见、访问码可见4种权限模式; - - 支持基于账户的API接口,可以借助账户token通过API获取文集、上传图片和创建文档; + - 支持基于账户的`API`接口,可以借助账户`token`通过`API`获取文集、上传图片和创建文档; - 支持文集协作功能,一个文集可以拥有一个创建者和多个协作者,可灵活选择协作权限; + - 支持附件上传和管理、图片上传和管理; + +当前版本为:**v0.4**,版本发布时间为**2020-04-06** + +完整更新记录详见:[CHANGES.md](./CHANGES.md) 在开发过程中,参考和借鉴了GitBook、ShowDoc、Wordbook等应用和网站的功能与样式,并使用了众多开源组件、插件。 @@ -103,14 +102,13 @@ python manage.py runserver ## 使用说明文档 -详见MrDoc使用文档:http://mrdoc.zmister.com - +详见MrDoc使用文档: [http://mrdoc.zmister.com](http://mrdoc.zmister.com) ## 问题提交和反馈 ### 1、提交issue -直接在https://gitee.com/zmister/MrDoc/issues 页面提交问题。 +直接在[https://gitee.com/zmister/MrDoc/issues](https://gitee.com/zmister/MrDoc/issues) 页面提交问题。 ### 2、加入MrDoc交流群 @@ -119,26 +117,23 @@ python manage.py runserver ## 更多应用截图 -### 首页 -![MrDoc首页](./docs/mrdoc_index.jpg) +### 文集浏览页面 +![MrDoc文集页面](./captrue/mrdoc-project-index.png) -### 文集页 -![](./docs/mrdoc_project.jpg) +### 文档阅读页面 +![MrDoc文档页](./captrue/mrdoc-doc.png) -### 文档界面 -![MrDoc文档页](./docs/mrdoc_doc.jpg) +### 文档编写页面 +![](./captrue/mrdoc-create-doc.png) -### 文档编写界面 -![](./docs/mrdoc_doc_write.jpg) +### 普通用户个人中心 +![MrDoc普通用户后台](./captrue/mrdoc-manage-project.png) -### 普通用户后台界面 -![MrDoc普通用户后台](./docs/mrdoc_user.jpg) +### 管理员后台页面 +![MrDoc管理员后台](./captrue/mrdoc-admin-register-code.png) -### 管理员后台界面 -![MrDoc管理员后台](./docs/mrdoc_admin.jpg) +### 登录页面 +![MrDoc登录页](./captrue/mrdoc-login.png) -### 登录界面 -![MrDoc登录页](./docs/mrdoc_login.png) - -### 注册界面 -![MrDoc注册页](./docs/mrdoc_register.png) +### 注册页面 +![MrDoc注册页](./captrue/mrdoc-register.png) diff --git a/app_admin/views.py b/app_admin/views.py index 91ab6e4..18534b5 100644 --- a/app_admin/views.py +++ b/app_admin/views.py @@ -7,6 +7,7 @@ from django.contrib.auth.decorators import login_required # 登录需求装饰 from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage,InvalidPage # 后端分页 from app_admin.decorators import superuser_only,open_register from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Q import json,datetime,hashlib,random from app_doc.models import * from app_admin.models import * @@ -372,7 +373,7 @@ def admin_doc(request): except EmptyPage: docs = paginator.page(paginator.num_pages) else: - doc_list = Doc.objects.filter(pre_content__icontains=kw).order_by('-modify_time') + doc_list = Doc.objects.filter(Q(content__icontains=kw) | Q(name__icontains=kw)).order_by('-modify_time') paginator = Paginator(doc_list, 10) page = request.GET.get('page', 1) try: diff --git a/app_doc/migrations/0016_attachment.py b/app_doc/migrations/0016_attachment.py new file mode 100644 index 0000000..09de46a --- /dev/null +++ b/app_doc/migrations/0016_attachment.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.11 on 2020-04-04 08:37 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('app_doc', '0015_projectcollaborator'), + ] + + operations = [ + migrations.CreateModel( + name='Attachment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='attachment/%Y/%m/', verbose_name='附件')), + ('create_time', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': '附件管理', + 'verbose_name_plural': '附件管理', + }, + ), + ] diff --git a/app_doc/migrations/0017_auto_20200404_0934.py b/app_doc/migrations/0017_auto_20200404_0934.py new file mode 100644 index 0000000..6f74b57 --- /dev/null +++ b/app_doc/migrations/0017_auto_20200404_0934.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.11 on 2020-04-04 09:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('app_doc', '0016_attachment'), + ] + + operations = [ + migrations.RenameField( + model_name='attachment', + old_name='file', + new_name='file_path', + ), + migrations.AddField( + model_name='attachment', + name='file_name', + field=models.CharField(default='mrdoc_附件.zip', max_length=200, verbose_name='附件名'), + ), + migrations.AddField( + model_name='attachment', + name='file_size', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='附件大小'), + ), + ] diff --git a/app_doc/models.py b/app_doc/models.py index f168427..0b1eb29 100644 --- a/app_doc/models.py +++ b/app_doc/models.py @@ -124,4 +124,20 @@ class Image(models.Model): class Meta: verbose_name = '素材图片' + verbose_name_plural = verbose_name + + +# 附件模型 +class Attachment(models.Model): + file_name = models.CharField(max_length=200,verbose_name="附件名",default='mrdoc_附件.zip') + file_size = models.CharField(max_length=100,verbose_name="附件大小",blank=True,null=True) + file_path = models.FileField(upload_to='attachment/%Y/%m/',verbose_name='附件') + user = models.ForeignKey(User,on_delete=models.CASCADE,) + create_time = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.file_name + + class Meta: + verbose_name = '附件管理' verbose_name_plural = verbose_name \ No newline at end of file diff --git a/app_doc/urls.py b/app_doc/urls.py index 53ad3fe..d951cc0 100644 --- a/app_doc/urls.py +++ b/app_doc/urls.py @@ -7,6 +7,7 @@ urlpatterns = [ path('project-/', views.project_index, name='pro_index'), # 文集浏览页 path('create_project/', views.create_project, name='create_project'), # 新建文集 path('get_pro_doc/', views.get_pro_doc, name="get_pro_doc"), # 获取某个文集的下级文档 + path('get_pro_doc_tree/', views.get_pro_doc_tree, name="get_pro_doc_tree"), # 获取某个文集的下级文档树数据 path('modify_pro/',views.modify_project,name='modify_project'), # 修改文集 path('manage_project',views.manage_project,name="manage_project"), # 管理文集 path('del_project/',views.del_project,name='del_project'), # 删除文集 @@ -32,6 +33,7 @@ urlpatterns = [ #################文件管理相关 path('manage_image/',views.manage_image,name="manage_image"), # 图片管理 path('manage_image_group/',views.manage_img_group,name="manage_img_group"), # 图片分组管理 + path('manage_attachment/',views.manage_attachment,name='manage_attachment'), # 附件管理 ################其他功能相关 path('upload_doc_img/',util_upload_img.upload_img,name="upload_doc_img"), # 上传图片 ] \ No newline at end of file diff --git a/app_doc/views.py b/app_doc/views.py index 345bf17..155c818 100644 --- a/app_doc/views.py +++ b/app_doc/views.py @@ -22,22 +22,80 @@ def validateTitle(title): new_title = re.sub(rstr, "_", title) # 替换为下划线 return new_title + +# 文件大小 字节转换 +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: + return f'{round(size, precision)}{i}' + return f'{round(size, precision)}{i}' + + # 文集列表 def project_list(request): - # 登录用户 - if request.user.is_authenticated: - # 用户的协作文集 - 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) - ) + kw = request.GET.get('kw','') + if kw == '': + # 登录用户 + if request.user.is_authenticated: + # 用户的协作文集 + 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) + ) + else: + # 非登录用户只显示公开文集和需要访问码的文集 + project_list = Project.objects.filter(role__in=[0,3]) else: - # 非登录用户只显示公开文集和需要访问码的文集 - project_list = Project.objects.filter(role__in=[0,3]) + # 登录用户 + if request.user.is_authenticated: + # 用户的协作文集 + 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) + ) + else: + # 非登录用户只显示公开文集和需要访问码的文集 + project_list = Project.objects.filter( + Q(name__icontains=kw) | Q(intro__icontains=kw), + role__in=[0, 3] + ) + # 分页处理 + 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()) @@ -124,7 +182,7 @@ def project_index(request,pro_id): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request,'404.html') # 修改文集 @@ -272,7 +330,7 @@ def manage_project(request): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request,'404.html') else: return HttpResponse('方法不允许') @@ -435,7 +493,7 @@ def doc(request,pro_id,doc_id): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request,'404.html') # 创建文档 @@ -451,7 +509,7 @@ def create_doc(request): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request,'404.html') elif request.method == 'POST': try: project = request.POST.get('project','') @@ -507,7 +565,7 @@ def modify_doc(request,doc_id): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request,'404.html') elif request.method == 'POST': try: doc_id = request.POST.get('doc_id','') # 文档ID @@ -596,8 +654,8 @@ def manage_doc(request): # 查询文档 if doc_status == 'all': doc_list = Doc.objects.filter( + Q(content__icontains=search_kw) | Q(name__icontains=search_kw), # 文本或文档标题包含搜索词 create_user=request.user, - content__icontains=search_kw ).order_by('-modify_time') elif doc_status == 'published': doc_list = Doc.objects.filter( @@ -607,12 +665,12 @@ def manage_doc(request): ).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, - content__icontains=search_kw, status = 0 ).order_by('-modify_time') # 分页处理 - paginator = Paginator(doc_list, 20) + paginator = Paginator(doc_list, 15) page = request.GET.get('page', 1) try: docs = paginator.page(page) @@ -654,7 +712,7 @@ def manage_doc(request): else: doc_list = Doc.objects.filter(create_user=request.user).order_by('-modify_time') # 分页处理 - paginator = Paginator(doc_list, 20) + paginator = Paginator(doc_list, 15) page = request.GET.get('page', 1) try: docs = paginator.page(page) @@ -672,6 +730,7 @@ def manage_doc(request): @login_required() 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: @@ -702,13 +761,14 @@ def modify_doctemp(request,doctemp_id): 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: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request, '404.html') elif request.method == 'POST': try: doctemp_id = request.POST.get('doctemp_id','') @@ -784,7 +844,7 @@ def manage_doctemp(request): except Exception as e: if settings.DEBUG: print(traceback.print_exc()) - return HttpResponse('请求出错') + return render(request, '404.html') else: return HttpResponse('方法不允许') @@ -844,6 +904,56 @@ def get_pro_doc(request): else: return JsonResponse({'status':False,'data':'方法错误'}) +# 获取指定文集的文档树数据 +@login_required() +@require_http_methods(['POST']) +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).order_by('sort') + for doc in top_docs: + top_item = { + 'id':doc.id, + 'field':doc.name, + 'title':doc.name, + 'spread':True, + 'level':1 + } + # 获取二级文档 + sec_docs = Doc.objects.filter(top_doc=pro_id,parent_doc=doc.id,status=1).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, + 'level':2 + } + # 获取三级文档 + thr_docs = Doc.objects.filter(top_doc=pro_id,parent_doc=doc.id,status=1).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, + '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): @@ -1062,4 +1172,79 @@ def manage_img_group(request): except: if settings.DEBUG: print(traceback.print_exc()) - return JsonResponse({'status':False,'data':'出现错误'}) \ No newline at end of file + return JsonResponse({'status':False,'data':'出现错误'}) + + +# 附件管理 +@login_required() +def manage_attachment(request): + 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) + 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) + 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: + if settings.DEBUG: + print(traceback.print_exc()) + 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) + 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':'无效参数'}) \ No newline at end of file diff --git a/captrue/mrdoc-admin-register-code.png b/captrue/mrdoc-admin-register-code.png new file mode 100644 index 0000000..2271b55 Binary files /dev/null and b/captrue/mrdoc-admin-register-code.png differ diff --git a/captrue/mrdoc-admin-settings.png b/captrue/mrdoc-admin-settings.png new file mode 100644 index 0000000..a1bc573 Binary files /dev/null and b/captrue/mrdoc-admin-settings.png differ diff --git a/captrue/mrdoc-admin-user.png b/captrue/mrdoc-admin-user.png new file mode 100644 index 0000000..cf5ad66 Binary files /dev/null and b/captrue/mrdoc-admin-user.png differ diff --git a/captrue/mrdoc-create-doc-create-project.png b/captrue/mrdoc-create-doc-create-project.png new file mode 100644 index 0000000..dda3289 Binary files /dev/null and b/captrue/mrdoc-create-doc-create-project.png differ diff --git a/captrue/mrdoc-create-doc-select-temp.png b/captrue/mrdoc-create-doc-select-temp.png new file mode 100644 index 0000000..fbf5ca0 Binary files /dev/null and b/captrue/mrdoc-create-doc-select-temp.png differ diff --git a/captrue/mrdoc-create-doc.png b/captrue/mrdoc-create-doc.png new file mode 100644 index 0000000..5d036dd Binary files /dev/null and b/captrue/mrdoc-create-doc.png differ diff --git a/captrue/mrdoc-doc-closeleft.png b/captrue/mrdoc-doc-closeleft.png new file mode 100644 index 0000000..fa7ea95 Binary files /dev/null and b/captrue/mrdoc-doc-closeleft.png differ diff --git a/captrue/mrdoc-doc.png b/captrue/mrdoc-doc.png new file mode 100644 index 0000000..4278759 Binary files /dev/null and b/captrue/mrdoc-doc.png differ diff --git a/captrue/mrdoc-index.png b/captrue/mrdoc-index.png new file mode 100644 index 0000000..b809f23 Binary files /dev/null and b/captrue/mrdoc-index.png differ diff --git a/captrue/mrdoc-login.png b/captrue/mrdoc-login.png new file mode 100644 index 0000000..66b63cc Binary files /dev/null and b/captrue/mrdoc-login.png differ diff --git a/captrue/mrdoc-manage-attachment.png b/captrue/mrdoc-manage-attachment.png new file mode 100644 index 0000000..5d4119a Binary files /dev/null and b/captrue/mrdoc-manage-attachment.png differ diff --git a/captrue/mrdoc-manage-doc.png b/captrue/mrdoc-manage-doc.png new file mode 100644 index 0000000..bbb4aef Binary files /dev/null and b/captrue/mrdoc-manage-doc.png differ diff --git a/captrue/mrdoc-manage-doctemp.png b/captrue/mrdoc-manage-doctemp.png new file mode 100644 index 0000000..ca18f14 Binary files /dev/null and b/captrue/mrdoc-manage-doctemp.png differ diff --git a/captrue/mrdoc-manage-project.png b/captrue/mrdoc-manage-project.png new file mode 100644 index 0000000..dbd41ff Binary files /dev/null and b/captrue/mrdoc-manage-project.png differ diff --git a/captrue/mrdoc-manage-token.png b/captrue/mrdoc-manage-token.png new file mode 100644 index 0000000..af1c6c3 Binary files /dev/null and b/captrue/mrdoc-manage-token.png differ diff --git a/captrue/mrdoc-project-index.png b/captrue/mrdoc-project-index.png new file mode 100644 index 0000000..4e760c4 Binary files /dev/null and b/captrue/mrdoc-project-index.png differ diff --git a/captrue/mrdoc-register.png b/captrue/mrdoc-register.png new file mode 100644 index 0000000..bc1802d Binary files /dev/null and b/captrue/mrdoc-register.png differ diff --git a/docs/mrdoc_2019080101.gif b/docs/mrdoc_2019080101.gif deleted file mode 100644 index 7ca0812..0000000 Binary files a/docs/mrdoc_2019080101.gif and /dev/null differ diff --git a/docs/mrdoc_admin.jpg b/docs/mrdoc_admin.jpg deleted file mode 100644 index e540026..0000000 Binary files a/docs/mrdoc_admin.jpg and /dev/null differ diff --git a/docs/mrdoc_doc.jpg b/docs/mrdoc_doc.jpg deleted file mode 100644 index 83e3f7c..0000000 Binary files a/docs/mrdoc_doc.jpg and /dev/null differ diff --git a/docs/mrdoc_doc_write.jpg b/docs/mrdoc_doc_write.jpg deleted file mode 100644 index 8cb2102..0000000 Binary files a/docs/mrdoc_doc_write.jpg and /dev/null differ diff --git a/docs/mrdoc_index.jpg b/docs/mrdoc_index.jpg deleted file mode 100644 index 0f14795..0000000 Binary files a/docs/mrdoc_index.jpg and /dev/null differ diff --git a/docs/mrdoc_login.png b/docs/mrdoc_login.png deleted file mode 100644 index d0cc7aa..0000000 Binary files a/docs/mrdoc_login.png and /dev/null differ diff --git a/docs/mrdoc_project.jpg b/docs/mrdoc_project.jpg deleted file mode 100644 index 037d609..0000000 Binary files a/docs/mrdoc_project.jpg and /dev/null differ diff --git a/docs/mrdoc_register.png b/docs/mrdoc_register.png deleted file mode 100644 index 6a123ea..0000000 Binary files a/docs/mrdoc_register.png and /dev/null differ diff --git a/docs/mrdoc_user.jpg b/docs/mrdoc_user.jpg deleted file mode 100644 index 81f7158..0000000 Binary files a/docs/mrdoc_user.jpg and /dev/null differ diff --git a/static/mrdoc-editor/add.gif b/static/mrdoc-editor/add.gif new file mode 100644 index 0000000..bfd9cfc Binary files /dev/null and b/static/mrdoc-editor/add.gif differ diff --git a/static/mrdoc-editor/delete.gif b/static/mrdoc-editor/delete.gif new file mode 100644 index 0000000..18d1f7d Binary files /dev/null and b/static/mrdoc-editor/delete.gif differ diff --git a/static/mrdoc.css b/static/mrdoc.css index 178f548..17cca4f 100644 --- a/static/mrdoc.css +++ b/static/mrdoc.css @@ -14,6 +14,7 @@ position: absolute; left: 20px; top: 16px; + color:black; } .logo img { /*width: 85px;*/ @@ -49,10 +50,11 @@ .project-item{ /*float: left;*/ - /*width: 200px;*/ + width: 350px; height: 170px; - margin-top: 20px; - margin-left: 20px; + /*margin-top: 20px;*/ + /*margin-left: 20px;*/ + margin:10px; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,.055); @@ -140,10 +142,10 @@ } .create-doc-form{ margin-top: 20px; - margin-bottom: 20px; + /*margin-bottom: 20px;*/ } .doc-form-label{ - margin-left: 10px; + /*margin-left: 10px;*/ /*margin-right: 10px;*/ } /* 文档浏览页 */ @@ -250,7 +252,7 @@ body, html { text-decoration: underline; } li.active > a,li.active > div > a{ - color: #008cff; + color: #1E9FFF; } .bq a { padding: 15px; @@ -365,6 +367,21 @@ li.active > a,li.active > div > a{ /* 移动端小屏幕样式 */ @media screen and (max-width:768px){ + /* 首页 */ + .project-item{ + width: 100%; + height: 170px; + margin:10px; + border: 1px solid #ddd; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0,0,0,.055); + } + .layui-container{ + padding:0 5px; + } + .layui-fluid{ + padding: 0 25px; + } /* 文档浏览页 顶部控制按钮 */ .doc-header .btn{ padding:0 10px; diff --git a/static/mrdoc.editor.js b/static/mrdoc.editor.js new file mode 100644 index 0000000..6ae2a57 --- /dev/null +++ b/static/mrdoc.editor.js @@ -0,0 +1,190 @@ +function InsertLine(obj) { + var table_id = "#" + $(obj).attr("name"); + var name = $(obj).attr("name"); + var count = $(obj).parent().prevAll().length - 1; + console.log(count); + $(obj).parent().parent().after(linebody(count, name)); + for (var i = 1; i < $(table_id).find("tr").length; i++) { + var Lnum = i + "#"; + $(table_id).find("tr").eq(i).find("td").eq(0).html(Lnum); + } +} + +function linebody(count, name) { + var body = ""; + for (var i = 0; i < count; i++) { + body += "
"; + } + + body += "" + + ""; + body += ""; + + return body; +} + +function DeleteLine(obj) { + var table_id = "#" + $(obj).attr("name"); + $(obj).parent().parent().remove(); + for (var i = 1; i < $(table_id).find("tr").length; i++) { + var Lnum = i + "#"; + $(table_id).find("tr").eq(i).find("td").eq(0).html(Lnum); + } +} + +function Deleterow(obj) { + var table_id = "#" + $(obj).attr("name"); + var ti = $(obj).parent().prevAll().length; + console.log(ti); + for (var i = 0; i < $(table_id).find("tr").length; i++) { + $(table_id).find("tr").eq(i).find("td").eq(ti).remove(); + } +} + +function Insertrow(obj) { + var ti = $(obj).parent().prevAll().length; + var table_id = "#" + $(obj).attr("name"); + var name=$(obj).attr("name"); + var width = $(table_id).width(); + var td1 = "
" + var td = "
列名
" + for (var i = 0; i < $(table_id).find("tr").length; i++) { + if (i == 0) { + $(table_id).find("tr").eq(i).find("td").eq(ti).before(td); + } else { + $(table_id).find("tr").eq(i).find("td").eq(ti).before(td1); + } + + } + var n = $(table_id).find("tr").length; + width = width / n; + for (var i = 0; i < $(table_id).find("tr").eq(0).find("td").length - 1; i++) { + $(table_id).find("tr").eq(0).find("td").eq(i).width(width); + } +} + +function addbutton() { + var btn = $("#TableGroup").find("table").length; + var button = ""; + $("#BtnGroup").append(button); + addtable(btn); + var id = "#DataBtn" + btn; +} + +function addtable(btn) { + $("#TableGroup").empty(); + var row = $("#row").val(); + var col = $("#col").val(); + var id = '#DataTable' + btn; + var name = 'DataTable' + btn; + var body = ""; + for (var i = 0; i <= col; i++) { + if (i == 0) { + body += "" + } else { + body += ""; + + } + } + body += "" + for (var i = 1; i <= row; i++) { + body += ""; + for (var j = 0; j <= col; j++) { + if (j == 0) { + body += ""; + } else { + body += ""; + } + } + body += ""; + } + body += "
序号
列名
" + i + "#
"; + $("#TableGroup").append(body); + + addsrc(id, name); + $(id).siblings().hide(); + $(id).show(); + +} + +function changetable(obj) { + var table_id = "#" + $(obj).attr("name"); + $(table_id).siblings().hide(); + $(table_id).show(); + $(obj).addClass("btn-success"); + $(obj).siblings().removeClass("btn-success"); +} + +function addsrc(id, name) { + for (var i = 0; i < $(id).find("tr").length; i++) { + if (i == 0) { + var td = ""; + $(id).find("tr").eq(i).append(td); + } else { + var td = "" + + ""; + $(id).find("tr").eq(i).append(td); + } + + } +} + + +// **********HTML Table转Markdown相关js**************************** // + +var NL = "\n"; + +// 转换表格 - 传入一个默认的id1 +function convertTable(id) { + var table = document.getElementById('DataTable1') + var markdownResults = ''; + var tableElement = table; + var markdownTable = convertTableElementToMarkdown(tableElement); + markdownResults += markdownTable + NL + NL; + return markdownResults; + } + +function reportResult(msg) { + console.log(msg) +} + +// 转换表格为Markdown +function convertTableElementToMarkdown(tableEl) { + var rows = []; + // 删除每行tr的第一个和最后一个td + var trEls = tableEl.getElementsByTagName('tr'); + for(var i=0; i