添加站点地图功能并优化了一些细节

This commit is contained in:
yangjian 2020-02-27 20:58:37 +08:00
parent 44ad624a3a
commit 00e7c097c3
20 changed files with 265 additions and 30 deletions

View File

@ -1,5 +1,14 @@
## 版本更新记录
### v0.2.12
- 优化Markdown编辑器的扩展工具栏按钮未选择文本时点击“楷”按钮光标移动到span标签中间
- 优化文集内点击新建文档操作体验,在文集内点击【新建】按钮,跳转到文档新建页面后自动选择所属文集;
- 优化新建文档页面的布局,使之更适合在中等屏幕下的操作;
- 当Django的Debug设置为True时后台会显示站点目前处于Debug调试模式
- 添加站点地图sitemap功能
### v0.2.11 2020-02-24
- 修复:删除文档导致其子文档找不到父级文档从而产生异常的Bug

View File

@ -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.2.11'
VERSIONS = '0.2.12'
ALLOWED_HOSTS = ['*']
@ -41,6 +41,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'app_admin',
'app_doc',
'django.contrib.sitemaps',
]
MIDDLEWARE = [

View File

@ -17,6 +17,8 @@ from django.contrib import admin
from django.urls import path,include,re_path
from django.views.static import serve
from django.conf import settings
from django.contrib.sitemaps import views
from app_doc.sitemaps import all_sitemaps as sitemaps
urlpatterns = [
path('admin/', admin.site.urls),
@ -24,4 +26,7 @@ urlpatterns = [
path('user/',include('app_admin.urls'),),
re_path('^static/(?P<path>.*)$',serve,{'document_root':settings.STATIC_ROOT}),# 静态文件
re_path('^media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}),# 媒体文件
path('sitemap.xml', views.index, {'sitemaps': sitemaps,'template_name':'sitemap/sitemap-index.xml'},name='sitemap',), # 站点地图索引
path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps,'template_name':'sitemap/sitemap.xml'}, # 站点地图
name='django.contrib.sitemaps.views.sitemap')
]

View File

@ -8,7 +8,7 @@
州的先生zmister.com自用并完全开源、基于Python编写的文档写作系统。
当前版本为:**v0.2.11**,版本发布时间为**2020-02-24**,更新记录详见:[CHANGES.md](./CHANGES.md)
当前版本为:**v0.2.12**,版本发布时间为**2020-02-27**,更新记录详见:[CHANGES.md](./CHANGES.md)
MrDoc拥有以下特点

View File

@ -19,6 +19,13 @@ class Project(models.Model):
verbose_name = '文集'
verbose_name_plural = verbose_name
def get_absolute_url(self):
from django.urls import reverse
return reverse("pro_index",
kwargs={
"pro_id":self.pk}
)
# 文档模型
class Doc(models.Model):
name = models.CharField(verbose_name="文档标题",max_length=50)
@ -41,6 +48,14 @@ class Doc(models.Model):
verbose_name_plural = verbose_name
# ordering = ['-create_time','sort']
def get_absolute_url(self):
from django.urls import reverse
return reverse("doc",
kwargs={
"pro_id": str(self.top_doc),
"doc_id":self.pk}
)
# 文档模板模型
class DocTemp(models.Model):
name = models.CharField(verbose_name="模板名称",max_length=50)

56
app_doc/sitemaps.py Normal file
View File

@ -0,0 +1,56 @@
# coding:utf-8
# @文件: sitemaps.py
# @创建者:州的先生
# #日期2020/2/26
# 博客地址zmister.com
from django.contrib.sitemaps import Sitemap,GenericSitemap
from django.urls import reverse
from app_doc.models import Doc,Project
# 首页地图
class HomeSitemap(Sitemap):
priority = 0.5
changefreq = 'daily'
def items(self):
return ['pro_list']
def location(self, item):
return reverse(item)
# 文集地图
class ProjectSitemap(Sitemap):
changefreq = "daily"
priority = 0.8
def items(self):
return Project.objects.filter(role=0)
# 文档地图
class DocSitemap(Sitemap):
changefreq = "daily"
priority = 0.8
def __init__(self,pro):
self.pro = pro
def items(self):
return Doc.objects.filter(status=1,top_doc=self.pro)
def lastmod(self,obj):
return obj.modify_time
all_sitemaps = {}
all_sitemaps['home'] = HomeSitemap()
for project in Project.objects.filter(role=0):
info_dict = {
'queryset': Doc.objects.filter(status=1,top_doc=project.id),
}
# sitemap = GenericSitemap(info_dict,priority=0.6)
sitemap = DocSitemap(pro=project.id)
# dict key is provided as 'section' in sitemap index view
all_sitemaps[str(project.id)] = sitemap
# print(all_sitemaps)

View File

@ -285,6 +285,7 @@ def doc(request,pro_id,doc_id):
def create_doc(request):
if request.method == 'GET':
try:
pid = request.GET.get('pid',-999)
# doc_list = Doc.objects.filter(create_user=request.user)
project_list = Project.objects.filter(create_user=request.user)
doctemp_list = DocTemp.objects.filter(create_user=request.user).values('id','name','create_time')

View File

@ -70,7 +70,6 @@
}
/* Gap filler */
.tooltip-item::after {
content: '';
position: absolute;
@ -88,7 +87,6 @@
}
/* 文集简介提示工具 */
.tooltip-content {
position: absolute;
z-index: 9999;
@ -121,7 +119,6 @@
}
/* 箭头 */
.tooltip-content::after {
content: '';
bottom: 100%; /* 箭头在头部 */
@ -147,7 +144,7 @@
}
.doc-form-label{
margin-left: 10px;
margin-right: 10px;
/*margin-right: 10px;*/
}
/* 文档浏览页 */
body, html {

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>XML站点地图源 - 索引</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">body{font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif;font-size:13px}#header,#footer{padding:2px;margin:10px;font-size:8pt;color:gray}a{color:black}td{font-size:11px}th{text-align:left;padding-right:30px;font-size:11px}tr.high{background-color:whitesmoke}#footer img{vertical-align:middle}</style>
</head>
<body>
<h1>XML站点地图源 - 索引</h1>
<div id="header">
<p>这是MrDoc站点地图索引用来帮助搜索引擎比如<a href="https://www.google.com">Google</a>, <a href="https://www.bing.com/">Bing</a>, <a href="https://www.yahoo.com">Yahoo!</a><a href="https://www.baidu.com">百度</a>更好地索引你的网站。 可以在<a href="https://www.sitemaps.org/">Sitemaps.org</a>上阅读更多有关于XML站点地图的信息</p>
</div>
<div id="content">
<table cellpadding="5">
<tr class="high">
<th>#</th>
<th>XML 站点地图</th>
<th>上次修改时间</th>
</tr>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:for-each select="sitemap:sitemapindex/sitemap:sitemap">
<tr><xsl:if test="position() mod 2 != 1"><xsl:attribute name="class">high</xsl:attribute></xsl:if>
<td><xsl:value-of select="position()"/></td>
<td><xsl:variable name="itemURL"><xsl:value-of select="sitemap:loc"/></xsl:variable>
<a href="{$itemURL}"><xsl:value-of select="sitemap:loc"/></a>
</td>
<td><xsl:if test="sitemap:lastmod"><xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,8)))"/> (<xsl:value-of select="substring(sitemap:lastmod,20,6)"/>)</xsl:if></td>
</tr>
</xsl:for-each>
</table>
</div>
<div id="footer">
<p>
<img src="data:image/gif;base64,R0lGODlhUAAPAJEAAGZmZv////9mAImOeSwAAAAAUAAPAAACoISPqcvtD0+YtNqLs968myCE4kiW5jkGw8q27gvDwYfWdq3G+i7T9w/M8Ya7GQAUoiSTEyYSKYA2nSKhdXUdCIlaXzRVDVdB0+dS2lJZ1bkt0Sgti6NysvM5jbq2ai2WywJHYrZUaEhIWJXm99foNiRI9XUoV4g4GJjJyEgBGAkEivIIyPUZeppCqorlheo6ulr00UFba3uLEaG7y9urUAAAOw%3D%3D" alt="XML Sitemap" title="XML Sitemap" /> 基于<a href="https://status301.net/wordpress-plugins/xml-sitemap-feed/">XML Sitemap &amp; Google News</a> 适配 <a href="https://gitee.com/zmister/MrDoc">MrDoc</a>
</p>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>XML站点地图源</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">body{font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif;font-size:13px}#header,#footer{padding:2px;margin:10px;font-size:8pt;color:gray}a{color:black}td{font-size:11px}th{text-align:left;padding-right:30px;font-size:11px}tr.high{background-color:whitesmoke}#footer img{vertical-align:middle}</style>
</head>
<body>
<h1>XML站点地图源</h1>
<div id="header">
<p>这是MrDoc站点地图索引用来帮助搜索引擎比如<a href="https://www.google.com">Google</a><a href="https://www.bing.com/">Bing</a><a href="https://www.yahoo.com">Yahoo!</a><a href="https://www.baidu.com">百度</a>更好地索引你的网站。 可以在<a href="https://www.sitemaps.org/">Sitemaps.org</a>上阅读更多有关于XML站点地图的信息</p>
</div>
<div id="content">
<table cellpadding="5">
<tr class="high">
<th>#</th>
<th>URL</th>
<th># Images</th>
<th>Priority</th>
<th>Last Modified</th>
</tr>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:for-each select="sitemap:urlset/sitemap:url">
<tr><xsl:if test="position() mod 2 != 1"><xsl:attribute name="class">high</xsl:attribute></xsl:if>
<td><xsl:value-of select="position()"/></td>
<td><xsl:variable name="itemURL"><xsl:value-of select="sitemap:loc"/></xsl:variable><a href="{$itemURL}"><xsl:value-of select="sitemap:loc"/></a></td>
<td><xsl:if test="image:image"><xsl:value-of select="count(image:image)"/></xsl:if></td>
<td><xsl:if test="sitemap:priority"><xsl:value-of select="concat(sitemap:priority*100,'%')"/></xsl:if></td>
<td><xsl:if test="sitemap:lastmod"><xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,8)))"/> (<xsl:value-of select="substring(sitemap:lastmod,20,6)"/>)</xsl:if></td>
</tr>
</xsl:for-each>
</table>
</div>
<div id="footer">
<p>
<img src="data:image/gif;base64,R0lGODlhUAAPAJEAAGZmZv////9mAImOeSwAAAAAUAAPAAACoISPqcvtD0+YtNqLs968myCE4kiW5jkGw8q27gvDwYfWdq3G+i7T9w/M8Ya7GQAUoiSTEyYSKYA2nSKhdXUdCIlaXzRVDVdB0+dS2lJZ1bkt0Sgti6NysvM5jbq2ai2WywJHYrZUaEhIWJXm99foNiRI9XUoV4g4GJjJyEgBGAkEivIIyPUZeppCqorlheo6ulr00UFba3uLEaG7y9urUAAAOw%3D%3D" alt="XML Sitemap" title="XML Sitemap" /> 基于<a href="https://status301.net/wordpress-plugins/xml-sitemap-feed/">XML Sitemap &amp; Google News</a> 适配 <a href="https://gitee.com/zmister/MrDoc">MrDoc</a>
</p>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -67,7 +67,12 @@
<div class="layui-body">
<!-- 内容主体区域 -->
<div style="padding: 15px;">{% block content %}{% endblock %}</div>
<div style="padding: 15px;">
{% if debug %}
<blockquote class="layui-elem-quote">当前站点处于Debug调试模式</blockquote>
{% endif %}
{% block content %}{% endblock %}
</div>
</div>
<div class="layui-footer" style="text-align:center;">

View File

@ -37,6 +37,14 @@
<div class="layui-form-mid layui-word-aux">开启此选项,新用户注册将需要填写注册码</div>
</div>
<!--<div class="layui-form-item">-->
<!--<label class="layui-form-label">启用文集导出</label>-->
<!--<div class="layui-input-inline">-->
<!--<input type="checkbox" name="enable_project_report" lay-skin="switch" lay-text="开启|关闭" {% if enable_project_report %}checked{% endif %}>-->
<!--</div>-->
<!--<div class="layui-form-mid layui-word-aux">开启此选项文集允许导出为EPUB和DOCX等格式文件文集拥有者可进行进一步控制文集是否开放导出</div>-->
<!--</div>-->
<div class="layui-form-item">
<label class="layui-form-label">启用邮箱</label>
<div class="layui-input-inline">

View File

@ -92,7 +92,7 @@
cm.replaceSelection('<span style="font-family:楷体">' + selection + "</span>");
// 如果当前没有选中的文本,将光标移到要输入的位置
if(selection === "") {
cm.setCursor(cursor.line, cursor.ch + 1);
cm.setCursor(cursor.line, cursor.ch + 29);
}
// this == 当前editormd实例
//console.log("testIcon =>", this, cm, icon, cursor, selection);

View File

@ -7,16 +7,16 @@
<div class="create-doc-form">
<div class="layui-form" style="">
<!-- 标题 -->
<div>
<label class="layui-form-label" style="padding-left:0px;padding-right:0px;"><i class="layui-icon layui-icon-edit"></i> 文档标题</label>
<div style="padding-bottom:10px;">
<label class="layui-form-label" style="padding-left:0px;padding-right:0px;"><i class="fa fa-header"></i> 文档标题</label>
<div class="layui-input-block" style="margin-left:95px;">
<input type="text" name="doc-name" id="doc-name" required lay-verify="required" placeholder="请输入文档标题" autocomplete="off" class="layui-input">
</div>
</div><br>
</div>
<div class="layui-row">
<div class="layui-col-md4 layui-col-sm6 " style="padding-bottom:10px;">
<label class="doc-form-label"><i class="fa fa-file-text"></i> 所属文集</label>
<label class="doc-form-label">所属文集</label>
<div class="layui-input-inline">
<select name="pro_id" lay-verify="required" lay-filter="project" id="project">
<option value=""></option>
@ -25,19 +25,19 @@
{% if p.role == 1 %}
<option value="{{ p.id }}">[私密]《{{ p.name }}》</option>
{% elif p.role == 2 %}
<option value="{{ p.id }}">[指定用户]《{{ p.name }}》</option>
<option value="{{ p.id }}" >[指定用户]《{{ p.name }}》</option>
{% elif p.role == 3 %}
<option value="{{ p.id }}">[访问码]《{{ p.name }}》</option>
<option value="{{ p.id }}" >[访问码]《{{ p.name }}》</option>
{% else %}
<option value="{{ p.id }}">[公开]《{{ p.name }}》</option>
<option value="{{ p.id }}" >[公开]《{{ p.name }}》</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
<div class="layui-col-md4 layui-col-sm6" style="padding-bottom:10px;">
<label class="doc-form-label"><i class="fa fa-chevron-circle-up"></i> 所属上级</label>
<div class="layui-col-md3 layui-col-sm6" style="padding-bottom:10px;">
<label class="doc-form-label">所属上级</label>
<div class="layui-input-inline">
<select name="parent_id" lay-verify="required" id="parent-doc">
<option value=""></option>
@ -45,29 +45,36 @@
</div>
</div>
<div class="layui-col-md4 layui-col-sm6 layui-col-xs12" style="padding-bottom:10px;">
<label class="doc-form-label"><i class="fa fa-list-ol"></i> 文档排序</label>
<div class="layui-col-md5 layui-col-sm12 layui-col-xs12" style="padding-bottom:10px;">
<label class="doc-form-label"><i class="fa fa-list-ol"></i> 排序</label>
<div class="layui-input-inline">
<input class="layui-input" placeholder="99" style="width:50px;" name="sort" id="sort"/>
</div>
<label class="doc-form-label" style="margin-right:0px;">
<button class="layui-btn layui-btn-normal layui-btn-sm" id="sel-doctemp">插入模板</button>
<button class="layui-btn layui-btn-normal layui-btn-sm" id="sel-doctemp" title="插入模板内容">
<i class="fa fa-clipboard"></i> 模板
</button>
</label>
<label class="doc-form-label" style="margin-right:0px;">
<input type="file" id="insert-local-file" onchange="insertLocalFile(this)" style="display:none;">
<button class="layui-btn layui-btn-normal layui-btn-sm" id="sel-local" onclick="selectLocalFile()">插入本地文本</button>
<button class="layui-btn layui-btn-normal layui-btn-sm" id="sel-local" onclick="selectLocalFile()" title="插入本地文本文件内容">
<i class="fa fa-clipboard"></i> 文本
</button>
</label>
</div>
<div class="layui-row">
<label class="doc-form-label">
<button class="layui-btn layui-btn-normal layui-btn-sm" onclick="saveDoc()">保存草稿</button>
<button class="layui-btn layui-btn-normal layui-btn-sm" onclick="saveDoc()" title="保存当前内容为草稿文档">
<i class="fa fa-save"></i> 保存
</button>
</label>
<label class="doc-form-label">
<button class="layui-btn layui-btn-normal layui-btn-sm" onclick="createDoc()">发布文档</button>
<button class="layui-btn layui-btn-normal layui-btn-sm" onclick="createDoc()" id="create_doc" title="发布当前内容">
<i class="fa fa-save"></i> 发布
</button>
</label>
</div>
</div>
</div>
@ -81,6 +88,7 @@
{% block custom_script %}
<script>
//选择文集
form.on('select(project)', function(data){
console.log(data.value); //得到被选中的值
@ -132,7 +140,15 @@
});
}
});
//保存文档
//带pid参数自动选择文集
var sel_pro_list = $('dl.layui-anim dd');
for(var i = 0;i < sel_pro_list.length; i++){
if(sel_pro_list[i].getAttribute('lay-value') == {{pid}}){
var sel_pro = 'dd[lay-value=' + sel_pro_list[i].getAttribute('lay-value') + ']';
$('#project').siblings("div.layui-form-select").find('dl').find(sel_pro).click();
}
}
//发布文档
createDoc = function(){
var data = {
'project':$("#project").val(),
@ -151,6 +167,8 @@
layer.msg('请选择文集!');
}
else{
//发布按钮设为禁用
$("#create_doc").attr({"disabled":"disabled"});
$.post("{% url 'create_doc' %}",data,function(r){
if(r.status){
//创建成功
@ -164,6 +182,8 @@
}else{
//创建失败
layer.msg('发布文档失败:'+r.data);
//恢复按钮状态
$("#create_doc").removeAttr("disabled");
}
});
}

View File

@ -12,7 +12,7 @@
<a class="btn pull-left" aria-label="" href="{% url 'modify_doc' doc_id=doc.id %}">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}" target="_blank">
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}?pid={{project.id}}" target="_blank">
<i class="fa fa-file"></i> 新建
</a>
{% endif %}

View File

@ -2,5 +2,7 @@
<div style="margin-top:10px;">
© <a href="/">MrDoc 2019</a>&nbsp;-&nbsp;
基于<a href="https://www.djangoproject.com/" target="_blank">Django框架</a>&nbsp;-&nbsp;
<a href="https://zmister.com" target="_blank">州的先生</a>出品</div>
<a href="https://zmister.com" target="_blank">州的先生</a>出品 -
<a href="{% url 'sitemap' %}" target="_blank">网站地图</a>
</div>
</div>

View File

@ -7,7 +7,7 @@
{% block head_toolbar %}
{% if request.user == project.create_user %}
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}" target="_blank">
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}?pid={{project.id}}" target="_blank">
<i class="fa fa-edit"></i> 添加文档
</a>
{% endif %}

View File

@ -7,7 +7,7 @@
{% block head_toolbar %}
{% if request.user == project.create_user %}
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}" target="_blank">
<a class="btn pull-left" aria-label="" href="{% url 'create_doc' %}?pid={{project.id}}" target="_blank">
<i class="fa fa-edit"></i> 添加文档
</a>
{% endif %}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/static/xml-sitemap-feed/styles/sitemap-index.xsl?version={{mrdoc_version}}"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for location in sitemaps %}<sitemap><loc>{{ location }}</loc></sitemap>{% endfor %}
</sitemapindex>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/static/xml-sitemap-feed/styles/sitemap.xsl?version={{mrdoc_version}}"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% spaceless %}
{% for url in urlset %}
<url>
<loc>{{ url.location }}</loc>
{% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
{% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
</url>
{% endfor %}
{% endspaceless %}
</urlset>