From 7a453da303928dd86b923480d48e6d0389520845 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Thu, 7 Nov 2024 20:23:41 +0800
Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=B4=E5=83=8F?=
=?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=E7=BB=84=E4=BB=B6=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E6=97=B6url=E4=BC=A0=E5=80=BC=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/views/system/personal/index.vue | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/web/src/views/system/personal/index.vue b/web/src/views/system/personal/index.vue
index 6c7d6b4..79f29d3 100644
--- a/web/src/views/system/personal/index.vue
+++ b/web/src/views/system/personal/index.vue
@@ -354,7 +354,8 @@ const uploadImg = (data: any) => {
api.uploadAvatar(formdata).then((res: any) => {
if (res.code === 2000) {
selectImgVisible.value = false;
- state.personalForm.avatar = getBaseURL() + res.data.url;
+ // state.personalForm.avatar = getBaseURL() + res.data.url;
+ state.personalForm.avatar = res.data.url;
api.updateUserInfo(state.personalForm).then((res: any) => {
successMessage('更新成功');
getUserInfo();
From b9976cc2dda79e5a409e0542e8bd10715bc9400c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Thu, 7 Nov 2024 23:08:11 +0800
Subject: [PATCH 2/7] =?UTF-8?q?=E9=99=84=E4=BB=B6=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E7=9A=84=E8=BF=87=E6=BB=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/dvadmin/system/views/file_list.py | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/backend/dvadmin/system/views/file_list.py b/backend/dvadmin/system/views/file_list.py
index c595699..3d4b515 100644
--- a/backend/dvadmin/system/views/file_list.py
+++ b/backend/dvadmin/system/views/file_list.py
@@ -1,6 +1,7 @@
import hashlib
import mimetypes
+import django_filters
from rest_framework import serializers
from rest_framework.decorators import action
@@ -64,6 +65,15 @@ class FileSerializer(CustomModelSerializer):
return super().create(validated_data)
+class FileFilter(django_filters.FilterSet):
+ name = django_filters.CharFilter(field_name="name", lookup_expr="icontains", help_text="文件名")
+ mime_type = django_filters.CharFilter(field_name="mime_type", lookup_expr="icontains", help_text="文件类型")
+
+ class Meta:
+ model = FileList
+ fields = ['name', 'mime_type', 'upload_method']
+
+
class FileViewSet(CustomModelViewSet):
"""
文件管理接口
@@ -75,5 +85,5 @@ class FileViewSet(CustomModelViewSet):
"""
queryset = FileList.objects.all()
serializer_class = FileSerializer
- filter_fields = ['name', ]
+ filter_class = FileFilter
permission_classes = []
\ No newline at end of file
From 6ad048b86a7576b64c083de6e89f4dc002b2aed2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Thu, 7 Nov 2024 23:08:25 +0800
Subject: [PATCH 3/7] =?UTF-8?q?=E9=99=84=E4=BB=B6model=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/dvadmin/system/models.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py
index f9d2287..517792c 100644
--- a/backend/dvadmin/system/models.py
+++ b/backend/dvadmin/system/models.py
@@ -408,6 +408,11 @@ class FileList(CoreModel):
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")
+ UPLOAD_METHOD_CHOIDES = (
+ (0, '默认上传'),
+ (1, '文件选择器上传'),
+ )
+ upload_method = models.SmallIntegerField(default=0, blank=True, null=True, choices=UPLOAD_METHOD_CHOIDES, verbose_name='上传方式', help_text='上传方式')
def save(self, *args, **kwargs):
if not self.md5sum: # file is new
From 4f85de32474bc002caaa401a93531729742c006d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Fri, 8 Nov 2024 23:20:17 +0800
Subject: [PATCH 4/7] =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/dvadmin/system/models.py | 7 +
backend/dvadmin/system/views/file_list.py | 17 +-
web/src/components/fileSelector/fileItem.vue | 67 ++++++
web/src/components/fileSelector/index.vue | 222 +++++++++++++++++++
web/src/components/fileSelector/types.ts | 7 +
web/src/views/system/fileList/crud.tsx | 97 +++++++-
web/src/views/system/fileList/index.vue | 35 ++-
web/vite.config.ts | 2 +-
8 files changed, 436 insertions(+), 18 deletions(-)
create mode 100644 web/src/components/fileSelector/fileItem.vue
create mode 100644 web/src/components/fileSelector/index.vue
create mode 100644 web/src/components/fileSelector/types.ts
diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py
index 517792c..5d500b7 100644
--- a/backend/dvadmin/system/models.py
+++ b/backend/dvadmin/system/models.py
@@ -413,6 +413,13 @@ class FileList(CoreModel):
(1, '文件选择器上传'),
)
upload_method = models.SmallIntegerField(default=0, blank=True, null=True, choices=UPLOAD_METHOD_CHOIDES, verbose_name='上传方式', help_text='上传方式')
+ FILE_TYPE_CHOIDES = (
+ (0, '图片'),
+ (1, '视频'),
+ (2, '音频'),
+ (3, '其他'),
+ )
+ file_type = models.SmallIntegerField(default=3, choices=FILE_TYPE_CHOIDES, blank=True, null=True, verbose_name='文件类型', help_text='文件类型')
def save(self, *args, **kwargs):
if not self.md5sum: # file is new
diff --git a/backend/dvadmin/system/views/file_list.py b/backend/dvadmin/system/views/file_list.py
index 3d4b515..9841dab 100644
--- a/backend/dvadmin/system/views/file_list.py
+++ b/backend/dvadmin/system/views/file_list.py
@@ -36,6 +36,8 @@ class FileSerializer(CustomModelSerializer):
validated_data['md5sum'] = md5.hexdigest()
validated_data['engine'] = file_engine
validated_data['mime_type'] = file.content_type
+ ft = {'image':0,'video':1,'audio':2}.get(file.content_type.split('/')[0], None)
+ validated_data['file_type'] = 3 if ft is None else ft
if file_backup:
validated_data['url'] = file
if file_engine == 'oss':
@@ -65,13 +67,20 @@ class FileSerializer(CustomModelSerializer):
return super().create(validated_data)
+class FileAllSerializer(CustomModelSerializer):
+
+ class Meta:
+ model = FileList
+ fields = ['id', 'name']
+
+
class FileFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name="name", lookup_expr="icontains", help_text="文件名")
mime_type = django_filters.CharFilter(field_name="mime_type", lookup_expr="icontains", help_text="文件类型")
class Meta:
model = FileList
- fields = ['name', 'mime_type', 'upload_method']
+ fields = ['name', 'mime_type', 'upload_method', 'file_type']
class FileViewSet(CustomModelViewSet):
@@ -86,4 +95,8 @@ class FileViewSet(CustomModelViewSet):
queryset = FileList.objects.all()
serializer_class = FileSerializer
filter_class = FileFilter
- permission_classes = []
\ No newline at end of file
+ permission_classes = []
+
+ @action(methods=['GET'], detail=False)
+ def get_all(self, request):
+ return DetailResponse(data=self.get_serializer(self.get_queryset(), many=True).data)
diff --git a/web/src/components/fileSelector/fileItem.vue b/web/src/components/fileSelector/fileItem.vue
new file mode 100644
index 0000000..fc75d89
--- /dev/null
+++ b/web/src/components/fileSelector/fileItem.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/web/src/components/fileSelector/index.vue b/web/src/components/fileSelector/index.vue
new file mode 100644
index 0000000..e826b4e
--- /dev/null
+++ b/web/src/components/fileSelector/index.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
+
+ 文件选择
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/src/components/fileSelector/types.ts b/web/src/components/fileSelector/types.ts
new file mode 100644
index 0000000..76d135b
--- /dev/null
+++ b/web/src/components/fileSelector/types.ts
@@ -0,0 +1,7 @@
+export const SHOW = {
+ IMAGE: 0b1000, // 图片
+ VIDEO: 0b0100, // 视频
+ AUDIO: 0b0010, // 音频
+ OTHER: 0b0001, // 其他
+ ALL: 0b1111, // 全部
+};
\ No newline at end of file
diff --git a/web/src/views/system/fileList/crud.tsx b/web/src/views/system/fileList/crud.tsx
index 5c6a0d5..4a77c35 100644
--- a/web/src/views/system/fileList/crud.tsx
+++ b/web/src/views/system/fileList/crud.tsx
@@ -1,7 +1,17 @@
import * as api from './api';
-import { UserPageQuery, AddReq, DelReq, EditReq, CrudExpose, CrudOptions, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud';
+import {
+ UserPageQuery,
+ AddReq,
+ DelReq,
+ EditReq,
+ CrudExpose,
+ CrudOptions,
+ CreateCrudOptionsProps,
+ CreateCrudOptionsRet,
+ dict
+} from '@fast-crud/fast-crud';
-export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery) => {
return await api.GetList(query);
};
@@ -20,7 +30,8 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
actionbar: {
buttons: {
add: {
- show: false,
+ show: true,
+ click: () => context.openAddHandle?.()
},
},
},
@@ -34,7 +45,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
//固定右侧
fixed: 'right',
width: 200,
- show:false,
+ show: false,
buttons: {
view: {
show: false,
@@ -95,12 +106,13 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
show: true,
},
type: 'input',
- column:{
- minWidth: 120,
+ column: {
+ minWidth: 200,
},
form: {
component: {
placeholder: '请输入文件名称',
+ clearable: true
},
},
},
@@ -110,8 +122,8 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
search: {
disabled: true,
},
- column:{
- minWidth: 200,
+ column: {
+ minWidth: 360,
},
},
md5sum: {
@@ -119,13 +131,76 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
search: {
disabled: true,
},
- column:{
- minWidth: 120,
+ column: {
+ minWidth: 300,
},
form: {
- disabled: false,
+ disabled: false
},
},
+ mime_type: {
+ title: '文件类型',
+ type: 'input',
+ form: {
+ show: false,
+ component: {
+ placeholder: '请输入文件名称',
+ clearable: true
+ },
+ },
+ column: {
+ minWidth: 160
+ }
+ },
+ file_type: {
+ title: '文件类型',
+ type: 'dict-select',
+ dict: dict({
+ data: [
+ { label: '图片', value: 0, color: 'success' },
+ { label: '视频', value: 1, color: 'warning' },
+ { label: '音频', value: 2, color: 'danger' },
+ { label: '其他', value: 3, color: 'primary' },
+ ]
+ }),
+ column: {
+ show: false
+ },
+ search: {
+ show: true
+ },
+ form: {
+ show: false,
+ component: {
+ placeholder: '请选择文件类型'
+ }
+ }
+ },
+ size: {
+ title: '文件大小',
+ column: {
+ minWidth: 120
+ },
+ form: {
+ show: false
+ }
+ },
+ upload_method: {
+ title: '上传方式',
+ type: 'dict-select',
+ dict: dict({
+ data: [
+ { label: '默认上传', value: 0, color: 'primary' },
+ { label: '文件选择器上传', value: 1, color: 'warning' },
+ ]
+ }),
+ column: {
+ minWidth: 140
+ },
+ search: {
+ show: true
+ }
+ }
},
},
};
diff --git a/web/src/views/system/fileList/index.vue b/web/src/views/system/fileList/index.vue
index 119c73a..294603a 100644
--- a/web/src/views/system/fileList/index.vue
+++ b/web/src/views/system/fileList/index.vue
@@ -1,13 +1,40 @@
-
+
+
+
+ 上传
+
+
+
+ {{ scope.row.size ? getSizeDisplay(scope.row.size) : '0b' }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/vite.config.ts b/web/vite.config.ts
index ed6dec2..51ffc73 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -31,7 +31,7 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
server: {
host: '0.0.0.0',
port: env.VITE_PORT as unknown as number,
- open: true,
+ open: false,
hmr: true,
proxy: {
'/gitee': {
From 72e046fd6defe2f78540e2c768b516bb3f96660a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Fri, 8 Nov 2024 23:30:25 +0800
Subject: [PATCH 5/7] =?UTF-8?q?=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/components/fileSelector/fileItem.vue | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/web/src/components/fileSelector/fileItem.vue b/web/src/components/fileSelector/fileItem.vue
index fc75d89..5493770 100644
--- a/web/src/components/fileSelector/fileItem.vue
+++ b/web/src/components/fileSelector/fileItem.vue
@@ -10,9 +10,7 @@ import { ref, defineProps, PropType, watch, onMounted, h } from 'vue';
const props = defineProps({
fileData: { type: Object as PropType, required: true },
});
-const _OtherFileComponent = defineComponent({
- template: ''
-})
+const _OtherFileComponent = defineComponent({ template: '' });
const FileTypes = [
{ tag: 'img', attr: { src: props.fileData.url, draggable: false } },
{ tag: 'video', attr: { src: props.fileData.url, controls: false, autoplay: true, muted: true, loop: true } },
From 21d61794bc596df1319ea659b32cb5b0e92bff13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Sun, 10 Nov 2024 19:06:36 +0800
Subject: [PATCH 6/7] =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E5=99=A8=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/components/fileSelector/index.vue | 17 +++++++++++++----
web/src/views/system/fileList/index.vue | 9 ++-------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/web/src/components/fileSelector/index.vue b/web/src/components/fileSelector/index.vue
index e826b4e..89401a3 100644
--- a/web/src/components/fileSelector/index.vue
+++ b/web/src/components/fileSelector/index.vue
@@ -1,10 +1,10 @@
-
+ @open="if (listData.length === 0) listRequest();" @closed="if (!props.selectable) clear();">
文件选择
@@ -50,7 +50,7 @@
:hide-on-single-page="false" @change="handlePageChange" />
-
+
取消
确定
@@ -70,10 +70,17 @@ const AcceptList = ['image/*', 'video/*', 'audio/*', ''];
const props = defineProps({
modelValue: {},
tabsType: { type: Object as PropType<'' | 'card' | 'border-card'>, default: '' },
+ itemSize: { type: Number, default: 100 },
+
// 1000图片 100视频 10音频 1 其他 控制tabs的显示
tabsShow: { type: Number, default: SHOW.ALL },
- itemSize: { type: Number, default: 100 },
+
+ // 是否可以多选,默认单选
multiple: { type: Boolean, default: false },
+
+ // 是否可选,该参数用于控制是否显示select输入框。若赋值为false,则不会显示select输入框,也不会显示底部按钮
+ // 如果不显示select输入框,则无法触发dialog,需要父组件通过修改本组件暴露的 selectVisiable 状态来控制dialog
+ selectable: { type: Boolean, default: true },
} as any);
const selectVisiable = ref(false);
const tabsActived = ref(0);
@@ -108,6 +115,7 @@ const handlePageChange = (currentPage: number, pageSize: number) => { pageForm.p
// 选择的行为
const listContainerRef = ref();
const onItemClick = async (e: MouseEvent) => {
+ if (!props.selectable) return;
let target = e.target as HTMLElement;
let flat = 0; // -1删除 0不变 1添加
while (!target.dataset.id) target = target.parentElement as HTMLElement;
@@ -138,6 +146,7 @@ const onItemClick = async (e: MouseEvent) => {
};
// 每次列表刷新都得更新一下选择状态,因为所有标签页共享列表
const selectedInit = async () => {
+ if (!props.selectable) return;
await nextTick();
for (let i of (listContainerRef.value?.children || [])) {
i.classList.remove('active');
diff --git a/web/src/views/system/fileList/index.vue b/web/src/views/system/fileList/index.vue
index 294603a..b388ad4 100644
--- a/web/src/views/system/fileList/index.vue
+++ b/web/src/views/system/fileList/index.vue
@@ -11,11 +11,7 @@
{{ scope.row.size ? getSizeDisplay(scope.row.size) : '0b' }}
-
-
-
-
-
+
@@ -27,12 +23,11 @@ import { getBaseURL } from '/@/utils/baseUrl';
import FileSelector from '/@/components/fileSelector/index.vue';
import { SHOW } from '/@/components/fileSelector/types';
-const selectorVisiable = ref(false);
const fileSelectorRef = ref(null);
const getSizeDisplay = (n: number) => n < 1024 ? n + 'b' : (n < 1024 * 1024 ? (n / 1024).toFixed(2) + 'Kb' : (n / (1024 * 1024)).toFixed(2) + 'Mb');
const openAddHandle = async () => {
- selectorVisiable.value = true;
+ fileSelectorRef.value.selectVisiable = true;
await nextTick();
}
// crud组件的ref
From 98413bf1258e3b74e8ea63dc4f2bbda08cd8a8a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=98=BF=E8=BE=89?=
Date: Mon, 11 Nov 2024 18:30:07 +0800
Subject: [PATCH 7/7] =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E5=99=A8=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/components/fileSelector/index.vue | 29 ++++++++++++-----------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/web/src/components/fileSelector/index.vue b/web/src/components/fileSelector/index.vue
index 89401a3..00160be 100644
--- a/web/src/components/fileSelector/index.vue
+++ b/web/src/components/fileSelector/index.vue
@@ -1,7 +1,7 @@
-
-
+
+
@@ -18,8 +18,8 @@