4
4
:destroy-on-close =" true"
5
5
:close-on-click-modal =" false"
6
6
:close-on-press-escape =" false"
7
- size =" 40% "
7
+ size =" 675 "
8
8
>
9
9
<template #header >
10
10
<DrawerHeader :header =" title" :back =" handleClose" />
33
33
<el-radio :value =" false" size =" large" >{{ $t('file.rename') }}</el-radio >
34
34
</el-radio-group >
35
35
</div >
36
+ <div v-if =" existFiles.length > 0 && !changeName" class =" text-center" >
37
+ <el-alert :show-icon =" true" type =" warning" :closable =" false" >
38
+ <div class =" whitespace-break-spaces" >
39
+ <span >{{ $t('file.existFileDirHelper') }}</span >
40
+ </div >
41
+ </el-alert >
42
+ <el-transfer
43
+ v-model =" skipFiles"
44
+ class =" text-left inline-block mt-4"
45
+ :titles =" [$t('commons.button.cover'), $t('commons.button.skip')]"
46
+ :format =" {
47
+ noChecked: '${total}',
48
+ hasChecked: '${checked}/${total}',
49
+ }"
50
+ :data =" transferData"
51
+ />
52
+ </div >
36
53
</el-form >
37
54
</el-col >
38
55
</el-row >
48
65
</template >
49
66
50
67
<script lang="ts" setup>
51
- import { CheckFile , MoveFile } from ' @/api/modules/files' ;
68
+ import { BatchCheckFiles , CheckFile , MoveFile } from ' @/api/modules/files' ;
52
69
import { Rules } from ' @/global/form-rules' ;
53
70
import i18n from ' @/lang' ;
54
71
import { FormInstance , FormRules } from ' element-plus' ;
55
- import { ref , reactive , computed } from ' vue' ;
72
+ import { ref , reactive , computed , ComputedRef } from ' vue' ;
56
73
import FileList from ' @/components/file-list/index.vue' ;
57
74
import DrawerHeader from ' @/components/drawer-header/index.vue' ;
58
75
import { MsgSuccess } from ' @/utils/message' ;
59
76
import { getDateStr } from ' @/utils/util' ;
60
77
61
78
interface MoveProps {
62
79
oldPaths: Array <string >;
80
+ allNames: Array <string >;
63
81
type: string ;
64
82
path: string ;
65
83
name: string ;
84
+ isDir: boolean ;
66
85
}
67
86
68
87
const fileForm = ref <FormInstance >();
@@ -71,6 +90,9 @@ const open = ref(false);
71
90
const type = ref (' cut' );
72
91
const changeName = ref (false );
73
92
const oldName = ref (' ' );
93
+ const existFiles = ref ([]);
94
+ const skipFiles = ref ([]);
95
+ const transferData = ref ([]);
74
96
75
97
const title = computed (() => {
76
98
if (type .value === ' cut' ) {
@@ -85,6 +107,8 @@ const addForm = reactive({
85
107
newPath: ' ' ,
86
108
type: ' ' ,
87
109
name: ' ' ,
110
+ allNames: [] as string [],
111
+ isDir: false ,
88
112
cover: false ,
89
113
});
90
114
@@ -103,6 +127,18 @@ const handleClose = (search: boolean) => {
103
127
em (' close' , search );
104
128
};
105
129
130
+ const getFileName = (filePath : string ) => {
131
+ if (filePath .endsWith (' /' )) {
132
+ filePath = filePath .slice (0 , - 1 );
133
+ }
134
+
135
+ return filePath .split (' /' ).pop ();
136
+ };
137
+
138
+ const coverFiles: ComputedRef <string []> = computed (() => {
139
+ return addForm .oldPaths .filter ((item ) => ! skipFiles .value .includes (getFileName (item ))).map ((item ) => item );
140
+ });
141
+
106
142
const getPath = (path : string ) => {
107
143
addForm .newPath = path ;
108
144
};
@@ -111,7 +147,7 @@ const changeType = () => {
111
147
if (addForm .cover ) {
112
148
addForm .name = oldName .value ;
113
149
} else {
114
- addForm .name = oldName .value + ' - ' + getDateStr ( );
150
+ addForm .name = renameFileWithSuffix ( oldName .value , addForm . isDir );
115
151
}
116
152
};
117
153
@@ -137,24 +173,80 @@ const submit = async (formEl: FormInstance | undefined) => {
137
173
return ;
138
174
}
139
175
loading .value = true ;
176
+ addForm .oldPaths = coverFiles .value ;
140
177
mvFile ();
141
178
});
142
179
};
143
180
181
+ const getCompleteExtension = (filename : string ): string => {
182
+ const compoundExtensions = [
183
+ ' .tar.gz' ,
184
+ ' .tar.bz2' ,
185
+ ' .tar.xz' ,
186
+ ' .tar.lzma' ,
187
+ ' .tar.Z' ,
188
+ ' .tar.zst' ,
189
+ ' .tar.lzo' ,
190
+ ' .tar.sz' ,
191
+ ' .tgz' ,
192
+ ' .tbz2' ,
193
+ ' .txz' ,
194
+ ' .tzst' ,
195
+ ];
196
+ const foundExtension = compoundExtensions .find ((ext ) => filename .endsWith (ext ));
197
+ if (foundExtension ) {
198
+ return foundExtension ;
199
+ }
200
+ const match = filename .match (/ \. [a-zA-Z0-9 ] + $ / );
201
+ return match ? match [0 ] : ' ' ;
202
+ };
203
+
204
+ const renameFileWithSuffix = (fileName : string , isDir : boolean ): string => {
205
+ const insertStr = ' -' + getDateStr ();
206
+ const completeExt = isDir ? ' ' : getCompleteExtension (fileName );
207
+ if (! completeExt ) {
208
+ return ` ${fileName }${insertStr } ` ;
209
+ } else {
210
+ const baseName = fileName .slice (0 , fileName .length - completeExt .length );
211
+ return ` ${baseName }${insertStr }${completeExt } ` ;
212
+ }
213
+ };
214
+
215
+ const handleFilePaths = async (fileNames : string [], newPath : string ) => {
216
+ const uniqueFiles = [... new Set (fileNames )];
217
+ const fileNamesWithPath = uniqueFiles .map ((file ) => newPath + ' /' + file );
218
+ const existData = await BatchCheckFiles (fileNamesWithPath );
219
+ existFiles .value = existData .data ;
220
+ transferData .value = existData .data .map ((file ) => ({
221
+ key: file .name ,
222
+ label: file .name ,
223
+ }));
224
+ };
225
+
144
226
const acceptParams = async (props : MoveProps ) => {
145
227
changeName .value = false ;
146
228
addForm .oldPaths = props .oldPaths ;
147
229
addForm .type = props .type ;
148
230
addForm .newPath = props .path ;
231
+ addForm .isDir = props .isDir ;
149
232
addForm .name = ' ' ;
233
+ addForm .allNames = props .allNames ;
150
234
type .value = props .type ;
151
235
if (props .name && props .name != ' ' ) {
152
236
oldName .value = props .name ;
153
237
const res = await CheckFile (props .path + ' /' + props .name );
154
238
if (res .data ) {
155
239
changeName .value = true ;
156
240
addForm .cover = false ;
157
- addForm .name = props .name + ' -' + getDateStr ();
241
+ addForm .name = renameFileWithSuffix (props .name , addForm .isDir );
242
+ open .value = true ;
243
+ } else {
244
+ mvFile ();
245
+ }
246
+ } else if (props .allNames && props .allNames .length > 0 ) {
247
+ await handleFilePaths (addForm .allNames , addForm .newPath );
248
+ if (existFiles .value .length > 0 ) {
249
+ changeName .value = false ;
158
250
open .value = true ;
159
251
} else {
160
252
mvFile ();
@@ -166,3 +258,41 @@ const acceptParams = async (props: MoveProps) => {
166
258
167
259
defineExpose ({ acceptParams });
168
260
</script >
261
+
262
+ <style lang="scss" scoped>
263
+ :deep(.el-transfer ) {
264
+ --el-transfer-panel-width : 250px ;
265
+ .el-button {
266
+ padding : 4px 7px ;
267
+ }
268
+ }
269
+
270
+ :deep(.el-transfer__buttons ) {
271
+ padding : 5px 15px ;
272
+ @media (max-width : 600px ) {
273
+ width : 250px ;
274
+ text-align : center ;
275
+ padding : 10px 0 ;
276
+ .el-button [class *= ' el-icon' ] svg {
277
+ transform : rotate (90deg );
278
+ }
279
+ }
280
+
281
+ @media (min-width : 601px ) {
282
+ display : inline-flex ;
283
+ flex-direction : column ;
284
+ align-items : center ;
285
+ gap : 10px ;
286
+ width : 40px ;
287
+ height : 40px ;
288
+ justify-content : center ;
289
+ .el-button + .el-button {
290
+ margin-left : 0 ;
291
+ }
292
+ }
293
+ }
294
+
295
+ :deep(.el-transfer-panel .el-transfer-panel__footer ) {
296
+ height : 65px ;
297
+ }
298
+ </style >
0 commit comments