新增收藏管理功能

This commit is contained in:
yangjian 2021-01-04 20:05:01 +08:00
parent 68bd783c33
commit 8a98473753
10 changed files with 361 additions and 8 deletions

View File

@ -12,6 +12,8 @@
- [优化]文档编辑器界面样式和交互;
- [修复]仅有私密文集的站点游客可搜索到私密文集的问题;
- [新增]文集水印配置;
- [新增]文集文档收藏功能;
- [优化]首页样式;
### v0.6.2 2020-12

View File

@ -40,7 +40,7 @@ SECRET_KEY = '5&71mt9@^58zdg*_!t(x6g14q*@84d%ptr%%s6e0l50zs0we3d'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = CONFIG.getboolean('site','debug')
VERSIONS = '0.6.2'
VERSIONS = '0.6.3'
ALLOWED_HOSTS = ['*']

View File

@ -65,4 +65,5 @@ urlpatterns = [
path('manage_overview/',views.manage_overview,name="manage_overview"), # 个人中心概览
path('manage_self/',views.manage_self,name="manage_self"), # 个人设置
path('my_collect/',views.my_collect,name="my_collect"), # 我的收藏
path('manage_collect/',views.manage_collect,name="manage_collect"), # 收藏管理
]

View File

@ -1,6 +1,7 @@
# coding:utf-8
from django.shortcuts import render,redirect
from django.http.response import JsonResponse,Http404,HttpResponseNotAllowed,HttpResponse
from django.http import QueryDict
from django.http import HttpResponseForbidden
from django.contrib.auth.decorators import login_required # 登录需求装饰器
from django.views.decorators.csrf import csrf_exempt
@ -2982,4 +2983,118 @@ def my_collect(request):
return JsonResponse({'status':True,'data':'收藏成功'})
elif request.method == 'DELETE':
pass
pass
# 收藏管理
@login_required()
@require_http_methods(['GET','POST','DELETE'])
@csrf_exempt
def manage_collect(request):
if request.method == 'GET':
# 收藏文集数量
collect_project_cnt = MyCollect.objects.filter(create_user=request.user, collect_type=2).count()
# 收藏文档数量
collect_doc_cnt = MyCollect.objects.filter(create_user=request.user, collect_type=1).count()
# 所有收藏数量
all_cnt = collect_project_cnt + collect_doc_cnt
return render(request,'app_doc/manage/manage_collect.html',locals())
elif request.method == 'POST':
kw = request.POST.get('kw', '') # 搜索词
collect_type = request.POST.get('type', '') # 收藏类型
if collect_type in ['1', '2']:
q_type = [int(collect_type)]
else:
q_type = [1, 2]
page = request.POST.get('page', 1)
limit = request.POST.get('limit', 10)
# 没有搜索
if kw == '':
collect_list = MyCollect.objects.filter(
create_user=request.user,
collect_type__in=q_type,
).order_by('-create_time')
# 有搜索
else:
collect_list = MyCollect.objects.filter(
Q(content__icontains=kw) | Q(name__icontains=kw),
create_user=request.user, collect_type__in=q_type
).order_by('-create_time')
# 分页处理
paginator = Paginator(collect_list, limit)
page = request.GET.get('page', page)
try:
collects = paginator.page(page)
except PageNotAnInteger:
collects = paginator.page(1)
except EmptyPage:
collects = paginator.page(paginator.num_pages)
table_data = []
for collect in collects:
if collect.collect_type == 1:
item_doc = Doc.objects.get(id=collect.collect_id)
item_id = item_doc.id
item_name = item_doc.name
item_project = Project.objects.get(id=item_doc.top_doc)
item_project_name = item_project.name
item_project_id = item_project.id
else:
item_project = Project.objects.get(id=collect.collect_id)
item_id = item_project.id
item_name = item_project.name
item_project_name = ''
item_project_id = ''
item = {
'id': collect.id,
'item_id':item_id,
'item_name': item_name,
'type': collect.collect_type,
'item_project_id':item_project_id,
'item_project_name':item_project_name,
'create_time': collect.create_time,
}
table_data.append(item)
resp_data = {
"code": 0,
"msg": "ok",
"count": collect_list.count(),
"data": table_data
}
return JsonResponse(resp_data)
elif request.method == 'DELETE':
try:
# 获取收藏ID
DELETE = QueryDict(request.body)
collect_id = DELETE.get('collect_id', None)
range = DELETE.get('range', 'single')
if collect_id:
if range == 'single':
# 查询收藏
try:
collect = MyCollect.objects.get(id=collect_id)
except ObjectDoesNotExist:
return JsonResponse({'status': False, 'data': '收藏不存在'})
# 如果请求用户为站点管理员、收藏的创建者,可以删除
if (request.user == collect.create_user) or (request.user.is_superuser):
MyCollect.objects.filter(id=collect_id).delete()
return JsonResponse({'status': True, 'data': '删除完成'})
else:
return JsonResponse({'status': False, 'data': '非法请求'})
elif range == 'multi':
collects = collect_id.split(",")
try:
MyCollect.objects.filter(id__in=collects, create_user=request.user).delete()
return JsonResponse({'status': True, 'data': '删除完成'})
except:
return JsonResponse({'status': False, 'data': '非法请求'})
else:
return JsonResponse({'status': False, 'data': '类型错误'})
else:
return JsonResponse({'status': False, 'data': '参数错误'})
except Exception as e:
logger.exception("取消收藏出错")
return JsonResponse({'status': False, 'data': '请求出错'})

View File

@ -152,6 +152,14 @@ def user_center_menu(request):
},
]
},
{
"id": "my_collect",
"title": "我的收藏",
"icon": "layui-icon layui-icon-star",
"type": 1,
"openType": "_iframe",
"href": reverse("manage_collect")
},
{
"id": "self_settings",
"title": "个人管理",

Binary file not shown.

1
static/icon_img/simi.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1609668475194" class="icon" viewBox="0 0 1194 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6789" xmlns:xlink="http://www.w3.org/1999/xlink" width="23.3203125" height="20"><defs><style type="text/css"></style></defs><path d="M1187.2 329.941333c12.8-20.650667 8.533333-48.213333-8.533333-64.298666-19.2-16.042667-44.885333-11.477333-59.818667 9.216-2.133333 2.261333-239.274667 303.018667-521.301333 303.018666-273.493333 0-521.301333-303.018667-523.434667-305.322666-14.933333-18.346667-42.752-20.650667-59.818667-4.608-17.109333 16.085333-19.242667 45.909333-4.266666 64.298666 4.266667 6.869333 55.509333 68.864 136.704 137.728L37.76 591.616c-17.066667 18.346667-14.933333 48.213333 2.133333 64.298667 4.266667 9.173333 14.933333 13.781333 25.642667 13.781333 10.666667 0 21.376-4.608 29.909333-13.781333l117.504-130.858667c55.552 41.344 121.813333 80.341333 194.432 107.904l-44.842666 162.986667c-6.4 25.258667 6.4 50.517333 29.866666 57.386666h12.842667c19.2 0 36.309333-13.781333 40.576-34.432l44.885333-162.986666c34.176 6.869333 70.485333 11.477333 106.837334 11.477333 36.309333 0 72.618667-4.608 106.794666-11.52l44.885334 160.725333c4.266667 20.650667 23.466667 34.432 40.576 34.432 4.266667 0 8.533333 0 10.666666-2.304 23.552-6.869333 36.352-32.128 29.952-57.386666l-44.885333-160.682667c72.661333-27.562667 138.88-66.56 194.432-107.904l115.370667 128.554667c8.533333 9.216 19.2 13.781333 29.909333 13.781333 10.666667 0 21.333333-4.565333 29.909333-13.781333 17.066667-18.346667 17.066667-45.909333 2.133334-64.256l-108.970667-121.685334c87.594667-68.864 138.88-135.424 138.88-135.424z" p-id="6790" fill="#e6e6e6"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -291,15 +291,16 @@
//修改成功
window.localStorage.removeItem('mrdoc_doc_cache') // 清空文档缓存
if(status === 1){
layer.msg('发布成功,即将跳转',function(){
layer.msg('发布成功',function(){
md_changed = false;
window.location.href = "{% url 'doc' pro_id=doc.top_doc doc_id=doc.id %}";
// window.location.href = "{% url 'doc' pro_id=doc.top_doc doc_id=doc.id %}";
window.location.href = "/modify_doc/{{doc.id}}/";
});
}else{
layer.msg('保存成功',{time:1000},function(){
md_changed = false;
//跳转到文档修改
window.location.href = "/modify_doc/"+r.data.doc+"/";
window.location.href = "/modify_doc/{{doc.id}}/";
});
}
}else{

View File

@ -0,0 +1,223 @@
{% extends 'app_doc/user/user_base.html' %}
{% load static %}
{% load i18n %}
{% block title %}{% trans "收藏管理" %}{% endblock %}
{% block content %}
<div class="layui-card">
<div class="layui-card-header">{% trans "高级筛选" %}</div>
<div class="layui-card-body">
<div class="layui-form">
<!-- <div class="layui-form-item">
<label class="layui-form-label">{% trans "关键词" %}</label>
<div class="layui-input-inline">
<input type="text" name="kw" placeholder="请输入标题" autocomplete="off" class="layui-input">
</div>
<button class="layui-btn layui-btn-normal layui-btn-sm" id="search">{% trans "搜索" %}</button>
</div> -->
<div class="layui-form-item">
<label class="layui-form-label">{% trans "收藏类型" %}</label>
<div class="layui-input-block">
<input type="radio" name="status" title="全部({{all_cnt}})" value="-1" lay-skin="primary" checked lay-filter="collect_type">
<input type="radio" name="status" title="文集({{collect_project_cnt}})" value="2" lay-skin="primary" lay-filter="collect_type">
<input type="radio" name="status" title="文档({{collect_doc_cnt}})" value="1" lay-skin="primary" lay-filter="collect_type">
</div>
</div>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="collect-table" lay-filter="collect-table"></table>
</div>
</div>
<!-- 表格工具栏 -->
<script type="text/html" id="doc-toolbar">
<button class="layui-btn layui-btn-warm pear-btn-sm" lay-event="batchRemove">
<i class="layui-icon layui-icon-delete"></i>取消收藏
</button>
</script>
<!-- 文档名称 -->
<script type="text/html" id="collect-name">
{% verbatim %}
{{#if (d.type == 1) { }}
<img src="/static/icon_img/manage-doc-icon.svg" height="14px" width="14px"></img>
<a href="/project-{{d.item_project_id}}/doc-{{d.item_id}}" target="_blank">{{d.item_name}}</a>
{{# }else if(d.type == 2){ }}
<!-- <span class="layui-badge-dot layui-bg-orange"></span> -->
<img src="/static/icon_img/manage-pro-icon.svg" height="14px" width="14px"></img>
<a href="/project-{{d.item_id}}/" target="_blank">{{ d.item_name }} </a>
{{# } }}
{% endverbatim %}
</script>
<!-- 修改时间 -->
<script type="text/html" id="collect-create-time">
{% verbatim %}
{{layui.util.toDateString(d.create_time, "yyyy-MM-dd HH:mm:ss")}}
{% endverbatim %}
</script>
<!-- 单个收藏操作 -->
<script type="text/html" id="doc-bar">
{% verbatim %}
<button class="layui-btn layui-btn-warm pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i></button>
{% endverbatim %}
</script>
{% endblock %}
{% block custom_script %}
<script>
layui.use(['table', 'form', 'jquery', 'dtree','layer'], function() {
let table = layui.table;
let form = layui.form;
let $ = layui.jquery;
let dtree = layui.dtree;
var layer = layui.layer;
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
let cols = [
[
{type: 'checkbox',width:20},
{title: '名称',field: 'name',align: 'left',templet:"#collect-name",minWidth:280},
{title: '归属',field: 'item_project_name',align: 'left',templet:"#project-role"},
{title: '收藏时间',field: 'create_time',align: 'left',templet:"#collect-create-time"},
{title: '操作',toolbar: '#doc-bar',align: 'left',} ]
]
// 渲染表格
table.render({
elem: '#collect-table',
method:'post',
where:{
'type':-1,
},
url: "{% url 'manage_collect' %}",
page: true,
cols: cols,
skin: 'line',
toolbar: '#doc-toolbar',
defaultToolbar: ['filter']
});
// 取消收藏
delCollect = function(collect_id){
layer.open({
type:1,
title:'删除收藏',
area:'300px;',
id:'delPro',//配置ID
content:'<div style="margin-left:10px;">警告:此操作将删除此收藏!</div>',
btn:['确定','取消'], //添加按钮
btnAlign:'c', //按钮居中
yes:function (index,layero) {
let loading = layer.load();
$.ajax({
url: "{% url 'manage_collect' %}",
dataType: 'json',
type: 'delete',
data:{'collect_id':collect_id,'range':'single',},
success: function(r) {
layer.closeAll();
if (r.status) {
layer.msg("取消成功", {
icon: 1,
time: 1000
}, function() {
table.reload('collect-table');
});
} else {
layer.msg(r.data, {
icon: 2,
time: 1000
});
}
}
})
},
});
};
// 批量取消收藏
batchRemoveCollect = function(obj) {
let data = table.checkStatus(obj.config.id).data;
if (data.length === 0) {
layer.msg("未选中任何收藏", {
icon: 3,
time: 1000
});
return false;
}
let collect_id = "";
for (let i = 0; i < data.length; i++) {
collect_id += data[i].id + ",";
}
collect_id = collect_id.substr(0, collect_id.length - 1);
// console.log(pro_id)
layer.confirm('确定要取消这些收藏?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{% url 'manage_collect' %}",
dataType: 'json',
type: 'delete',
data:{'collect_id':collect_id,'range':'multi'},
success: function(r) {
layer.close(loading);
if (r.status) {
layer.msg("取消成功", {
icon: 1,
time: 1000
}, function() {
table.reload('collect-table');
});
} else {
layer.msg(r.data, {
icon: 2,
time: 1000
});
}
}
})
});
}
// 监听类型筛选
form.on('radio(collect_type)', function(data){
console.log(data.value); //被点击的radio的value值
table.reload('collect-table',{
where:{
'type':data.value,
},
})
});
// 监听搜索按钮
$("#search").click(function(){
table.reload('collect-table',{
where:{
'type':1,'kw':$("input[name=kw]").val(),
},
})
});
// 侦听取消收藏按钮
table.on("tool(collect-table)",function(obj){
if (obj.event === 'remove') {
// console.log(obj)
delCollect(obj.data.id)
}
});
// 侦听表格工具栏
table.on("toolbar(collect-table)",function(obj){
if (obj.event === 'add') { // 新增文集
createProject();
}else if(obj.event === 'batchRemove'){ // 批量删除文集
batchRemoveCollect(obj)
}
});
})
</script>
{% endblock %}

View File

@ -15,7 +15,6 @@
<link href="{% static 'layui/css/layui.css' %}" rel="stylesheet">
<link href="{% static 'mrdoc/mrdoc.css' %}?version={{mrdoc_version}}" rel="stylesheet">
<link rel="icon" href="{% static 'search/mrdoc_logo_300.png' %}" sizes="192x192" />
<!-- <link href="//at.alicdn.com/t/font_2281207_xtauo52jlgk.css" rel="stylesheet"> -->
<style>
.layui-nav .layui-this:after, .layui-nav-bar, .layui-nav-tree, .layui-nav-itemed:after {
background-color: #333 !important;
@ -129,7 +128,11 @@
<div class="layui-col-md3 layui-col-xs12 project-item">
<a href="{% url 'pro_index' p.id %}" target="_blank">
<div class="layui-card">
<div class="layui-card-header" >
<div class="layui-card-header"
{% if p.role == 1 %}
style="background: url({% static 'icon_img/simi.svg' %}) no-repeat right bottom;"
{% endif %}
>
{% if p.icon %}
<p class="layui-elip" style="font-weight: 700;"><svg class="icon" aria-hidden="true"><use xlink:href="#{{p.icon}}"></use></svg> {{ p.name }}&nbsp;&nbsp;<span class="layui-badge-rim">{{p.id|get_doc_count}}</span></p>
{% else %}
@ -137,7 +140,6 @@
{% endif %}
</div>
<div class="layui-card-body" style="font-size: 12px;">
<!-- <p class="layui-word-aux layui-elip"><i class="layui-icon layui-icon-user"></i> {% if p.create_user.first_name != '' %} {{p.create_user.first_name}} {% else %} {{p.create_user}}{% endif %}</p> -->
<p class="tooltip layui-word-aux">
<i class="layui-icon layui-icon-speaker"></i>
{% if p.intro == "" %}