This commit is contained in:
parent
e85bfe3f08
commit
48900fec5e
|
@ -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/'
|
||||||
|
@ -6,4 +7,12 @@ 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
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -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: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
|
@ -59,26 +59,27 @@ 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 '全部' in data_range:
|
if hasattr(queryset.model, 'belong_to'):
|
||||||
return queryset
|
if '全部' in data_range:
|
||||||
elif '自定义' in data_range:
|
|
||||||
if roles.depts.exists():
|
|
||||||
queryset = queryset.filter(belong_to__in = roles.depts)
|
|
||||||
return queryset
|
return queryset
|
||||||
elif '同级及以下' in data_range:
|
elif '自定义' in data_range:
|
||||||
if user.dept.pid:
|
if roles.depts.exists():
|
||||||
belong_tos = get_child_queryset2(user.dept.pid)
|
queryset = queryset.filter(belong_to__in = roles.depts)
|
||||||
|
return queryset
|
||||||
|
elif '同级及以下' in data_range:
|
||||||
|
if user.dept.pid:
|
||||||
|
belong_tos = get_child_queryset2(user.dept.pid)
|
||||||
|
queryset = queryset.filter(belong_to__in = belong_tos)
|
||||||
|
return queryset
|
||||||
|
elif '本级及以下' in data_range:
|
||||||
|
belong_tos = get_child_queryset2(user.dept)
|
||||||
queryset = queryset.filter(belong_to__in = belong_tos)
|
queryset = queryset.filter(belong_to__in = belong_tos)
|
||||||
return queryset
|
return queryset
|
||||||
elif '本级及以下' in data_range:
|
elif '本级' in data_range:
|
||||||
belong_tos = get_child_queryset2(user.dept)
|
queryset = queryset.filter(belong_to = user.dept)
|
||||||
queryset = queryset.filter(belong_to__in = belong_tos)
|
return queryset
|
||||||
return queryset
|
elif '仅本人' in data_range:
|
||||||
elif '本级' in data_range:
|
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
|
||||||
queryset = queryset.filter(belong_to = user.dept)
|
return queryset
|
||||||
return queryset
|
|
||||||
elif '仅本人' in data_range:
|
|
||||||
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
|
|
||||||
return queryset
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue