This commit is contained in:
caoqianming 2020-05-28 20:24:41 +08:00
parent e85bfe3f08
commit 48900fec5e
9 changed files with 210 additions and 57 deletions

View File

@ -1,4 +1,5 @@
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth"
import request from '@/utils/request'
export function uploadUrl() { export function uploadUrl() {
return process.env.VUE_APP_BASE_API + '/file/' return process.env.VUE_APP_BASE_API + '/file/'
@ -7,3 +8,11 @@ export function uploadUrl() {
export function upHeaders() { export function upHeaders() {
return { Authorization: "Bearer " + getToken() } return { Authorization: "Bearer " + getToken() }
} }
export function getFileList(query) {
return request({
url: '/file/',
method: 'get',
params: query
})
}

View File

@ -97,6 +97,12 @@ export const asyncRoutes = [
name: 'Dict', name: 'Dict',
component: () => import('@/views/system/dict'), component: () => import('@/views/system/dict'),
meta: { title: '数据字典', icon: 'example', perms: ['dict_manage'] } meta: { title: '数据字典', icon: 'example', perms: ['dict_manage'] }
},
{
path: 'file',
name: 'File',
component: () => import('@/views/system/file'),
meta: { title: '文件库', icon: 'documentation', perms: ['file_room'] }
} }
] ]
}, },
@ -114,7 +120,17 @@ export const asyncRoutes = [
meta: { title: '权限菜单', icon: 'example', perms: ['perm_manage'] } meta: { title: '权限菜单', icon: 'example', perms: ['perm_manage'] }
}, },
{ {
path: 'external-link', path: 'form-gen-link',
component: Layout,
children: [
{
path: 'https://jakhuang.github.io/form-generator/',
meta: { title: '表单设计器', icon: 'link', perms: ['dev_form_gen'] }
}
]
},
{
path: 'docs-link',
component: Layout, component: Layout,
children: [ children: [
{ {
@ -124,7 +140,7 @@ export const asyncRoutes = [
] ]
}, },
{ {
path: 'external-link2', path: 'admin-link',
component: Layout, component: Layout,
children: [ children: [
{ {

View File

@ -0,0 +1,132 @@
<template>
<div class="app-container">
<div>
<el-select
v-model="listQuery.type"
placeholder="文件类型"
clearable
style="width: 200px"
class="filter-item"
@change="handleFilter"
>
<el-option
v-for="item in enabledOptions"
:key="item.key"
:label="item.display_name"
:value="item.key"
/>
</el-select>
<el-input
v-model="listQuery.search"
placeholder="文件名"
style="width: 300px;"
class="filter-item"
@keyup.enter.native="handleFilter"
/>
<el-button
class="filter-item"
type="primary"
icon="el-icon-search"
@click="handleFilter"
>搜索</el-button>
<el-button
class="filter-item"
style="margin-left: 10px;"
type="primary"
icon="el-icon-refresh-left"
@click="resetFilter"
>刷新重置</el-button>
</div>
<el-table
v-loading="listLoading"
:data="fileList.results"
style="width: 100%;margin-top:10px;"
border
fit
stripe
highlight-current-row
max-height="600"
>
<el-table-column type="index" width="50" />
<el-table-column align="center" label="名称">
<template slot-scope="scope">
<el-link type="primary" :href="scope.row.file" target="_blank">{{ scope.row.name }}</el-link>
</template>
</el-table-column>
<el-table-column align="header-center" label="类型">
<template slot-scope="scope">{{ scope.row.type }}</template>
</el-table-column>
<el-table-column align="header-center" label="格式">
<template slot-scope="scope">{{ scope.row.mime }}</template>
</el-table-column>
<el-table-column align="header-center" label="大小(B)">
<template slot-scope="scope">{{ scope.row.size }}</template>
</el-table-column>
<el-table-column align="header-center" label="地址">
<template slot-scope="scope">{{ scope.row.path }}</template>
</el-table-column>
<el-table-column label="上传日期">
<template slot-scope="scope">
<span>{{ scope.row.create_time }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="fileList.count>0"
:total="fileList.count"
:page.sync="listQuery.page"
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</div>
</template>
<script>
import { getFileList } from "@/api/file"
import Pagination from "@/components/Pagination"
export default {
components: { Pagination },
data() {
return {
fileList: {count:0},
listLoading: true,
listQuery: {
page: 1,
page_size: 20
},
enabledOptions: [
{ key: "文档", display_name: "文档" },
{ key: "图片", display_name: "图片" },
{ key: "音频", display_name: "音频" },
{ key: "视频", display_name: "视频" },
{ key: "其它", display_name: "其它" }
],
};
},
created() {
this.getList();
},
methods: {
getList() {
this.listLoading = true;
getFileList(this.listQuery).then(response => {
if (response.data) {
this.fileList = response.data
}
this.listLoading = false;
});
},
resetFilter() {
this.listQuery = {
page: 1,
page_size: 20
};
this.getList();
},
handleFilter() {
this.listQuery.page = 1;
this.getList();
},
}
};
</script>

View File

@ -82,16 +82,6 @@
slot-scope="scope" slot-scope="scope"
>{{ scope.row.dept_name }}</template> >{{ scope.row.dept_name }}</template>
</el-table-column> </el-table-column>
<!-- <el-table-column align="header-center" label="状态">
<template slot-scope="scope">
<el-switch
v-model="scope.row.is_active"
:disabled="!checkPermission(['user_update'])"
active-color="#409EFF"
inactive-color="#F56C6C"
/>
</template>
</el-table-column>-->
<el-table-column label="创建日期"> <el-table-column label="创建日期">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.date_joined }}</span> <span>{{ scope.row.date_joined }}</span>

View File

@ -193,6 +193,9 @@ class CommonBModel(SoftModel):
class File(CommonAModel): class File(CommonAModel):
"""
文件存储表,业务表根据具体情况选择是否外键关联
"""
name = models.CharField('名称', max_length=30, null=True, blank=True) name = models.CharField('名称', max_length=30, null=True, blank=True)
size = models.IntegerField('文件大小', default=1, null=True, blank=True) size = models.IntegerField('文件大小', default=1, null=True, blank=True)
file = models.FileField('文件', upload_to='%Y/%m/%d/') file = models.FileField('文件', upload_to='%Y/%m/%d/')
@ -206,3 +209,10 @@ class File(CommonAModel):
mime = models.CharField('文件格式', max_length=50, null=True, blank=True) mime = models.CharField('文件格式', max_length=50, null=True, blank=True)
type = models.CharField('文件类型', max_length=50, choices=type_choices, default='文档') type = models.CharField('文件类型', max_length=50, choices=type_choices, default='文档')
path = models.CharField('地址', max_length=1000, null=True, blank=True) path = models.CharField('地址', max_length=1000, null=True, blank=True)
class Meta:
verbose_name = '文件库'
verbose_name_plural = verbose_name
def __str__(self):
return self.name

View File

@ -59,6 +59,7 @@ def rbac_filter_queryset(user, queryset):
""" """
roles = user.roles roles = user.roles
data_range = roles.values_list('datas', flat=True) data_range = roles.values_list('datas', flat=True)
if hasattr(queryset.model, 'belong_to'):
if '全部' in data_range: if '全部' in data_range:
return queryset return queryset
elif '自定义' in data_range: elif '自定义' in data_range:

View File

@ -222,6 +222,7 @@ class FileViewSet(ModelViewSet):
parser_classes = [MultiPartParser, JSONParser] parser_classes = [MultiPartParser, JSONParser]
queryset = File.objects.all() queryset = File.objects.all()
serializer_class = FileSerializer serializer_class = FileSerializer
filterset_fields = ['type']
search_fields = ['name'] search_fields = ['name']
ordering = '-create_time' ordering = '-create_time'

View File

@ -13,26 +13,21 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from rest_framework import routers
from rest_framework.documentation import include_docs_urls from rest_framework.documentation import include_docs_urls
from rest_framework_simplejwt.views import (TokenObtainPairView, from rest_framework_simplejwt.views import (TokenObtainPairView,
TokenRefreshView) TokenRefreshView)
from django.conf import settings from apps.system.views import FileViewSet, LogoutView
from apps.system.views import LogoutView
from utils.view import UploadFileView
from rest_framework import routers
from apps.system.views import FileViewSet
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('file', FileViewSet, basename="file") router.register('file', FileViewSet, basename="file")
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('upload/', UploadFileView.as_view(), name='file_upload'),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('token/black/', LogoutView.as_view(), name='token_black'), path('token/black/', LogoutView.as_view(), name='token_black'),
@ -42,4 +37,3 @@ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -10,21 +10,21 @@ import os
import uuid import uuid
class UploadFileView(APIView): # class UploadFileView(APIView):
permission_classes = [IsAuthenticated] # permission_classes = [IsAuthenticated]
parser_classes = (MultiPartParser,) # parser_classes = (MultiPartParser,)
def post(self, request, *args, **kwargs): # def post(self, request, *args, **kwargs):
fileobj = request.FILES['file'] # fileobj = request.FILES['file']
file_name = fileobj.name.encode('utf-8').decode('utf-8') # file_name = fileobj.name.encode('utf-8').decode('utf-8')
file_name_new = str(uuid.uuid1()) + '.' + file_name.split('.')[-1] # file_name_new = str(uuid.uuid1()) + '.' + file_name.split('.')[-1]
subfolder = os.path.join('media', datetime.now().strftime("%Y%m%d")) # subfolder = os.path.join('media', datetime.now().strftime("%Y%m%d"))
if not os.path.exists(subfolder): # if not os.path.exists(subfolder):
os.mkdir(subfolder) # os.mkdir(subfolder)
file_path = os.path.join(subfolder, file_name_new) # file_path = os.path.join(subfolder, file_name_new)
file_path = file_path.replace('\\', '/') # file_path = file_path.replace('\\', '/')
with open(file_path, 'wb') as f: # with open(file_path, 'wb') as f:
for chunk in fileobj.chunks(): # for chunk in fileobj.chunks():
f.write(chunk) # f.write(chunk)
resdata = {"name": file_name, "path": '/' + file_path} # resdata = {"name": file_name, "path": '/' + file_path}
return Response(resdata) # return Response(resdata)