Files
guofu-admin/src/components/SelectFile/index.vue
2024-10-19 10:38:52 +08:00

165 lines
4.2 KiB
Vue

<template>
<a-space style="display: flex;
align-items: center;
justify-content: flex-start;flex-wrap: wrap">
<template v-for="(item, index) in data" :key="index">
<div v-if="type === 'video' || item.url.includes('.mp4')" class="relative cursor-pointer" @click="open(item.url)">
<img
:src="item.url + '?x-oss-process=video/snapshot,t_2000,f_jpg,w_200,h_200'"
style="width: 80px; height: 80px"
/>
<div class="absolute" style="left: 30px; top: 30px">
<play-circle-outlined style="font-size: 20px; color:white"/>
</div>
</div>
<a-tag :key="item.url" closable @close="onDeleteItem(index)"
@click.native="open(item.url)" style="cursor: pointer"
v-else-if="type && ['audio', 'file'].includes(type)"> {{ item.url }}
</a-tag>
<div class="image-upload-item bg-gray-300" v-else>
<a-image-preview-group>
<a-image
:width="width"
:height="width"
style="border: 1px dashed var(--grey-7)"
:src="item.url"
/>
<a class="image-upload-close" @click="onDeleteItem(index)">
<CloseOutlined/>
</a>
</a-image-preview-group>
</div>
</template>
<template v-if="type === 'video'">
<a-button type="primary"
@click="openEdit"
v-if="data?.length < limit">
选择视频
</a-button>
</template>
<template v-else-if="type === 'audio'">
<a-button type="primary"
@click="openEdit"
v-if="data?.length < limit">
选择音频
</a-button>
</template>
<template v-else>
<a-button
@click="openEdit"
v-if="data?.length < limit || limit === -1"
class="select-picture-btn ele-text-placeholder"
>
<PlusOutlined/>
</a-button>
</template>
</a-space>
<!-- 选择弹窗 -->
<SelectData
v-model:visible="showEdit"
:data="current"
:title="placeholder"
:type="type"
@done="onChange"
/>
</template>
<script lang="ts" setup>
import {PlusOutlined, CloseOutlined, PlayCircleOutlined} from '@ant-design/icons-vue';
import {ref} from 'vue';
import SelectData from './components/select-data.vue';
import {FileRecord} from '@/api/system/file/model';
const props = withDefaults(
defineProps<{
value?: any;
data?: any[];
width?: number;
type?: string;
limit?: number;
placeholder?: string;
index?: number;
}>(),
{
placeholder: '请选择数据',
width: 80,
limit: 1
}
);
const emit = defineEmits<{
(e: 'done', data: FileRecord): void;
(e: 'del', index: number): void;
(e: 'clear'): void;
}>();
// 是否显示编辑弹窗
const showEdit = ref(false);
// 当前编辑数据
const current = ref<FileRecord | null>(null);
/* 打开编辑弹窗 */
const openEdit = (row?: FileRecord) => {
current.value = row ?? null;
showEdit.value = true;
};
const onChange = (row) => {
row.index = props.index;
emit('done', row);
};
const onDeleteItem = (index: number) => {
emit('del', index);
};
const open = (url: string) => {
if (['docx', 'doc', 'xlsx', 'xls', 'pdf'].includes(url.split('.').pop()!)) {
window.open(`https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`);
} else window.open(url)
}
</script>
<style lang="less" scoped>
.select-picture-btn {
background-color: var(--grey-9);
border: 1px dashed var(--border-color-base);
width: 80px;
height: 80px;
font-size: 16px;
}
//.ant-image-img {
// width: 100px !important;
// height: 100px !important;
//}
.image-upload-item {
position: relative;
}
.image-upload-close {
width: 18px;
height: 18px;
color: rgb(255, 255, 255);
font-size: 10px;
border-bottom-left-radius: 18px;
border-top-right-radius: 2px;
background: rgba(0, 0, 0, 0.6);
position: absolute;
top: 1px;
right: 1px;
line-height: 1;
box-sizing: border-box;
padding: 2px 0 0 5px;
transition: background-color 0.2s ease-in-out 0s;
cursor: pointer;
z-index: 2;
//display: flex;
//justify-content: center;
//align-items: center;
}
.image-upload-close:hover {
background-color: var(--red-6);
}
</style>