添加用户API功能
@ -1,6 +1,11 @@
|
||||
## 版本更新记录
|
||||
|
||||
### v0.3.3
|
||||
### v0.3.4
|
||||
|
||||
- 添加基于用户的API模块,支持通过用户Token获取文集、新建文档和上传图片;
|
||||
- 优化文档编辑页面布局;
|
||||
|
||||
### v0.3.3 2020-03-21
|
||||
|
||||
- 修复后台管理无法删除文档的错误;
|
||||
- 修复后台新建无法新建文集的错误;
|
||||
|
@ -25,7 +25,7 @@ SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d'
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
|
||||
VERSIONS = '0.3.3'
|
||||
VERSIONS = '0.3.4'
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
@ -41,6 +41,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'app_admin',
|
||||
'app_doc',
|
||||
'app_api',
|
||||
'django.contrib.sitemaps',
|
||||
]
|
||||
|
||||
|
@ -23,12 +23,13 @@ from app_doc.sitemaps import SitemapAll
|
||||
sitemaps = SitemapAll()
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('',include('app_doc.urls')),
|
||||
path('user/',include('app_admin.urls'),),
|
||||
path('admin/', admin.site.urls), # Django自带admin
|
||||
path('',include('app_doc.urls')), # doc应用
|
||||
path('user/',include('app_admin.urls'),), # admin应用
|
||||
path('api/',include('app_api.urls')), # API应用
|
||||
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')
|
||||
path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps,'template_name':'sitemap/sitemap.xml'},
|
||||
name='django.contrib.sitemaps.views.sitemap') # 站点地图
|
||||
]
|
||||
|
65
README.md
@ -1,16 +1,14 @@
|
||||
# MrDoc - 记录文档,汇聚思想,一个简单的文档记录和管理应用
|
||||
|
||||
**PC端文档阅读界面:**
|
||||
# MrDoc - 记录文档,汇聚思想
|
||||
|
||||

|
||||
|
||||
## 介绍
|
||||
|
||||
州的先生 - https://zmister.com - 自用并完全开源、基于Python编写的文档写作系统。
|
||||
基于Python编写的文档写作系统,适合作为文档、知识和笔记管理工具。
|
||||
|
||||
使用MarkDown快速记录你所思所想,仿GitBook两栏式阅读界面,清晰高效浏览。
|
||||
MarkDown快速书写,两栏式阅读布局,清晰高效浏览。
|
||||
|
||||
当前版本为:**v0.3.3**,版本发布时间为**2020-03-21**,此版本主要更新了如下内容:
|
||||
当前版本为:**v0.3.4**,版本发布时间为**2020-03-29**,此版本主要更新了如下内容:
|
||||
|
||||
- 修复后台管理无法删除文档的错误;
|
||||
- 修复后台新建无法新建文集的错误;
|
||||
@ -25,14 +23,14 @@
|
||||
|
||||
MrDoc拥有以下特点:
|
||||
|
||||
- 站点与用户系统简洁
|
||||
- 简洁的站点与用户系统
|
||||
- 基于Django自带的用户模型,实现简单高效的用户管理,支持用户注册、用户登录、管理员等控制等功能;
|
||||
- 支持全站关闭注册;
|
||||
- 支持注册邀请码配置;
|
||||
- 支持广告位自定义配置;
|
||||
- 支持统计代码自定义配置;
|
||||
|
||||
- 文档系统清晰
|
||||
- 结构清晰地文档系统
|
||||
- 基于文集的文档撰写和阅读;
|
||||
- 基于Editormd的Markdown编辑器,支持Markdown语法的文档写作,支持图片粘贴上传,支持从本地MD文件中插入内容;
|
||||
- 提供文档模板功能,支持文档模板的创建、修改;
|
||||
@ -41,15 +39,15 @@ MrDoc拥有以下特点:
|
||||
- 支持文集后台导出为markdown文本格式.md文件、前台导出为EPUB电子书;
|
||||
- 基于文集进行权限控制,提供公开、私密、指定用户可见、访问码可见4种权限模式;
|
||||
|
||||
|
||||
在开发过程中,参考和借鉴了GitBook、ShowDoc、Wordbook等应用和网站的功能与样式,并使用了众多开源组件、插件。
|
||||
|
||||
## 应用核心依赖环境
|
||||
|
||||
- 编程语言:Python 3+
|
||||
- Django框架:2.0+
|
||||
MrDoc基于Python语言的Django Web框架配合前端的LayUI、JQuery等库进行开发。
|
||||
|
||||
## 安装教程
|
||||
后端环境推荐使用Python3.4+、Django2.1+的版本。
|
||||
|
||||
## 安装简明教程
|
||||
|
||||
### 1、安装依赖库
|
||||
```
|
||||
@ -57,7 +55,9 @@ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2、配置数据库信息
|
||||
默认情况下,MrDoc使用Django的SQLite数据库,在旧版本MrDoc附带了一个Sqlit数据库,如果你使用的是MrDoc源码附带的Sqlite数据库,或使用Sqlite数据库,则无需另外配置数据库。
|
||||
|
||||
默认情况下,MrDoc使用Django的SQLite数据库,如果你使用Sqlite数据库,则无需另外配置数据库。
|
||||
|
||||
如果有配置其他数据库的需求,请在/MrDoc/MrDoc目录下打开settings.py文件,在约80行的位置,将如下代码:
|
||||
```
|
||||
DATABASES = {
|
||||
@ -81,6 +81,7 @@ DATABASES = {
|
||||
}
|
||||
```
|
||||
### 3、初始化数据库
|
||||
|
||||
在安装完所需的第三方库并配置好数据库信息之后,我们需要对数据库进行初始化。
|
||||
|
||||
在项目路径下打开命令行界面,运行如下命令生成数据库迁移:
|
||||
@ -107,13 +108,10 @@ python manage.py createsuperuser
|
||||
python manage.py runserver
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
## 使用说明文档
|
||||
|
||||
详见MrDoc使用文档:http://mrdoc.zmister.com
|
||||
|
||||
## 二次开发说明
|
||||
|
||||
详见MrDoc使用文档:http://mrdoc.zmister.com
|
||||
|
||||
## 问题提交和反馈
|
||||
|
||||
@ -123,32 +121,31 @@ python manage.py runserver
|
||||
|
||||
### 2、加入MrDoc交流群
|
||||
|
||||
加入MrDoc交流QQ群,群号为735507293,入群密码:mrdoc
|
||||
加入MrDoc交流QQ群,群号为**735507293**,入群密码:**mrdoc**
|
||||
|
||||
|
||||
## 版本更新
|
||||
## 更多应用截图
|
||||
|
||||
关注州的先生微信公众号(ID:zmister2016)、博客 https://zmister.com 及时获取MrDoc版本更新信息。
|
||||
### 首页
|
||||

|
||||
|
||||
## 更多截图
|
||||
### 文集页
|
||||

|
||||
|
||||
### 文档界面
|
||||

|
||||

|
||||
|
||||
### 文档编写界面
|
||||

|
||||
|
||||
### 普通用户后台界面
|
||||

|
||||
|
||||
### 管理员后台界面
|
||||

|
||||
|
||||
### 登录界面
|
||||

|
||||
|
||||
### 注册界面
|
||||

|
||||
|
||||
### 文档写作界面
|
||||

|
||||
|
||||
### 文档模板界面
|
||||

|
||||
|
||||
### 管理员后台界面
|
||||

|
||||
|
||||
### 普通用户后台界面
|
||||

|
@ -1,6 +1,8 @@
|
||||
from django.core.exceptions import PermissionDenied # 权限拒绝异常
|
||||
from django.http import Http404
|
||||
from django.http import Http404,JsonResponse
|
||||
from app_admin.models import SysSetting
|
||||
from app_api.models import UserToken
|
||||
from django import VERSION as django_version
|
||||
|
||||
# 超级管理员用户需求
|
||||
def superuser_only(function):
|
||||
@ -55,4 +57,24 @@ def allow_report_file(function):
|
||||
return function(request, *args, **kwargs)
|
||||
else:
|
||||
raise Http404
|
||||
return _inner
|
||||
return _inner
|
||||
|
||||
|
||||
# Token头验证
|
||||
# def check_token(function):
|
||||
# def _inner(request,*args,**kwargs):
|
||||
# if django_version[0] == 2 and django_version[1] >= 2:
|
||||
# headers = request.headers
|
||||
# print(headers)
|
||||
# if 'Mrdoc-Token' not in headers:
|
||||
# return JsonResponse({'data':'非法请求'})
|
||||
# else:
|
||||
# token = headers['Mrdoc-Token']
|
||||
# is_vail = UserToken.objects.filter(token=token)
|
||||
# if is_vail.exists():
|
||||
# return function(request,*args,**kwargs)
|
||||
# else:
|
||||
# return JsonResponse({'data':'无效Token'})
|
||||
# else:
|
||||
# metas = request.META
|
||||
# return _inner
|
0
app_api/__init__.py
Normal file
3
app_api/admin.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
5
app_api/apps.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AppApiConfig(AppConfig):
|
||||
name = 'app_api'
|
29
app_api/migrations/0001_initial.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.2.11 on 2020-03-22 09:28
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserToken',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('token', models.CharField(max_length=250, verbose_name='token值')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '用户Token',
|
||||
'verbose_name_plural': '用户Token',
|
||||
},
|
||||
),
|
||||
]
|
18
app_api/migrations/0002_auto_20200322_0929.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2.11 on 2020-03-22 09:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app_api', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='usertoken',
|
||||
name='token',
|
||||
field=models.CharField(max_length=250, unique=True, verbose_name='token值'),
|
||||
),
|
||||
]
|
0
app_api/migrations/__init__.py
Normal file
14
app_api/models.py
Normal file
@ -0,0 +1,14 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# Token模型
|
||||
class UserToken(models.Model):
|
||||
user = models.OneToOneField(User,on_delete=models.CASCADE)
|
||||
token = models.CharField(verbose_name="token值",max_length=250,unique=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.user
|
||||
|
||||
class Meta:
|
||||
verbose_name = '用户Token'
|
||||
verbose_name_plural = verbose_name
|
3
app_api/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
14
app_api/urls.py
Normal file
@ -0,0 +1,14 @@
|
||||
# coding:utf-8
|
||||
# @文件: urls.py
|
||||
# @创建者:州的先生
|
||||
# #日期:2020/3/22
|
||||
# 博客地址:zmister.com
|
||||
from django.urls import path,re_path
|
||||
from app_api import views
|
||||
|
||||
urlpatterns = [
|
||||
path('manage_token/',views.manage_token,name='manage_token'),# 用户Token管理
|
||||
path('get_projects/',views.get_projects,name="api_get_projects"), # 获取文集列表
|
||||
path('create_doc/',views.create_doc,name="api_create_doc"), # 新建文档
|
||||
path('upload_img/',views.upload_img,name="api_upload_img"), # 粘贴上传文件
|
||||
]
|
116
app_api/views.py
Normal file
@ -0,0 +1,116 @@
|
||||
from django.shortcuts import render
|
||||
from django.http.response import JsonResponse,HttpResponse
|
||||
from django.views.decorators.csrf import csrf_exempt # CSRF装饰器
|
||||
from django.views.decorators.http import require_http_methods,require_safe,require_GET
|
||||
from django.contrib.auth.decorators import login_required # 登录需求装饰器
|
||||
from django.core.exceptions import PermissionDenied,ObjectDoesNotExist
|
||||
from app_api.models import UserToken
|
||||
from app_doc.models import Project,Doc,Image
|
||||
import time,hashlib
|
||||
import traceback,json
|
||||
from django.conf import settings
|
||||
from app_doc.util_upload_img import upload_generation_dir,base_img_upload
|
||||
|
||||
# MrDoc 基于用户的Token访问API模块
|
||||
|
||||
# Token管理页面
|
||||
@require_http_methods(['POST','GET'])
|
||||
@login_required()
|
||||
def manage_token(request):
|
||||
if request.method == 'GET':
|
||||
try:
|
||||
token = UserToken.objects.get(user=request.user).token # 查询用户Token
|
||||
except ObjectDoesNotExist:
|
||||
token = '你还没有生成过Token!'
|
||||
return render(request,'app_api/manage_token.html',locals())
|
||||
elif request.method == 'POST':
|
||||
try:
|
||||
user = request.user
|
||||
now_time =str(time.time())
|
||||
string = 'user_{}_time_{}'.format(user,now_time).encode('utf-8')
|
||||
token_str = hashlib.sha224(string).hexdigest()
|
||||
user_token = UserToken.objects.filter(user=user)
|
||||
if user_token.exists():
|
||||
UserToken.objects.get(user=user).delete()
|
||||
UserToken.objects.create(
|
||||
user=user,
|
||||
token=token_str
|
||||
)
|
||||
return JsonResponse({'status':True,'data':token_str})
|
||||
except:
|
||||
if settings.DEBUG:
|
||||
print(traceback.print_exc())
|
||||
return JsonResponse({'status':False,'data':'生成出错,请重试!'})
|
||||
|
||||
|
||||
# 获取文集
|
||||
@require_GET
|
||||
def get_projects(request):
|
||||
token = request.GET.get('token','')
|
||||
try:
|
||||
token = UserToken.objects.get(token=token)
|
||||
projects = Project.objects.filter(create_user=token.user) # 查询文集
|
||||
project_list = []
|
||||
for project in projects:
|
||||
item = {
|
||||
'id':project.id, # 文集ID
|
||||
'name':project.name, # 文集名称
|
||||
'type':project.role # 文集状态
|
||||
}
|
||||
project_list.append(item)
|
||||
return JsonResponse({'status':True,'data':project_list})
|
||||
except ObjectDoesNotExist:
|
||||
return JsonResponse({'status':False,'data':'token无效'})
|
||||
|
||||
|
||||
# 新建文档
|
||||
@require_http_methods(['GET','POST'])
|
||||
@csrf_exempt
|
||||
def create_doc(request):
|
||||
token = request.GET.get('token', '')
|
||||
project_id = request.POST.get('pid','')
|
||||
doc_title = request.POST.get('title','')
|
||||
doc_content = request.POST.get('doc','')
|
||||
try:
|
||||
# 验证Token
|
||||
token = UserToken.objects.get(token=token)
|
||||
# 文集是否属于用户
|
||||
is_project = Project.objects.filter(create_user=token.user,id=project_id)
|
||||
# 新建文档
|
||||
if is_project.exists():
|
||||
Doc.objects.create(
|
||||
name = doc_title, # 文档内容
|
||||
pre_content = doc_content, # 文档的编辑内容,意即编辑框输入的内容
|
||||
top_doc = project_id, # 所属文集
|
||||
create_user = token.user # 创建的用户
|
||||
)
|
||||
return JsonResponse({'status': True, 'data': 'ok'})
|
||||
else:
|
||||
return JsonResponse({'status':False,'data':'非法请求'})
|
||||
except ObjectDoesNotExist:
|
||||
return JsonResponse({'status': False, 'data': 'token无效'})
|
||||
|
||||
|
||||
# 上传图片
|
||||
@csrf_exempt
|
||||
@require_http_methods(['GET','POST'])
|
||||
def upload_img(request):
|
||||
##################
|
||||
# {"success": 0, "message": "出错信息"}
|
||||
# {"success": 1, "url": "图片地址"}
|
||||
##################
|
||||
token = request.GET.get('token', '')
|
||||
base64_img = request.POST.get('data','')
|
||||
try:
|
||||
# 验证Token
|
||||
token = UserToken.objects.get(token=token)
|
||||
# 上传图片
|
||||
result = base_img_upload(base64_img, '', token.user)
|
||||
return JsonResponse(result)
|
||||
# return HttpResponse(json.dumps(result), content_type="application/json")
|
||||
except ObjectDoesNotExist:
|
||||
return JsonResponse({'success': 0, 'data': 'token无效'})
|
||||
except:
|
||||
if settings.DEBUG:
|
||||
print(traceback.print_exc())
|
||||
return JsonResponse({'success':0,'data':'上传出错'})
|
23
app_doc/migrations/0014_auto_20200322_1459.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 2.2.11 on 2020-03-22 14:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app_doc', '0013_image_file_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='doc',
|
||||
name='content',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='文档内容'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='doc',
|
||||
name='pre_content',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='编辑内容'),
|
||||
),
|
||||
]
|
@ -26,11 +26,27 @@ class Project(models.Model):
|
||||
"pro_id":self.pk}
|
||||
)
|
||||
|
||||
# # 文集协作模型
|
||||
# class ProjectCollaborator(models.Model):
|
||||
# project = models.ForeignKey(Project,on_delete=models.CASCADE)
|
||||
# user = models.ForeignKey(User,on_delete=models.CASCADE)
|
||||
# # 用户的协作模式:0表示可新建文档可修改删除自己新建的文档,1表示可新建文档可修改删除所有文档
|
||||
# role = models.IntegerField(choices=((0,0),(1,1)),default=0,verbose_name='协作模式')
|
||||
# create_time = models.DateTimeField(auto_now=True,verbose_name='添加时间')
|
||||
# modify_time = models.DateTimeField(auto_now_add=True,verbose_name='修改时间')
|
||||
#
|
||||
# def __str__(self):
|
||||
# return self.project
|
||||
#
|
||||
# class Meta:
|
||||
# verbose_name = '文集协作'
|
||||
# verbose_name_plural = verbose_name
|
||||
|
||||
# 文档模型
|
||||
class Doc(models.Model):
|
||||
name = models.CharField(verbose_name="文档标题",max_length=50)
|
||||
pre_content = models.TextField(verbose_name="编辑内容")
|
||||
content = models.TextField(verbose_name="文档内容")
|
||||
pre_content = models.TextField(verbose_name="编辑内容",null=True,blank=True)
|
||||
content = models.TextField(verbose_name="文档内容",null=True,blank=True)
|
||||
parent_doc = models.IntegerField(default=0,verbose_name="上级文档")
|
||||
top_doc = models.IntegerField(default=0,verbose_name="所属项目")
|
||||
sort = models.IntegerField(verbose_name='排序',default=99)
|
||||
@ -65,7 +81,7 @@ class DocTemp(models.Model):
|
||||
modify_time = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
self.name
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = '文档模板'
|
||||
@ -78,7 +94,7 @@ class ProjectReport(models.Model):
|
||||
allow_epub = models.IntegerField(default=0,verbose_name="前台导出EPUB")
|
||||
|
||||
def __str__(self):
|
||||
self.project.name
|
||||
return self.project.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = '文集导出'
|
||||
|
@ -5,7 +5,6 @@
|
||||
# 博客地址:zmister.com
|
||||
# MrDoc文集文档导出相关功能代码
|
||||
from django.conf import settings
|
||||
|
||||
import subprocess
|
||||
import datetime,time
|
||||
import re
|
||||
|
@ -50,9 +50,9 @@ def img_upload(files, dir_name, user):
|
||||
file_name = files.name.replace(file_suffix,'').replace('.','') + '_' +str(int(time.time())) + '.' + file_suffix
|
||||
path_file=os.path.join(relative_path, file_name)
|
||||
path_file = settings.MEDIA_ROOT + path_file
|
||||
print('文件路径:',path_file)
|
||||
# print('文件路径:',path_file)
|
||||
file_url = settings.MEDIA_URL + relative_path + file_name
|
||||
print("文件URL:",file_url)
|
||||
# print("文件URL:",file_url)
|
||||
with open(path_file, 'wb') as f:
|
||||
for chunk in files.chunks():
|
||||
f.write(chunk) # 保存文件
|
||||
@ -72,9 +72,9 @@ def base_img_upload(files,dir_name, user):
|
||||
file_name = str(datetime.datetime.today()).replace(':', '').replace(' ', '_').split('.')[0] + '.png' # 日期时间
|
||||
path_file = os.path.join(relative_path, file_name)
|
||||
path_file = settings.MEDIA_ROOT + path_file
|
||||
print('文件路径:', path_file)
|
||||
# print('文件路径:', path_file)
|
||||
file_url = settings.MEDIA_URL + relative_path + file_name
|
||||
print("文件URL:", file_url)
|
||||
# print("文件URL:", file_url)
|
||||
with open(path_file, 'wb') as f:
|
||||
f.write(files_base) # 保存文件
|
||||
Image.objects.create(
|
||||
|
Before Width: | Height: | Size: 34 KiB |
BIN
docs/mrdoc_admin.jpg
Normal file
After Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 62 KiB |
BIN
docs/mrdoc_doc.jpg
Normal file
After Width: | Height: | Size: 244 KiB |
BIN
docs/mrdoc_doc_write.jpg
Normal file
After Width: | Height: | Size: 349 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 16 KiB |
BIN
docs/mrdoc_project.jpg
Normal file
After Width: | Height: | Size: 173 KiB |
BIN
docs/mrdoc_user.jpg
Normal file
After Width: | Height: | Size: 287 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 26 KiB |
67
template/app_api/manage_token.html
Normal file
@ -0,0 +1,67 @@
|
||||
{% extends 'app_doc/manage_base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% block title %}用户Token管理{% endblock %}
|
||||
{% block content %}
|
||||
<div class="layui-card-header" style="margin-bottom: 10px;">
|
||||
<div class="layui-row">
|
||||
<span style="font-size:18px;">用户Token管理
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row">
|
||||
<form>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Token值</label>
|
||||
<div class="layui-input-inline" style="width:450px;">
|
||||
<input type="text" name="token" id="token" value="{{token}}" autocomplete="off" class="layui-input" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">操作</label>
|
||||
<button class="layui-btn layui-btn-normal" type="button" id="copy-token" onclick="copyToken()">复制</button>
|
||||
<button class="layui-btn layui-btn-normal" type="button" onclick="generaToken()">重新生成Token</button>
|
||||
</div>
|
||||
</form>
|
||||
</div><hr>
|
||||
<div class="layui-row">
|
||||
*借助Token,你可以无需打开MrDoc网站,直接通过更加自动化的方式进行文档编写;配合MrDoc浏览器剪藏扩展,还能将MrDoc化身为便捷的网页内容摘录工具;
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_script %}
|
||||
<script>
|
||||
//复制Token
|
||||
copyToken = function(){
|
||||
var token_val = document.getElementById("token");
|
||||
token_val.select();
|
||||
document.execCommand("Copy");
|
||||
layer.msg("已复制!")
|
||||
};
|
||||
//生成Token
|
||||
generaToken = function(){
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'重置Token',
|
||||
area:'300px;',
|
||||
id:'delPro',//配置ID
|
||||
content:'<div style="margin:10px;">警告:此操作将重新为你的账户生成Token,旧Token将失效!</div>',
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
$.post("{% url 'manage_token' %}",function(r){
|
||||
if(r.status){
|
||||
//生成成功
|
||||
//window.location.reload();
|
||||
$('#token').val(r.data);
|
||||
layer.close(index)
|
||||
}else{
|
||||
//生成失败,提示
|
||||
//console.log(r)
|
||||
layer.close(index)
|
||||
layer.msg(r.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
@ -8,18 +8,18 @@
|
||||
<div class="layui-form" style="">
|
||||
<!-- 标题 -->
|
||||
<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;">
|
||||
<!--<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:0px;">
|
||||
<input type="text" name="doc-name" id="doc-name" required lay-verify="required" placeholder="请输入文档标题" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md4 layui-col-sm6 " style="padding-bottom:10px;">
|
||||
<label class="doc-form-label">所属文集</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="pro_id" lay-verify="required" lay-filter="project" id="project">
|
||||
<option value=""></option>
|
||||
<option value="">请选择一个文集</option>
|
||||
<option value="-1">新建文集</option>
|
||||
{% for p in project_list %}
|
||||
{% if p.role == 1 %}
|
||||
@ -37,10 +37,10 @@
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3 layui-col-sm6" style="padding-bottom:10px;">
|
||||
<label class="doc-form-label">所属上级</label>
|
||||
<!--<label class="doc-form-label">所属上级</label>-->
|
||||
<div class="layui-input-inline">
|
||||
<select name="parent_id" lay-verify="required" id="parent-doc">
|
||||
<option value=""></option>
|
||||
<option value="">请选择所属上级</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -64,6 +64,9 @@
|
||||
<li class="layui-nav-item layui-nav-itemed">
|
||||
<a href="{% url 'manage_image' %}"><i class="layui-icon layui-icon-picture"></i> 图片素材管理</a>
|
||||
</li>
|
||||
<li class="layui-nav-item layui-nav-itemed">
|
||||
<a href="{% url 'manage_token' %}"><i class="layui-icon layui-icon-key"></i> 用户Token管理</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,18 +23,12 @@
|
||||
|
||||
<!-- 标题 -->
|
||||
<div>
|
||||
<label class="layui-form-label" style="padding-left:0px;padding-right:0px;"><i class="layui-icon layui-icon-edit"></i> 文档标题</label>
|
||||
<div class="layui-input-block" style="margin-left:95px;">
|
||||
<!--<label class="layui-form-label" style="padding-left:0px;padding-right:0px;"><i class="layui-icon layui-icon-edit"></i> 文档标题</label>-->
|
||||
<div class="layui-input-block" style="margin-left:0;">
|
||||
<input type="text" name="doc-name" id="doc-name" required lay-verify="required" placeholder="请输入文档标题" value="{{ doc.name }}" class="layui-input">
|
||||
</div>
|
||||
</div><br>
|
||||
|
||||
<!--<label class="doc-form-label">标题</label>-->
|
||||
<!--<div class="layui-input-inline">-->
|
||||
<!--<input type="text" name="doc-name" id="doc-name" required lay-verify="required" placeholder="请输入文档标题" value="{{ doc.name }}" class="layui-input" >-->
|
||||
<!--</div>-->
|
||||
|
||||
|
||||
<label class="doc-form-label">文集</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="pro_id" lay-verify="required" lay-filter="project" id="project" disabled>
|
||||
@ -42,10 +36,10 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label class="doc-form-label">上级文档</label>
|
||||
<!--<label class="doc-form-label">上级文档</label>-->
|
||||
<div class="layui-input-inline">
|
||||
<select name="parent_id" lay-verify="required" id="parent-doc">
|
||||
<option value="0"></option>
|
||||
<option value="0">选择上级文档</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<p>作者:{{p.create_user}}</p>
|
||||
<p>最新:<u>{{p.id | get_new_doc}}</u></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">简介:
|
||||
{% if p.intro == "" %}
|
||||
<span class="">此文集没有填写简介</span>
|
||||
|