优化项目目录,新增后台设置强制登录功能,优化样式
This commit is contained in:
parent
682fb7156b
commit
62d1c6c9e2
11
CHANGES.md
11
CHANGES.md
@ -1,6 +1,15 @@
|
|||||||
## 版本更新记录
|
## 版本更新记录
|
||||||
|
|
||||||
### v.0.5.0 2020-05-02
|
### v0.5.1 2020-05-08
|
||||||
|
|
||||||
|
- 优化个人中心交互体验;
|
||||||
|
- 添加站点异常报错的日志功能;
|
||||||
|
- 优化项目结构;
|
||||||
|
- 修改文档页面新增删除文档功能;
|
||||||
|
- 优化首页样式排版;
|
||||||
|
- 后台支持设置全站强制登录;
|
||||||
|
|
||||||
|
### v0.5.0 2020-05-02
|
||||||
|
|
||||||
- MrDoc正式中文取名:觅道文档;
|
- MrDoc正式中文取名:觅道文档;
|
||||||
- 文档编辑器添加Markdown折叠功能;
|
- 文档编辑器添加Markdown折叠功能;
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
from loguru import logger
|
||||||
|
from django.conf import settings
|
||||||
|
import os
|
||||||
|
|
||||||
|
LOG_DIR = os.path.join(settings.BASE_DIR,'log')
|
||||||
|
|
||||||
|
if os.path.exists(LOG_DIR) is False:
|
||||||
|
os.makedirs(LOG_DIR)
|
||||||
|
|
||||||
|
logger.add(os.path.join(LOG_DIR,'{time}.log'),rotation='1 days',retention='30 days',encoding='utf-8')
|
||||||
@ -12,10 +12,16 @@ https://docs.djangoproject.com/en/2.1/ref/settings/
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from configparser import ConfigParser
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# 配置文件和数据文件目录
|
||||||
|
CONFIG_DIR = os.path.join(BASE_DIR, 'config')
|
||||||
|
CONFIG = ConfigParser()
|
||||||
|
CONFIG.read(os.path.join(CONFIG_DIR,'config.ini'),encoding='utf-8')
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
|
||||||
@ -24,9 +30,9 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d'
|
SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d'
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = False
|
DEBUG = CONFIG.getboolean('site','debug')
|
||||||
|
|
||||||
VERSIONS = '0.5.0'
|
VERSIONS = '0.5.1'
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
@ -54,6 +60,7 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
'app_admin.middleware.require_login_middleware.RequiredLoginMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'MrDoc.urls'
|
ROOT_URLCONF = 'MrDoc.urls'
|
||||||
@ -81,17 +88,37 @@ WSGI_APPLICATION = 'MrDoc.wsgi.application'
|
|||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
|
# 数据库配置
|
||||||
|
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASE_MAP = {
|
||||||
|
'sqlite':'django.db.backends.sqlite3',
|
||||||
|
'mysql':'django.db.backends.mysql',
|
||||||
|
'postgresql':'django.db.backends.postgresql_psycopg2',
|
||||||
|
'oracle':'django.db.backends.oracle',
|
||||||
|
}
|
||||||
|
|
||||||
|
if CONFIG['database']['engine'] == 'sqlite':
|
||||||
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': DATABASE_MAP[CONFIG['database']['engine']],
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
'NAME': os.path.join(CONFIG_DIR, 'db.sqlite3'),
|
||||||
'OPTIONS':{
|
'OPTIONS':{
|
||||||
'timeout':20,
|
'timeout':20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else:
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': DATABASE_MAP[CONFIG['database']['engine']],
|
||||||
|
'NAME': CONFIG['database']['name'],
|
||||||
|
'USER': CONFIG['database']['user'],
|
||||||
|
'PASSWORD': CONFIG['database']['password'],
|
||||||
|
'HOST': CONFIG['database']['host'],
|
||||||
|
'PORT': CONFIG['database']['port'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
|
|||||||
50
README.md
50
README.md
@ -45,7 +45,7 @@
|
|||||||
- 支持**文集协作**功能,一个文集可以拥有一个创建者和多个协作者,可灵活选择协作权限;
|
- 支持**文集协作**功能,一个文集可以拥有一个创建者和多个协作者,可灵活选择协作权限;
|
||||||
- 支持**文档历史版本**功能,可以查看和对比历史版本与现有版本的差异,恢复某个历史版本为当前版本;
|
- 支持**文档历史版本**功能,可以查看和对比历史版本与现有版本的差异,恢复某个历史版本为当前版本;
|
||||||
|
|
||||||
当前版本为:**v0.5.0**,版本发布时间为**2020-05-02**
|
当前版本为:**v0.5.1**,版本发布时间为**2020-05-08**
|
||||||
|
|
||||||
完整更新记录详见:[CHANGES.md](./CHANGES.md)
|
完整更新记录详见:[CHANGES.md](./CHANGES.md)
|
||||||
|
|
||||||
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
`MrDoc`基于`Python`语言的`Django Web`框架配合前端的`LayUI`、`JQuery`等库进行开发。
|
`MrDoc`基于`Python`语言的`Django Web`框架配合前端的`LayUI`、`JQuery`等库进行开发。
|
||||||
|
|
||||||
`MrDoc`在`Python3.6` + `Django 2.2`上进行开发,并且在Django 2.1、2.2和Python3.5、3.6、3.7上测试运行良好,在其他环境下运行MrDoc不排除有未知的异常。。
|
`MrDoc`在`Python 3.6` + `Django 2.2`上进行开发,并且在Django 2.1、2.2和Python3.5、3.6、3.7上测试运行良好,在其他环境下运行MrDoc不排除有未知的异常。。
|
||||||
|
|
||||||
## 简明安装教程
|
## 简明安装教程
|
||||||
|
|
||||||
@ -70,43 +70,32 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
如果有配置其他数据库的需求,请首先按照Django官方的[数据库支持说明](https://docs.djangoproject.com/zh-hans/2.2/ref/databases/),安装特定数据库的Python绑定库,
|
如果有配置其他数据库的需求,请首先按照Django官方的[数据库支持说明](https://docs.djangoproject.com/zh-hans/2.2/ref/databases/),安装特定数据库的Python绑定库,
|
||||||
|
|
||||||
然后在/MrDoc/MrDoc目录下打开settings.py文件,在约80行的位置,将如下代码:
|
然后在/MrDoc/config目录下打开conig.ini文件,根据自己的数据库信息进行修改:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
DATABASES = {
|
# engine,指定数据库类型,接受sqlite、mysql、oracle、postgresql
|
||||||
'default': {
|
engine = sqlite
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
# name表示数据库的名称
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
# name = db_name
|
||||||
}
|
# user表示数据库用户名
|
||||||
}
|
# user = db_user
|
||||||
|
# password表示数据库用户密码
|
||||||
|
# password = db_pwd
|
||||||
|
# host表示数据库主机地址
|
||||||
|
# host = db_host
|
||||||
|
# port表示数据库端口
|
||||||
|
# port = db_port
|
||||||
```
|
```
|
||||||
|
|
||||||
按照自己数据库的信息,将其修改如下格式,下面以MySQL为例:
|
按照自己数据库的信息,将其修改如下格式,下面以MySQL为例:
|
||||||
|
|
||||||
```python
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.mysql', # 使用的数据库后端
|
|
||||||
'NAME': 'mrdoc', # 数据库名
|
|
||||||
'USER':'root', # 数据库用户
|
|
||||||
'PASSWORD':'123456789', # 数据库用户密码
|
|
||||||
'HOST':'', # 数据库主机地址
|
|
||||||
'PORT':'3306', # 数据库端口
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3、初始化数据库
|
### 3、初始化数据库
|
||||||
|
|
||||||
在安装完所需的第三方库并配置好数据库信息之后,我们需要对数据库进行初始化。
|
在安装完所需的第三方库并配置好数据库信息之后,我们需要对数据库进行初始化。
|
||||||
|
|
||||||
在项目路径下打开命令行界面,运行如下命令生成数据库迁移:
|
在项目路径下打开命令行界面,运行如下命令生成和执行数据库迁移:
|
||||||
```
|
```
|
||||||
python manage.py makemigrations
|
python manage.py makemigrations && python manage.py migrate
|
||||||
```
|
|
||||||
接着,运行如下命令执行数据库迁移:
|
|
||||||
```
|
|
||||||
python manage.py migrate
|
|
||||||
```
|
```
|
||||||
执行完毕之后,数据库就初始化完成了。
|
执行完毕之后,数据库就初始化完成了。
|
||||||
|
|
||||||
@ -120,14 +109,11 @@ python manage.py createsuperuser
|
|||||||
在完成上述步骤之后,即可运行使用MrDoc。
|
在完成上述步骤之后,即可运行使用MrDoc。
|
||||||
|
|
||||||
在测试环境中,可以使用Django自带的服务器运行MrDoc,其命令为:
|
在测试环境中,可以使用Django自带的服务器运行MrDoc,其命令为:
|
||||||
|
|
||||||
```
|
```
|
||||||
python manage.py runserver
|
python manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用说明文档
|
|
||||||
|
|
||||||
详见MrDoc使用文档: [http://mrdoc.zmister.com](http://mrdoc.zmister.com)
|
|
||||||
|
|
||||||
## 问题提交和反馈
|
## 问题提交和反馈
|
||||||
|
|
||||||
### 1、提交issue
|
### 1、提交issue
|
||||||
|
|||||||
@ -2,13 +2,18 @@
|
|||||||
# coding:utf-8
|
# coding:utf-8
|
||||||
# 生成验证码图片
|
# 生成验证码图片
|
||||||
import random
|
import random
|
||||||
|
import os
|
||||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z
|
_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z
|
||||||
_upper_cases = _letter_cases.upper() # 大写字母
|
_upper_cases = _letter_cases.upper() # 大写字母
|
||||||
_numbers = ''.join(map(str, range(3, 10))) # 数字
|
_numbers = ''.join(map(str, range(3, 10))) # 数字
|
||||||
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
|
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
|
||||||
|
|
||||||
|
static_path = os.path.join(settings.BASE_DIR,"static") # 静态文件路径
|
||||||
|
font_path = os.path.join(static_path,"MONACO.TTF") # 字体路径
|
||||||
|
|
||||||
def create_validate_code(size=(120, 30),
|
def create_validate_code(size=(120, 30),
|
||||||
chars=init_chars,
|
chars=init_chars,
|
||||||
img_type="GIF",
|
img_type="GIF",
|
||||||
@ -16,7 +21,7 @@ def create_validate_code(size=(120, 30),
|
|||||||
bg_color=(255, 255, 255),
|
bg_color=(255, 255, 255),
|
||||||
fg_color=(0, 0, 255),
|
fg_color=(0, 0, 255),
|
||||||
font_size=18,
|
font_size=18,
|
||||||
font_type="MONACO.TTF",
|
font_type=font_path,
|
||||||
length=4,
|
length=4,
|
||||||
draw_lines=True,
|
draw_lines=True,
|
||||||
n_line=(1, 2),
|
n_line=(1, 2),
|
||||||
|
|||||||
50
app_admin/middleware/require_login_middleware.py
Normal file
50
app_admin/middleware/require_login_middleware.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
# @文件: require_login_middleware.py
|
||||||
|
# @创建者:州的先生
|
||||||
|
# #日期:2020/5/8
|
||||||
|
# 博客地址:zmister.com
|
||||||
|
|
||||||
|
from app_admin.models import SysSetting
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class RequiredLoginMiddleware():
|
||||||
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
# 设置排除URL
|
||||||
|
compile_tuple = (r'/user/login(.*)$', r'/user/logout(.*)$', r'/user/register(.*)$',r'/user/check_code(.*)$')
|
||||||
|
self.exceptions = tuple(re.compile(url) for url in compile_tuple)
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||||
|
# 登陆用户不理会
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 获取数据库的设置值
|
||||||
|
data = SysSetting.objects.get(name='require_login').value
|
||||||
|
# 如果设置值为on,表示开启了验证
|
||||||
|
if data == 'on':
|
||||||
|
is_exceptions = False
|
||||||
|
# 遍历排除列表
|
||||||
|
for url in self.exceptions:
|
||||||
|
# 如果当前url匹配到排除列表,不理会
|
||||||
|
if url.match(request.path):
|
||||||
|
# print('排除URL:',request.path)
|
||||||
|
is_exceptions = True
|
||||||
|
if is_exceptions:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
# print("验证URL:",request.path)
|
||||||
|
return login_required(view_func)(request, *view_args, **view_kwargs)
|
||||||
|
# 否则,不理会
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
# 如果查询异常,说明数据库无此设置值,不理会
|
||||||
|
return None
|
||||||
@ -13,6 +13,7 @@ from app_doc.models import *
|
|||||||
from app_admin.models import *
|
from app_admin.models import *
|
||||||
from app_admin.utils import *
|
from app_admin.utils import *
|
||||||
import traceback
|
import traceback
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
# 返回验证码图片
|
# 返回验证码图片
|
||||||
@ -30,12 +31,14 @@ def check_code(request):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("生成验证码图片异常")
|
||||||
return HttpResponse("请求异常:{}".format(repr(e)))
|
return HttpResponse("请求异常:{}".format(repr(e)))
|
||||||
|
|
||||||
|
|
||||||
# 登录视图
|
# 登录视图
|
||||||
def log_in(request):
|
def log_in(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
|
# 登录用户访问登录页面自动跳转到首页
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
@ -62,12 +65,15 @@ def log_in(request):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("登录异常")
|
||||||
return HttpResponse('请求出错')
|
return HttpResponse('请求出错')
|
||||||
|
|
||||||
|
|
||||||
# 注册视图
|
# 注册视图
|
||||||
@open_register
|
@open_register
|
||||||
|
@logger.catch()
|
||||||
def register(request):
|
def register(request):
|
||||||
|
# 如果登录用户访问注册页面,跳转到首页
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
@ -146,6 +152,7 @@ def log_out(request):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("注销异常")
|
||||||
return redirect(request.META['HTTP_REFERER'])
|
return redirect(request.META['HTTP_REFERER'])
|
||||||
|
|
||||||
|
|
||||||
@ -175,11 +182,13 @@ def forget_pwd(request):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("修改密码异常")
|
||||||
errormsg = "验证码错误"
|
errormsg = "验证码错误"
|
||||||
return render(request,'forget_pwd.html',locals())
|
return render(request,'forget_pwd.html',locals())
|
||||||
|
|
||||||
|
|
||||||
# 发送电子邮箱验证码
|
# 发送电子邮箱验证码
|
||||||
|
@logger.catch()
|
||||||
def send_email_vcode(request):
|
def send_email_vcode(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
email = request.POST.get('email',None)
|
email = request.POST.get('email',None)
|
||||||
@ -205,9 +214,12 @@ def send_email_vcode(request):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
return JsonResponse({'status':False,'data':'电子邮箱不存在!'})
|
return JsonResponse({'status':False,'data':'电子邮箱不存在!'})
|
||||||
|
else:
|
||||||
|
return JsonResponse({'status':False,'data':'方法错误'})
|
||||||
|
|
||||||
# 管理员后台首页 - 用户管理
|
# 管理员后台首页 - 用户管理
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_user(request):
|
def admin_user(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# user_list = User.objects.all()
|
# user_list = User.objects.all()
|
||||||
@ -235,10 +247,13 @@ def admin_user(request):
|
|||||||
}
|
}
|
||||||
table_data.append(item)
|
table_data.append(item)
|
||||||
return JsonResponse({'status':True,'data':table_data})
|
return JsonResponse({'status':True,'data':table_data})
|
||||||
|
else:
|
||||||
|
return JsonResponse({'status':False,'data':'方法错误'})
|
||||||
|
|
||||||
|
|
||||||
# 管理员后台首页 - 创建用户
|
# 管理员后台首页 - 创建用户
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_create_user(request):
|
def admin_create_user(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
username = request.POST.get('username','') # 接收用户名参数
|
username = request.POST.get('username','') # 接收用户名参数
|
||||||
@ -263,6 +278,7 @@ def admin_create_user(request):
|
|||||||
|
|
||||||
# 管理员后台 - 修改密码
|
# 管理员后台 - 修改密码
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_change_pwd(request):
|
def admin_change_pwd(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
@ -288,6 +304,7 @@ def admin_change_pwd(request):
|
|||||||
|
|
||||||
# 管理员后台 - 删除用户
|
# 管理员后台 - 删除用户
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_del_user(request):
|
def admin_del_user(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
@ -303,6 +320,7 @@ def admin_del_user(request):
|
|||||||
|
|
||||||
# 管理员后台 - 文集管理
|
# 管理员后台 - 文集管理
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_project(request):
|
def admin_project(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
search_kw = request.GET.get('kw','')
|
search_kw = request.GET.get('kw','')
|
||||||
@ -334,6 +352,7 @@ def admin_project(request):
|
|||||||
|
|
||||||
# 管理员后台 - 修改文集权限
|
# 管理员后台 - 修改文集权限
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_project_role(request,pro_id):
|
def admin_project_role(request,pro_id):
|
||||||
pro = Project.objects.get(id=pro_id)
|
pro = Project.objects.get(id=pro_id)
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
@ -368,6 +387,7 @@ def admin_project_role(request,pro_id):
|
|||||||
|
|
||||||
# 管理员后台 - 文档管理
|
# 管理员后台 - 文档管理
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_doc(request):
|
def admin_doc(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
kw = request.GET.get('kw','')
|
kw = request.GET.get('kw','')
|
||||||
@ -397,6 +417,7 @@ def admin_doc(request):
|
|||||||
|
|
||||||
# 管理员后台 - 文档模板管理
|
# 管理员后台 - 文档模板管理
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_doctemp(request):
|
def admin_doctemp(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
kw = request.GET.get('kw','')
|
kw = request.GET.get('kw','')
|
||||||
@ -426,6 +447,7 @@ def admin_doctemp(request):
|
|||||||
|
|
||||||
# 管理员后台 - 注册邀请码管理
|
# 管理员后台 - 注册邀请码管理
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_register_code(request):
|
def admin_register_code(request):
|
||||||
# 返回注册邀请码管理页面
|
# 返回注册邀请码管理页面
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
@ -482,6 +504,7 @@ def admin_register_code(request):
|
|||||||
|
|
||||||
# 普通用户修改密码
|
# 普通用户修改密码
|
||||||
@login_required()
|
@login_required()
|
||||||
|
@logger.catch()
|
||||||
def change_pwd(request):
|
def change_pwd(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
@ -506,6 +529,7 @@ def change_pwd(request):
|
|||||||
|
|
||||||
# 管理员后台 - 应用设置
|
# 管理员后台 - 应用设置
|
||||||
@superuser_only
|
@superuser_only
|
||||||
|
@logger.catch()
|
||||||
def admin_setting(request):
|
def admin_setting(request):
|
||||||
email_settings = SysSetting.objects.filter(types="email")
|
email_settings = SysSetting.objects.filter(types="email")
|
||||||
if email_settings.count() == 6:
|
if email_settings.count() == 6:
|
||||||
@ -522,6 +546,7 @@ def admin_setting(request):
|
|||||||
# 基础设置
|
# 基础设置
|
||||||
if types == 'basic':
|
if types == 'basic':
|
||||||
close_register = request.POST.get('close_register',None) # 禁止注册
|
close_register = request.POST.get('close_register',None) # 禁止注册
|
||||||
|
require_login = request.POST.get('require_login',None) # 全站登录
|
||||||
static_code = request.POST.get('static_code',None) # 统计代码
|
static_code = request.POST.get('static_code',None) # 统计代码
|
||||||
ad_code = request.POST.get('ad_code',None) # 广告位1
|
ad_code = request.POST.get('ad_code',None) # 广告位1
|
||||||
ad_code_2 = request.POST.get('ad_code_2',None) # 广告位2
|
ad_code_2 = request.POST.get('ad_code_2',None) # 广告位2
|
||||||
@ -530,9 +555,14 @@ def admin_setting(request):
|
|||||||
enable_register_code = request.POST.get('enable_register_code',None) # 注册邀请码
|
enable_register_code = request.POST.get('enable_register_code',None) # 注册邀请码
|
||||||
enable_project_report = request.POST.get('enable_project_report',None) # 文集导出
|
enable_project_report = request.POST.get('enable_project_report',None) # 文集导出
|
||||||
# 更新开放注册状态
|
# 更新开放注册状态
|
||||||
|
SysSetting.objects.update_or_create(
|
||||||
|
name='require_login',
|
||||||
|
defaults={'value':require_login,'types':'basic'}
|
||||||
|
)
|
||||||
|
# 更新全站登录状态
|
||||||
SysSetting.objects.update_or_create(
|
SysSetting.objects.update_or_create(
|
||||||
name='close_register',
|
name='close_register',
|
||||||
defaults={'value':close_register,'types':'basic'}
|
defaults={'value': close_register, 'types': 'basic'}
|
||||||
)
|
)
|
||||||
# 更新统计代码状态
|
# 更新统计代码状态
|
||||||
SysSetting.objects.update_or_create(
|
SysSetting.objects.update_or_create(
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import time,hashlib
|
|||||||
import traceback,json
|
import traceback,json
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from app_doc.util_upload_img import upload_generation_dir,base_img_upload
|
from app_doc.util_upload_img import upload_generation_dir,base_img_upload
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
# MrDoc 基于用户的Token访问API模块
|
# MrDoc 基于用户的Token访问API模块
|
||||||
|
|
||||||
@ -22,6 +23,10 @@ def manage_token(request):
|
|||||||
token = UserToken.objects.get(user=request.user).token # 查询用户Token
|
token = UserToken.objects.get(user=request.user).token # 查询用户Token
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
token = '你还没有生成过Token!'
|
token = '你还没有生成过Token!'
|
||||||
|
except:
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(traceback.print_exc())
|
||||||
|
logger.exception("Token管理页面异常")
|
||||||
return render(request,'app_api/manage_token.html',locals())
|
return render(request,'app_api/manage_token.html',locals())
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
@ -40,6 +45,7 @@ def manage_token(request):
|
|||||||
except:
|
except:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("用户Token生成异常")
|
||||||
return JsonResponse({'status':False,'data':'生成出错,请重试!'})
|
return JsonResponse({'status':False,'data':'生成出错,请重试!'})
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +67,11 @@ def get_projects(request):
|
|||||||
return JsonResponse({'status':True,'data':project_list})
|
return JsonResponse({'status':True,'data':project_list})
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
return JsonResponse({'status':False,'data':'token无效'})
|
return JsonResponse({'status':False,'data':'token无效'})
|
||||||
|
except:
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(traceback.print_exc())
|
||||||
|
logger.exception("token获取文集异常")
|
||||||
|
return JsonResponse({'status':False,'data':'系统异常'})
|
||||||
|
|
||||||
|
|
||||||
# 新建文档
|
# 新建文档
|
||||||
@ -89,7 +100,11 @@ def create_doc(request):
|
|||||||
return JsonResponse({'status':False,'data':'非法请求'})
|
return JsonResponse({'status':False,'data':'非法请求'})
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
return JsonResponse({'status': False, 'data': 'token无效'})
|
return JsonResponse({'status': False, 'data': 'token无效'})
|
||||||
|
except:
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(traceback.print_exc())
|
||||||
|
logger.exception("token创建文档异常")
|
||||||
|
return JsonResponse({'status':False,'data':'系统异常'})
|
||||||
|
|
||||||
# 上传图片
|
# 上传图片
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@ -113,4 +128,5 @@ def upload_img(request):
|
|||||||
except:
|
except:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
|
logger.exception("token上传图片异常")
|
||||||
return JsonResponse({'success':0,'data':'上传出错'})
|
return JsonResponse({'success':0,'data':'上传出错'})
|
||||||
@ -10,6 +10,7 @@ from app_doc.models import Project,Doc,DocTemp
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from loguru import logger
|
||||||
import datetime
|
import datetime
|
||||||
import traceback
|
import traceback
|
||||||
import re
|
import re
|
||||||
@ -23,7 +24,8 @@ def validateTitle(title):
|
|||||||
new_title = re.sub(rstr, "_", title) # 替换为下划线
|
new_title = re.sub(rstr, "_", title) # 替换为下划线
|
||||||
return new_title
|
return new_title
|
||||||
|
|
||||||
|
# 文集列表(首页)
|
||||||
|
@logger.catch('文集列表获取异常')
|
||||||
def project_list(request):
|
def project_list(request):
|
||||||
kw = request.GET.get('kw','') # 搜索词
|
kw = request.GET.get('kw','') # 搜索词
|
||||||
sort = request.GET.get('sort',0) # 排序,0表示按时间升序排序,1表示按时间降序排序,默认为0
|
sort = request.GET.get('sort',0) # 排序,0表示按时间升序排序,1表示按时间降序排序,默认为0
|
||||||
@ -1411,7 +1413,7 @@ def manage_image(request):
|
|||||||
image_list = Image.objects.filter(user=request.user,group_id=None) # 查询指定分组的图片
|
image_list = Image.objects.filter(user=request.user,group_id=None) # 查询指定分组的图片
|
||||||
else:
|
else:
|
||||||
image_list = Image.objects.filter(user=request.user,group_id=g_id) # 查询指定分组的图片
|
image_list = Image.objects.filter(user=request.user,group_id=g_id) # 查询指定分组的图片
|
||||||
paginator = Paginator(image_list, 20)
|
paginator = Paginator(image_list, 18)
|
||||||
page = request.GET.get('page', 1)
|
page = request.GET.get('page', 1)
|
||||||
try:
|
try:
|
||||||
images = paginator.page(page)
|
images = paginator.page(page)
|
||||||
|
|||||||
17
config/config.ini
Normal file
17
config/config.ini
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[site]
|
||||||
|
# True表示开启站点调试模式,False表示关闭站点调试模式
|
||||||
|
debug = False
|
||||||
|
|
||||||
|
[database]
|
||||||
|
# engine,指定数据库类型,接受sqlite、mysql、oracle、postgresql
|
||||||
|
engine = sqlite
|
||||||
|
# name表示数据库的名称
|
||||||
|
# name = db_name
|
||||||
|
# user表示数据库用户名
|
||||||
|
# user = db_user
|
||||||
|
# password表示数据库用户密码
|
||||||
|
# password = db_pwd
|
||||||
|
# host表示数据库主机地址
|
||||||
|
# host = db_host
|
||||||
|
# port表示数据库端口
|
||||||
|
# port = db_port
|
||||||
@ -3,3 +3,4 @@ beautifulsoup4==4.8.2
|
|||||||
lxml
|
lxml
|
||||||
pillow==6.2.2
|
pillow==6.2.2
|
||||||
pyppeteer==0.0.25
|
pyppeteer==0.0.25
|
||||||
|
loguru==0.4.1
|
||||||
@ -30,11 +30,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">启用注册码</label>
|
<label class="layui-form-label">全站登录</label>
|
||||||
<div class="layui-input-inline">
|
<div class="layui-input-inline">
|
||||||
<input type="checkbox" name="enable_register_code" lay-skin="switch" lay-text="开启|关闭" {% if enable_register_code %}checked{% endif %}>
|
<input type="checkbox" name="require_login" lay-skin="switch" lay-text="开启|关闭" {% if require_login %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-mid layui-word-aux">开启此选项,新用户注册将需要填写注册码</div>
|
<div class="layui-form-mid layui-word-aux">开启此选项,除注册、登录页面外的所有页面的访问都需要登录</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
|
|||||||
@ -74,6 +74,9 @@
|
|||||||
.layui-laypage .layui-laypage-curr .layui-laypage-em{
|
.layui-laypage .layui-laypage-curr .layui-laypage-em{
|
||||||
background-color: #1E9FFF !important;
|
background-color: #1E9FFF !important;
|
||||||
}
|
}
|
||||||
|
.layui-form-select dl dd.layui-this{
|
||||||
|
background-color: #1E9FFF !important;
|
||||||
|
}
|
||||||
/* HTML预览样式 */
|
/* HTML预览样式 */
|
||||||
.markdown-body h1{
|
.markdown-body h1{
|
||||||
font-size: 1.7em;
|
font-size: 1.7em;
|
||||||
|
|||||||
@ -285,7 +285,7 @@
|
|||||||
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
|
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||||
});
|
});
|
||||||
//解析Markdown为HTML
|
//解析Markdown为HTML
|
||||||
layer.load(1);
|
// layer.load(1);
|
||||||
editormd.markdownToHTML("content", {
|
editormd.markdownToHTML("content", {
|
||||||
htmlDecode : "style,script,iframe",
|
htmlDecode : "style,script,iframe",
|
||||||
emoji : true, //emoji表情
|
emoji : true, //emoji表情
|
||||||
@ -300,7 +300,7 @@
|
|||||||
atLink : false,//禁用@链接
|
atLink : false,//禁用@链接
|
||||||
|
|
||||||
});
|
});
|
||||||
layer.closeAll("loading");
|
// layer.closeAll("loading");
|
||||||
//为当前页面的目录链接添加蓝色样式
|
//为当前页面的目录链接添加蓝色样式
|
||||||
$("nav li a").each(function (i) {
|
$("nav li a").each(function (i) {
|
||||||
var $me = $(this);
|
var $me = $(this);
|
||||||
|
|||||||
@ -78,7 +78,9 @@
|
|||||||
<script src="{% static 'viewerjs/viewer.js' %}"></script>
|
<script src="{% static 'viewerjs/viewer.js' %}"></script>
|
||||||
<script>
|
<script>
|
||||||
var form = layui.form;
|
var form = layui.form;
|
||||||
|
var flow = layui.flow;
|
||||||
|
// 懒加载图片
|
||||||
|
flow.lazyimg({elem:'img.image-list-i'});
|
||||||
//悬浮显示图片按钮
|
//悬浮显示图片按钮
|
||||||
$(".image-list").mouseover(function(){
|
$(".image-list").mouseover(function(){
|
||||||
$(this).find(".opera-img-btn").show();
|
$(this).find(".opera-img-btn").show();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user