feat: 图片拖拽问题处理,VueDraggable不支持jsx写法
This commit is contained in:
@ -220,9 +220,9 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{loading.value ? (
|
{loading.value ? (
|
||||||
<Spin spinning={loading.value} class="h-500px w-full flex justify-center items-center" size={60} />
|
<Spin spinning={loading.value} class="flex-1 w-full flex justify-center items-center" size={60} />
|
||||||
) : (
|
) : (
|
||||||
<div class={`page-wrap relative ${isExpand.value ? 'expand' : ''}`}>
|
<section class={`page-wrap relative ${isExpand.value ? 'expand' : ''}`}>
|
||||||
<div class="fold-box cursor-pointer" onClick={() => (isExpand.value = true)}>
|
<div class="fold-box cursor-pointer" onClick={() => (isExpand.value = true)}>
|
||||||
<icon-menu-fold size={20} class="color-#55585F hover:color-#6D4CFE" />
|
<icon-menu-fold size={20} class="color-#55585F hover:color-#6D4CFE" />
|
||||||
</div>
|
</div>
|
||||||
@ -261,7 +261,7 @@ export default {
|
|||||||
onDeleteComment={onDeleteComment}
|
onDeleteComment={onDeleteComment}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</section>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
background: #fff;
|
||||||
.explore-detail-wrap {
|
.explore-detail-wrap {
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
width: 684px;
|
width: 684px;
|
||||||
|
|||||||
@ -50,10 +50,10 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{loading.value ? (
|
<section class="page-wrapper flex justify-center">
|
||||||
<Spin spinning={loading.value} class="h-500px w-full flex justify-center items-center" size={60} />
|
{loading.value ? (
|
||||||
) : (
|
<Spin spinning={loading.value} class="w-full flex justify-center items-center" size={60} />
|
||||||
<section class="page-wrapper flex justify-center">
|
) : (
|
||||||
<div class="explore-container">
|
<div class="explore-container">
|
||||||
<div class="explore-list-wrap pt-24px pb-28px">
|
<div class="explore-list-wrap pt-24px pb-28px">
|
||||||
<TextOverTips context={`${works.value[0]?.title}等${works.value.length}个文件`} class="mb-8px" />
|
<TextOverTips context={`${works.value[0]?.title}等${works.value.length}个文件`} class="mb-8px" />
|
||||||
@ -99,8 +99,8 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
)}
|
||||||
)}
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.page-wrapper {
|
.page-wrapper {
|
||||||
|
background: #fff;
|
||||||
min-height: calc(100vh - $navbar-height);
|
min-height: calc(100vh - $navbar-height);
|
||||||
.explore-container {
|
.explore-container {
|
||||||
width: 1200px;
|
width: 1200px;
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<a-form-item field="files">
|
||||||
|
<template #label>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="cts !color-#211F24 mr-4px">图片</span>
|
||||||
|
<span class="cts mr-8px !color-#939499">{{ `(${files.length ?? 0}/18)` }}</span>
|
||||||
|
<span class="cts !color-#939499">第一张为首图,支持拖拽排序</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<VueDraggable v-model="files" class="grid grid-cols-7 gap-y-8px" @end="handleChange" draggable=".group">
|
||||||
|
<div
|
||||||
|
v-for="(file, index) in files"
|
||||||
|
:key="file.url"
|
||||||
|
class="group relative cursor-move overflow-visible py-8px pr-8px"
|
||||||
|
>
|
||||||
|
<div class="group-container relative rounded-8px w-100px h-100px">
|
||||||
|
<img :src="file.url" class="object-cover w-full h-full border-1px border-#E6E6E8 rounded-8px" />
|
||||||
|
<icon-close-circle-fill
|
||||||
|
:size="16"
|
||||||
|
class="absolute top--8px right--8px cursor-pointer hidden color-#939499 hidden group-hover:block z-50"
|
||||||
|
@click="() => handleDeleteFile(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-upload
|
||||||
|
v-if="files.length < 18"
|
||||||
|
ref="uploadRef"
|
||||||
|
action="/"
|
||||||
|
draggable
|
||||||
|
:custom-request="(option) => emit('upload', option)"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.webp"
|
||||||
|
:show-file-list="false"
|
||||||
|
multiple
|
||||||
|
class="!flex !items-center"
|
||||||
|
:limit="18 - files.length"
|
||||||
|
>
|
||||||
|
<template #upload-button>
|
||||||
|
<div class="upload-box">
|
||||||
|
<icon-plus size="14" class="mb-16px color-#3C4043" />
|
||||||
|
<span class="cts !color-#211F24">上传图片</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-upload>
|
||||||
|
</VueDraggable>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const files = ref([]);
|
||||||
|
const uploadRef = ref(null);
|
||||||
|
|
||||||
|
const emit = defineEmits(['change', 'delete', 'upload']);
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
emit('change', files.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteFile = (index) => {
|
||||||
|
emit('delete', index);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.files,
|
||||||
|
(newVal) => {
|
||||||
|
files.value = newVal;
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.upload-box {
|
||||||
|
display: flex;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px dashed var(--Border-1, #d7d7d9);
|
||||||
|
background: var(--BG-200, #f2f3f5);
|
||||||
|
&:hover {
|
||||||
|
background: var(--Primary-1, #e6e6e8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -4,6 +4,7 @@ import { Form, FormItem, Input, Textarea, Upload, Message as AMessage, Button }
|
|||||||
import CommonSelect from '@/components/common-select';
|
import CommonSelect from '@/components/common-select';
|
||||||
import { VueDraggable } from 'vue-draggable-plus';
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
|
import ImgBox from './img-box';
|
||||||
|
|
||||||
import { formatFileSize, getVideoInfo, formatDuration, formatUploadSpeed } from '@/utils/tools';
|
import { formatFileSize, getVideoInfo, formatDuration, formatUploadSpeed } from '@/utils/tools';
|
||||||
import { getProjectList } from '@/api/all/propertyMarketing';
|
import { getProjectList } from '@/api/all/propertyMarketing';
|
||||||
@ -293,60 +294,9 @@ export default {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderImage = () => {
|
const handleImagesChange = (files) => {
|
||||||
return (
|
formData.value.files = cloneDeep(files);
|
||||||
<FormItem
|
onChange();
|
||||||
field="files"
|
|
||||||
v-slots={{
|
|
||||||
label: () => (
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="cts !color-#211F24 mr-4px">图片</span>
|
|
||||||
<span class="cts mr-8px !color-#939499">{`(${formData.value.files?.length ?? 0}/18)`}</span>
|
|
||||||
<span class="cts !color-#939499">第一张为首图,支持拖拽排序</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{/* 已上传的图片列表 */}
|
|
||||||
<VueDraggable v-model={formData.value.files} class="grid grid-cols-7 gap-y-8px">
|
|
||||||
{formData.value.files?.map((file, index) => (
|
|
||||||
<div key={index} class="group relative cursor-move overflow-visible py-8px pr-8px">
|
|
||||||
<div class="group-container relative rounded-8px w-100px h-100px">
|
|
||||||
<img src={file.url} class=" object-cover w-full h-full border-1px border-#E6E6E8 rounded-8px" />
|
|
||||||
<icon-close-circle-fill
|
|
||||||
size={16}
|
|
||||||
class="absolute top--8px right--8px cursor-pointer hidden color-#939499 hidden group-hover:block z-50"
|
|
||||||
onClick={() => handleDeleteFile(index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</VueDraggable>
|
|
||||||
{formData.value.files?.length < 18 && (
|
|
||||||
<Upload
|
|
||||||
ref={uploadRef}
|
|
||||||
action="/"
|
|
||||||
draggable
|
|
||||||
custom-request={uploadImage}
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.webp"
|
|
||||||
show-file-list={false}
|
|
||||||
multiple
|
|
||||||
limit={18 - formData.value.files?.length}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
'upload-button': () => (
|
|
||||||
<div class="upload-box">
|
|
||||||
<icon-plus size="14" class="mb-16px color-#3C4043" />
|
|
||||||
<span class="cts !color-#211F24">上传图片</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
</Upload>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
@ -392,7 +342,16 @@ export default {
|
|||||||
auto-size={{ minRows: 7, maxRows: 12 }}
|
auto-size={{ minRows: 7, maxRows: 12 }}
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
{isVideo.value ? renderVideo() : renderImage()}
|
{isVideo.value ? (
|
||||||
|
renderVideo()
|
||||||
|
) : (
|
||||||
|
<ImgBox
|
||||||
|
files={formData.value.files}
|
||||||
|
onChange={handleImagesChange}
|
||||||
|
onDelete={handleDeleteFile}
|
||||||
|
onUpload={uploadImage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* <FormItem label="所属项目" field="project_ids">
|
{/* <FormItem label="所属项目" field="project_ids">
|
||||||
<CommonSelect
|
<CommonSelect
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<a-form-item field="files">
|
||||||
|
<template #label>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="cts !color-#211F24 mr-4px">图片</span>
|
||||||
|
<span class="cts mr-8px !color-#939499">{{ `(${files.length ?? 0}/18)` }}</span>
|
||||||
|
<span class="cts !color-#939499">第一张为首图,支持拖拽排序</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<VueDraggable v-model="files" class="grid grid-cols-7 gap-y-8px" @end="handleChange" draggable=".group">
|
||||||
|
<div
|
||||||
|
v-for="(file, index) in files"
|
||||||
|
:key="file.url"
|
||||||
|
class="group relative cursor-move overflow-visible py-8px pr-8px"
|
||||||
|
>
|
||||||
|
<div class="group-container relative rounded-8px w-100px h-100px">
|
||||||
|
<img :src="file.url" class="object-cover w-full h-full border-1px border-#E6E6E8 rounded-8px" />
|
||||||
|
<icon-close-circle-fill
|
||||||
|
:size="16"
|
||||||
|
class="absolute top--8px right--8px cursor-pointer hidden color-#939499 hidden group-hover:block z-50"
|
||||||
|
@click="() => handleDeleteFile(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-upload
|
||||||
|
v-if="files.length < 18"
|
||||||
|
ref="uploadRef"
|
||||||
|
action="/"
|
||||||
|
draggable
|
||||||
|
:custom-request="(option) => emit('upload', option)"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.webp"
|
||||||
|
:show-file-list="false"
|
||||||
|
multiple
|
||||||
|
class="!flex !items-center"
|
||||||
|
:limit="18 - files.length"
|
||||||
|
>
|
||||||
|
<template #upload-button>
|
||||||
|
<div class="upload-box">
|
||||||
|
<icon-plus size="14" class="mb-16px color-#3C4043" />
|
||||||
|
<span class="cts !color-#211F24">上传图片</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-upload>
|
||||||
|
</VueDraggable>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const files = ref([]);
|
||||||
|
const uploadRef = ref(null);
|
||||||
|
|
||||||
|
const emit = defineEmits(['change', 'delete', 'upload']);
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
emit('change', files.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteFile = (index) => {
|
||||||
|
emit('delete', index);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.files,
|
||||||
|
(newVal) => {
|
||||||
|
files.value = newVal;
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.upload-box {
|
||||||
|
display: flex;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px dashed var(--Border-1, #d7d7d9);
|
||||||
|
background: var(--BG-200, #f2f3f5);
|
||||||
|
&:hover {
|
||||||
|
background: var(--Primary-1, #e6e6e8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -4,6 +4,7 @@ import { Form, FormItem, Input, Textarea, Upload, Message as AMessage, Button }
|
|||||||
import CommonSelect from '@/components/common-select';
|
import CommonSelect from '@/components/common-select';
|
||||||
import { VueDraggable } from 'vue-draggable-plus';
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
|
import ImgBox from './img-box';
|
||||||
|
|
||||||
import { formatFileSize, getVideoInfo, formatDuration, formatUploadSpeed } from '@/utils/tools';
|
import { formatFileSize, getVideoInfo, formatDuration, formatUploadSpeed } from '@/utils/tools';
|
||||||
import { getProjectList } from '@/api/all/propertyMarketing';
|
import { getProjectList } from '@/api/all/propertyMarketing';
|
||||||
@ -293,60 +294,9 @@ export default {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderImage = () => {
|
const handleImagesChange = (files) => {
|
||||||
return (
|
formData.value.files = cloneDeep(files);
|
||||||
<FormItem
|
onChange();
|
||||||
field="files"
|
|
||||||
v-slots={{
|
|
||||||
label: () => (
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="cts !color-#211F24 mr-4px">图片</span>
|
|
||||||
<span class="cts mr-8px !color-#939499">{`(${formData.value.files?.length ?? 0}/18)`}</span>
|
|
||||||
<span class="cts !color-#939499">第一张为首图,支持拖拽排序</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{/* 已上传的图片列表 */}
|
|
||||||
<VueDraggable v-model={formData.value.files} class="grid grid-cols-7 gap-y-8px">
|
|
||||||
{formData.value.files?.map((file, index) => (
|
|
||||||
<div key={index} class="group relative cursor-move overflow-visible py-8px pr-8px">
|
|
||||||
<div class="group-container relative rounded-8px w-100px h-100px">
|
|
||||||
<img src={file.url} class=" object-cover w-full h-full border-1px border-#E6E6E8 rounded-8px" />
|
|
||||||
<icon-close-circle-fill
|
|
||||||
size={16}
|
|
||||||
class="absolute top--8px right--8px cursor-pointer hidden color-#939499 hidden group-hover:block z-50"
|
|
||||||
onClick={() => handleDeleteFile(index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</VueDraggable>
|
|
||||||
{formData.value.files?.length < 18 && (
|
|
||||||
<Upload
|
|
||||||
ref={uploadRef}
|
|
||||||
action="/"
|
|
||||||
draggable
|
|
||||||
custom-request={uploadImage}
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.webp"
|
|
||||||
show-file-list={false}
|
|
||||||
multiple
|
|
||||||
limit={18 - formData.value.files?.length}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
'upload-button': () => (
|
|
||||||
<div class="upload-box">
|
|
||||||
<icon-plus size="14" class="mb-16px color-#3C4043" />
|
|
||||||
<span class="cts !color-#211F24">上传图片</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
</Upload>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
@ -392,7 +342,16 @@ export default {
|
|||||||
auto-size={{ minRows: 7, maxRows: 12 }}
|
auto-size={{ minRows: 7, maxRows: 12 }}
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
{isVideo.value ? renderVideo() : renderImage()}
|
{isVideo.value ? (
|
||||||
|
renderVideo()
|
||||||
|
) : (
|
||||||
|
<ImgBox
|
||||||
|
files={formData.value.files}
|
||||||
|
onChange={handleImagesChange}
|
||||||
|
onDelete={handleDeleteFile}
|
||||||
|
onUpload={uploadImage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* <FormItem label="所属项目" field="project_ids">
|
{/* <FormItem label="所属项目" field="project_ids">
|
||||||
<CommonSelect
|
<CommonSelect
|
||||||
|
|||||||
Reference in New Issue
Block a user