新增脑图功能、首页筛选、优化表格输入、交互细节
This commit is contained in:
parent
c789e1008a
commit
c64e62749b
@ -1,5 +1,12 @@
|
||||
## 版本更新记录
|
||||
|
||||
### v0.4.2 2020-04-20
|
||||
|
||||
- 添加思维导图功能的支持,可以在文档编辑器通过图标和`mindmap`标识代码块来创建脑图;
|
||||
- 首页添加文集筛选、文集排序和文集网格/列表视图切换;
|
||||
- 文档编辑器优化表格插入按钮,新增粘贴Excel内容转Markdown的功能;
|
||||
- 优化交互体验;
|
||||
|
||||
### v0.4.1
|
||||
|
||||
- 添加文档历史版本功能,可在修改文档时对比查看和选择恢复文档的历史版本;
|
||||
|
||||
@ -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.4.1'
|
||||
VERSIONS = '0.4.2'
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
||||
41
README.md
41
README.md
@ -14,22 +14,27 @@
|
||||
|
||||
## 特性:
|
||||
|
||||
- 简洁的站点与用户系统
|
||||
- 支持用户注册、用户登录、用户管理、管理员等控制等功能;
|
||||
- 支持注册邀请码配置,支持全站关闭注册;
|
||||
- 支持广告代码、统计代码自定义配置;
|
||||
- **站点与用户系统**
|
||||
- 支持用户注册、用户登录、用户管理、管理员等基础用户功能;
|
||||
- 支持注册邀请码配置、广告代码配置、统计代码配置、邮箱找回密码、全站关闭注册等管理功能;
|
||||
|
||||
- 结构清晰地文档系统
|
||||
- 基于文集进行文档撰写和阅读,拥有文集、文档、文档模板、图片和附件5大模块;
|
||||
- 使用基于`Editormd`的`Markdown`编辑器并扩展,以`Markdown`语法进行文档写作;
|
||||
- 两栏式文档阅读页面、三级目录层级显示,文档阅读字体缩放,字体类型切换,页面社交分享,移动端阅读优化;
|
||||
- 支持文集后台导出打包`markdown`文本格式`.md`文件、前台导出为`EPUB`等格式文件;
|
||||
- 基于文集进行文档权限控制,提供公开、私密、指定用户可见、访问码可见4种权限模式;
|
||||
- 支持基于账户的`API`接口,可以借助账户`token`通过`API`获取文集、上传图片和创建文档;
|
||||
- 支持文集协作功能,一个文集可以拥有一个创建者和多个协作者,可灵活选择协作权限;
|
||||
- 支持文档历史版本功能;
|
||||
- **文档系统**
|
||||
- 基于文集进行文档撰写和阅读,拥有**文集**、**文档**、**文档模板**、**图片**和**附件**5大模块;
|
||||
- 使用基于`Editormd`的`Markdown`编辑器并扩展,以`Markdown`语法进行文档写作:
|
||||
- 支持**基础Markdown语法**
|
||||
- 支持**GFM语法**
|
||||
- 优化**图片上传**,支持粘贴上传、本地文件上传和图片管理插入
|
||||
- 优化**表格写入**,支持编辑HTML表格转为Markdown、Excel内容粘贴为Markdown
|
||||
- 支持**思维导图**,以Markdown的语法创建思维导图
|
||||
- 支持流程图、时序图的绘制;
|
||||
- 两栏式**文档阅读**页面、三级目录层级显示,文档阅读字体缩放,字体类型切换,页面社交分享,移动端阅读优化;
|
||||
- 支持文集后台**导出打包**`markdown`文本格式`.md`文件、前台导出为`EPUB`等格式文件;
|
||||
- 基于文集进行**文档权限**控制,提供公开、私密、指定用户可见、访问码可见4种权限模式;
|
||||
- 支持基于账户的**`API`接口**,可以借助账户`token`通过`API`获取文集、上传图片和创建文档;
|
||||
- 支持**文集协作**功能,一个文集可以拥有一个创建者和多个协作者,可灵活选择协作权限;
|
||||
- 支持**文档历史版本**功能,可以查看和对比历史版本与现有版本的差异,恢复某个历史版本为当前版本;
|
||||
|
||||
当前版本为:**v0.4.1**,版本发布时间为**2020-04-11**
|
||||
当前版本为:**v0.4.2**,版本发布时间为**2020-04-20**
|
||||
|
||||
完整更新记录详见:[CHANGES.md](./CHANGES.md)
|
||||
|
||||
@ -37,9 +42,9 @@
|
||||
|
||||
## 应用核心依赖环境
|
||||
|
||||
MrDoc基于Python语言的Django Web框架配合前端的LayUI、JQuery等库进行开发。
|
||||
`MrDoc`基于`Python`语言的`Django Web`框架配合前端的`LayUI`、`JQuery`等库进行开发。
|
||||
|
||||
在Django2.1、2.2和Python3.5、3.6、3.7上测试运行良好。
|
||||
`MrDoc`在`Python3.6` + `Django 2.2`上进行开发,并且在Django 2.1、2.2和Python3.5、3.6、3.7上测试运行良好,在其他环境下运行MrDoc不排除有未知的异常。。
|
||||
|
||||
## 简明安装教程
|
||||
|
||||
@ -53,7 +58,7 @@ pip install -r requirements.txt
|
||||
默认情况下,MrDoc使用Django的SQLite数据库,如果你使用Sqlite数据库,则无需另外配置数据库。
|
||||
|
||||
如果有配置其他数据库的需求,请在/MrDoc/MrDoc目录下打开settings.py文件,在约80行的位置,将如下代码:
|
||||
```
|
||||
```python
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
@ -62,7 +67,7 @@ DATABASES = {
|
||||
}
|
||||
```
|
||||
按照自己数据库的信息,将其修改如下格式,下面以MySQL为例:
|
||||
```
|
||||
```python
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql', # 使用的数据库后端
|
||||
|
||||
167
app_doc/views.py
167
app_doc/views.py
@ -23,43 +23,141 @@ def validateTitle(title):
|
||||
return new_title
|
||||
|
||||
|
||||
# 文集列表
|
||||
def project_list(request):
|
||||
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])
|
||||
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:
|
||||
# 登录用户
|
||||
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)
|
||||
)
|
||||
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),
|
||||
role__in=[0, 3]
|
||||
)
|
||||
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)
|
||||
@ -71,7 +169,6 @@ def project_list(request):
|
||||
projects = paginator.page(paginator.num_pages)
|
||||
return render(request, 'app_doc/pro_list.html', locals())
|
||||
|
||||
|
||||
# 创建文集
|
||||
@login_required()
|
||||
def create_project(request):
|
||||
@ -1291,6 +1388,10 @@ def manage_attachment(request):
|
||||
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,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 170 KiB |
@ -168,6 +168,7 @@
|
||||
tex : false, // TeX(LaTeX), based on KaTeX
|
||||
flowChart : false, // flowChart.js only support IE9+
|
||||
sequenceDiagram : false, // sequenceDiagram.js only support IE9+
|
||||
mindMap : true, // 脑图
|
||||
previewCodeHighlight : true,
|
||||
|
||||
toolbar : true, // show/hide toolbar
|
||||
@ -1492,7 +1493,6 @@
|
||||
*/
|
||||
|
||||
katexRender : function() {
|
||||
|
||||
if (timer === null)
|
||||
{
|
||||
return this;
|
||||
@ -1507,6 +1507,24 @@
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* 解析思维导图 - 2020-04-12
|
||||
*
|
||||
* @returns {editormd} 返回editormd的实例对象
|
||||
*/
|
||||
mindmapRender:function(){
|
||||
// console.log("开始解析脑图")
|
||||
this.previewContainer.find(".mindmap").each(function(){
|
||||
var mmap = $(this);
|
||||
var md_data = window.markmap.transform(mmap.text().trim());
|
||||
window.markmap.markmap("svg#"+this.id,md_data)
|
||||
//drawMindMap(mmap[0]) // kityminder的实现
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 解析和渲染流程图及时序图
|
||||
@ -1529,7 +1547,7 @@
|
||||
return this;
|
||||
}
|
||||
|
||||
previewContainer.find(".flowchart").flowChart();
|
||||
previewContainer.find(".flowchart").flowChart();
|
||||
}
|
||||
|
||||
if (settings.sequenceDiagram) {
|
||||
@ -1999,6 +2017,7 @@
|
||||
emailLink : settings.emailLink, // for mail address auto link
|
||||
flowChart : settings.flowChart,
|
||||
sequenceDiagram : settings.sequenceDiagram,
|
||||
mindMap : settings.mindMap,
|
||||
previewCodeHighlight : settings.previewCodeHighlight,
|
||||
};
|
||||
|
||||
@ -2032,13 +2051,13 @@
|
||||
this.htmlTextarea.text(newMarkdownDoc);
|
||||
}
|
||||
|
||||
if(settings.watch || (!settings.watch && state.preview))
|
||||
if(settings.watch || (!settings.watch && state.preview))//如果开启了预览
|
||||
{
|
||||
previewContainer.html(newMarkdownDoc);
|
||||
|
||||
this.previewCodeHighlight();
|
||||
|
||||
if (settings.toc)
|
||||
if (settings.toc) // 渲染目录
|
||||
{
|
||||
var tocContainer = (settings.tocContainer === "") ? previewContainer : $(settings.tocContainer);
|
||||
var tocMenu = tocContainer.find("." + this.classPrefix + "toc-menu");
|
||||
@ -2063,7 +2082,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.tex)
|
||||
if (settings.tex) // 渲染公式
|
||||
{
|
||||
if (!editormd.kaTeXLoaded && settings.autoLoadModules)
|
||||
{
|
||||
@ -2078,8 +2097,17 @@
|
||||
editormd.$katex = katex;
|
||||
this.katexRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染脑图
|
||||
if(settings.mindMap){
|
||||
setTimeout(function(){
|
||||
_this.mindmapRender();
|
||||
},10)
|
||||
|
||||
}
|
||||
|
||||
// 渲染流程图和时序图
|
||||
if (settings.flowChart || settings.sequenceDiagram)
|
||||
{
|
||||
flowchartTimer = setTimeout(function(){
|
||||
@ -3633,10 +3661,21 @@
|
||||
else if ( lang === "math" || lang === "latex" || lang === "katex")
|
||||
{
|
||||
return "<p class=\"" + editormd.classNames.tex + "\">" + code + "</p>";
|
||||
}
|
||||
else if (/^mindmap/i.test(lang)){
|
||||
var len = 9 || 32;
|
||||
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
||||
var maxPos = $chars.length;
|
||||
var map_id = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
map_id += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
// var map_id = lang.split('>')[1];
|
||||
// console.log(map_id)
|
||||
return "<svg class='mindmap' style='width:100%;min-height=150px;' id='mindmap-"+ map_id +"'>"+code+"</svg>";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return marked.Renderer.prototype.code.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
@ -3913,6 +3952,7 @@
|
||||
taskList : false, // Github Flavored Markdown task lists
|
||||
emoji : false,
|
||||
flowChart : false,
|
||||
mindMap : true, //百度脑图
|
||||
sequenceDiagram : false,
|
||||
previewCodeHighlight : true
|
||||
};
|
||||
@ -3944,6 +3984,7 @@
|
||||
emailLink : settings.emailLink, // for mail address auto link
|
||||
flowChart : settings.flowChart,
|
||||
sequenceDiagram : settings.sequenceDiagram,
|
||||
mindMap : settings.mindMap, // 思维导图
|
||||
previewCodeHighlight : settings.previewCodeHighlight,
|
||||
};
|
||||
|
||||
@ -4020,7 +4061,6 @@
|
||||
tex.find(".katex").css("font-size", "1.6em");
|
||||
});
|
||||
};
|
||||
|
||||
if (settings.autoLoadKaTeX && !editormd.$katex && !editormd.kaTeXLoaded)
|
||||
{
|
||||
this.loadKaTeX(function() {
|
||||
@ -4034,6 +4074,20 @@
|
||||
katexHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// 前台渲染脑图
|
||||
if(settings.mindMap){
|
||||
// console.log("前台渲染脑图")
|
||||
var mindmapHandle = function(){
|
||||
div.find(".mindmap").each(function(){
|
||||
var mmap = $(this);
|
||||
var md_data = window.markmap.transform(mmap.text().trim());
|
||||
window.markmap.markmap("svg#"+this.id,md_data)
|
||||
//drawMindMap(mmap[0]) // kityminder的实现
|
||||
});
|
||||
}
|
||||
mindmapHandle();
|
||||
}
|
||||
|
||||
div.getMarkdown = function() {
|
||||
return saveTo.val();
|
||||
@ -4181,9 +4235,9 @@
|
||||
// You can custom KaTeX load url.
|
||||
editormd.katexURL = {
|
||||
//css : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min",
|
||||
css : "/static/katex/katex.min.css",
|
||||
css : "/static/katex/katex.min",
|
||||
//js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min"
|
||||
js : "/static/katex/katex.min.js",
|
||||
js : "/static/katex/katex.min",
|
||||
};
|
||||
|
||||
editormd.kaTeXLoaded = false;
|
||||
|
||||
@ -3622,7 +3622,45 @@
|
||||
else if ( lang === "math" || lang === "latex" || lang === "katex")
|
||||
{
|
||||
return "<p class=\"" + editormd.classNames.tex + "\">" + code + "</p>";
|
||||
}
|
||||
}
|
||||
else if (/^mindmap/i.test(lang)){
|
||||
lang=lang+" ";//加一个空格,便于解析各参数使用
|
||||
//各参数解析开始
|
||||
var sizeps = lang.match(/(?<=size:)(mindmap-sm|mindmap-md|mindmap-lg)(?= )/i);
|
||||
var Templateps = lang.match(/(?<=Template:)(fresh-blue|filetree|fish-bone|right|structure|tianpan)(?= )/i);
|
||||
var Themeps = lang.match(/(?<=Theme:)(classic|classic-compact|fish|fresh-blue|fresh-blue-compat|fresh-green|fresh-green-compat|fresh-pink|fresh-pink-compat|fresh-purple|fresh-purple-compat|fresh-red|fresh-red-compat|fresh-soil|fresh-soil-compat|snow|snow-compact|tianpan|tianpan-compact|wire)(?= )/i);
|
||||
var protocolps=lang.match(/(?<=protocol:)(json|text|markdown|list)(?= )/i);
|
||||
var tmpshowps=lang.match(/(?<=tmpshow:)(true)(?= )/i);
|
||||
var size=(sizeps!== null)?sizeps[0]:"mindmap-md";
|
||||
var Theme=(Themeps!== null)?Themeps[0]:"fresh-blue";
|
||||
var protocol=(protocolps!== null)?protocolps[0]:"markdown";
|
||||
var Template=(Templateps!== null)?Templateps[0]:"default";
|
||||
var tmpshow=(tmpshowps!== null)?"":"style=\"display:none;\"";
|
||||
//参数解析结束
|
||||
|
||||
//生成两个div,其中一个存放参数,一个存放待生成的数据。
|
||||
if(protocol=="list"){
|
||||
code=marked(code);
|
||||
}
|
||||
else {
|
||||
//先将code解析为json数据,并添加主题和模板,
|
||||
//如果不先解析,按照官方文档,使用minder.execCommand('Template', "right");
|
||||
//或minder.useTemplate;minder.setTemplate;
|
||||
//等均没有效果,需要单独添加一个按钮或标签,等加载完才可以改变,有点无语。
|
||||
var minder=new kityminder.Minder();
|
||||
try {
|
||||
var tmpcode = minder.decodeData(protocol,code);
|
||||
tmpcode=tmpcode.fulfillValue;
|
||||
tmpcode.template=Template;
|
||||
tmpcode.theme=Theme;
|
||||
code=JSON.stringify(tmpcode);
|
||||
}catch(e){}
|
||||
}
|
||||
var mindmapoption="<div class=\"mindmapoption\" style=\"display:none;\" >" + lang + "</div>";
|
||||
var midmaptmpdiv="<div class=\"mindmaptmp\"" +tmpshow+" >" + code + "</div>";
|
||||
return "<div class=\"mindmap "+size+"\">"+mindmapoption+midmaptmpdiv+"</div>";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -4183,6 +4221,9 @@
|
||||
*/
|
||||
|
||||
editormd.loadKaTeX = function (callback) {
|
||||
// editormd.loadCSS(editormd.katexURL.css, function(){
|
||||
// editormd.loadScript(editormd.katexURL.js, callback || function(){});
|
||||
// });
|
||||
editormd.loadCSS(editormd.katexURL.css, function(){
|
||||
editormd.loadScript(editormd.katexURL.js, callback || function(){});
|
||||
});
|
||||
|
||||
2
static/mindmap/d3@5.js
vendored
Normal file
2
static/mindmap/d3@5.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7496
static/mindmap/transform.js
Normal file
7496
static/mindmap/transform.js
Normal file
File diff suppressed because it is too large
Load Diff
883
static/mindmap/view.js
Normal file
883
static/mindmap/view.js
Normal file
@ -0,0 +1,883 @@
|
||||
/*! markmap-lib v0.4.2 | MIT License */
|
||||
(function (exports, d3) {
|
||||
'use strict';
|
||||
|
||||
function count(node) {
|
||||
var sum = 0,
|
||||
children = node.children,
|
||||
i = children && children.length;
|
||||
if (!i) sum = 1;
|
||||
else while (--i >= 0) sum += children[i].value;
|
||||
node.value = sum;
|
||||
}
|
||||
|
||||
function node_count() {
|
||||
return this.eachAfter(count);
|
||||
}
|
||||
|
||||
function node_each(callback) {
|
||||
var node = this, current, next = [node], children, i, n;
|
||||
do {
|
||||
current = next.reverse(), next = [];
|
||||
while (node = current.pop()) {
|
||||
callback(node), children = node.children;
|
||||
if (children) for (i = 0, n = children.length; i < n; ++i) {
|
||||
next.push(children[i]);
|
||||
}
|
||||
}
|
||||
} while (next.length);
|
||||
return this;
|
||||
}
|
||||
|
||||
function node_eachBefore(callback) {
|
||||
var node = this, nodes = [node], children, i;
|
||||
while (node = nodes.pop()) {
|
||||
callback(node), children = node.children;
|
||||
if (children) for (i = children.length - 1; i >= 0; --i) {
|
||||
nodes.push(children[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
function node_eachAfter(callback) {
|
||||
var node = this, nodes = [node], next = [], children, i, n;
|
||||
while (node = nodes.pop()) {
|
||||
next.push(node), children = node.children;
|
||||
if (children) for (i = 0, n = children.length; i < n; ++i) {
|
||||
nodes.push(children[i]);
|
||||
}
|
||||
}
|
||||
while (node = next.pop()) {
|
||||
callback(node);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
function node_sum(value) {
|
||||
return this.eachAfter(function(node) {
|
||||
var sum = +value(node.data) || 0,
|
||||
children = node.children,
|
||||
i = children && children.length;
|
||||
while (--i >= 0) sum += children[i].value;
|
||||
node.value = sum;
|
||||
});
|
||||
}
|
||||
|
||||
function node_sort(compare) {
|
||||
return this.eachBefore(function(node) {
|
||||
if (node.children) {
|
||||
node.children.sort(compare);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function node_path(end) {
|
||||
var start = this,
|
||||
ancestor = leastCommonAncestor(start, end),
|
||||
nodes = [start];
|
||||
while (start !== ancestor) {
|
||||
start = start.parent;
|
||||
nodes.push(start);
|
||||
}
|
||||
var k = nodes.length;
|
||||
while (end !== ancestor) {
|
||||
nodes.splice(k, 0, end);
|
||||
end = end.parent;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function leastCommonAncestor(a, b) {
|
||||
if (a === b) return a;
|
||||
var aNodes = a.ancestors(),
|
||||
bNodes = b.ancestors(),
|
||||
c = null;
|
||||
a = aNodes.pop();
|
||||
b = bNodes.pop();
|
||||
while (a === b) {
|
||||
c = a;
|
||||
a = aNodes.pop();
|
||||
b = bNodes.pop();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function node_ancestors() {
|
||||
var node = this, nodes = [node];
|
||||
while (node = node.parent) {
|
||||
nodes.push(node);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function node_descendants() {
|
||||
var nodes = [];
|
||||
this.each(function(node) {
|
||||
nodes.push(node);
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function node_leaves() {
|
||||
var leaves = [];
|
||||
this.eachBefore(function(node) {
|
||||
if (!node.children) {
|
||||
leaves.push(node);
|
||||
}
|
||||
});
|
||||
return leaves;
|
||||
}
|
||||
|
||||
function node_links() {
|
||||
var root = this, links = [];
|
||||
root.each(function(node) {
|
||||
if (node !== root) { // Don’t include the root’s parent, if any.
|
||||
links.push({source: node.parent, target: node});
|
||||
}
|
||||
});
|
||||
return links;
|
||||
}
|
||||
|
||||
function hierarchy(data, children) {
|
||||
var root = new Node(data),
|
||||
valued = +data.value && (root.value = data.value),
|
||||
node,
|
||||
nodes = [root],
|
||||
child,
|
||||
childs,
|
||||
i,
|
||||
n;
|
||||
|
||||
if (children == null) children = defaultChildren;
|
||||
|
||||
while (node = nodes.pop()) {
|
||||
if (valued) node.value = +node.data.value;
|
||||
if ((childs = children(node.data)) && (n = childs.length)) {
|
||||
node.children = new Array(n);
|
||||
for (i = n - 1; i >= 0; --i) {
|
||||
nodes.push(child = node.children[i] = new Node(childs[i]));
|
||||
child.parent = node;
|
||||
child.depth = node.depth + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root.eachBefore(computeHeight);
|
||||
}
|
||||
|
||||
function node_copy() {
|
||||
return hierarchy(this).eachBefore(copyData);
|
||||
}
|
||||
|
||||
function defaultChildren(d) {
|
||||
return d.children;
|
||||
}
|
||||
|
||||
function copyData(node) {
|
||||
node.data = node.data.data;
|
||||
}
|
||||
|
||||
function computeHeight(node) {
|
||||
var height = 0;
|
||||
do node.height = height;
|
||||
while ((node = node.parent) && (node.height < ++height));
|
||||
}
|
||||
|
||||
function Node(data) {
|
||||
this.data = data;
|
||||
this.depth =
|
||||
this.height = 0;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
Node.prototype = hierarchy.prototype = {
|
||||
constructor: Node,
|
||||
count: node_count,
|
||||
each: node_each,
|
||||
eachAfter: node_eachAfter,
|
||||
eachBefore: node_eachBefore,
|
||||
sum: node_sum,
|
||||
sort: node_sort,
|
||||
path: node_path,
|
||||
ancestors: node_ancestors,
|
||||
descendants: node_descendants,
|
||||
leaves: node_leaves,
|
||||
links: node_links,
|
||||
copy: node_copy
|
||||
};
|
||||
|
||||
var version = "2.1.1";
|
||||
|
||||
const defaults = Object.freeze({
|
||||
children: data => data.children,
|
||||
nodeSize: node => node.data.size,
|
||||
spacing: 0,
|
||||
});
|
||||
|
||||
// Create a layout function with customizable options. Per D3-style, the
|
||||
// options can be set at any time using setter methods. The layout function
|
||||
// will compute the tree node positions based on the options in effect at the
|
||||
// time it is called.
|
||||
function flextree(options) {
|
||||
const opts = Object.assign({}, defaults, options);
|
||||
function accessor(name) {
|
||||
const opt = opts[name];
|
||||
return typeof opt === 'function' ? opt : () => opt;
|
||||
}
|
||||
|
||||
function layout(tree) {
|
||||
const wtree = wrap(getWrapper(), tree, node=>node.children);
|
||||
wtree.update();
|
||||
return wtree.data;
|
||||
}
|
||||
|
||||
function getFlexNode() {
|
||||
const nodeSize = accessor('nodeSize');
|
||||
const spacing = accessor('spacing');
|
||||
return class FlexNode extends hierarchy.prototype.constructor {
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
copy() {
|
||||
const c = wrap(this.constructor, this, node=>node.children);
|
||||
c.each(node => node.data = node.data.data);
|
||||
return c;
|
||||
}
|
||||
get size() { return nodeSize(this); }
|
||||
spacing(oNode) { return spacing(this, oNode); }
|
||||
get nodes() { return this.descendants(); }
|
||||
get xSize() { return this.size[0]; }
|
||||
get ySize() { return this.size[1]; }
|
||||
get top() { return this.y; }
|
||||
get bottom() { return this.y + this.ySize; }
|
||||
get left() { return this.x - this.xSize / 2; }
|
||||
get right() { return this.x + this.xSize / 2; }
|
||||
get root() {
|
||||
const ancs = this.ancestors();
|
||||
return ancs[ancs.length - 1];
|
||||
}
|
||||
get numChildren() {
|
||||
return this.hasChildren ? this.children.length : 0;
|
||||
}
|
||||
get hasChildren() { return !this.noChildren; }
|
||||
get noChildren() { return this.children === null; }
|
||||
get firstChild() {
|
||||
return this.hasChildren ? this.children[0] : null;
|
||||
}
|
||||
get lastChild() {
|
||||
return this.hasChildren ? this.children[this.numChildren - 1] : null;
|
||||
}
|
||||
get extents() {
|
||||
return (this.children || []).reduce(
|
||||
(acc, kid) => FlexNode.maxExtents(acc, kid.extents),
|
||||
this.nodeExtents);
|
||||
}
|
||||
get nodeExtents() {
|
||||
return {
|
||||
top: this.top,
|
||||
bottom: this.bottom,
|
||||
left: this.left,
|
||||
right: this.right,
|
||||
};
|
||||
}
|
||||
static maxExtents(e0, e1) {
|
||||
return {
|
||||
top: Math.min(e0.top, e1.top),
|
||||
bottom: Math.max(e0.bottom, e1.bottom),
|
||||
left: Math.min(e0.left, e1.left),
|
||||
right: Math.max(e0.right, e1.right),
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getWrapper() {
|
||||
const FlexNode = getFlexNode();
|
||||
const nodeSize = accessor('nodeSize');
|
||||
const spacing = accessor('spacing');
|
||||
return class extends FlexNode {
|
||||
constructor(data) {
|
||||
super(data);
|
||||
Object.assign(this, {
|
||||
x: 0, y: 0,
|
||||
relX: 0, prelim: 0, shift: 0, change: 0,
|
||||
lExt: this, lExtRelX: 0, lThr: null,
|
||||
rExt: this, rExtRelX: 0, rThr: null,
|
||||
});
|
||||
}
|
||||
get size() { return nodeSize(this.data); }
|
||||
spacing(oNode) { return spacing(this.data, oNode.data); }
|
||||
get x() { return this.data.x; }
|
||||
set x(v) { this.data.x = v; }
|
||||
get y() { return this.data.y; }
|
||||
set y(v) { this.data.y = v; }
|
||||
update() {
|
||||
layoutChildren(this);
|
||||
resolveX(this);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function wrap(FlexClass, treeData, children) {
|
||||
const _wrap = (data, parent) => {
|
||||
const node = new FlexClass(data);
|
||||
Object.assign(node, {
|
||||
parent,
|
||||
depth: parent === null ? 0 : parent.depth + 1,
|
||||
height: 0,
|
||||
length: 1,
|
||||
});
|
||||
const kidsData = children(data) || [];
|
||||
node.children = kidsData.length === 0 ? null
|
||||
: kidsData.map(kd => _wrap(kd, node));
|
||||
if (node.children) {
|
||||
Object.assign(node, node.children.reduce(
|
||||
(hl, kid) => ({
|
||||
height: Math.max(hl.height, kid.height + 1),
|
||||
length: hl.length + kid.length,
|
||||
}), node
|
||||
));
|
||||
}
|
||||
return node;
|
||||
};
|
||||
return _wrap(treeData, null);
|
||||
}
|
||||
|
||||
|
||||
Object.assign(layout, {
|
||||
nodeSize(arg) {
|
||||
return arguments.length ? (opts.nodeSize = arg, layout) : opts.nodeSize;
|
||||
},
|
||||
spacing(arg) {
|
||||
return arguments.length ? (opts.spacing = arg, layout) : opts.spacing;
|
||||
},
|
||||
children(arg) {
|
||||
return arguments.length ? (opts.children = arg, layout) : opts.children;
|
||||
},
|
||||
hierarchy(treeData, children) {
|
||||
const kids = typeof children === 'undefined' ? opts.children : children;
|
||||
return wrap(getFlexNode(), treeData, kids);
|
||||
},
|
||||
dump(tree) {
|
||||
const nodeSize = accessor('nodeSize');
|
||||
const _dump = i0 => node => {
|
||||
const i1 = i0 + ' ';
|
||||
const i2 = i0 + ' ';
|
||||
const {x, y} = node;
|
||||
const size = nodeSize(node);
|
||||
const kids = (node.children || []);
|
||||
const kdumps = (kids.length === 0) ? ' ' :
|
||||
`,${i1}children: [${i2}${kids.map(_dump(i2)).join(i2)}${i1}],${i0}`;
|
||||
return `{ size: [${size.join(', ')}],${i1}x: ${x}, y: ${y}${kdumps}},`;
|
||||
};
|
||||
return _dump('\n')(tree);
|
||||
},
|
||||
});
|
||||
return layout;
|
||||
}
|
||||
flextree.version = version;
|
||||
|
||||
const layoutChildren = (w, y = 0) => {
|
||||
w.y = y;
|
||||
(w.children || []).reduce((acc, kid) => {
|
||||
const [i, lastLows] = acc;
|
||||
layoutChildren(kid, w.y + w.ySize);
|
||||
// The lowest vertical coordinate while extreme nodes still point
|
||||
// in current subtree.
|
||||
const lowY = (i === 0 ? kid.lExt : kid.rExt).bottom;
|
||||
if (i !== 0) separate(w, i, lastLows);
|
||||
const lows = updateLows(lowY, i, lastLows);
|
||||
return [i + 1, lows];
|
||||
}, [0, null]);
|
||||
shiftChange(w);
|
||||
positionRoot(w);
|
||||
return w;
|
||||
};
|
||||
|
||||
// Resolves the relative coordinate properties - relX and prelim --
|
||||
// to set the final, absolute x coordinate for each node. This also sets
|
||||
// `prelim` to 0, so that `relX` for each node is its x-coordinate relative
|
||||
// to its parent.
|
||||
const resolveX = (w, prevSum, parentX) => {
|
||||
// A call to resolveX without arguments is assumed to be for the root of
|
||||
// the tree. This will set the root's x-coord to zero.
|
||||
if (typeof prevSum === 'undefined') {
|
||||
prevSum = -w.relX - w.prelim;
|
||||
parentX = 0;
|
||||
}
|
||||
const sum = prevSum + w.relX;
|
||||
w.relX = sum + w.prelim - parentX;
|
||||
w.prelim = 0;
|
||||
w.x = parentX + w.relX;
|
||||
(w.children || []).forEach(k => resolveX(k, sum, w.x));
|
||||
return w;
|
||||
};
|
||||
|
||||
// Process shift and change for all children, to add intermediate spacing to
|
||||
// each child's modifier.
|
||||
const shiftChange = w => {
|
||||
(w.children || []).reduce((acc, child) => {
|
||||
const [lastShiftSum, lastChangeSum] = acc;
|
||||
const shiftSum = lastShiftSum + child.shift;
|
||||
const changeSum = lastChangeSum + shiftSum + child.change;
|
||||
child.relX += changeSum;
|
||||
return [shiftSum, changeSum];
|
||||
}, [0, 0]);
|
||||
};
|
||||
|
||||
// Separates the latest child from its previous sibling
|
||||
/* eslint-disable complexity */
|
||||
const separate = (w, i, lows) => {
|
||||
const lSib = w.children[i - 1];
|
||||
const curSubtree = w.children[i];
|
||||
let rContour = lSib;
|
||||
let rSumMods = lSib.relX;
|
||||
let lContour = curSubtree;
|
||||
let lSumMods = curSubtree.relX;
|
||||
let isFirst = true;
|
||||
while (rContour && lContour) {
|
||||
if (rContour.bottom > lows.lowY) lows = lows.next;
|
||||
// How far to the left of the right side of rContour is the left side
|
||||
// of lContour? First compute the center-to-center distance, then add
|
||||
// the "spacing"
|
||||
const dist =
|
||||
(rSumMods + rContour.prelim) - (lSumMods + lContour.prelim) +
|
||||
rContour.xSize / 2 + lContour.xSize / 2 +
|
||||
rContour.spacing(lContour);
|
||||
if (dist > 0 || (dist < 0 && isFirst)) {
|
||||
lSumMods += dist;
|
||||
// Move subtree by changing relX.
|
||||
moveSubtree(curSubtree, dist);
|
||||
distributeExtra(w, i, lows.index, dist);
|
||||
}
|
||||
isFirst = false;
|
||||
// Advance highest node(s) and sum(s) of modifiers
|
||||
const rightBottom = rContour.bottom;
|
||||
const leftBottom = lContour.bottom;
|
||||
if (rightBottom <= leftBottom) {
|
||||
rContour = nextRContour(rContour);
|
||||
if (rContour) rSumMods += rContour.relX;
|
||||
}
|
||||
if (rightBottom >= leftBottom) {
|
||||
lContour = nextLContour(lContour);
|
||||
if (lContour) lSumMods += lContour.relX;
|
||||
}
|
||||
}
|
||||
// Set threads and update extreme nodes. In the first case, the
|
||||
// current subtree is taller than the left siblings.
|
||||
if (!rContour && lContour) setLThr(w, i, lContour, lSumMods);
|
||||
// In the next case, the left siblings are taller than the current subtree
|
||||
else if (rContour && !lContour) setRThr(w, i, rContour, rSumMods);
|
||||
};
|
||||
/* eslint-enable complexity */
|
||||
|
||||
// Move subtree by changing relX.
|
||||
const moveSubtree = (subtree, distance) => {
|
||||
subtree.relX += distance;
|
||||
subtree.lExtRelX += distance;
|
||||
subtree.rExtRelX += distance;
|
||||
};
|
||||
|
||||
const distributeExtra = (w, curSubtreeI, leftSibI, dist) => {
|
||||
const curSubtree = w.children[curSubtreeI];
|
||||
const n = curSubtreeI - leftSibI;
|
||||
// Are there intermediate children?
|
||||
if (n > 1) {
|
||||
const delta = dist / n;
|
||||
w.children[leftSibI + 1].shift += delta;
|
||||
curSubtree.shift -= delta;
|
||||
curSubtree.change -= dist - delta;
|
||||
}
|
||||
};
|
||||
|
||||
const nextLContour = w => {
|
||||
return w.hasChildren ? w.firstChild : w.lThr;
|
||||
};
|
||||
|
||||
const nextRContour = w => {
|
||||
return w.hasChildren ? w.lastChild : w.rThr;
|
||||
};
|
||||
|
||||
const setLThr = (w, i, lContour, lSumMods) => {
|
||||
const firstChild = w.firstChild;
|
||||
const lExt = firstChild.lExt;
|
||||
const curSubtree = w.children[i];
|
||||
lExt.lThr = lContour;
|
||||
// Change relX so that the sum of modifier after following thread is correct.
|
||||
const diff = lSumMods - lContour.relX - firstChild.lExtRelX;
|
||||
lExt.relX += diff;
|
||||
// Change preliminary x coordinate so that the node does not move.
|
||||
lExt.prelim -= diff;
|
||||
// Update extreme node and its sum of modifiers.
|
||||
firstChild.lExt = curSubtree.lExt;
|
||||
firstChild.lExtRelX = curSubtree.lExtRelX;
|
||||
};
|
||||
|
||||
// Mirror image of setLThr.
|
||||
const setRThr = (w, i, rContour, rSumMods) => {
|
||||
const curSubtree = w.children[i];
|
||||
const rExt = curSubtree.rExt;
|
||||
const lSib = w.children[i - 1];
|
||||
rExt.rThr = rContour;
|
||||
const diff = rSumMods - rContour.relX - curSubtree.rExtRelX;
|
||||
rExt.relX += diff;
|
||||
rExt.prelim -= diff;
|
||||
curSubtree.rExt = lSib.rExt;
|
||||
curSubtree.rExtRelX = lSib.rExtRelX;
|
||||
};
|
||||
|
||||
// Position root between children, taking into account their modifiers
|
||||
const positionRoot = w => {
|
||||
if (w.hasChildren) {
|
||||
const k0 = w.firstChild;
|
||||
const kf = w.lastChild;
|
||||
const prelim = (k0.prelim + k0.relX - k0.xSize / 2 +
|
||||
kf.relX + kf.prelim + kf.xSize / 2 ) / 2;
|
||||
Object.assign(w, {
|
||||
prelim,
|
||||
lExt: k0.lExt, lExtRelX: k0.lExtRelX,
|
||||
rExt: kf.rExt, rExtRelX: kf.rExtRelX,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Make/maintain a linked list of the indexes of left siblings and their
|
||||
// lowest vertical coordinate.
|
||||
const updateLows = (lowY, index, lastLows) => {
|
||||
// Remove siblings that are hidden by the new subtree.
|
||||
while (lastLows !== null && lowY >= lastLows.lowY)
|
||||
lastLows = lastLows.next;
|
||||
// Prepend the new subtree.
|
||||
return {
|
||||
lowY,
|
||||
index,
|
||||
next: lastLows,
|
||||
};
|
||||
};
|
||||
|
||||
function walkTree(tree, callback, key = 'c') {
|
||||
const walk = (item, parent) => callback(item, () => {
|
||||
var _item$key;
|
||||
|
||||
(_item$key = item[key]) == null ? void 0 : _item$key.forEach(child => {
|
||||
walk(child, item);
|
||||
});
|
||||
}, parent);
|
||||
|
||||
walk(tree);
|
||||
}
|
||||
|
||||
let canvas;
|
||||
|
||||
function getTextRect(items, font) {
|
||||
// re-use canvas object for better performance
|
||||
if (!canvas) canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
context.font = font;
|
||||
let maxWidth = 0;
|
||||
let width = 0;
|
||||
let row = 0;
|
||||
|
||||
const walk = item => {
|
||||
if (item.t === 'text') {
|
||||
item.p = { ...item.p
|
||||
};
|
||||
if (!width && row) item.p.newline = true;
|
||||
const metrics = context.measureText(item.v);
|
||||
width += metrics.width;
|
||||
if (maxWidth < width) maxWidth = width;
|
||||
} else if (item.t === 'softbreak') {
|
||||
width = 0;
|
||||
row += 1;
|
||||
} else if (item.t === 'link') {
|
||||
item.c.forEach(walk);
|
||||
}
|
||||
};
|
||||
|
||||
items.forEach(walk);
|
||||
return [maxWidth, row + 1];
|
||||
}
|
||||
|
||||
function linkWidth(nodeData) {
|
||||
const data = nodeData.data;
|
||||
return Math.max(6 - 2 * data.d, 1.5);
|
||||
}
|
||||
|
||||
function getKey(v) {
|
||||
const result = ['<'];
|
||||
v.forEach(item => {
|
||||
if (item.t === 'text') result.push(item.v.replace(/[<|&]/g, m => `&${m}`));else if (item.c) result.push(getKey(item.c));
|
||||
});
|
||||
result.push('>');
|
||||
return result.join('');
|
||||
}
|
||||
|
||||
function addSpacing(tree, spacing) {
|
||||
let depth = 0;
|
||||
walkTree(tree, (item, next) => {
|
||||
item.y += depth * spacing;
|
||||
depth += 1;
|
||||
next();
|
||||
depth -= 1;
|
||||
}, 'children');
|
||||
}
|
||||
|
||||
function getChildNodes() {
|
||||
return this.childNodes;
|
||||
}
|
||||
|
||||
function markmap(svg, data, opts) {
|
||||
svg = svg.datum ? svg : d3.select(svg);
|
||||
const classList = (svg.attr('class') || '').split(' ').filter(Boolean);
|
||||
|
||||
if (classList.indexOf('markmap') < 0) {
|
||||
classList.push('markmap');
|
||||
svg.attr('class', classList.join(' '));
|
||||
}
|
||||
|
||||
const style = svg.append('style');
|
||||
const g = svg.append('g');
|
||||
const zoom = d3.zoom().on('zoom', handleZoom);
|
||||
const svgNode = svg.node();
|
||||
const options = {
|
||||
duration: 500,
|
||||
nodeFont: '300 16px sans-serif',
|
||||
lineHeight: 20,
|
||||
spacingVertical: 5,
|
||||
spacingHorizontal: 80,
|
||||
autoFit: false,
|
||||
fitRatio: 0.95,
|
||||
color: d3.scaleOrdinal(d3.schemeCategory10),
|
||||
colorDepth: 0,
|
||||
...opts
|
||||
};
|
||||
const state = {};
|
||||
updateStyle();
|
||||
|
||||
if (data) {
|
||||
setData(data);
|
||||
fit(); // always fit for the first render
|
||||
}
|
||||
|
||||
svg.call(zoom);
|
||||
return {
|
||||
setData,
|
||||
setOptions,
|
||||
fit
|
||||
};
|
||||
|
||||
function updateStyle() {
|
||||
style.text(`\
|
||||
.markmap a { fill: #0097e6; }
|
||||
.markmap a:hover { fill: #00a8ff; }
|
||||
.markmap path { fill: none; }
|
||||
.markmap text { font: ${options.nodeFont} }
|
||||
.markmap tspan.markmap-em { font-style: italic; }
|
||||
.markmap tspan.markmap-strong { font-weight: 500; }
|
||||
.markmap g > g { cursor: pointer; }
|
||||
`);
|
||||
}
|
||||
|
||||
function handleZoom() {
|
||||
const {
|
||||
transform
|
||||
} = d3.event;
|
||||
g.attr('transform', transform);
|
||||
}
|
||||
|
||||
function addKeys(node) {
|
||||
let i = 1;
|
||||
const {
|
||||
colorDepth
|
||||
} = options;
|
||||
walkTree(node, (item, next, parent) => {
|
||||
var _item$v;
|
||||
|
||||
options.color(`${i}`); // preload colors
|
||||
|
||||
item.p = {
|
||||
i,
|
||||
...item.p
|
||||
};
|
||||
|
||||
if ((_item$v = item.v) == null ? void 0 : _item$v.length) {
|
||||
var _parent$p;
|
||||
|
||||
item.p.k = ((parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.k) || '') + getKey(item.v);
|
||||
}
|
||||
|
||||
next();
|
||||
if (!colorDepth || item.d === colorDepth) i += 1;
|
||||
});
|
||||
}
|
||||
|
||||
function setOptions(opts) {
|
||||
Object.assign(options, opts);
|
||||
}
|
||||
|
||||
function setData(data, opts) {
|
||||
addKeys(data);
|
||||
state.data = data;
|
||||
if (opts) setOptions(opts);
|
||||
renderData(data);
|
||||
}
|
||||
|
||||
function fit() {
|
||||
const {
|
||||
width: offsetWidth,
|
||||
height: offsetHeight
|
||||
} = svgNode.getBoundingClientRect();
|
||||
const {
|
||||
minX,
|
||||
maxX,
|
||||
minY,
|
||||
maxY
|
||||
} = state;
|
||||
const naturalWidth = maxY - minY;
|
||||
const naturalHeight = maxX - minX;
|
||||
const scale = Math.min(offsetWidth / naturalWidth * options.fitRatio, offsetHeight / naturalHeight * options.fitRatio, 2);
|
||||
const initialZoom = d3.zoomIdentity.translate((offsetWidth - naturalWidth * scale) / 2 - minY * scale, (offsetHeight - naturalHeight * scale) / 2 - minX * scale).scale(scale);
|
||||
svg.transition().duration(options.duration).call(zoom.transform, initialZoom);
|
||||
}
|
||||
|
||||
function handleClick(d) {
|
||||
var _data$p;
|
||||
|
||||
const {
|
||||
data
|
||||
} = d;
|
||||
data.p = { ...data.p,
|
||||
f: !((_data$p = data.p) == null ? void 0 : _data$p.f)
|
||||
};
|
||||
renderData(d.data);
|
||||
}
|
||||
|
||||
function handleLink(d) {
|
||||
d3.event.preventDefault();
|
||||
window.open(d.p.href);
|
||||
}
|
||||
|
||||
function renderTextNode(t, d) {
|
||||
if (d.t === 'link') {
|
||||
const a = t.append('a').attr('href', d.p.href).attr('title', d.p.title).on('click', handleLink);
|
||||
const text = a.selectAll(getChildNodes).data(d => d.c);
|
||||
text.enter().each(function (d) {
|
||||
const t = d3.select(this);
|
||||
renderTextNode(t, d);
|
||||
});
|
||||
}
|
||||
|
||||
if (d.t === 'text') {
|
||||
t.append('tspan').text(d.v).attr('class', d => {
|
||||
var _d$p;
|
||||
|
||||
const style = ((_d$p = d.p) == null ? void 0 : _d$p.style) || {};
|
||||
return [style.em && 'markmap-em', style.strong && 'markmap-strong'].filter(Boolean).join(' ');
|
||||
}).attr('x', d => {
|
||||
var _d$p2;
|
||||
|
||||
return ((_d$p2 = d.p) == null ? void 0 : _d$p2.newline) ? 8 : null;
|
||||
}).attr('dy', d => {
|
||||
var _d$p3;
|
||||
|
||||
return ((_d$p3 = d.p) == null ? void 0 : _d$p3.newline) ? options.lineHeight : null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function renderText(text) {
|
||||
const textNode = text.selectAll(getChildNodes).data(d => d.data.v);
|
||||
textNode.enter().each(function (d) {
|
||||
const t = d3.select(this);
|
||||
renderTextNode(t, d);
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
function renderData(originData) {
|
||||
var _origin$data$x, _origin$data$y;
|
||||
|
||||
if (!state.data) return;
|
||||
const layout = flextree().children(d => {
|
||||
var _d$p4;
|
||||
|
||||
return !((_d$p4 = d.p) == null ? void 0 : _d$p4.f) && d.c;
|
||||
}).nodeSize(d => {
|
||||
const [width, rows] = getTextRect(d.data.v, options.nodeFont);
|
||||
return [rows * options.lineHeight, width + 16];
|
||||
}).spacing((a, b) => {
|
||||
return a.parent === b.parent ? options.spacingVertical : options.spacingVertical * 2;
|
||||
});
|
||||
const tree = layout.hierarchy(state.data);
|
||||
layout(tree);
|
||||
addSpacing(tree, options.spacingHorizontal);
|
||||
const descendants = tree.descendants().reverse();
|
||||
const links = tree.links();
|
||||
const linkShape = d3.linkHorizontal();
|
||||
const minX = d3.min(descendants, d => d.x - d.xSize / 2);
|
||||
const maxX = d3.max(descendants, d => d.x + d.xSize / 2);
|
||||
const minY = d3.min(descendants, d => d.y);
|
||||
const maxY = d3.max(descendants, d => d.y + d.ySize);
|
||||
state.minX = minX;
|
||||
state.maxX = maxX;
|
||||
state.minY = minY;
|
||||
state.maxY = maxY;
|
||||
if (options.autoFit) fit();
|
||||
const origin = originData ? descendants.find(item => item.data === originData) : tree;
|
||||
const x0 = (_origin$data$x = origin.data.x0) != null ? _origin$data$x : origin.x;
|
||||
const y0 = (_origin$data$y = origin.data.y0) != null ? _origin$data$y : origin.y; // Update the nodes
|
||||
|
||||
const node = g.selectAll('g').data(descendants, d => d.data.p.k);
|
||||
const nodeEnter = node.enter().append('g').attr('transform', d => `translate(${y0 + origin.ySize - d.ySize},${x0 + origin.xSize / 2 - d.xSize})`).on('click', handleClick);
|
||||
const nodeExit = node.exit().transition().duration(options.duration);
|
||||
nodeExit.select('rect').attr('width', 0).attr('x', d => d.ySize);
|
||||
nodeExit.select('text').attr('fill-opacity', 0);
|
||||
nodeExit.attr('transform', d => `translate(${origin.y + origin.ySize - d.ySize},${origin.x + origin.xSize / 2 - d.xSize})`).remove();
|
||||
const nodeMerge = node.merge(nodeEnter);
|
||||
nodeMerge.transition().duration(options.duration).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`);
|
||||
nodeMerge.selectAll('rect').data(d => [d], d => d.data.p.k).join(enter => {
|
||||
return enter.append('rect').attr('x', d => d.ySize).attr('y', d => d.xSize - linkWidth(d) / 2).attr('width', 0).attr('height', linkWidth);
|
||||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('x', -1).attr('width', d => d.ySize + 2).attr('fill', d => options.color(d.data.p.i));
|
||||
nodeMerge.selectAll('circle').data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => {
|
||||
return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySize).attr('cy', d => d.xSize).attr('r', 0);
|
||||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('r', 6).attr('stroke', d => options.color(d.data.p.i)).attr('fill', d => {
|
||||
var _d$data$p;
|
||||
|
||||
return ((_d$data$p = d.data.p) == null ? void 0 : _d$data$p.f) ? options.color(d.data.p.i) : '#fff';
|
||||
});
|
||||
nodeMerge.selectAll('text').data(d => [d], d => d.data.p.k).join(enter => {
|
||||
return enter.append('text').attr('x', 8).attr('y', options.lineHeight - 4).attr('text-anchor', 'start').attr('fill-opacity', 0).call(renderText);
|
||||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('fill-opacity', 1); // Update the links
|
||||
|
||||
g.selectAll('path').data(links, d => d.target.data.p.k).join(enter => {
|
||||
const source = [y0 + origin.ySize, x0 + origin.xSize / 2];
|
||||
return enter.insert('path', 'g').attr('d', linkShape({
|
||||
source,
|
||||
target: source
|
||||
}));
|
||||
}, update => update, exit => {
|
||||
const source = [origin.y + origin.ySize, origin.x + origin.xSize / 2];
|
||||
return exit.transition().duration(options.duration).attr('d', linkShape({
|
||||
source,
|
||||
target: source
|
||||
})).remove();
|
||||
}).transition().duration(options.duration).attr('stroke', d => options.color(d.target.data.p.i)).attr('stroke-width', d => linkWidth(d.target)).attr('d', d => {
|
||||
const source = [d.source.y + d.source.ySize, d.source.x + d.source.xSize / 2];
|
||||
const target = [d.target.y, d.target.x + d.target.xSize / 2];
|
||||
return linkShape({
|
||||
source,
|
||||
target
|
||||
});
|
||||
});
|
||||
descendants.forEach(d => {
|
||||
d.data.x0 = d.x;
|
||||
d.data.y0 = d.y;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.markmap = markmap;
|
||||
|
||||
}(this.markmap = this.markmap || {}, d3));
|
||||
@ -50,6 +50,7 @@
|
||||
|
||||
.project-item{
|
||||
/*float: left;*/
|
||||
min-width: 0;
|
||||
width: 350px;
|
||||
height: 170px;
|
||||
/*margin-top: 20px;*/
|
||||
@ -167,7 +168,7 @@ body, html {
|
||||
min-width: 0;
|
||||
}
|
||||
.project-title{
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin:20px;
|
||||
text-align: center;
|
||||
@ -369,6 +370,7 @@ li.active > a,li.active > div > a{
|
||||
@media screen and (max-width:768px){
|
||||
/* 首页 */
|
||||
.project-item{
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
margin:10px;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// ****生成可编辑HTML表格****
|
||||
function InsertLine(obj) {
|
||||
var table_id = "#" + $(obj).attr("name");
|
||||
var name = $(obj).attr("name");
|
||||
|
||||
@ -1,142 +0,0 @@
|
||||
/* PrismJS 1.16.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+abap+abnf+actionscript+ada+apacheconf+apl+applescript+c+arff+asciidoc+asm6502+csharp+autohotkey+autoit+bash+basic+batch+bison+bnf+brainfuck+bro+cpp+aspnet+arduino+cil+coffeescript+cmake+clojure+ruby+csp+css-extras+d+dart+diff+markup-templating+dns-zone-file+docker+ebnf+eiffel+ejs+elixir+elm+erb+erlang+fsharp+flow+fortran+gcode+gedcom+gherkin+git+glsl+gml+go+graphql+groovy+less+handlebars+haskell+haxe+hcl+http+hpkp+hsts+ichigojam+icon+inform7+ini+io+j+java+scala+php+javastacktrace+jolie+jq+javadoclike+n4js+json+jsonp+json5+julia+keyman+kotlin+latex+markdown+liquid+lisp+livescript+lolcode+lua+makefile+crystal+django+matlab+mel+mizar+monkey+n1ql+typescript+nand2tetris-hdl+nasm+nginx+nim+nix+nsis+objectivec+ocaml+opencl+oz+parigp+parser+pascal+pascaligo+pcaxis+perl+jsdoc+phpdoc+php-extras+sql+powershell+processing+prolog+properties+protobuf+scss+puppet+pure+python+q+qore+r+js-extras+jsx+renpy+reason+vala+rest+rip+roboconf+textile+rust+sas+sass+stylus+javadoc+scheme+shell-session+smalltalk+smarty+plsql+soy+twig+swift+yaml+tcl+haml+toml+tt2+pug+tsx+t4-templating+visual-basic+t4-cs+regex+vbnet+velocity+verilog+vhdl+vim+t4-vb+wasm+wiki+xeora+xojo+xquery+tap */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -101,10 +101,12 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'doc_id':doc_id,
|
||||
}
|
||||
$.post("{% url 'del_doc' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
|
||||
@ -88,10 +88,12 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'doctemp_id':doctemp_id,
|
||||
}
|
||||
$.post("{% url 'del_doctemp' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
|
||||
@ -118,11 +118,13 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pname':$("#pname").val(),
|
||||
'desc':$("#desc").val(),
|
||||
}
|
||||
$.post("{% url 'create_project' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//创建成功
|
||||
window.location.reload();
|
||||
|
||||
@ -108,11 +108,13 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'types':1,
|
||||
'all_cnt':$("#regCodeCnt").val(),
|
||||
}
|
||||
$.post("{% url 'register_code_manage' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//新增成功,刷新页面
|
||||
window.location.reload();
|
||||
|
||||
@ -61,7 +61,9 @@
|
||||
var layer = layui.layer;
|
||||
//获取用户列表
|
||||
getUserInfo = function () {
|
||||
layer.load(1);
|
||||
$.post("{% url 'user_manage' %}",{'username':$("#username").val()},function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//执行表格渲染
|
||||
table.render({
|
||||
@ -94,12 +96,14 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'username':$("#user").val(),
|
||||
'password':$("#password").val(),
|
||||
'email':$("#email").val()
|
||||
}
|
||||
$.post("{% url 'create_user' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//创建成功,刷新页面
|
||||
window.location.reload();
|
||||
@ -122,12 +126,14 @@
|
||||
content:'<div style="padding:10px 0 0 20px;">修改用户[' + username + ']的密码:</div><div style="padding: 20px;"><input class="layui-input" type="password" id="newPwd1" style="margin-bottom:10px;" placeholder="输入新密码" required lay-verify="required"><input class="layui-input" type="password" id="newPwd2" placeholder="再次确认新密码" required lay-verify="required"></div>',
|
||||
btn:['确认修改','取消'],
|
||||
yes:function (index,layero) {
|
||||
layer.load();
|
||||
data = {
|
||||
'user_id':uid,
|
||||
'password':$("#newPwd1").val(),
|
||||
'password2':$("#newPwd2").val(),
|
||||
}
|
||||
$.post("{% url 'change_pwd' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
@ -152,10 +158,12 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'user_id':uid,
|
||||
}
|
||||
$.post("{% url 'del_user' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//删除成功
|
||||
window.location.reload();
|
||||
|
||||
@ -47,7 +47,9 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
$.post("{% url 'manage_token' %}",function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//生成成功
|
||||
//window.location.reload();
|
||||
|
||||
@ -139,7 +139,13 @@
|
||||
<script src="{% static 'editor.md/lib/sequence-diagram.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/lib/flowchart.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/lib/jquery.flowchart.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/editormd.min.js' %}"></script>
|
||||
<!-- 脑图开始 -->
|
||||
<script src="{% static 'mindmap/d3@5.js' %}"></script>
|
||||
<script src="{% static 'mindmap/transform.js' %}"></script>
|
||||
<script src="{% static 'mindmap/view.js' %}"></script>
|
||||
<!-- 脑图结束 -->
|
||||
<script src="{% static 'editor.md/editormd.js' %}"></script>
|
||||
<!-- <script src="{% static 'editor.md/editormd.min.js' %}"></script> -->
|
||||
<script src="{% static 'mrdoc.editor.js' %}"></script>
|
||||
<script src="{% static 'mrdoc.js' %}?version={{mrdoc_version}}"></script>
|
||||
<script>
|
||||
@ -208,10 +214,10 @@
|
||||
toolbarIcons : function() {
|
||||
return [
|
||||
"undo", "redo", "|",
|
||||
"bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase","kaiSpan", "|",
|
||||
"bold", "del", "italic", "quote","kaiSpan", "|",
|
||||
"h1", "h2", "h3", "h4", "|",
|
||||
"list-ul", "list-ol", "hr", "link", "reference-link", "|",
|
||||
"imgUpload", "attachment" ,"code", "code-block", "htmltable", "datetime", "emoji", "html-entities", "pagebreak", "|",
|
||||
"mindmap","imgUpload", "attachment" ,"code", "code-block", "htmltable", "|","datetime", "emoji", "html-entities", "pagebreak", "|",
|
||||
"watch", "preview", "|",
|
||||
"help"
|
||||
]
|
||||
@ -225,6 +231,7 @@
|
||||
imgUpload:'fa-image',
|
||||
attachment:'fa-upload',
|
||||
htmltable:'fa-table',
|
||||
mindmap:'fa-sitemap',
|
||||
},
|
||||
//设置自定义工具栏按钮的事件
|
||||
toolbarHandlers : {
|
||||
@ -272,7 +279,7 @@
|
||||
id:'uploadAttach',//配置ID,
|
||||
content:$('#upload-attach'),
|
||||
success: function(layero, index){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
$.post('{% url "manage_attachment" %}',{types:2},function(r){
|
||||
$("#attach_table tbody").empty()
|
||||
if(r.status){
|
||||
@ -311,21 +318,44 @@
|
||||
type:1,
|
||||
id:'addTable',
|
||||
title:'添加表格',
|
||||
//content:"<div style='margin:10px;'><input type='number' id='row' class='layui-input' placeholder='输入行数'><input type='number' id='col' class='layui-input' placeholder='输入列数'></div>",
|
||||
area:['600px','400px'],
|
||||
content:$("#layer-table"),
|
||||
btn:['确定','取消'], //添加按钮
|
||||
yes:function(index,layero){
|
||||
var table_md = convertTable("DataTable1")
|
||||
console.log(table_md)
|
||||
editor.insertValue("\n" + table_md);
|
||||
var current_tab_id = $("#insert-table-div .layui-tab-title .layui-this").attr("lay-id");
|
||||
console.log(current_tab_id)
|
||||
//粘贴的表格
|
||||
if(current_tab_id == 'pasteTable'){
|
||||
// console.log("插入粘贴的表格")
|
||||
editor.insertValue("\n" + $("#pasteExcel").val())
|
||||
layer.close(index)
|
||||
}else{//创建编辑的表格
|
||||
try {
|
||||
var table_md = convertTable("DataTable1")
|
||||
// console.log(table_md)
|
||||
editor.insertValue("\n" + table_md);
|
||||
layer.close(index)
|
||||
} catch (error) {
|
||||
layer.msg("请生成表格")
|
||||
}
|
||||
}
|
||||
|
||||
$("#TableGroup").empty();//清空表格
|
||||
layer.close(index)
|
||||
$("#pasteExcel").val('');
|
||||
|
||||
},
|
||||
btn2:function(index,layero){
|
||||
$("#TableGroup").empty();//清空表格
|
||||
$("#pasteExcel").val('');
|
||||
layer.close(index) // 关闭弹出框
|
||||
}
|
||||
});
|
||||
},
|
||||
mindmap:function(cm,icon,cursor,selection){
|
||||
cm.replaceSelection('```mindmap\n' + selection + "\n```");
|
||||
if(selection === "") {
|
||||
cm.setCursor(cursor.line+1, cursor.ch);
|
||||
}
|
||||
}
|
||||
},
|
||||
//设置语言
|
||||
@ -335,6 +365,7 @@
|
||||
imgUpload:"添加图片到文档",
|
||||
attachment:"添加附件",
|
||||
htmltable:"添加表格",
|
||||
mindmap:"添加思维导图",
|
||||
}
|
||||
},
|
||||
//配置项
|
||||
@ -358,6 +389,9 @@
|
||||
onchange:function(){
|
||||
md_changed = true
|
||||
},
|
||||
onload : function() {
|
||||
// this.insertValue(" ")
|
||||
}
|
||||
});
|
||||
//粘贴上传图片
|
||||
$("#editor-md").on('paste', function (ev) {
|
||||
@ -371,7 +405,7 @@
|
||||
reader.onload = function (event) {
|
||||
var base64 = event.target.result;
|
||||
//ajax上传图片
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
$.post("{% url 'upload_doc_img' %}",{base:base64}, function (ret) {
|
||||
layer.msg(ret.message);
|
||||
if (ret.success === 1) {
|
||||
@ -388,6 +422,7 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//未保存离开提示
|
||||
window.onbeforeunload =function() {
|
||||
if(md_changed){
|
||||
@ -403,7 +438,7 @@
|
||||
//console.log(data.index); //得到当前Tab的所在下标
|
||||
//console.log(data.elem); //得到当前的Tab大容器
|
||||
if(data.index == 1){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
console.log('选择图片')
|
||||
$("#select-img-group").empty(); //删除已有分组按钮
|
||||
//请求新的分组数据
|
||||
@ -451,7 +486,7 @@
|
||||
};
|
||||
//切换图片分组
|
||||
switchImgGroup = function(e){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
$.post("{% url 'manage_image' %}", {
|
||||
'types': 2,
|
||||
'group_id': e
|
||||
@ -489,7 +524,6 @@
|
||||
layer.closeAll();
|
||||
}
|
||||
</script>
|
||||
<script src="{% static 'mrdoc.js' %}?version={{mrdoc_version}}"></script>
|
||||
{% block custom_script %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
@ -536,23 +570,37 @@
|
||||
</div>
|
||||
<!-- 添加表格div -->
|
||||
<div id="layer-table" style="display: none;margin: 10px;">
|
||||
<div class="layui-row" style="margin: 10px;">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline" style="width: 50px;">
|
||||
<input type="number" placeholder="行" id="row" class="layui-input" value="3">
|
||||
<div class="layui-tab" lay-filter="table-tab" id="insert-table-div">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this" lay-id="generaTable">生成表格</li>
|
||||
<li lay-id="pasteTable">粘贴表格</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show" >
|
||||
<div class="layui-row" style="margin: 10px;">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline" style="width: 50px;">
|
||||
<input type="number" placeholder="行" id="row" class="layui-input" value="3">
|
||||
</div>
|
||||
<div class="layui-form-mid">x</div>
|
||||
<div class="layui-input-inline" style="width: 50px;">
|
||||
<input type="number" placeholder="列" id="col" class="layui-input" value="3">
|
||||
</div>
|
||||
<div class="layui-form-mid" style="width: 100px;">
|
||||
<button class="layui-btn layui-btn-normal layui-btn-xs" onclick="addtable(1)" >生成表格</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-mid">x</div>
|
||||
<div class="layui-input-inline" style="width: 50px;">
|
||||
<input type="number" placeholder="列" id="col" class="layui-input" value="3">
|
||||
</div>
|
||||
<div class="layui-form-mid" style="width: 100px;">
|
||||
<button class="layui-btn layui-btn-normal layui-btn-xs" onclick="addtable(1)" >生成表格</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row" style="margin:10px;" id="TableGroup"></div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab-item" >
|
||||
<textarea placeholder="粘贴Excel或在线电子表格的内容" class="layui-textarea" style="height: 200px;" id="pasteExcel"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row" style="margin:10px;" id="TableGroup"></div>
|
||||
</div>
|
||||
<script>
|
||||
//按钮选择上传图片
|
||||
@ -561,7 +609,7 @@
|
||||
elem: '#upload_img',
|
||||
url: '{% url "upload_doc_img" %}',
|
||||
before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
|
||||
layer.load(); //上传loading
|
||||
layer.load(1); //上传loading
|
||||
},
|
||||
done: function(res, index, upload){ //上传后的回调
|
||||
//上传成功
|
||||
@ -587,7 +635,7 @@
|
||||
url: '{% url "manage_attachment" %}',
|
||||
data:{types:0,csrfmiddlewaretoken: '{{ csrf_token }}'},
|
||||
before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
|
||||
layer.load(); //上传loading
|
||||
layer.load(1); //上传loading
|
||||
},
|
||||
done: function(res, index, upload){ //上传后的回调
|
||||
//上传成功,刷新页面
|
||||
@ -608,5 +656,79 @@
|
||||
$('div.editormd-preview').on('click','a',function(e){
|
||||
e.target.target = '_blank';
|
||||
});
|
||||
// 粘贴表格文本框侦听paste粘贴事件
|
||||
// 列宽的函数
|
||||
function columnWidth(rows, columnIndex) {
|
||||
return Math.max.apply(null, rows.map(function(row) {
|
||||
return row[columnIndex].length
|
||||
}))
|
||||
};
|
||||
|
||||
// 检查是否是个表格
|
||||
function looksLikeTable(data) {
|
||||
return true
|
||||
};
|
||||
// 编辑器侦听paste粘贴事件
|
||||
var pasteExcel = document.getElementById('pasteExcel')
|
||||
pasteExcel.addEventListener("paste", function(event) {
|
||||
console.log('粘贴Excel')
|
||||
var clipboard = event.clipboardData
|
||||
var data = clipboard.getData('text/plain')
|
||||
data = data.replace(/(?:[\n\u0085\u2028\u2029]|\r\n?)$/, '');
|
||||
|
||||
if(looksLikeTable(data)) {
|
||||
event.preventDefault()
|
||||
}else{
|
||||
return
|
||||
}
|
||||
// 行
|
||||
var rows = data.split((/[\n\u0085\u2028\u2029]|\r\n?/g)).map(function(row) {
|
||||
console.log(row)
|
||||
return row.split("\t")
|
||||
})
|
||||
// 列对齐
|
||||
var colAlignments = []
|
||||
// 列宽
|
||||
var columnWidths = rows[0].map(function(column, columnIndex) {
|
||||
var alignment = "l"
|
||||
var re = /^(\^[lcr])/i
|
||||
var m = column.match(re)
|
||||
if (m) {
|
||||
var align = m[1][1].toLowerCase()
|
||||
if (align === "c") {
|
||||
alignment = "c"
|
||||
} else if (align === "r") {
|
||||
alignment = "r"
|
||||
}
|
||||
}
|
||||
colAlignments.push(alignment)
|
||||
column = column.replace(re, "")
|
||||
rows[0][columnIndex] = column
|
||||
return columnWidth(rows, columnIndex)
|
||||
})
|
||||
var markdownRows = rows.map(function(row, rowIndex) {
|
||||
return "| " + row.map(function(column, index) {
|
||||
return column + Array(columnWidths[index] - column.length + 1).join(" ")
|
||||
}).join(" | ") + " |"
|
||||
row.map
|
||||
})
|
||||
markdownRows.splice(1, 0, "|" + columnWidths.map(function(width, index) {
|
||||
var prefix = ""
|
||||
var postfix = ""
|
||||
var adjust = 0
|
||||
var alignment = colAlignments[index]
|
||||
if (alignment === "r") {
|
||||
postfix = ":"
|
||||
adjust = 1
|
||||
} else if (alignment == "c") {
|
||||
prefix = ":"
|
||||
postfix = ":"
|
||||
adjust = 2
|
||||
}
|
||||
return prefix + Array(columnWidths[index] + 3 - adjust).join("-") + postfix
|
||||
}).join("|") + "|")
|
||||
event.target.value = markdownRows.join("\n")
|
||||
return false
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
@ -160,7 +160,7 @@
|
||||
,none: '文集暂无文档' //数据为空时的提示文本
|
||||
},
|
||||
click: function(obj){
|
||||
console.log(obj.data); //得到当前点击的节点数据
|
||||
//console.log(obj.data); //得到当前点击的节点数据
|
||||
// console.log(obj.state); //得到当前节点的展开状态:open、close、normal
|
||||
// console.log(obj.elem); //得到当前节点元素
|
||||
if(obj.data.level != 3){
|
||||
@ -169,6 +169,7 @@
|
||||
var $me = $(this)
|
||||
if($me.data('id') == obj.data.id){
|
||||
// console.log('点击了')
|
||||
layer.msg("选择了上级文档:"+obj.data.title)
|
||||
$me.find('span.layui-tree-txt').first().addClass('selected-parent-doc')
|
||||
}else{
|
||||
$me.find('span.layui-tree-txt').first().removeClass('selected-parent-doc')
|
||||
|
||||
@ -188,12 +188,12 @@
|
||||
|
||||
// 页面加载执行
|
||||
window.onload = function() {
|
||||
value = document.getElementById('doc').innerHTML;
|
||||
orig2 = document.getElementById('history').innerHTML;
|
||||
initUI();
|
||||
var d = document.createElement("div");
|
||||
d.style.cssText = "width: 50px; margin: 7px; height: 14px";
|
||||
dv.editor().addLineWidget(57, d)
|
||||
value = document.getElementById('doc').innerHTML;
|
||||
orig2 = document.getElementById('history').innerHTML;
|
||||
initUI();
|
||||
var d = document.createElement("div");
|
||||
d.style.cssText = "width: 50px; margin: 7px; height: 14px";
|
||||
dv.editor().addLineWidget(57, d)
|
||||
};
|
||||
|
||||
function mergeViewHeight(mergeView) {
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
<title>{% block title %}{% endblock %} - MrDoc</title>
|
||||
<link href="{% static 'layui/css/layui.css' %}?version={{mrdoc_version}}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{% static 'editor.md/css/editormd.css' %}?version={{mrdoc_version}}" />
|
||||
<!--<link rel="stylesheet" href="{% static 'prism/prism.css' %}" />-->
|
||||
<link rel="stylesheet" href="{% static 'katex/katex.min.css' %}?version={{mrdoc_version}}" />
|
||||
<link rel="stylesheet" href="{% static 'share.js/css/share.min.css' %}?version={{mrdoc_version}}" />
|
||||
<link rel="icon" href="{% static 'favicon_16.png' %}"/>
|
||||
@ -198,7 +197,7 @@
|
||||
</div>
|
||||
<!-- 标题结束 -->
|
||||
<!-- 正文开始 -->
|
||||
<div class="markdown-body" id="content" style="padding: 0 20px;">
|
||||
<div class="markdown-body" id="content" style="padding: 20px;">
|
||||
{% block page_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
@ -227,7 +226,15 @@
|
||||
<script src="{% static 'editor.md/lib/sequence-diagram.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/lib/flowchart.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/lib/jquery.flowchart.min.js' %}"></script>
|
||||
<script src="{% static 'editor.md/editormd.min.js' %}"></script>
|
||||
<!-- 脑图开始 -->
|
||||
<script src="{% static 'mindmap/d3@5.js' %}"></script>
|
||||
<script src="{% static 'mindmap/transform.js' %}"></script>
|
||||
<script src="{% static 'mindmap/view.js' %}"></script>
|
||||
<!-- <script src="{% static 'mindmap/mindmap.js' %}"></script> -->
|
||||
<!-- 脑图结束 -->
|
||||
|
||||
<!-- <script src="{% static 'editor.md/editormd.min.js' %}"></script> -->
|
||||
<script src="{% static 'editor.md/editormd.js' %}"></script>
|
||||
<script src="{% static 'share.js/js/social-share.min.js' %}"></script>
|
||||
<script>
|
||||
//加载页面时执行一次
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="layui-footer" style="border-top: 1px #e6e6e6 solid;text-align:center;margin:20px;width:100%;">
|
||||
<div class="layui-footer" style="border-top: 1px #e6e6e6 solid;text-align:center;margin-top:20px;width:100%;">
|
||||
<div style="margin-top:10px;">
|
||||
© <a href="/">MrDoc 2019-2020</a> |
|
||||
<span class="layui-hide-xs">基于<a href="https://www.djangoproject.com/" target="_blank">Django</a> | </span>
|
||||
|
||||
@ -82,7 +82,11 @@
|
||||
elem: '#upload_attachment',
|
||||
url: '{% url "manage_attachment" %}',
|
||||
data:{types:0,csrfmiddlewaretoken: '{{ csrf_token }}'},
|
||||
before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
|
||||
layer.load(1); //上传loading
|
||||
},
|
||||
done: function(res, index, upload){ //上传后的回调
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
//上传成功,刷新页面
|
||||
if(res.status == 1){
|
||||
window.location.reload();
|
||||
@ -107,18 +111,20 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'attach_id':attach_id,
|
||||
'types':1
|
||||
}
|
||||
$.post("{% url 'manage_attachment' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//修改失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
|
||||
@ -106,10 +106,12 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'doc_id':doc_id,
|
||||
}
|
||||
$.post("{% url 'del_doc' %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
|
||||
@ -86,13 +86,13 @@
|
||||
'history_id':history_id,
|
||||
}
|
||||
$.post("{% url 'manage_doc_history' doc.id %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//修改失败,提示
|
||||
layer.close('loading')
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
|
||||
@ -86,17 +86,19 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'doctemp_id':doctemp_id,
|
||||
}
|
||||
$.post("{% url 'del_doctemp' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//修改失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
|
||||
@ -99,18 +99,20 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'img_id':img_id,
|
||||
'types':0
|
||||
}
|
||||
$.post("{% url 'manage_image' %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//删除成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//删除失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
@ -131,6 +133,7 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'types':1,
|
||||
'img_id':img_id,
|
||||
@ -138,13 +141,14 @@
|
||||
}
|
||||
console.log(data)
|
||||
$.post("{% url 'manage_image' %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//移动成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//移动失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
@ -176,18 +180,19 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1); //上传loading
|
||||
data = {
|
||||
'types':0,
|
||||
'group_name':$("#img_group_name").val(),
|
||||
}
|
||||
$.post("{% url 'manage_img_group' %}",data,function(r){
|
||||
layer.closeAll('loading');
|
||||
if(r.status){
|
||||
//新建成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//新建失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
@ -199,7 +204,11 @@
|
||||
upload.render({
|
||||
elem: '#upload_img',
|
||||
url: '{% url "upload_doc_img" %}',
|
||||
before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
|
||||
layer.load(); //上传loading
|
||||
},
|
||||
done: function(res, index, upload){ //上传后的回调
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
//上传成功,刷新页面
|
||||
if(res.success == 1){
|
||||
window.location.reload();
|
||||
|
||||
@ -67,11 +67,13 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'types':2,
|
||||
'group_id':group_id,
|
||||
}
|
||||
$.post("{% url 'manage_img_group' %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//删除成功
|
||||
window.location.reload();
|
||||
@ -95,19 +97,21 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'types':1,
|
||||
'group_id':group_id,
|
||||
'group_name':$("#new-group-name").val()
|
||||
}
|
||||
$.post("{% url 'manage_img_group' %}",data,function(r){
|
||||
layer.closeAll('loading')
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//修改失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
|
||||
@ -128,11 +128,13 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pname':$("#pname").val(),
|
||||
'desc':$("#desc").val(),
|
||||
}
|
||||
$.post("{% url 'create_project' %}",data,function(r){
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
if(r.status){
|
||||
//创建成功
|
||||
window.location.reload();
|
||||
@ -157,19 +159,21 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pro_id':pro_id,
|
||||
'name':$("#pname").val(),
|
||||
'desc':$("#desc").val(),
|
||||
}
|
||||
$.post("{% url 'modify_project' %}",data,function(r){
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//修改失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
@ -187,10 +191,12 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pro_id':pro_id,
|
||||
}
|
||||
$.post("{% url 'del_project' %}",data,function(r){
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
@ -220,14 +226,14 @@
|
||||
'project_id':pro_id,
|
||||
}
|
||||
$.post("{% url 'report_md' %}",data,function(r){
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
if(r.status){
|
||||
//导出成功
|
||||
layer.close(index)
|
||||
//文件下载提示
|
||||
downloadMd(r.data)
|
||||
}else{
|
||||
//导出失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
layer.close(load)
|
||||
|
||||
@ -98,19 +98,21 @@
|
||||
form.render('radio'); // 刷新checkbox开关渲染(否则开关按钮会不显示)
|
||||
},
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'types':0,
|
||||
'username':$("#username").val(),
|
||||
'role': $('input[name="add-role"]:checked').val()
|
||||
}
|
||||
$.post("{% url 'manage_pro_colla' pro.id %}",data,function(r){
|
||||
layer.closeAll('loading'); //关闭loading
|
||||
if(r.status){
|
||||
//添加成功
|
||||
window.location.reload();
|
||||
//layer.close(index)
|
||||
}else{
|
||||
//添加失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
|
||||
@ -117,7 +117,7 @@
|
||||
<script>
|
||||
//获取文档数和上级文档信息
|
||||
$(function(){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
var doc_parent_id = {{ doc.parent_doc }};
|
||||
$.post("{% url 'get_pro_doc_tree' %}",{'pro_id':$("#project").val()},function(r){
|
||||
if(r.status){
|
||||
@ -167,7 +167,7 @@
|
||||
});
|
||||
//发布文档
|
||||
createDoc = function(){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
var data = {
|
||||
'doc_id':{{ doc.id }},
|
||||
'project':$("#project").val(),
|
||||
@ -179,15 +179,14 @@
|
||||
'sort':$("#sort").val(),
|
||||
}
|
||||
$.post("{% url 'modify_doc' doc_id=doc.id %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
layer.closeAll("loading");
|
||||
//修改成功
|
||||
layer.msg('发布成功,即将跳转',function(){
|
||||
md_changed = false;
|
||||
window.location.href = "{% url 'doc' pro_id=doc.top_doc doc_id=doc.id %}";
|
||||
});
|
||||
}else{
|
||||
layer.closeAll("loading");
|
||||
//修改失败
|
||||
layer.msg('保存失败');
|
||||
}
|
||||
@ -195,7 +194,7 @@
|
||||
};
|
||||
//保存草稿
|
||||
saveDoc = function(){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
var data = {
|
||||
'doc_id':{{ doc.id }},
|
||||
'project':$("#project").val(),
|
||||
@ -207,15 +206,14 @@
|
||||
'status':0
|
||||
}
|
||||
$.post("{% url 'modify_doc' doc_id=doc.id %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
//修改成功
|
||||
layer.closeAll("loading");
|
||||
layer.msg('保存成功',function(){
|
||||
md_changed = false;
|
||||
window.location.href = "{% url 'modify_doc' doc.id %}";
|
||||
});
|
||||
}else{
|
||||
layer.closeAll("loading");
|
||||
//修改失败
|
||||
layer.msg('保存失败');
|
||||
}
|
||||
@ -257,11 +255,10 @@
|
||||
var url = "{% url 'diff_doc' 0 1 %}";
|
||||
url = url.replace(0,doc_id).replace(1,history_id)
|
||||
$.post(url,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
editor.setMarkdown(r.data);
|
||||
layer.closeAll()
|
||||
}else{
|
||||
layer.closeAll("loading");
|
||||
layer.msg(r.data)
|
||||
}
|
||||
});
|
||||
|
||||
@ -59,23 +59,22 @@
|
||||
<script>
|
||||
//修改文档模板
|
||||
modifyDocTemp = function(){
|
||||
layer.load();
|
||||
layer.load(1);
|
||||
var data = {
|
||||
'doctemp_id':{{ doctemp.id }},
|
||||
'name':$("#doctemp-name").val(),
|
||||
'content':editor.getMarkdown(),
|
||||
}
|
||||
$.post("{% url 'modify_doctemp' doctemp_id=doctemp.id %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
//修改成功
|
||||
layer.closeAll("loading");
|
||||
layer.msg('修改成功,即将跳转',function(){
|
||||
md_changed = false;
|
||||
window.location.href = "{% url 'manage_doctemp' %}";
|
||||
});
|
||||
}else{
|
||||
//创建失败
|
||||
layer.closeAll("loading");
|
||||
layer.msg('保存失败');
|
||||
}
|
||||
});
|
||||
|
||||
@ -25,6 +25,49 @@
|
||||
.layui-laypage .layui-laypage-curr .layui-laypage-em{
|
||||
background-color: #333 !important;
|
||||
}
|
||||
/* 控制栏表单下拉框样式 */
|
||||
.index-control .layui-input-inline{
|
||||
width: 100px;
|
||||
}
|
||||
.index-control .layui-input{
|
||||
height: 25px;
|
||||
border: none;
|
||||
}
|
||||
.index-control .layui-form-select dl {
|
||||
top: 30px;
|
||||
}
|
||||
.index-control .layui-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
/* 文集列表样式 */
|
||||
.project-item-list{
|
||||
/* float: left; */
|
||||
min-width: 0;
|
||||
width: 100vw;
|
||||
height: 120px;
|
||||
/* 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);
|
||||
}
|
||||
/* 移动端筛选控制栏样式 */
|
||||
@media screen and (max-width: 768px){
|
||||
/* 控制栏样式 */
|
||||
.index-control .layui-form-item .layui-inline{
|
||||
display: -webkit-inline-box;
|
||||
}
|
||||
.index-control .layui-form-item .layui-input-inline{
|
||||
display: -webkit-inline-box;
|
||||
float: none;
|
||||
left: -3px;
|
||||
/* width: auto; */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="layui-container">
|
||||
@ -32,8 +75,53 @@
|
||||
{% include 'app_doc/head_base.html' %}
|
||||
<!-- 页头结束 -->
|
||||
|
||||
<!-- 筛选栏 -->
|
||||
<div class="layui-container" style="margin-top: 10px;">
|
||||
<!-- 表单风格开始 -->
|
||||
<div class="layui-row">
|
||||
<form class="index-control layui-form" style="float: right;" lay-filter="filter-project-form">
|
||||
<div class="layui-form-item">
|
||||
<!-- 筛选开始 -->
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<select name="role" lay-verify="" id="sel-role">
|
||||
<option value="">筛选</option>
|
||||
{% if request.user.is_authenticated %}
|
||||
<option value="0">公开文集</option>
|
||||
<option value="1">私密文集</option>
|
||||
<option value="99">协作文集</option>
|
||||
<option value="3">访问码文集</option>
|
||||
{% else %}
|
||||
<option value="0">公开文集</option>
|
||||
<option value="3">访问码文集</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline">
|
||||
<select name="sort" lay-verify="" id="sel-sort">
|
||||
<option value="">排序</option>
|
||||
<option value="0" {% if sort == 0 %} checked {% endif %}>时间升序</option>
|
||||
<option value="1" {% if sort == 1 %} checked {% endif %}>时间降序</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 筛选结束 -->
|
||||
<!-- 切换开始 -->
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline" style="width: 40px;">
|
||||
<a href="javascript:void(0);" id="switch-grid-list"><i class="layui-icon layui-icon-align-left"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 切换结束 -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- 表单风格结束 -->
|
||||
</div>
|
||||
|
||||
<!-- 搜索结果提示 -->
|
||||
{% if kw != '' %}
|
||||
<div style="text-align: center;margin-top: 5px;">符合“<span style="color: #FF5722;font-weight: 700;">{{kw}}</span>”的搜索结果:</div>
|
||||
<div style="text-align: center;margin-top: 0px;">符合“<span style="color: #FF5722;font-weight: 700;">{{kw}}</span>”的搜索结果:</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- 主体 -->
|
||||
@ -41,25 +129,25 @@
|
||||
<!-- 遍历文集列表 -->
|
||||
{% load project_filter %}
|
||||
{% for p in projects %}
|
||||
<!-- 网格布局 -->
|
||||
<div class="layui-col-md3 layui-col-xs12 project-item">
|
||||
<a href="{% url 'pro_index' p.id %}" title="{{p.name}}">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header" style="overflow:hidden;white-space: nowrap;text-overflow: ellipsis;color: black;">
|
||||
<div class="layui-card-header" >
|
||||
{% if p.role == 1 %}
|
||||
<strong><i class="layui-icon layui-icon-password"></i> {{ p.name }}</strong>
|
||||
<p class="layui-elip" style="font-weight: 700;"><i class="layui-icon layui-icon-circle-dot" style="color: #FF5722;"></i> {{ p.name }}</p>
|
||||
{% elif p.role == 2 %}
|
||||
<strong><i class="layui-icon layui-icon-user"></i> {{ p.name }}</strong>
|
||||
<p class="layui-elip" style="font-weight: 700;"><i class="layui-icon layui-icon-circle-dot" style="color: #009688;"></i> {{ p.name }}</p>
|
||||
{% elif p.role == 3 %}
|
||||
<strong><i class="layui-icon layui-icon-key"></i> {{ p.name }}</strong>
|
||||
<p class="layui-elip" style="font-weight: 700;"><i class="layui-icon layui-icon-circle-dot" style="color: #1E9FFF;"></i> {{ p.name }}</p>
|
||||
{% else %}
|
||||
<strong>{{ p.name }}</strong>
|
||||
<p class="layui-elip" style="font-weight: 700;"><i class="layui-icon layui-icon-circle-dot" style="color: #5FB878;"></i> {{ p.name }}</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<p>作者:{{p.create_user}}</p>
|
||||
<p style="overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">最新:<u title="{{p.id | get_new_doc}}">{{p.id | get_new_doc}}</u></p>
|
||||
<p class="tooltip">简介:
|
||||
<p class="layui-word-aux layui-elip">作者:{{p.create_user}}</p>
|
||||
<p class="layui-word-aux">最新:{{p.id | get_new_doc}}</p>
|
||||
<p class="tooltip layui-word-aux">简介:
|
||||
{% if p.intro == "" %}
|
||||
<span class="">此文集没有填写简介</span>
|
||||
{% else %}
|
||||
@ -67,11 +155,49 @@
|
||||
<span class="tooltip-content clearfix">{{ p.intro }}</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<!-- 网格布局结束 -->
|
||||
<!-- 列表布局开始 -->
|
||||
<div class="project-item-list layui-row layui-hide">
|
||||
<a href="{% url 'pro_index' p.id %}" title="{{p.name}}">
|
||||
<div class="layui-col-md1 layui-col-xs2" style="height: 100%;;text-align: center;display: flex;display: -webkit-flex;justify-content: center;align-items:center;">
|
||||
{% if p.role == 1 %}
|
||||
<i class="layui-icon layui-icon-menu-fill" style="font-size: 30px;color: #FF5722;"></i>
|
||||
{% elif p.role == 2 %}
|
||||
<i class="layui-icon layui-icon-group" style="font-size: 30px;color: #009688;"></i>
|
||||
{% elif p.role == 3 %}
|
||||
<i class="layui-icon layui-icon-key" style="font-size: 30px;color: #1E9FFF;"></i>
|
||||
{% else %}
|
||||
<i class="layui-icon layui-icon-read" style="font-size: 30px;color: #5FB878;"></i>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="layui-col-md11 layui-col-xs10">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header layui-elip" >
|
||||
<strong class="layui-elip">{{p.name}}</strong>
|
||||
</div>
|
||||
<div class="layui-card-body layui-word-aux layui-elip">
|
||||
<p class="">
|
||||
<i class="layui-icon layui-icon-user"></i> {{p.create_user}}
|
||||
</p>
|
||||
<p class="tooltip layui-word-aux">
|
||||
{% if p.intro == "" %}
|
||||
此文集没有填写简介
|
||||
{% else %}
|
||||
<!-- <span class="">{{ p.intro | slice:'30' }}…</span> -->
|
||||
{{ p.intro }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
<!-- 列表布局结束 -->
|
||||
{% endfor %}
|
||||
{% if project_list.count == 0 %}
|
||||
<img src="{% static 'non_doc.png' %}">
|
||||
@ -83,7 +209,7 @@
|
||||
<div class="layui-box layui-laypage layui-laypage-default">
|
||||
<!-- 上一页 -->
|
||||
{% if projects.has_previous %}
|
||||
<a href="?page={{ projects.previous_page_number }}&kw={{projects.kw}}" class="layui-btn layui-btn-xs layui-btn-normal">上一页</a>
|
||||
<a href="?page={{ projects.previous_page_number }}&kw={{kw}}&sort={{sort}}&role={{role}}" class="layui-btn layui-btn-xs layui-btn-normal">上一页</a>
|
||||
{% else %}
|
||||
<a href="javascript:;" class="layui-btn layui-btn-xs layui-btn-disabled">上一页</a>
|
||||
{% endif %}
|
||||
@ -94,12 +220,13 @@
|
||||
</span>
|
||||
<!-- 下一页 -->
|
||||
{% if projects.has_next %}
|
||||
<a href="?page={{ projects.next_page_number }}&kw={{projects.kw}}" class="layui-btn layui-btn-xs layui-btn-normal">下一页</a>
|
||||
<a href="?page={{ projects.next_page_number }}&kw={{kw}}&sort={{sort}}&role={{role}}" class="layui-btn layui-btn-xs layui-btn-normal">下一页</a>
|
||||
{% else %}
|
||||
<a class="layui-btn layui-btn-xs layui-btn-disabled">下一页</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页结束 -->
|
||||
|
||||
<!-- 页脚 -->
|
||||
{% include 'app_doc/foot_base.html' %}
|
||||
@ -113,6 +240,53 @@
|
||||
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
});
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
function positionFooter() {
|
||||
// 获取页脚的高度
|
||||
footerHeight = $(".layui-footer").height();
|
||||
// 获取页脚的高度
|
||||
/*
|
||||
scrollTop() 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
|
||||
*/
|
||||
footerTop = ($(window).scrollTop() + $(window).height() - footerHeight - 40)+"px";
|
||||
// console.log("页脚高度:",footerHeight)
|
||||
// console.log(footerTop)
|
||||
// console.log($(".layui-header").height()+$(".layui-container").height())
|
||||
// console.log("窗口高度:",$(window).height())
|
||||
//如果页面内容高度小于屏幕高度,div#footer将绝对定位到屏幕底部,否则div#footer保留它的正常静态定位
|
||||
if(($(".layui-header").height() + $(".index-control").height() + $(".project-list-content").height() + $(".project-list-page").height() + 15) < $(window).height()) {
|
||||
console.log("页脚置底")
|
||||
$(".layui-footer").css({ position: "absolute",left:"0" }).stop().css({top:footerTop});
|
||||
}else{
|
||||
$(".layui-footer").css({ position: ""})
|
||||
}
|
||||
};
|
||||
$(window).bind("load", function() {
|
||||
// 设置页脚位置
|
||||
var footerHeight = 0;
|
||||
var footerTop = 0;
|
||||
positionFooter();
|
||||
//$(window).scroll(positionFooter).resize(positionFooter);
|
||||
//设置条件栏选中值
|
||||
var url = layui.url();
|
||||
console.log(url)
|
||||
$("#sel-role").val(url.search.role);
|
||||
$("#sel-sort").val(url.search.sort);
|
||||
layui.form.render('select');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// 侦听Select下拉框的选择事件
|
||||
form.on('select()', function(data){
|
||||
var filter_data = form.val("filter-project-form");
|
||||
console.log(filter_data)
|
||||
window.location.href = '/?sort=' + filter_data['sort'] + '&role=' + filter_data['role'] + '&kw={{kw}}'
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
|
||||
//创建新文集
|
||||
createPro = function () {
|
||||
layer.open({
|
||||
@ -124,11 +298,13 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pname':$("#pname").val(),
|
||||
'desc':$("#desc").val(),
|
||||
}
|
||||
$.post("{% url 'create_project' %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
//创建成功,刷新页面
|
||||
window.location.reload();
|
||||
@ -152,18 +328,21 @@
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'pro_id':pro_id,
|
||||
'name':$("#pname").val(),
|
||||
'desc':$("#desc").val(),
|
||||
}
|
||||
$.post("{% url 'modify_project' %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
//修改成功,刷新页面
|
||||
window.location.reload();
|
||||
}else{
|
||||
//修改失败,提示
|
||||
console.log(r)
|
||||
// console.log(r)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
@ -179,11 +358,13 @@
|
||||
content:'<div style="padding:10px 0 0 20px;">修改用户[' + username + ']的密码:</div><div style="padding: 20px;"><input class="layui-input" type="password" id="newPwd1" style="margin-bottom:10px;" placeholder="输入新密码" required lay-verify="required"><input class="layui-input" type="password" id="newPwd2" placeholder="再次确认新密码" required lay-verify="required"></div>',
|
||||
btn:['确认修改','取消'],
|
||||
yes:function (index,layero) {
|
||||
layer.load(1);
|
||||
data = {
|
||||
'password':$("#newPwd1").val(),
|
||||
'password2':$("#newPwd2").val(),
|
||||
}
|
||||
$.post("{% url 'modify_pwd' %}",data,function(r){
|
||||
layer.closeAll("loading");
|
||||
if(r.status){
|
||||
//修改成功
|
||||
window.location.reload();
|
||||
@ -197,6 +378,18 @@
|
||||
},
|
||||
})
|
||||
};
|
||||
//切换文集列表和网格
|
||||
$("#switch-grid-list").click(function(){
|
||||
// 切换按钮图标
|
||||
$(this).children("i").toggleClass("layui-icon-align-left layui-icon-app");//切换图标
|
||||
// 切换class
|
||||
$(".project-item").toggleClass("layui-hide")
|
||||
$(".project-item-list").toggleClass("layui-hide")
|
||||
// 重新计算底部
|
||||
var footerHeight = 0;
|
||||
var footerTop = 0;
|
||||
positionFooter();
|
||||
});
|
||||
</script>
|
||||
<!-- 统计代码开始 -->
|
||||
{% if debug %}
|
||||
@ -204,32 +397,6 @@
|
||||
{{ static_code | safe }}
|
||||
{% endif %}
|
||||
<!-- 统计代码结束 -->
|
||||
<script>
|
||||
$(window).bind("load", function() {
|
||||
var footerHeight = 0;
|
||||
var footerTop = 0;
|
||||
positionFooter();
|
||||
function positionFooter() {
|
||||
// 获取页脚的高度
|
||||
footerHeight = $(".layui-footer").height();
|
||||
// 获取页脚的高度
|
||||
/*
|
||||
scrollTop() 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
|
||||
*/
|
||||
footerTop = ($(window).scrollTop()+$(window).height()-footerHeight-40)+"px";
|
||||
console.log(footerHeight)
|
||||
console.log(footerTop)
|
||||
console.log($(".layui-header").height()+$(".layui-container").height())
|
||||
console.log($(window).height())
|
||||
//如果页面内容高度小于屏幕高度,div#footer将绝对定位到屏幕底部,否则div#footer保留它的正常静态定位
|
||||
if(($(".layui-header").height() + $(".project-list-content").height() + $(".project-list-page").height()) < $(window).height()) {
|
||||
console.log("页脚置底")
|
||||
$(".layui-footer").css({ position: "absolute",left:"0" }).stop().css({top:footerTop});
|
||||
}
|
||||
}
|
||||
//$(window).scroll(positionFooter).resize(positionFooter);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@ -9,18 +9,23 @@
|
||||
{% if request.user == project.create_user or colla_user > 0 %}
|
||||
<span class="btn pull-left">|</span>
|
||||
<a class="btn pull-left" href="{% url 'create_doc' %}?pid={{project.id}}" target="_blank">
|
||||
<i class="fa fa-plus-square"></i> 添加
|
||||
<i class="fa fa-plus-square"></i> <span class="layui-hide-xs">添加</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if request.user == project.create_user %}
|
||||
<a class="btn pull-left" href="{% url 'manage_project' %}" target="_blank">
|
||||
<i class="fa fa-cubes"></i> 管理
|
||||
<i class="fa fa-cubes"></i> <span class="layui-hide-xs">管理</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_head %}
|
||||
<h1>{{ project.name }}</h1><hr>
|
||||
<p style="color: #c2c2c2;font-size:12px;">
|
||||
<!--<i class="fa fa-th-large"></i> 发表:{{ doc.create_time }}-->
|
||||
<i class="fa fa-user"></i> 创建人:{{ project.create_user.username }}
|
||||
<i class="fa fa-timer"></i> 创建于:{{ project.create_time }}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user