Files
Docker/WebVue/src/components/basic/OperatorStation.vue
T
2026-09-08 13:55:01 +08:00

258 lines
7.4 KiB
Vue

<template>
<div class="operator-station">
<div class="operator-group main-actions">
<a-tooltip title="新增文件夹">
<a-button type="primary" v-if="canCreate" :icon="h(FolderAddOutlined)"
@click="$emit('create-folder')">新增</a-button>
</a-tooltip>
<a-tooltip title="上传文件">
<a-button type="primary" v-if="canCreate" :icon="h(UploadOutlined)" @click="triggerUpload">上传</a-button>
</a-tooltip>
</div>
<a-divider type="vertical" v-if="hasSelection" />
<div class="operator-group selection-actions" v-if="hasSelection">
<template v-if="!isDirectorySelected && isSingleItem">
<a-tooltip title="下载">
<a-button type="text" :icon="h(DownloadOutlined)" :disabled="!canAmend" @click="onDownload" >下载</a-button>
</a-tooltip>
<a-tooltip title="共享">
<a-button type="text" :icon="h(ShareAltOutlined)" @click="onShare">共享</a-button>
</a-tooltip>
<a-tooltip :title="publishTooltip">
<a-button type="text" :icon="h(NotificationOutlined)" @click="onPublish" >{{ publishTooltip }}</a-button>
</a-tooltip>
<a-tooltip :title="previewTooltip">
<a-button type="text" :icon="h(UnorderedListOutlined)" @click="onViewPreview" >{{ previewTooltip }}</a-button>
</a-tooltip>
<template v-if="isSingleVideo">
<a-tooltip title="播放">
<a-button type="text" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })" @click="onPlayVideo" >播放</a-button>
</a-tooltip>
</template>
<template v-if="isSingleAudio">
<a-tooltip v-if="selectedItem.IsPlay != 'Y'" title="播放">
<a-button type="text" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })" @click="onPlayAudio" >播放</a-button>
</a-tooltip>
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'" title="暂停">
<a-button type="text" :icon="h(PauseCircleOutlined)" @click="onPauseAudio" >暂停</a-button>
</a-tooltip>
<a-tooltip v-else title="继续">
<a-button type="text" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })" @click="onContinueAudio" >继续</a-button>
</a-tooltip>
</template>
</template>
</div>
<a-divider type="vertical" v-if="hasSelection" />
<div class="operator-group more-actions" v-if="hasSelection">
<a-dropdown>
<a-button>
更多
<DownOutlined />
</a-button>
<template #overlay>
<a-menu>
<a-menu-item key="preview" v-if="isImage(selectedOrderKey) && isSingleItem" :disabled="!canAmend" @click="$emit('preview', selectedItems)">
<EyeOutlined /> 预览
</a-menu-item>
<a-menu-item key="rename" v-if="isSingleItem" :disabled="!canAmend" @click="$emit('rename', selectedItems)">
<EditOutlined /> 重命名
</a-menu-item>
<a-menu-item key="move" v-if="isSingleItem" :disabled="!canView" @click="$emit('move', selectedItems)">
<ScissorOutlined /> 移动
</a-menu-item>
<a-menu-divider />
<a-menu-item key="delete":disabled="!canDelete" @click="$emit('delete', selectedItems)">
<DeleteOutlined /> 删除
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
<div style="display: none">
<a-upload v-if="canCreate" v-model:file-list="fileList" name="file" :before-upload="onBeforeUpload"
:headers="headers" :show-upload-list="false" :action="uploadUrl" ref="uploadRef">
</a-upload>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, h } from "vue";
import {
UploadOutlined,
FolderAddOutlined,
DownloadOutlined,
ShareAltOutlined,
NotificationOutlined,
UnorderedListOutlined,
PlayCircleOutlined,
PauseCircleOutlined,
EyeOutlined,
EditOutlined,
ScissorOutlined,
DeleteOutlined,
DownOutlined,
} from "@ant-design/icons-vue";
import { DmsFileUploadViewDisplayData } from "@/data/auto/dmsFileUploadViewDisplayData";
import type { UploadProps } from "ant-design-vue";
const props = defineProps<{
selectedItems: DmsFileUploadViewDisplayData[];
uploadUrl: string;
headers: any;
canCreate: boolean;
canAmend: boolean;
canDelete: boolean;
canView: boolean;
}>();
const emit = defineEmits([
"create-folder",
"before-upload",
"download",
"share",
"publish",
"view-preview",
"play-video",
"play-audio",
"pause-audio",
"continue-audio",
"preview",
"rename",
"move",
"delete",
]);
const fileList = ref<UploadProps["fileList"]>([]);
const uploadRef = ref<any>(null);
const hasSelection = computed(() => props.selectedItems.length > 0);
const isDirectorySelected = computed(() =>
props.selectedItems.some((s) => s.IsDirectoryIndc == "Y"),
);
const isSingleItem = computed(() => props.selectedItems.length === 1);
const selectedItem = computed(() => {
return props.selectedItems[0] || ({} as DmsFileUploadViewDisplayData);
});
const selectedOrderKey = computed(() => {
return selectedItem.value?.OrderKey || selectedItem.value?.OrgFileName || "";
});
const isImage = (key: string) => {
if (!key) return false;
return /\.(png|jpe?g|gif|bmp|webp)$/i.test(key);
};
const isVideo = (key: string) => {
if (!key) return false;
return /\.(mp4|m3u8|rm|mpeg|mov|wmv|avi)$/i.test(key);
};
const isAudio = (key: string) => {
if (!key) return false;
return /\.(mp3|wav|flac|aac|ogg|wma)$/i.test(key);
};
const isSingleVideo = computed(() => {
return isSingleItem.value && isVideo(selectedOrderKey.value);
});
const isSingleAudio = computed(() => {
return isSingleItem.value && isAudio(selectedOrderKey.value);
});
const publishTooltip = computed(() => {
if (isImage(selectedOrderKey.value)) return "发布相册";
if (isVideo(selectedOrderKey.value)) return "发布影视专辑";
if (isAudio(selectedOrderKey.value)) return "发布音乐专辑";
return "发布";
});
const previewTooltip = computed(() => {
if (isImage(selectedOrderKey.value)) return "相册展览";
if (isVideo(selectedOrderKey.value)) return "影视厅播放";
if (isAudio(selectedOrderKey.value)) return "音乐厅播放";
return "预览";
});
const triggerUpload = () => {
uploadRef.value?.$el?.querySelector("input")?.click();
};
const onBeforeUpload: UploadProps["beforeUpload"] = (file) => {
emit("before-upload", file);
return false;
};
const onDownload = () => {
emit("download", props.selectedItems);
};
const onShare = () => {
emit("share", props.selectedItems);
};
const onPublish = () => {
emit("publish", props.selectedItems);
};
const onViewPreview = () => {
emit("view-preview", props.selectedItems);
};
const onPlayVideo = () => {
emit("play-video", selectedItem.value);
};
const onPlayAudio = () => {
emit("play-audio", selectedItem.value);
};
const onPauseAudio = () => {
emit("pause-audio", selectedItem.value);
};
const onContinueAudio = () => {
emit("continue-audio", selectedItem.value);
};
</script>
<style scoped>
.operator-station {
display: flex;
align-items: center;
padding: 6px 12px;
background: #fafafa;
border-bottom: 1px solid #e8e8e8;
gap: 8px;
flex-wrap: wrap;
}
.operator-group {
display: flex;
align-items: center;
gap: 4px;
}
.main-actions :deep(.ant-btn) {
height: 32px;
}
.selection-actions :deep(.ant-btn) {
padding: 4px 8px;
font-size: 16px;
}
</style>