forked from mirror/MrDoc
后台管理新增图片和附件管理页面及功能
This commit is contained in:
parent
712387ebbb
commit
0be750850c
@ -24,5 +24,13 @@ urlpatterns = [
|
||||
path('admin_center/',views.admin_center,name="admin_center"), # 后台管理
|
||||
path('admin/center_menu/',views.admin_center_menu,name="admin_center_menu"), # 后台管理菜单数据
|
||||
path('admin_overview/',views.admin_overview,name="admin_overview"), # 后台管理仪表盘
|
||||
# 图片管理及接口
|
||||
path('manage/image/', views.admin_image, name="image_manage"), # 图片管理页面
|
||||
path('api/imgs/', views.AdminImageList.as_view(), name="api_admin_imgs"), # 图片列表接口
|
||||
path('api/img/<int:id>/', views.AdminImageDetail.as_view(), name="api_admin_img"), # 图片详情接口
|
||||
# 附件管理及接口
|
||||
path('manage/attachment/', views.admin_attachment, name="attachment_manage"), # 附件管理页面
|
||||
path('api/attachments/', views.AdminAttachmentList.as_view(), name="api_admin_attachments"), # 附件列表接口
|
||||
path('api/attachment/<int:id>/', views.AdminAttachmentDetail.as_view(), name="api_admin_attachment"), # 附件详情接口
|
||||
|
||||
]
|
@ -26,6 +26,7 @@ from loguru import logger
|
||||
import re
|
||||
import datetime
|
||||
import requests
|
||||
import os
|
||||
|
||||
|
||||
# 返回验证码图片
|
||||
@ -719,6 +720,146 @@ def admin_doctemp(request):
|
||||
return render(request,'app_admin/admin_doctemp.html',locals())
|
||||
|
||||
|
||||
# 后台管理 - 图片管理页面
|
||||
@superuser_only
|
||||
def admin_image(request):
|
||||
return render(request,'app_admin/admin_image.html',locals())
|
||||
|
||||
# 图片列表接口
|
||||
class AdminImageList(APIView):
|
||||
authentication_classes = [SessionAuthentication,AppMustAuth]
|
||||
permission_classes = [SuperUserPermission]
|
||||
|
||||
# 获取图片列表
|
||||
def get(self, request):
|
||||
kw = request.query_params.get('kw', '')
|
||||
username = request.query_params.get('username', '')
|
||||
page_num = request.query_params.get('page', 1)
|
||||
limit = request.query_params.get('limit', 10)
|
||||
if kw == '' and username == '':
|
||||
img_data = Image.objects.all().order_by('-create_time')
|
||||
elif kw != '':
|
||||
img_data = Image.objects.filter(file_name__icontains=kw).order_by('-create_time')
|
||||
elif username != '':
|
||||
user = User.objects.get(id=username)
|
||||
img_data = Image.objects.filter(user=user).order_by('-create_time')
|
||||
page = PageNumberPagination() # 实例化一个分页器
|
||||
page.page_size = limit
|
||||
page_imgs = page.paginate_queryset(img_data, request, view=self) # 进行分页查询
|
||||
serializer = ImageSerializer(page_imgs, many=True) # 对分页后的结果进行序列化处理
|
||||
resp = {
|
||||
'code': 0,
|
||||
'data': serializer.data,
|
||||
'count': img_data.count()
|
||||
}
|
||||
|
||||
return Response(resp)
|
||||
|
||||
# 批量删除图片
|
||||
def delete(self,request):
|
||||
ids = request.data.get('id','').split(',')
|
||||
try:
|
||||
image = Image.objects.filter(id__in=ids) # 查询附件
|
||||
for a in image: # 遍历附件
|
||||
file_path = settings.BASE_DIR + a.file_path
|
||||
is_exist = os.path.exists(file_path)
|
||||
if is_exist:
|
||||
os.remove(file_path)
|
||||
image.delete() # 删除数据库记录
|
||||
return JsonResponse({'code': 0, 'data': _('删除成功')})
|
||||
except Exception as e:
|
||||
logger.exception("删除图片异常")
|
||||
return JsonResponse({'code': 4, 'data': _('删除异常')})
|
||||
|
||||
# 图片详情接口
|
||||
class AdminImageDetail(APIView):
|
||||
authentication_classes = [SessionAuthentication,AppMustAuth]
|
||||
permission_classes = [SuperUserPermission]
|
||||
|
||||
# 删除图片
|
||||
def delete(self,request,id):
|
||||
try:
|
||||
image = Image.objects.filter(id=id) # 查询附件
|
||||
for a in image: # 遍历附件
|
||||
file_path = settings.BASE_DIR + a.file_path
|
||||
is_exist = os.path.exists(file_path)
|
||||
if is_exist:
|
||||
os.remove(file_path)
|
||||
image.delete() # 删除数据库记录
|
||||
return JsonResponse({'code': 0, 'data': _('删除成功')})
|
||||
except Exception as e:
|
||||
logger.exception("删除图片异常")
|
||||
return JsonResponse({'code': 4, 'data': _('删除异常')})
|
||||
|
||||
|
||||
@superuser_only
|
||||
# 后台管理 - 附件管理页面
|
||||
def admin_attachment(request):
|
||||
return render(request,'app_admin/admin_attachment.html',locals())
|
||||
|
||||
|
||||
# 附件列表接口
|
||||
class AdminAttachmentList(APIView):
|
||||
authentication_classes = [SessionAuthentication,AppMustAuth]
|
||||
permission_classes = [SuperUserPermission]
|
||||
|
||||
# 获取附件列表
|
||||
def get(self, request):
|
||||
kw = request.query_params.get('kw', '')
|
||||
username = request.query_params.get('username', '')
|
||||
page_num = request.query_params.get('page', 1)
|
||||
limit = request.query_params.get('limit', 10)
|
||||
if kw == '' and username == '':
|
||||
attachment_data = Attachment.objects.all().order_by('-create_time')
|
||||
elif kw != '':
|
||||
attachment_data = Attachment.objects.filter(file_name__icontains=kw).order_by('-create_time')
|
||||
elif username != '':
|
||||
user = User.objects.get(id=username)
|
||||
attachment_data = Attachment.objects.filter(user=user).order_by('-create_time')
|
||||
page = PageNumberPagination() # 实例化一个分页器
|
||||
page.page_size = limit
|
||||
page_attachments = page.paginate_queryset(attachment_data, request, view=self) # 进行分页查询
|
||||
serializer = AttachmentSerializer(page_attachments, many=True) # 对分页后的结果进行序列化处理
|
||||
resp = {
|
||||
'code': 0,
|
||||
'data': serializer.data,
|
||||
'count': attachment_data.count()
|
||||
}
|
||||
|
||||
return Response(resp)
|
||||
|
||||
# 批量删除附件
|
||||
def delete(self,request):
|
||||
ids = request.data.get('id','').split(',')
|
||||
try:
|
||||
attachment = Attachment.objects.filter(id__in=ids) # 查询附件
|
||||
for a in attachment: # 遍历附件
|
||||
a.file_path.delete() # 删除文件
|
||||
attachment.delete() # 删除数据库记录
|
||||
return JsonResponse({'code': 0, 'data': _('删除成功')})
|
||||
except Exception as e:
|
||||
logger.exception("删除附件异常")
|
||||
return JsonResponse({'code': 4, 'data': _('删除异常')})
|
||||
|
||||
|
||||
# 附件详情接口
|
||||
class AdminAttachmentDetail(APIView):
|
||||
authentication_classes = [SessionAuthentication,AppMustAuth]
|
||||
permission_classes = [SuperUserPermission]
|
||||
|
||||
# 删除图片
|
||||
def delete(self,request,id):
|
||||
try:
|
||||
attachment = Attachment.objects.filter(id=id) # 查询附件
|
||||
for a in attachment: # 遍历附件
|
||||
a.file_path.delete() # 删除文件
|
||||
attachment.delete() # 删除数据库记录
|
||||
return JsonResponse({'code': 0, 'data': _('删除成功')})
|
||||
except Exception as e:
|
||||
logger.exception("删除图片异常")
|
||||
return JsonResponse({'code': 4, 'data': _('删除异常')})
|
||||
|
||||
|
||||
# 后台管理 - 注册邀请码管理
|
||||
@superuser_only
|
||||
@logger.catch()
|
||||
@ -1086,6 +1227,31 @@ def admin_center_menu(request):
|
||||
"icon": "layui-icon layui-icon-templeate-1",
|
||||
"href": reverse('doctemp_manage'),
|
||||
},
|
||||
{
|
||||
"id": "my_fodder",
|
||||
"title": _("素材管理"),
|
||||
"icon": "layui-icon layui-icon-upload-drag",
|
||||
"type": 0,
|
||||
"href": "",
|
||||
"children": [
|
||||
{
|
||||
"id": "my_img",
|
||||
"title": _("图片管理"),
|
||||
"icon": "layui-icon layui-icon-face-smile",
|
||||
"type": 1,
|
||||
"openType": "_iframe",
|
||||
"href": reverse("image_manage")
|
||||
},
|
||||
{
|
||||
"id": "my_attachment",
|
||||
"title": _("附件管理"),
|
||||
"icon": "layui-icon layui-icon-face-cry",
|
||||
"type": 1,
|
||||
"openType": "_iframe",
|
||||
"href": reverse("attachment_manage")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": _("注册码管理"),
|
||||
|
@ -48,10 +48,14 @@ class DocTempSerializer(ModelSerializer):
|
||||
|
||||
# 图片序列化器
|
||||
class ImageSerializer(ModelSerializer):
|
||||
username = serializers.SerializerMethodField(label="用户名")
|
||||
class Meta:
|
||||
model = Image
|
||||
fields = ('__all__')
|
||||
|
||||
def get_username(self,obj):
|
||||
return obj.user.username
|
||||
|
||||
# 图片分组序列化器
|
||||
class ImageGroupSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
|
@ -67,4 +67,5 @@ urlpatterns = [
|
||||
path('my_collect/',views.my_collect,name="my_collect"), # 我的收藏
|
||||
path('manage_collect/',views.manage_collect,name="manage_collect"), # 收藏管理
|
||||
path('get_version/',views.get_version,name="get_version"), # 获取当前版本
|
||||
path('api/usergroups/userlist', views.UserGroupUserList.as_view(), name="api_usergroups_userlist"), # 用户分组的用户列表接口
|
||||
]
|
@ -11,6 +11,10 @@ from django.core.exceptions import PermissionDenied,ObjectDoesNotExist
|
||||
from django.core.serializers import serialize
|
||||
from app_doc.models import Project,Doc,DocTemp
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework.views import APIView # 视图
|
||||
from rest_framework.response import Response # 响应
|
||||
from rest_framework.pagination import PageNumberPagination # 分页
|
||||
from rest_framework.authentication import SessionAuthentication # 认证
|
||||
from django.db.models import Q
|
||||
from django.db import transaction
|
||||
from django.utils.html import strip_tags
|
||||
@ -19,6 +23,7 @@ from loguru import logger
|
||||
from app_doc.report_utils import *
|
||||
from app_admin.models import UserOptions,SysSetting
|
||||
from app_admin.decorators import check_headers,allow_report_file
|
||||
from app_api.auth_app import AppAuth,AppMustAuth # 自定义认证
|
||||
import datetime
|
||||
import traceback
|
||||
import re
|
||||
@ -3212,4 +3217,29 @@ def get_version(request):
|
||||
'status':False,
|
||||
'data':_('异常')
|
||||
}
|
||||
return JsonResponse(data)
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
# 用户分组用户列表接口
|
||||
class UserGroupUserList(APIView):
|
||||
authentication_classes = [SessionAuthentication, AppMustAuth]
|
||||
|
||||
def get(self,request):
|
||||
user_data = User.objects.filter(is_active=True).values(
|
||||
'id', 'username', 'first_name'
|
||||
)
|
||||
user_list = []
|
||||
for user in user_data:
|
||||
item = {
|
||||
'name':user['username'],
|
||||
'value':user['id']
|
||||
}
|
||||
user_list.append(item)
|
||||
# serializer = UserSerializer(user_data, many=True) # 对结果进行序列化处理
|
||||
resp = {
|
||||
'code': 0,
|
||||
'data': user_list,
|
||||
'count': user_data.count()
|
||||
}
|
||||
|
||||
return Response(resp)
|
||||
|
490
static/xm-select/CHANGELOG.md
Normal file
490
static/xm-select/CHANGELOG.md
Normal file
@ -0,0 +1,490 @@
|
||||
## 更新日志
|
||||
|
||||
|
||||
### 1.2.2
|
||||
|
||||
*2021-01-19*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增配置 `model.type: fixed`, 切换为`fixed`布局模式 [体验传送门](https://maplemei.gitee.io/xm-select/#/senior/table)
|
||||
- 新增实例方法`calcPosition`, fixed布局模式下重新计算位置
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修改直接设置父节点无法选中的问题
|
||||
- 修改非严格模式下设置父节点, 子节点受影响
|
||||
- 修复渲染失败页面监听错误的问题
|
||||
- 修改数据重复时分组错乱的问题
|
||||
|
||||
|
||||
### 1.2.1
|
||||
|
||||
*2020-11-27*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增配置`enableKeyboard`, 用于控制是否使用键盘操作, 用于取消因为键盘事件带来的性能影响
|
||||
- tree模式新增配置`clickExpand`, 是否点击节点即展开节点
|
||||
- tree模式新增配置`clickCheck`, 是否点击节点即选中节点
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- [紧急修复]tree模式下节点超过2层, 父节点半选状态异常
|
||||
|
||||
|
||||
### 1.2.0
|
||||
|
||||
*2020-11-26*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 图标自定义
|
||||
- 新增实例方法`getTreeValue`, 用于获取树结构下的父节点和半选节点
|
||||
- 新增实例方法`changeExpandedKeys`, 用于操作树结构的节点展开状态
|
||||
- 新增实例方法`enable`, `disable`, 动态操作选项的启用禁用
|
||||
- 新增配置`layReqText`, 表单验证, 同`layui`的`lay-reqText`
|
||||
- 新增全局方法`arr2tree`, 用于把列表数据转化为树状结构
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复分页模式下的上一页下一页没有国际化
|
||||
- 修复远程分页时搜索过滤数据异常
|
||||
- 修改`update`方法无法更新远程
|
||||
- 修复tree模式下非严格模式搜索异常
|
||||
- 修复tree模式下工具条操作异常
|
||||
- 修复tree模式下`initValue`赋值数据错乱
|
||||
- 修复tree模式下`append`和`delete`方法不更新父节点状态
|
||||
|
||||
|
||||
### 1.1.9
|
||||
|
||||
*2020-07-20*
|
||||
|
||||
- 更新一下目录结构说明
|
||||
- 增加③群`1145047250`
|
||||
|
||||
|
||||
### 1.1.9
|
||||
|
||||
*2020-05-04*
|
||||
|
||||
#### 新增
|
||||
|
||||
- tree新增配置`simple`, 代表极简模式, 子级全部被选中后只会显示父级
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 设置远程模式`totalSize`默认为1
|
||||
- 修复普通多选模式下设置`max`配置后, 工具条的全选和反选 选中数据错误
|
||||
- 修复`getValue`方法获取到的部分数据中携带`__node`参数无法进行序列化
|
||||
- 修复同时开启远程搜索和远程分页的时候会出发两次`remoteMethod`
|
||||
- 优化`remoteMethod`的内部回调机制
|
||||
|
||||
|
||||
### 1.1.8
|
||||
|
||||
*2020-02-10*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增级联模式(第一版, 欢迎测试Bug)
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修改class .hidden为.xm-hidden 避免冲突
|
||||
- 修改tree模式下只有一个子节点是的虚线样式错误
|
||||
- 修改tree非严格模式下的工具条操作数据错误
|
||||
|
||||
|
||||
### 1.1.7
|
||||
|
||||
*2020-01-02*
|
||||
|
||||
#### 新增
|
||||
|
||||
- tree模式下可以使用工具条
|
||||
- tree模式新增远程搜索
|
||||
- tree模式新增搜索结束回调
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复搜索模式下, 有分页的情况, 二次搜索没有回到第一页的问题
|
||||
- 修复数据过多时的滚动样式问题
|
||||
|
||||
#### 预告
|
||||
|
||||
- 级联正在路上
|
||||
|
||||
|
||||
### 1.1.6
|
||||
|
||||
*2019-12-18*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增显示模式, 可以始终显示下拉内容
|
||||
- tree模式新增配置, 可以直接展开所有节点
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复动态开启动态搜索, 搜索无反应
|
||||
- 修复radio模式下setValue能设置多值的问题
|
||||
|
||||
|
||||
### 1.1.5
|
||||
|
||||
*2019-12-12*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复el为dom模式时, 点击页面其他位置无法关闭下拉的问题
|
||||
- 修复tree模式的虚线显示问题
|
||||
- 修复tree默认选中半选状态不完全的问题
|
||||
|
||||
|
||||
### 1.1.4
|
||||
|
||||
*2019-12-09*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 支持表单的重置按钮
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 调整表单验证时, 如果不满足条件, 边框变色
|
||||
- 修复radio模式下, 工具条操作全选的问题
|
||||
|
||||
|
||||
### 1.1.3
|
||||
|
||||
*2019-12-04*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 调整使用dom渲染get等方法的错误
|
||||
- 调整宽度过窄时分页的样式
|
||||
- 修复选项过宽时, label的展示溢出
|
||||
- 修复setValue自定义数据时 操作报错
|
||||
- 修复create创建新数据时 操作报错
|
||||
|
||||
|
||||
### 1.1.2
|
||||
|
||||
*2019-12-02*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复tree模式下, 第一级为叶子节点的排版问题
|
||||
- 修复tree模式鼠标hover无背景
|
||||
- 修复鼠标hover时使用隐藏图标的方式选中状态下背景色异常
|
||||
- 修改IE下的bug
|
||||
|
||||
|
||||
### 1.1.1
|
||||
|
||||
*2019-11-26*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 键盘操作,up(上),down(下),Left(上一页),Right(下一页),enter(选中、取消)
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修改分组模式下第一级数据中children为空数组报错
|
||||
- 修改tree模式+radio模式无法选中父节点的bug
|
||||
|
||||
|
||||
### 1.1.0
|
||||
|
||||
*2019-11-25*
|
||||
|
||||
- 经过了将近一周的测试, 树形结构也趋向于完善阶段, 当然现有的功能并不能满足所有的需求, xm-select将会继续前行
|
||||
|
||||
#### 新增
|
||||
|
||||
- 树形组件
|
||||
- 懒加载
|
||||
- 严格/非严格父子结构
|
||||
- 搜索模式
|
||||
- 新增参数`layVerify`和`layVerType`, 用于表单验证
|
||||
- `el`配置可以指定dom对象
|
||||
- 解决`on`监听时无法使用`setValue`, 增加return处理
|
||||
- 新增远程分页配置`pageRemote`
|
||||
- label也可以自定义渲染
|
||||
- label新增title提示
|
||||
|
||||
#### 调整
|
||||
|
||||
- 移除分组中的optgroup模式
|
||||
- 调整代码文件夹结构
|
||||
- 调整preact版本
|
||||
|
||||
|
||||
### 1.1.0.Beta
|
||||
|
||||
#### 2019-11-25
|
||||
#### 新增
|
||||
|
||||
- 树形组件
|
||||
- [新增]搜索模式
|
||||
|
||||
#### 2019-11-23
|
||||
#### 新增
|
||||
|
||||
- 新增参数`layVerify`和`layVerType`, 用于表单验证
|
||||
- `el`配置可以指定dom对象
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 树形组件
|
||||
- [修改]修复懒加载模式下回调无数据还展示三角图标
|
||||
- 解决`on`监听时无法使用`setValue`, 增加return处理
|
||||
- 修复IE下无`Object.values`的问题
|
||||
|
||||
#### 2019-11-22
|
||||
#### 新增
|
||||
|
||||
- 新增远程分页配置`pageRemote`
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 树形组件
|
||||
- [新增]`strict`严格父子结构
|
||||
- [新增]`lazy`懒加载模式
|
||||
- 修改搜索模式下输入中文的bug
|
||||
|
||||
#### 2019-11-21
|
||||
#### 新增
|
||||
|
||||
- label也可以自定义渲染
|
||||
- label新增title提示
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 树形组件
|
||||
- [修改]树状结构使用`setValue`数据错误
|
||||
- [修改]树状结构中`children`属性为空数组时无法操作节点的问题
|
||||
- [修改]半选状态下如无可选子项则变更操作为取消
|
||||
- 修改`initValue`失效的问题
|
||||
- 修改`getValue()`方法无法序列化的问题
|
||||
- 调整拓展中心下拉日期多选的样式
|
||||
|
||||
|
||||
#### 2019-11-19
|
||||
|
||||
- 历时半个月, 也算是一次大的版本更新, 此版本仅为测试版本, 升级需谨慎
|
||||
|
||||
#### 新增
|
||||
|
||||
- 树形组件
|
||||
|
||||
#### 调整
|
||||
|
||||
- 移除分组中的optgroup模式
|
||||
- 调整代码文件夹结构
|
||||
- 调整preact版本
|
||||
|
||||
|
||||
### 1.0.13
|
||||
|
||||
*2019-11-07*
|
||||
|
||||
#### 新增
|
||||
|
||||
- `get`方法新增`single`参数, 可以获取单实例
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复`reset`方法报错
|
||||
- 修复IE下工具条全选数据错误
|
||||
- 修改文档简单兼容IE
|
||||
|
||||
|
||||
### 1.0.12
|
||||
|
||||
*2019-10-24*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增配置`pageEmptyShow`, 调整分页+搜索模式下, 如果无数据是否展示分页
|
||||
- 新增`create`创建条目时的回调参数`data`, 当前下拉的数据
|
||||
- 工具条新增反选`REVERSE`
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复`create`创建条目时, 工具条不能操作的创建条目的问题
|
||||
- 修复`create`创建条目时, 分页页码显示异常的问题
|
||||
- 修复`create`创建条目时, 搜索不存在的回调逻辑
|
||||
- 修复多语言下工具条一直显示中文的问题
|
||||
- 调整分页模式下无数据显示页码 0 -> 1
|
||||
|
||||
|
||||
### 1.0.11
|
||||
|
||||
*2019-10-23*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增`disabled`配置, 可以禁用多选
|
||||
- 新增`create`配置, 可以创建条目, 具体见 [创建条目](https://maplemei.gitee.io/xm-select/#/basic/create)
|
||||
- 方法`warning`新增参数`sustain`, 可以配置是否持续显示
|
||||
- 新增全局`get`方法, 可以获取多选渲染后的对象
|
||||
- 新增全局`batch`方法, 可以批量给渲染后的多选执行方法
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复`update`方法, 会使已选中数据丢失的问题
|
||||
- 修复`Safari`浏览器下, 搜索框无法聚焦的问题
|
||||
|
||||
|
||||
### 1.0.10
|
||||
|
||||
*2019-10-20*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增`content`配置, 可自定义下拉框HTML, 具体见 [下拉自定义](https://maplemei.gitee.io/xm-select/#/plugin/customer)
|
||||
- 方法`setValue`新增参数`listenOn`, 可以设置是否通过`on`监听
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复初始化渲染也会被`on`监听的bug
|
||||
- 修复分组模式下, 搜索后分组显示错误
|
||||
- 调整分组模式下也可以使用分页, 选项控制
|
||||
|
||||
|
||||
### 1.0.9
|
||||
|
||||
*2019-10-17*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增`size`尺寸设置, `large`, `medium`, `small`, `mini`
|
||||
- 新增`warning`方法, 可以闪烁边框提示
|
||||
- 新增搜索完成回调参数, `list`:当前过滤后的数据
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复远程搜索模式下 搜索完成回调错误
|
||||
|
||||
|
||||
### 1.0.8
|
||||
|
||||
*2019-10-16*
|
||||
|
||||
#### 兼容提示
|
||||
|
||||
- 此版本的on方法结构调整, 升级请注意
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增分组单击事件 click, 可选值 `SELECT`, `CLEAR`, `AUTO`, `自定义`
|
||||
- 新增`append`方法追加赋值, `delete`方法删除赋值
|
||||
- 新增搜索完成回调`filterDone`
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复全选和请空不走on监听的问题
|
||||
- 修复`autoRow`模式下, 无选项时的css样式错误
|
||||
- 修复`update`后, 下拉框显示状态被重置为隐藏
|
||||
- 优化`setValue`方法, 可自行判断下拉框的显示状态
|
||||
- 修复文档错误, 实例没有`render`方法
|
||||
|
||||
|
||||
### 1.0.7
|
||||
|
||||
*2019-10-16*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增`autoRow`配置, 可以开启自动换行
|
||||
- 新增是否显示icon配置, 隐藏图标后将变换背景色显示
|
||||
|
||||
|
||||
### 1.0.6
|
||||
|
||||
*2019-10-14*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增`showCount`配置, 可以控制选项的数量, 提高渲染性能
|
||||
- 新增分组模式, 可以在选项中使用`optgroup`或`children`来开启, 分组时不建议开启分页模式
|
||||
- 远程搜索中新增`show`参数, 可以查看当前下拉框是否显示
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复工具条中`全选`和`清空`还可以操作禁用选项的问题
|
||||
- 修复远程搜索中`selected`不回显的问题
|
||||
|
||||
|
||||
### 1.0.5
|
||||
|
||||
*2019-10-10*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复本地搜索模式下多次重复触发过滤方法, 优化搜索性能
|
||||
- 修复选项过多时, 可以使用鼠标进行横向滚动
|
||||
|
||||
|
||||
### 1.0.4
|
||||
|
||||
*2019-09-27*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增多选上限设置, 可以设置多选选中上限
|
||||
- 新增工具条, 可以全选, 清空, 自定义
|
||||
- 新增name设置, 可以表单提交, 隐藏input实现, 值为value逗号分隔
|
||||
- 新增getValue参数, 可以获取不同类型的值
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 修复搜索模式下输入中文不显示的问题
|
||||
- 修改render不能及时渲染, 需要二次渲染的问题
|
||||
- 修改IE下输入循环触发input事件的问题, IE 慎入
|
||||
|
||||
|
||||
### 1.0.3
|
||||
|
||||
*2019-09-25*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 借鉴[ElementUI](https://element.eleme.cn/#/zh-CN)的文档编写方式, 重新编辑使用文档
|
||||
- 修改on监听时已选中数据不对的问题
|
||||
- 修改显示模式也支持html方式
|
||||
- 存在layui时, 同样也能直接使用xmSelect, 不用必须layui.xmSelect
|
||||
|
||||
|
||||
### 1.0.2
|
||||
|
||||
*2019-09-23*
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 搜索时输入中文延迟后才进行回显
|
||||
- 远程搜索时, loading状态也能进行输入的问题
|
||||
- 单选模式下, 前面的图标变成圆形
|
||||
- 修正Windows下的一些样式错乱, 兼容IE10以上
|
||||
- 启动分页, 当搜索时, 如果搜索总页码为0, 再次搜索有页码时, 当前页面为0的问题
|
||||
- 当底部空间不足时, 再次判断顶部空间是否充足, 优化展开方向
|
||||
|
||||
|
||||
|
||||
### 1.0.1
|
||||
|
||||
*2019-09-22*
|
||||
|
||||
#### 新增
|
||||
|
||||
- 物理分页配置
|
||||
- 自定义搜索模式(远程搜索)
|
||||
- 下拉选高度配置
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- 调整布局为flex布局
|
||||
- 展开下拉选时, 自动聚焦搜索框
|
201
static/xm-select/LICENSE
Normal file
201
static/xm-select/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2019] [maplemei@aliyun.com]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
8
static/xm-select/dist/xm-select.js
vendored
Normal file
8
static/xm-select/dist/xm-select.js
vendored
Normal file
File diff suppressed because one or more lines are too long
276
template/app_admin/admin_attachment.html
Normal file
276
template/app_admin/admin_attachment.html
Normal file
@ -0,0 +1,276 @@
|
||||
{% extends 'app_admin/admin_base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block title %}附件管理{% endblock %}
|
||||
{% block custom_element %}
|
||||
<link href="{% static 'viewerjs/viewer.css' %}?version={{mrdoc_version}}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-card-header" style="margin-bottom: 10px;">
|
||||
<div class="layui-row">
|
||||
<span style="font-size:18px;">附件管理
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关键词</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="kw" placeholder="请输入附件名称" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" id="search">搜索</button>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户</label>
|
||||
<div class="layui-input-inline">
|
||||
<div id="select-user"></div>
|
||||
</div>
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" id="searchUser">筛选</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row" id="img-div">
|
||||
<table class="layui-table" id="attachment-list" lay-filter="attachment-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格工具栏 -->
|
||||
<script type="text/html" id="img-toolbar">
|
||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="batchRemove">
|
||||
<i class="layui-icon layui-icon-delete"></i> 批量删除
|
||||
</button>
|
||||
</script>
|
||||
|
||||
<!-- 附件名 -->
|
||||
<script type="text/html" id="fileName">
|
||||
{% verbatim %}
|
||||
{{#if (d.file_path.startsWith('attachment')) { }}
|
||||
<a href="/media/{{d.file_path}}" target="_blank">{{d.file_name}}</a>
|
||||
{{# }else{ }}
|
||||
<a href="{{decodeURI(d.file_path.replace('/media/',''))}}" target="_blank" >{{ d.file_name }} </a>
|
||||
{{# } }}
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 上传时间 -->
|
||||
<script type="text/html" id="registerTime">
|
||||
{% verbatim %}
|
||||
{{layui.util.toDateString(d.date_joined, "yyyy-MM-dd HH:mm:ss")}}
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 最后登录时间 -->
|
||||
<script type="text/html" id="lastLoginTime">
|
||||
{% verbatim %}
|
||||
{{layui.util.toDateString(d.last_login, "yyyy-MM-dd HH:mm:ss")}}
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 用户操作模板 -->
|
||||
<script type="text/html" id="userOpera">
|
||||
{% verbatim %}
|
||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i></button>
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_script %}
|
||||
|
||||
<script src="{% static 'viewerjs/viewer.min.js' %}"></script>
|
||||
<script>
|
||||
layui.use(['table','jquery','form','layer','element','table'], function() {
|
||||
let table = layui.table;
|
||||
let form = layui.form;
|
||||
let $ = layui.jquery;
|
||||
let layer = layui.layer;
|
||||
let element = layui.element;
|
||||
$.ajaxSetup({
|
||||
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
headers: {"X-CSRFToken":'{{ csrf_token }}'},
|
||||
});
|
||||
// 获取用户列表
|
||||
getUserList = function(usergroup_list){
|
||||
$.ajax({
|
||||
url:"{% url 'api_usergroups_userlist' %}",
|
||||
type:'get',
|
||||
success:function(r){
|
||||
if(r.code === 0){
|
||||
select_user.update({
|
||||
data:r.data,
|
||||
autoRow: true,
|
||||
})
|
||||
}else{
|
||||
layer.msg("用户列表获取出错")
|
||||
}
|
||||
},
|
||||
error:function(){
|
||||
layer.msg("用户列表获取异常")
|
||||
}
|
||||
})
|
||||
};
|
||||
//获取附件列表,执行表格渲染
|
||||
table.render({
|
||||
elem: '#attachment-list',
|
||||
url: "{% url 'api_admin_attachments' %}",
|
||||
method:'get',
|
||||
where:{
|
||||
'username':$("#username").val(),
|
||||
},
|
||||
page:true,
|
||||
toolbar: '#img-toolbar',
|
||||
cols: [[
|
||||
{type: 'checkbox',width:20},
|
||||
{field:'file_name',title:'附件名称',templet:"#fileName"},
|
||||
{field:'file_path',title:'附件路径',},
|
||||
{field:'file_size',title:'附件大小',},
|
||||
{field:'username',title:'用户',},
|
||||
{field:'create_time',title:'上传时间',width:160,templet:'#registerTime'},
|
||||
{field:'oprate',title:'操作',width:180,templet:'#userOpera'},
|
||||
]],
|
||||
skin: 'line',
|
||||
});
|
||||
// [文集权限指定用户]渲染用户多选下拉框
|
||||
var select_user = xmSelect.render({
|
||||
el:'#select-user',
|
||||
filterable: true,
|
||||
radio: true,
|
||||
paging: true,
|
||||
pageSize: 20,
|
||||
theme: {
|
||||
color: '#333333',
|
||||
},
|
||||
data:[]
|
||||
});
|
||||
getUserList();
|
||||
// 删除附件
|
||||
delImg = function(id){
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'删除文档',
|
||||
area:'300px;',
|
||||
id:'delPro',//配置ID
|
||||
content:'<div style="margin-left:10px;">警告:操作将<span style="font-weight:700;color:red;">删除此附件且不可恢复!</span></div>',
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
$.ajax({
|
||||
url:'/admin/api/attachment/'+id + '/',
|
||||
type:'delete',
|
||||
success:function(r){
|
||||
layer.closeAll()
|
||||
if(r.code == 0){
|
||||
layer.msg("删除成功",{icon:1},function(){
|
||||
table.reload('attachment-list',{page:{curr:1}});
|
||||
})
|
||||
|
||||
}else{
|
||||
layer.msg(r.data,{icon:2})
|
||||
}
|
||||
},
|
||||
error:function(){
|
||||
layer.closeAll()
|
||||
layer.mag("删除异常",{icon:2,})
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
};
|
||||
// 批量删除
|
||||
batchRemove = function(obj) {
|
||||
let data = table.checkStatus(obj.config.id).data;
|
||||
if (data.length === 0) {
|
||||
layer.msg("{% trans '未选中任何附件' %}", {
|
||||
icon: 3,
|
||||
time: 1000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
let pro_id = "";
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
pro_id += data[i].id + ",";
|
||||
}
|
||||
pro_id = pro_id.substr(0, pro_id.length - 1);
|
||||
// console.log(pro_id)
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'{% trans "删除附件" %}',
|
||||
area:'300px;',
|
||||
id:'delPro',//配置ID
|
||||
content:'<div style="margin-left:10px;">你正在批量删除附件!<br><br>警告!此操作将<span style="font-weight:700;color:red;">删除所选附件!</span>并且<span style="font-weight:700;color:red;">不可恢复!</span><br><br>请输入“DELETE”以再次确认删除。<br><input class="layui-input" style="width:95%;" id="confirm_batch_delete_project" placeholder="DELETE"></div>',
|
||||
btn:['{% trans "批量删除" %}','{% trans "取消" %}'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
var confirm_delete = $("#confirm_batch_delete_project").val()
|
||||
if(confirm_delete === 'DELETE'){
|
||||
let loading = layer.load();
|
||||
$.ajax({
|
||||
url: "{% url 'api_admin_attachments' %}",
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
data:{'id':pro_id},
|
||||
success: function(r) {
|
||||
layer.closeAll();
|
||||
if (r.code == 0) {
|
||||
layer.msg("{% trans '删除成功' %}", {
|
||||
icon: 1,
|
||||
time: 1000
|
||||
}, function() {
|
||||
table.reload('attachment-list',{page:{curr:1}});
|
||||
});
|
||||
} else {
|
||||
layer.msg(r.data, {
|
||||
icon: 2,
|
||||
time: 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
layer.msg("输入错误!")
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 侦听文档删除按钮
|
||||
table.on("tool(attachment-table)",function(obj){
|
||||
if (obj.event === 'remove') {
|
||||
// console.log(obj)
|
||||
delImg(obj.data.id)
|
||||
}
|
||||
});
|
||||
// 侦听表格工具栏
|
||||
table.on("toolbar(attachment-table)",function(obj){
|
||||
if(obj.event === 'batchRemove'){ // 批量删除附件
|
||||
batchRemove(obj)
|
||||
}else if(obj.event === 'search'){ // 搜索附件
|
||||
table.reload('attachment-list',{
|
||||
where:{'kw':$('input[name="project-search-kw"]').val()
|
||||
},
|
||||
})
|
||||
}
|
||||
});
|
||||
// 监听搜索按钮
|
||||
$("#search").click(function(){
|
||||
table.reload('attachment-list',{
|
||||
where:{
|
||||
'kw':$("input[name=kw]").val(),
|
||||
},
|
||||
})
|
||||
});
|
||||
// 监听用户筛选按钮
|
||||
$("#searchUser").click(function(){
|
||||
table.reload('attachment-list',{
|
||||
where:{
|
||||
'username':select_user.getValue('valueStr'),
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@ -27,6 +27,7 @@
|
||||
{% endblock %}
|
||||
<script src="{% static 'PearAdminLayui/component/layui/layui.js' %}?version={{mrdoc_version}}"></script>
|
||||
<script src="{% static 'PearAdminLayui/component/pear/pear.js' %}?version={{mrdoc_version}}"></script>
|
||||
<script src="{% static 'xm-select/dist/xm-select.js' %}"></script>
|
||||
<script async>
|
||||
layui.use(['jquery','layer'], function() {
|
||||
let $ = layui.jquery;
|
||||
|
286
template/app_admin/admin_image.html
Normal file
286
template/app_admin/admin_image.html
Normal file
@ -0,0 +1,286 @@
|
||||
{% extends 'app_admin/admin_base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block title %}图片管理{% endblock %}
|
||||
{% block custom_element %}
|
||||
<link href="{% static 'viewerjs/viewer.css' %}?version={{mrdoc_version}}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-card-header" style="margin-bottom: 10px;">
|
||||
<div class="layui-row">
|
||||
<span style="font-size:18px;">图片管理
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关键词</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="kw" placeholder="请输入图片名称" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" id="search">搜索</button>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户</label>
|
||||
<div class="layui-input-inline">
|
||||
<div id="select-user"></div>
|
||||
</div>
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" id="searchUser">筛选</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row" id="img-div">
|
||||
<table class="layui-table" id="img-list" lay-filter="img-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格工具栏 -->
|
||||
<script type="text/html" id="img-toolbar">
|
||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="batchRemove">
|
||||
<i class="layui-icon layui-icon-delete"></i> 批量删除
|
||||
</button>
|
||||
</script>
|
||||
|
||||
<!-- 图片缩略图模板 -->
|
||||
<script type="text/html" id="imgShow">
|
||||
{% verbatim %}
|
||||
<img src="{{d.file_path}}" style="width:20px;height:20px" />
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 上传时间 -->
|
||||
<script type="text/html" id="registerTime">
|
||||
{% verbatim %}
|
||||
{{layui.util.toDateString(d.date_joined, "yyyy-MM-dd HH:mm:ss")}}
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 最后登录时间 -->
|
||||
<script type="text/html" id="lastLoginTime">
|
||||
{% verbatim %}
|
||||
{{layui.util.toDateString(d.last_login, "yyyy-MM-dd HH:mm:ss")}}
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
|
||||
<!-- 用户操作模板 -->
|
||||
<script type="text/html" id="userOpera">
|
||||
{% verbatim %}
|
||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i></button>
|
||||
{% endverbatim %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_script %}
|
||||
|
||||
<script src="{% static 'viewerjs/viewer.min.js' %}"></script>
|
||||
<script>
|
||||
layui.use(['table','jquery','form','layer','element','table'], function() {
|
||||
let table = layui.table;
|
||||
let form = layui.form;
|
||||
let $ = layui.jquery;
|
||||
let layer = layui.layer;
|
||||
let element = layui.element;
|
||||
$.ajaxSetup({
|
||||
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
headers: {"X-CSRFToken":'{{ csrf_token }}'},
|
||||
});
|
||||
// 获取用户列表
|
||||
getUserList = function(usergroup_list){
|
||||
$.ajax({
|
||||
url:"{% url 'api_usergroups_userlist' %}",
|
||||
type:'get',
|
||||
success:function(r){
|
||||
if(r.code === 0){
|
||||
select_user.update({
|
||||
data:r.data,
|
||||
autoRow: true,
|
||||
})
|
||||
}else{
|
||||
layer.msg("用户列表获取出错")
|
||||
}
|
||||
},
|
||||
error:function(){
|
||||
layer.msg("用户列表获取异常")
|
||||
}
|
||||
})
|
||||
};
|
||||
//获取图片列表,执行表格渲染
|
||||
table.render({
|
||||
elem: '#img-list',
|
||||
url: "{% url 'api_admin_imgs' %}",
|
||||
method:'get',
|
||||
where:{
|
||||
'username':$("#username").val(),
|
||||
},
|
||||
page:true,
|
||||
toolbar: '#img-toolbar',
|
||||
cols: [[
|
||||
{type: 'checkbox',width:20},
|
||||
{field:'file_path',width:60,title:"",templet:'#imgShow'},
|
||||
{field:'file_name',title:'图片名称',},
|
||||
{field:'file_path',title:'图片路径',},
|
||||
{field:'remark',title:'备注',},
|
||||
{field:'username',title:'用户',},
|
||||
{field:'create_time',title:'上传时间',width:160,templet:'#registerTime'},
|
||||
{field:'oprate',title:'操作',width:180,templet:'#userOpera'},
|
||||
]],
|
||||
skin: 'line',
|
||||
done:function(){
|
||||
//查看图片
|
||||
var options = {
|
||||
//inline: true,
|
||||
url: 'data-original',
|
||||
fullscreen:false,//全屏
|
||||
rotatable:false,//旋转
|
||||
scalable:false,//翻转
|
||||
//zoomable:false,//缩放
|
||||
button:false,//关闭按钮
|
||||
};
|
||||
var viewer = new Viewer(document.getElementById('img-div'), options);
|
||||
}
|
||||
});
|
||||
// [文集权限指定用户]渲染用户多选下拉框
|
||||
var select_user = xmSelect.render({
|
||||
el:'#select-user',
|
||||
filterable: true,
|
||||
radio: true,
|
||||
paging: true,
|
||||
pageSize: 20,
|
||||
theme: {
|
||||
color: '#333333',
|
||||
},
|
||||
data:[]
|
||||
});
|
||||
getUserList();
|
||||
// 删除图片
|
||||
delImg = function(id){
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'删除文档',
|
||||
area:'300px;',
|
||||
id:'delPro',//配置ID
|
||||
content:'<div style="margin-left:10px;">警告:操作将<span style="font-weight:700;color:red;">删除此图片且不可恢复!</span></div>',
|
||||
btn:['确定','取消'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
$.ajax({
|
||||
url:'/admin/api/img/'+id + '/',
|
||||
type:'delete',
|
||||
success:function(r){
|
||||
layer.closeAll()
|
||||
if(r.code == 0){
|
||||
layer.msg("删除成功",{icon:1},function(){
|
||||
table.reload('img-list',{page:{curr:1}});
|
||||
})
|
||||
|
||||
}else{
|
||||
layer.msg(r.data,{icon:2})
|
||||
}
|
||||
},
|
||||
error:function(){
|
||||
layer.closeAll()
|
||||
layer.mag("删除异常",{icon:2,})
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
};
|
||||
// 批量删除图片
|
||||
batchRemove = function(obj) {
|
||||
let data = table.checkStatus(obj.config.id).data;
|
||||
if (data.length === 0) {
|
||||
layer.msg("{% trans '未选中任何图片' %}", {
|
||||
icon: 3,
|
||||
time: 1000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
let pro_id = "";
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
pro_id += data[i].id + ",";
|
||||
}
|
||||
pro_id = pro_id.substr(0, pro_id.length - 1);
|
||||
// console.log(pro_id)
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'{% trans "删除图片" %}',
|
||||
area:'300px;',
|
||||
id:'delPro',//配置ID
|
||||
content:'<div style="margin-left:10px;">你正在批量删除图片!<br><br>警告!此操作将<span style="font-weight:700;color:red;">删除所选图片!</span>并且<span style="font-weight:700;color:red;">不可恢复!</span><br><br>请输入“DELETE”以再次确认删除。<br><input class="layui-input" style="width:95%;" id="confirm_batch_delete_project" placeholder="DELETE"></div>',
|
||||
btn:['{% trans "批量删除" %}','{% trans "取消" %}'], //添加按钮
|
||||
btnAlign:'c', //按钮居中
|
||||
yes:function (index,layero) {
|
||||
var confirm_delete = $("#confirm_batch_delete_project").val()
|
||||
if(confirm_delete === 'DELETE'){
|
||||
let loading = layer.load();
|
||||
$.ajax({
|
||||
url: "{% url 'api_admin_imgs' %}",
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
data:{'id':pro_id},
|
||||
success: function(r) {
|
||||
layer.closeAll();
|
||||
if (r.code == 0) {
|
||||
layer.msg("{% trans '删除成功' %}", {
|
||||
icon: 1,
|
||||
time: 1000
|
||||
}, function() {
|
||||
table.reload('img-list',{page:{curr:1}});
|
||||
});
|
||||
} else {
|
||||
layer.msg(r.data, {
|
||||
icon: 2,
|
||||
time: 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
layer.msg("输入错误!")
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 侦听文档删除按钮
|
||||
table.on("tool(img-table)",function(obj){
|
||||
if (obj.event === 'remove') {
|
||||
// console.log(obj)
|
||||
delImg(obj.data.id)
|
||||
}
|
||||
});
|
||||
// 侦听表格工具栏
|
||||
table.on("toolbar(img-table)",function(obj){
|
||||
if(obj.event === 'batchRemove'){ // 批量删除图片
|
||||
batchRemove(obj)
|
||||
}else if(obj.event === 'search'){ // 搜索图片
|
||||
table.reload('img-list',{
|
||||
where:{'kw':$('input[name="project-search-kw"]').val()
|
||||
},
|
||||
})
|
||||
}
|
||||
});
|
||||
// 监听搜索按钮
|
||||
$("#search").click(function(){
|
||||
table.reload('img-list',{
|
||||
where:{
|
||||
'kw':$("input[name=kw]").val(),
|
||||
},
|
||||
})
|
||||
});
|
||||
// 监听用户筛选按钮
|
||||
$("#searchUser").click(function(){
|
||||
table.reload('img-list',{
|
||||
where:{
|
||||
'username':select_user.getValue('valueStr'),
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user