parent
7525e6cf2c
commit
e900deb2b4
|
@ -20,6 +20,7 @@ class CustomModelSerializer(ModelSerializer):
|
||||||
# 添加默认时间返回格式
|
# 添加默认时间返回格式
|
||||||
create_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
create_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
||||||
update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
||||||
|
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
||||||
|
|
||||||
def __init__(self, instance=None, data=empty, request=None, **kwargs):
|
def __init__(self, instance=None, data=empty, request=None, **kwargs):
|
||||||
super().__init__(instance, data, **kwargs)
|
super().__init__(instance, data, **kwargs)
|
||||||
|
|
|
@ -43,6 +43,7 @@ class SaveFileFilter(django_filters.rest_framework.FilterSet):
|
||||||
文件管理 简单过滤器
|
文件管理 简单过滤器
|
||||||
"""
|
"""
|
||||||
name = django_filters.CharFilter(lookup_expr='icontains')
|
name = django_filters.CharFilter(lookup_expr='icontains')
|
||||||
|
type = django_filters.CharFilter(lookup_expr='icontains')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SaveFile
|
model = SaveFile
|
||||||
|
|
|
@ -16,6 +16,7 @@ class SaveFile(CoreModel):
|
||||||
type = CharField(max_length=32, verbose_name="文件类型", null=True, blank=True)
|
type = CharField(max_length=32, verbose_name="文件类型", null=True, blank=True)
|
||||||
size = CharField(max_length=64, verbose_name="文件大小", null=True, blank=True)
|
size = CharField(max_length=64, verbose_name="文件大小", null=True, blank=True)
|
||||||
address = CharField(max_length=16, verbose_name="存储位置", null=True, blank=True) # 本地、阿里云、腾讯云..
|
address = CharField(max_length=16, verbose_name="存储位置", null=True, blank=True) # 本地、阿里云、腾讯云..
|
||||||
|
source = CharField(max_length=16, verbose_name="文件来源", null=True, blank=True) # 导出、用户上传.
|
||||||
oss_url = CharField(max_length=200, verbose_name="OSS地址", null=True, blank=True)
|
oss_url = CharField(max_length=200, verbose_name="OSS地址", null=True, blank=True)
|
||||||
status = BooleanField(default=True, verbose_name="文件是否存在")
|
status = BooleanField(default=True, verbose_name="文件是否存在")
|
||||||
file = FileField(verbose_name="文件URL", upload_to=files_path, )
|
file = FileField(verbose_name="文件URL", upload_to=files_path, )
|
||||||
|
|
|
@ -120,7 +120,7 @@ class ConfigSettingsCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
# ************** 参数设置 序列化器 ************** #
|
# ************** 文件管理 序列化器 ************** #
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
|
||||||
class SaveFileSerializer(CustomModelSerializer):
|
class SaveFileSerializer(CustomModelSerializer):
|
||||||
|
@ -136,7 +136,7 @@ class SaveFileSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class SaveFileCreateUpdateSerializer(CustomModelSerializer):
|
class SaveFileCreateUpdateSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
字典详情 创建/更新时的列化器
|
文件管理 创建/更新时的列化器
|
||||||
"""
|
"""
|
||||||
file_url = serializers.CharField(source='file.url', read_only=True)
|
file_url = serializers.CharField(source='file.url', read_only=True)
|
||||||
|
|
||||||
|
@ -146,6 +146,7 @@ class SaveFileCreateUpdateSerializer(CustomModelSerializer):
|
||||||
self.validated_data['size'] = files.size
|
self.validated_data['size'] = files.size
|
||||||
self.validated_data['type'] = files.content_type
|
self.validated_data['type'] = files.content_type
|
||||||
self.validated_data['address'] = '本地存储'
|
self.validated_data['address'] = '本地存储'
|
||||||
|
self.validated_data['source'] = '用户上传'
|
||||||
instance = super().save(**kwargs)
|
instance = super().save(**kwargs)
|
||||||
# 进行判断是否需要OSS上传
|
# 进行判断是否需要OSS上传
|
||||||
return instance
|
return instance
|
||||||
|
@ -228,7 +229,6 @@ class LoginInforSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
登录日志 简单序列化器
|
登录日志 简单序列化器
|
||||||
"""
|
"""
|
||||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LoginInfor
|
model = LoginInfor
|
||||||
|
@ -239,7 +239,6 @@ class ExportLoginInforSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
导出 登录日志 简单序列化器
|
导出 登录日志 简单序列化器
|
||||||
"""
|
"""
|
||||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LoginInfor
|
model = LoginInfor
|
||||||
|
@ -255,7 +254,6 @@ class OperationLogSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
操作日志 简单序列化器
|
操作日志 简单序列化器
|
||||||
"""
|
"""
|
||||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OperationLog
|
model = OperationLog
|
||||||
|
@ -266,7 +264,6 @@ class ExportOperationLogSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
导出 操作日志 简单序列化器
|
导出 操作日志 简单序列化器
|
||||||
"""
|
"""
|
||||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OperationLog
|
model = OperationLog
|
||||||
|
|
|
@ -42,5 +42,7 @@ urlpatterns = [
|
||||||
re_path('celery_log/clean/', CeleryLogModelViewSet.as_view({'delete': 'clean_all', })),
|
re_path('celery_log/clean/', CeleryLogModelViewSet.as_view({'delete': 'clean_all', })),
|
||||||
# 导出定时日志
|
# 导出定时日志
|
||||||
re_path('celery_log/export/', CeleryLogModelViewSet.as_view({'get': 'export', })),
|
re_path('celery_log/export/', CeleryLogModelViewSet.as_view({'get': 'export', })),
|
||||||
|
# 清除废弃文件
|
||||||
|
re_path('clearsavefile/', SaveFileModelViewSet.as_view({'post': 'clearsavefile', })),
|
||||||
]
|
]
|
||||||
urlpatterns += router.urls
|
urlpatterns += router.urls
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
|
|
||||||
|
@ -16,6 +19,7 @@ from ..system.serializers import DictDataSerializer, DictDataCreateUpdateSeriali
|
||||||
OperationLogSerializer, ExportOperationLogSerializer, ExportLoginInforSerializer, CeleryLogSerializer, \
|
OperationLogSerializer, ExportOperationLogSerializer, ExportLoginInforSerializer, CeleryLogSerializer, \
|
||||||
ExportCeleryLogSerializer
|
ExportCeleryLogSerializer
|
||||||
from ..utils.export_excel import export_excel_save_model
|
from ..utils.export_excel import export_excel_save_model
|
||||||
|
from ..utils.file_util import get_all_files, remove_empty_dir, delete_files
|
||||||
from ..utils.response import SuccessResponse
|
from ..utils.response import SuccessResponse
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,6 +153,26 @@ class SaveFileModelViewSet(CustomModelViewSet):
|
||||||
search_fields = ('configName',)
|
search_fields = ('configName',)
|
||||||
ordering = '-create_datetime' # 默认排序
|
ordering = '-create_datetime' # 默认排序
|
||||||
|
|
||||||
|
def clearsavefile(self, request: Request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
清理废弃文件
|
||||||
|
:param request:
|
||||||
|
:param args:
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# 获取废弃文件列表
|
||||||
|
file_list = get_all_files(os.path.join(settings.MEDIA_ROOT, 'system'))
|
||||||
|
queryset_files = [os.path.join(os.path.join(settings.MEDIA_ROOT) + os.sep, ele) for ele in
|
||||||
|
list(self.get_queryset().values_list('file', flat=True))]
|
||||||
|
|
||||||
|
delete_list = list(set(file_list) - set(queryset_files))
|
||||||
|
# 进行文件删除操作
|
||||||
|
delete_files(delete_list)
|
||||||
|
# 递归删除空文件
|
||||||
|
remove_empty_dir(os.path.join(settings.MEDIA_ROOT, 'system'))
|
||||||
|
return SuccessResponse(msg=f"成功清理废弃文件{len(delete_list)}个")
|
||||||
|
|
||||||
|
|
||||||
class MessagePushModelViewSet(CustomModelViewSet):
|
class MessagePushModelViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -134,7 +134,9 @@ def export_excel_save_model(request, field_data, data, FilName):
|
||||||
savefile.type = 'application/vnd.ms-excel'
|
savefile.type = 'application/vnd.ms-excel'
|
||||||
savefile.size = os.path.getsize(os.path.join(settings.MEDIA_ROOT, file_rul))
|
savefile.size = os.path.getsize(os.path.join(settings.MEDIA_ROOT, file_rul))
|
||||||
savefile.address = '本地存储'
|
savefile.address = '本地存储'
|
||||||
|
savefile.source = '导出'
|
||||||
savefile.creator = request.user
|
savefile.creator = request.user
|
||||||
|
savefile.dept_belong_id = getattr(request.user, 'dept_id', None)
|
||||||
savefile.modifier = request.user.username
|
savefile.modifier = request.user.username
|
||||||
savefile.save()
|
savefile.save()
|
||||||
return SaveFileSerializer(savefile).data
|
return SaveFileSerializer(savefile).data
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
"""
|
||||||
|
封装文件操作:
|
||||||
|
● 递归读取所有文件目录形成列表
|
||||||
|
● 递归删除空目录
|
||||||
|
● 批量删除文件
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_files(targetDir):
|
||||||
|
"""
|
||||||
|
递归读取所有文件目录形成列表
|
||||||
|
:param targetDir:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
files = []
|
||||||
|
listFiles = os.listdir(targetDir)
|
||||||
|
for i in range(0, len(listFiles)):
|
||||||
|
path = os.path.join(targetDir, listFiles[i])
|
||||||
|
if os.path.isdir(path):
|
||||||
|
files.extend(get_all_files(path))
|
||||||
|
elif os.path.isfile(path):
|
||||||
|
files.append(path)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def remove_empty_dir(path):
|
||||||
|
"""
|
||||||
|
递归删除空目录
|
||||||
|
:param path:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for root, dirs, files in os.walk(path, topdown=False):
|
||||||
|
if not files and not dirs:
|
||||||
|
os.rmdir(root)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_files(delete_list: list):
|
||||||
|
"""
|
||||||
|
批量删除文件
|
||||||
|
:param delete_list:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for file_path in delete_list:
|
||||||
|
try:
|
||||||
|
os.remove(file_path)
|
||||||
|
except(FileNotFoundError):
|
||||||
|
pass
|
|
@ -1,4 +1,5 @@
|
||||||
asgiref==3.3.1
|
asgiref==3.3.1
|
||||||
|
celery==5.0.5
|
||||||
Django==2.2.16
|
Django==2.2.16
|
||||||
django-cors-headers==3.7.0
|
django-cors-headers==3.7.0
|
||||||
django_celery_beat==2.2.0
|
django_celery_beat==2.2.0
|
||||||
|
|
|
@ -79,8 +79,8 @@
|
||||||
"vue-template-compiler": "2.6.12"
|
"vue-template-compiler": "2.6.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.9",
|
"node": ">=12.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 6.0.0"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<el-form-item label="文件类型" prop="type">
|
<el-form-item label="文件类型" prop="type">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.type"
|
v-model="queryParams.type"
|
||||||
placeholder="请输入文件类型(待完善)"
|
placeholder="请输入文件类型"
|
||||||
clearable
|
clearable
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
|
@ -72,8 +72,33 @@
|
||||||
<el-table-column label="文件类型" width="150" align="center" prop="type"/>
|
<el-table-column label="文件类型" width="150" align="center" prop="type"/>
|
||||||
<el-table-column label="文件大小" width="90" align="center" prop="size"/>
|
<el-table-column label="文件大小" width="90" align="center" prop="size"/>
|
||||||
<el-table-column label="存储位置" align="center" prop="address"/>
|
<el-table-column label="存储位置" align="center" prop="address"/>
|
||||||
<el-table-column label="文件本地地址" align="center" prop="file" :show-overflow-tooltip="true"/>
|
<el-table-column label="文件来源" align="center" prop="source"/>
|
||||||
<el-table-column label="OSS地址" align="center" prop="oss_url" :show-overflow-tooltip="true"/>
|
<el-table-column label="文件本地地址" align="center" prop="file" :show-overflow-tooltip="true">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-document-copy"
|
||||||
|
@click="CopyFileUrl(scope.row.file)"
|
||||||
|
v-if="scope.row.file"
|
||||||
|
></el-button>
|
||||||
|
|
||||||
|
<span>{{ scope.row.file }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="OSS地址" align="center" prop="oss_url" :show-overflow-tooltip="true">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-document-copy"
|
||||||
|
@click="CopyFileUrl(scope.row.oss_url)"
|
||||||
|
v-if="scope.row.oss_url"
|
||||||
|
></el-button>
|
||||||
|
|
||||||
|
<span>{{ scope.row.oss_url }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="create_datetime" width="160">
|
<el-table-column label="创建时间" align="center" prop="create_datetime" width="160">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.create_datetime) }}</span>
|
<span>{{ parseTime(scope.row.create_datetime) }}</span>
|
||||||
|
@ -218,9 +243,9 @@
|
||||||
type: "warning"
|
type: "warning"
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
return clearSaveFile();
|
return clearSaveFile();
|
||||||
}).then(() => {
|
}).then((values) => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess(values.msg);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/** 完成按钮 */
|
/** 完成按钮 */
|
||||||
|
@ -229,6 +254,17 @@
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.$refs.saveFile.fileList = []
|
this.$refs.saveFile.fileList = []
|
||||||
},
|
},
|
||||||
|
CopyFileUrl(values){
|
||||||
|
const input = document.createElement('input');
|
||||||
|
document.body.appendChild(input);
|
||||||
|
input.setAttribute('value', values);
|
||||||
|
input.select();
|
||||||
|
if (document.execCommand('copy')) {
|
||||||
|
document.execCommand('copy');
|
||||||
|
this.msgSuccess("复制成功");
|
||||||
|
}
|
||||||
|
document.body.removeChild(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue