23526ff5 by Holly

多文件上传且可拖拽

1 parent 24e4c535
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
10 "preview": "vite preview" 10 "preview": "vite preview"
11 }, 11 },
12 "dependencies": { 12 "dependencies": {
13 "sortablejs": "^1.15.6",
13 "@element-plus/icons-vue": "2.0.10", 14 "@element-plus/icons-vue": "2.0.10",
14 "@vueup/vue-quill": "1.2.0", 15 "@vueup/vue-quill": "1.2.0",
15 "@vueuse/core": "9.5.0", 16 "@vueuse/core": "9.5.0",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
5 :action="uploadFileUrl" 5 :action="uploadFileUrl"
6 :before-upload="handleBeforeUpload" 6 :before-upload="handleBeforeUpload"
7 :file-list="fileList" 7 :file-list="fileList"
8 :limit="limit"
8 :on-error="handleUploadError" 9 :on-error="handleUploadError"
9 :on-exceed="handleExceed" 10 :on-exceed="handleExceed"
10 :on-success="handleUploadSuccess" 11 :on-success="handleUploadSuccess"
...@@ -24,8 +25,20 @@ ...@@ -24,8 +25,20 @@
24 的文件 25 的文件
25 </div> 26 </div>
26 <!-- 文件列表 --> 27 <!-- 文件列表 -->
27 <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> 28 <transition-group
28 <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> 29 class="upload-file-list el-upload-list el-upload-list--text"
30 name="el-fade-in-linear"
31 tag="ul"
32 ref="fileListWrapper"
33 @update="handleSortUpdate"
34 >
35 <li
36 :key="file.uid"
37 class="el-upload-list__item ele-upload-list__item-content draggable"
38 v-for="(file, index) in fileList"
39 :draggable="true"
40 :title="limit > 1 ? '可拖动文件进行调序' : ''"
41 >
29 <el-link :href="`${file.url}`" :underline="false" target="_blank"> 42 <el-link :href="`${file.url}`" :underline="false" target="_blank">
30 <span class="el-icon-document"> {{ getFileName(file.name) }} </span> 43 <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
31 </el-link> 44 </el-link>
...@@ -40,9 +53,15 @@ ...@@ -40,9 +53,15 @@
40 <script setup> 53 <script setup>
41 import { getToken } from "@/utils/auth"; 54 import { getToken } from "@/utils/auth";
42 import { listByIds, delOss } from "@/api/system/oss"; 55 import { listByIds, delOss } from "@/api/system/oss";
56 import Sortable from 'sortablejs';
43 57
44 const props = defineProps({ 58 const props = defineProps({
45 modelValue: [String, Object, Array], 59 modelValue: [String, Object, Array],
60 // 数量限制
61 limit: {
62 type: Number,
63 default: 5,
64 },
46 // 大小限制(MB) 65 // 大小限制(MB)
47 fileSize: { 66 fileSize: {
48 type: Number, 67 type: Number,
...@@ -64,13 +83,43 @@ const { proxy } = getCurrentInstance(); ...@@ -64,13 +83,43 @@ const { proxy } = getCurrentInstance();
64 const emit = defineEmits(); 83 const emit = defineEmits();
65 const number = ref(0); 84 const number = ref(0);
66 const uploadList = ref([]); 85 const uploadList = ref([]);
67 const baseUrl = import.meta.env.VITE_APP_BASE_API; 86 const baseUrl = import.meta.env.VITE_APP_BASE_API || '';
68 const uploadFileUrl = ref(baseUrl + "/system/oss/upload"); // 上传文件服务器地址 87 const uploadFileUrl = ref(baseUrl + "/system/oss/upload"); // 上传文件服务器地址
69 const headers = ref({ Authorization: "Bearer " + getToken() }); 88 const headers = ref({ Authorization: "Bearer " + getToken() });
70 const fileList = ref([]); 89 const fileList = ref([]);
71 const showTip = computed( 90 const showTip = computed(
72 () => props.isShowTip && (props.fileType || props.fileSize) 91 () => props.isShowTip && (props.fileType || props.fileSize)
73 ); 92 );
93 // 初始化拖拽排序
94 onMounted(() => {
95 const el = proxy.$refs.fileListWrapper.$el; // 确保transition-group添加ref="fileListWrapper"
96 if (el) {
97 new Sortable(el, {
98 animation: 150, // 过渡动画时长
99 draggable: '.draggable', // 可拖拽的元素
100 onUpdate: (evt) => {
101 // 拖拽结束时更新列表顺序
102 const oldIndex = evt.oldIndex;
103 const newIndex = evt.newIndex;
104
105 // 移动元素位置
106 fileList.value.splice(newIndex, 0, fileList.value.splice(oldIndex, 1)[0]);
107
108 // 触发排序更新事件
109 handleSortUpdate();
110 }
111 });
112 }
113 });
114 // 排序更新处理
115 function handleSortUpdate() {
116 // 更新父组件modelValue
117 emit("update:modelValue", listToString(fileList.value));
118
119 // 输出排序后的列表(可选)
120 console.log('排序后的文件列表:', fileList.value);
121 }
122
74 123
75 watch(() => props.modelValue, async val => { 124 watch(() => props.modelValue, async val => {
76 if (val) { 125 if (val) {
...@@ -124,6 +173,10 @@ function handleBeforeUpload(file) { ...@@ -124,6 +173,10 @@ function handleBeforeUpload(file) {
124 return true; 173 return true;
125 } 174 }
126 175
176 // 文件个数超出
177 function handleExceed() {
178 proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
179 }
127 180
128 // 上传失败 181 // 上传失败
129 function handleUploadError(err) { 182 function handleUploadError(err) {
...@@ -206,4 +259,7 @@ function listToString(list, separator) { ...@@ -206,4 +259,7 @@ function listToString(list, separator) {
206 .ele-upload-list__item-content-action .el-link { 259 .ele-upload-list__item-content-action .el-link {
207 margin-right: 10px; 260 margin-right: 10px;
208 } 261 }
262 .draggable {
263 cursor: move;
264 }
209 </style> 265 </style>
......
...@@ -134,13 +134,13 @@ ...@@ -134,13 +134,13 @@
134 </template> 134 </template>
135 </el-form-item> 135 </el-form-item>
136 <el-form-item :label="$t('course.dialogCase')" prop="caseOssId" label-width="80"> 136 <el-form-item :label="$t('course.dialogCase')" prop="caseOssId" label-width="80">
137 <fileUpload v-model="showForm.form.caseOssId" :fileType='["mp4", "avi", "mov", "flv","pdf"]'/> 137 <fileUpload v-model="showForm.form.caseOssId" :limit="10" :fileType='["mp4", "avi", "mov", "flv","pdf"]'/>
138 </el-form-item> 138 </el-form-item>
139 <el-form-item :label="$t('course.dialogTeaching')" label-width="80"> 139 <el-form-item :label="$t('course.dialogTeaching')" label-width="80">
140 <fileUpload v-model="showForm.form.teachingOssId" :fileType='["pdf","mp4"]'/> 140 <fileUpload v-model="showForm.form.teachingOssId" :limit="10" :fileType='["pdf","mp4"]'/>
141 </el-form-item> 141 </el-form-item>
142 <el-form-item :label="$t('course.dialogPpt')" label-width="80"> 142 <el-form-item :label="$t('course.dialogPpt')" label-width="80">
143 <fileUpload v-model="showForm.form.pptOssId" :fileType='["pdf","mp4"]'/> 143 <fileUpload v-model="showForm.form.pptOssId" :limit="10" :fileType='["pdf","mp4"]'/>
144 </el-form-item> 144 </el-form-item>
145 <el-form-item :label="$t('course.dialogPhoto')" prop="ossId" label-width="80"> 145 <el-form-item :label="$t('course.dialogPhoto')" prop="ossId" label-width="80">
146 <imageUpload v-model="showForm.form.ossId" :limit='1' :fileType='["png", "jpg", "jpeg", "ico"]'/> 146 <imageUpload v-model="showForm.form.ossId" :limit='1' :fileType='["png", "jpg", "jpeg", "ico"]'/>
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!