feat(文件管理): 文件管理修改
This commit is contained in:
@@ -4,7 +4,7 @@ import os
|
||||
|
||||
exclude = ["venv"] # 需要排除的文件目录
|
||||
for root, dirs, files in os.walk('.'):
|
||||
dirs[:] = [d for d in set(dirs) - set(exclude)]
|
||||
dirs[:] = list(set(dirs) - set(exclude))
|
||||
if 'migrations' in dirs:
|
||||
dir = dirs[dirs.index('migrations')]
|
||||
for root_j, dirs_j, files_j in os.walk(os.path.join(root, dir)):
|
||||
|
||||
@@ -289,8 +289,7 @@ class Dictionary(CoreModel):
|
||||
(7, "images"),
|
||||
)
|
||||
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
|
||||
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号",
|
||||
help_text="字典编号/实际值")
|
||||
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号",help_text="字典编号/实际值")
|
||||
parent = models.ForeignKey(
|
||||
to="self",
|
||||
related_name="sublist",
|
||||
@@ -359,7 +358,11 @@ def media_file_name(instance, filename):
|
||||
|
||||
class FileList(CoreModel):
|
||||
name = models.CharField(max_length=200, null=True, blank=True, verbose_name="名称", help_text="名称")
|
||||
url = models.FileField(upload_to=media_file_name)
|
||||
url = models.FileField(upload_to=media_file_name, null=True, blank=True,)
|
||||
file_url = models.CharField(max_length=255, blank=True, verbose_name="文件地址", help_text="文件地址")
|
||||
engine = models.CharField(max_length=100, default='local', blank=True, verbose_name="引擎", help_text="引擎")
|
||||
mime_type = models.CharField(max_length=100, blank=True, verbose_name="Mime类型", help_text="Mime类型")
|
||||
size = models.CharField(max_length=36, blank=True, verbose_name="文件大小", help_text="文件大小")
|
||||
md5sum = models.CharField(max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
@@ -368,6 +371,11 @@ class FileList(CoreModel):
|
||||
for chunk in self.url.chunks():
|
||||
md5.update(chunk)
|
||||
self.md5sum = md5.hexdigest()
|
||||
if not self.size:
|
||||
self.size = self.url.size
|
||||
if not self.file_url:
|
||||
url = media_file_name(self,self.name)
|
||||
self.file_url = f'media/{url}'
|
||||
super(FileList, self).save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import hashlib
|
||||
import mimetypes
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import FileList
|
||||
from dvadmin.utils.json_response import DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
@@ -8,15 +15,52 @@ class FileSerializer(CustomModelSerializer):
|
||||
url = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_url(self, instance):
|
||||
return f'media/{str(instance.url)}'
|
||||
# return 'media/' + str(instance.url)
|
||||
return instance.file_url or (f'media/{str(instance.url)}')
|
||||
|
||||
class Meta:
|
||||
model = FileList
|
||||
fields = "__all__"
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = str(self.initial_data.get('file'))
|
||||
validated_data['url'] = self.initial_data.get('file')
|
||||
file_engine = dispatch.get_system_config_values("fileStorageConfig.file_engine") or 'local'
|
||||
file_backup = dispatch.get_system_config_values("fileStorageConfig.file_backup")
|
||||
file = self.initial_data.get('file')
|
||||
file_size = file.size
|
||||
validated_data['name'] = str(file)
|
||||
validated_data['size'] = file_size
|
||||
md5 = hashlib.md5()
|
||||
for chunk in file.chunks():
|
||||
md5.update(chunk)
|
||||
validated_data['md5sum'] = md5.hexdigest()
|
||||
validated_data['engine'] = file_engine
|
||||
validated_data['mime_type'] = file.content_type
|
||||
if file_backup:
|
||||
validated_data['url'] = file
|
||||
if file_engine == 'oss':
|
||||
from dvadmin_cloud_storage.views.aliyun import ali_oss_upload
|
||||
file_path = ali_oss_upload(file)
|
||||
if file_path:
|
||||
validated_data['file_url'] = file_path
|
||||
else:
|
||||
raise ValueError("上传失败")
|
||||
elif file_engine == 'cos':
|
||||
from dvadmin_cloud_storage.views.tencent import tencent_cos_upload
|
||||
file_path = tencent_cos_upload(file)
|
||||
if file_path:
|
||||
validated_data['file_url'] = file_path
|
||||
else:
|
||||
raise ValueError("上传失败")
|
||||
else:
|
||||
validated_data['url'] = file
|
||||
# 审计字段
|
||||
try:
|
||||
request_user = self.request.user
|
||||
validated_data['dept_belong_id'] = request_user.dept.id
|
||||
validated_data['creator'] = request_user.id
|
||||
validated_data['modifier'] = request_user.id
|
||||
except:
|
||||
pass
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
<template>
|
||||
<fs-page style="padding: 10px">
|
||||
<el-card :body-style="{height:'100%'}">
|
||||
<el-tabs tab-position="left" class="demo-tabs" style="height: 70vh">
|
||||
<el-tab-pane label="全部">
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :soan="6" :offset="18">
|
||||
这里放搜索框
|
||||
<fs-page>
|
||||
<el-row style="margin: 10px">
|
||||
<el-col :span="6" :offset="18">
|
||||
<el-input
|
||||
class="w-60"
|
||||
placeholder="请输入名称"
|
||||
v-model="fileParams.name"
|
||||
@keyup.enter="getData"
|
||||
clearable
|
||||
@blur="getData"
|
||||
>
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="getData">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div>
|
||||
<el-row :gutter="10">
|
||||
<el-row :gutter="10" style="height: 65vh;margin: 10px">
|
||||
<el-col :span="3" v-for="(item,index) in fileList" :key="index">
|
||||
<el-card>
|
||||
<el-image
|
||||
style="width: 150px; height: 150px"
|
||||
:src="formatImgUrl(item.url)"
|
||||
@@ -22,7 +29,8 @@
|
||||
fit="fill"
|
||||
/>
|
||||
<div>
|
||||
<div> <el-text>{{item.name}}</el-text></div>
|
||||
<el-text>{{ item.name }}</el-text>
|
||||
</div>
|
||||
<div>
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
@@ -37,9 +45,10 @@
|
||||
:column="2"
|
||||
border
|
||||
>
|
||||
<el-descriptions-item label="文件名称">{{item.name}}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建人">{{item.creator_name}}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{item.create_datetime}}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件名称">{{ item.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建人">{{ item.creator_name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="存储引擎">{{ item.engine }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ item.create_datetime }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-popover>
|
||||
@@ -48,54 +57,87 @@
|
||||
<el-button type="text">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Config">Config</el-tab-pane>
|
||||
<el-tab-pane label="Role">Role</el-tab-pane>
|
||||
<el-tab-pane label="Task">Task</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-divider></el-divider>
|
||||
<el-row>
|
||||
<el-col :span="12" :offset="12">
|
||||
这里放分页
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider></el-divider>
|
||||
<el-row style="margin-left: 10px">
|
||||
<el-col :span="12" >
|
||||
<el-pagination
|
||||
v-model:current-page="pageConfig.page"
|
||||
v-model:page-size="pageConfig.limit"
|
||||
background
|
||||
:page-sizes="[5, 10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="pageConfig.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {DelObj, GetList} from "./api";
|
||||
import {ref,onMounted} from "vue";
|
||||
import {DelObj, GetList, GetMimeType} from "./api";
|
||||
import {ref, onMounted,reactive} from "vue";
|
||||
import {getBaseURL} from "/@/utils/baseUrl";
|
||||
import {ElMessage} from "element-plus";
|
||||
import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue'
|
||||
const fileParams = reactive({name:''})
|
||||
const fileList = ref([])
|
||||
const getData = function (){
|
||||
GetList({}).then((res:any)=>{
|
||||
const {data} = res
|
||||
const mimeType = ref([])
|
||||
const pageConfig = reactive({
|
||||
page:1,
|
||||
limit:10,
|
||||
total:0
|
||||
})
|
||||
const getData = function () {
|
||||
let params = {
|
||||
page:pageConfig.page,
|
||||
limit:pageConfig.limit,
|
||||
name:fileParams.name
|
||||
}
|
||||
GetList(params).then((res: any) => {
|
||||
const {data,page,limit,total} = res
|
||||
pageConfig.page = page
|
||||
pageConfig.limit=limit
|
||||
pageConfig.total=total
|
||||
fileList.value = data
|
||||
})
|
||||
}
|
||||
|
||||
const onDel = function (item:any) {
|
||||
DelObj(item.id).then((res:any)=>{
|
||||
const getMimeType = function () {
|
||||
GetMimeType().then((res: any) => {
|
||||
const {data} = res
|
||||
mimeType.value = data
|
||||
})
|
||||
}
|
||||
|
||||
const onDel = function (item: any) {
|
||||
DelObj(item.id).then((res: any) => {
|
||||
ElMessage.success("删除成功!");
|
||||
getData()
|
||||
})
|
||||
}
|
||||
const formatImgUrl = function (src:string) {
|
||||
return getBaseURL()+src
|
||||
const formatImgUrl = function (src: string) {
|
||||
return getBaseURL() + src
|
||||
}
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
const handleSizeChange = function (val: any) {
|
||||
pageConfig.limit = val
|
||||
getData()
|
||||
}
|
||||
|
||||
const handleCurrentChange = function (val: any) {
|
||||
pageConfig.page = val
|
||||
getData()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getData()
|
||||
getMimeType()
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
@@ -110,7 +152,8 @@ onMounted(()=>{
|
||||
.el-tabs--left .el-tabs__content {
|
||||
height: 100%;
|
||||
}
|
||||
.el-tabs__nav-scroll{
|
||||
|
||||
.el-tabs__nav-scroll {
|
||||
border-right: 1px solid #efefef;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user