1381 lines
42 KiB
Vue
1381 lines
42 KiB
Vue
<template>
|
||
<a-spin size="large" :spinning="loading" :tip="spinTip">
|
||
<div class="dms-file-enquiry">
|
||
<Toolbar :path-stack="pathStack" :root-path="rootPath" @go-top="onGoTop" @go-back="onGoBack"
|
||
@refresh="onReSearch" @search="onSearchByName" @breadcrumb-click="onBreadcrumbClick" />
|
||
|
||
<OperatorStation ref="operatorStationRef" :selected-items="keys" :upload-url="uploadUrl" :headers="headers"
|
||
:can-create="canCreate" :can-amend="canAmend" :can-delete="canDelete" :can-view="canView"
|
||
:resolve-file-path="resolveUploadFilePath" multiple @create-folder="onCreate" @upload-start="onUploadStart"
|
||
@upload-progress="onUploadProgress" @upload-success="onUploadSuccess" @upload-complete="onUploadComplete"
|
||
@upload-interrupted="onUploadInterrupted" @upload-error="onUploadError" @download="onDownloadSelected"
|
||
@share="onShareSelected" @publish="onPublishSelected" @view-preview="onViewPreviewSelected"
|
||
@play-video="onUrlVideoPlayItem" @play-audio="onPlayAudioItem" @pause-audio="onPauseAudio"
|
||
@continue-audio="onContinueAudio" @preview="onPreviewSelected" @rename="onAmendSelected" @move="onMoveSelected"
|
||
@delete="onDeleteSelected" />
|
||
|
||
<MyComputer :datas="datas" v-model:selected-keys="keys" @select-change="onSelectChange"
|
||
@open-folder="onOpenFolder" @open-file="onOpenFile" @preview-image="onPreviewOrgFile" />
|
||
</div>
|
||
|
||
<a-image :width="1024" :style="{ display: 'none' }" :preview="{
|
||
visible,
|
||
onVisibleChange: setPicVisible,
|
||
}" :src="imageSrc" />
|
||
<dmsFolder @on-submit="onReload" @submit-start="loading = true" @submit-end="loading = false"></dmsFolder>
|
||
<VideoPlayModal v-model:open="videoPlayModal" :videos="videoPlayList" :start-index="videoPlayIndex"
|
||
:title="videoPlayTitle" :fullscreen="width < 640" />
|
||
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
||
@ok="handleSelectShare">
|
||
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
||
</dragModal>
|
||
<dragModal v-model:open="showModalPublishPhoto" width="60%" title="相册专辑查询" :mask-closable="false"
|
||
:fullscreen="width < 640" @ok="handleSelectPublishPhoto">
|
||
<PublishPhotoEnquiry ref="publishPhotoEnquiry"></PublishPhotoEnquiry>
|
||
</dragModal>
|
||
<dragModal v-model:open="showModalPublishAudio" width="60%" title="音乐专辑查询" :mask-closable="false"
|
||
:fullscreen="width < 640" @ok="handleSelectPublishAudio">
|
||
<PublishAudioEnquiry ref="publishAudioEnquiry"></PublishAudioEnquiry>
|
||
</dragModal>
|
||
<dragModal v-model:open="showModalPublishVideo" width="60%" title="影视专辑查询" :mask-closable="false"
|
||
:fullscreen="width < 640" @ok="handleSelectPublishVideo">
|
||
<PublishVideoEnquiry ref="publishVideoEnquiry"></PublishVideoEnquiry>
|
||
</dragModal>
|
||
|
||
<!-- 上传中断:问用户要不要从断点续传 -->
|
||
<a-modal v-model:open="showResumeModal" title="上传中断" :mask-closable="false" :closable="false" ok-text="继续上传"
|
||
cancel-text="放弃" @ok="onResumeUpload" @cancel="onDiscardUpload">
|
||
<p>「{{ interruptedInfo.fileName }}」已上传 {{ interruptedInfo.uploaded }}/{{ interruptedInfo.total }} 片。</p>
|
||
<p>网络似乎中断了,是否从断点继续上传?</p>
|
||
<p style="color: #8a919f; font-size: 12px">
|
||
提示:刷新页面会丢失已上传的分片,那之后只能重新选择文件从头上传。
|
||
</p>
|
||
</a-modal>
|
||
</a-spin>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { reactive, onMounted, onUnmounted, ref, unref, h, provide } from "vue";
|
||
import { BindOption } from "@/data/custom/bindOption";
|
||
import { SelectOption } from "@/data/auto/selectOption";
|
||
import { DmsFileUploadViewDisplayData } from "@/data/auto/dmsFileUploadViewDisplayData";
|
||
import { SearchFilter } from "@/data/auto/searchFilter";
|
||
import dmsFileService from "@/service/master/dmsFileService";
|
||
import publishPhotoService from "@/service/master/publishPhotoService";
|
||
import publishAudioService from "@/service/master/publishAudioService";
|
||
import { DmsFileSearchCriteria } from "@/data/auto/dmsFileSearchCriteria";
|
||
import dragModal from "@/components/basic/DragModal.vue";
|
||
import DmsFileShareModal from "./DmsFileShareModal.vue";
|
||
import PublishPhotoEnquiry from "./PublishPhotoEnquiry.vue";
|
||
import PublishAudioEnquiry from "./PublishAudioEnquiry.vue";
|
||
import PublishVideoEnquiry from "./PublishVideoEnquiry.vue";
|
||
import { FamilyGroupFolderEntity } from "@/data/auto/familyGroupFolderEntity";
|
||
import {
|
||
PermissionContext,
|
||
usePermissionContext,
|
||
} from "@/hooks/PermissionContext";
|
||
import { useRoute, useRouter } from "vue-router";
|
||
import { useBindOption } from "@/hooks/useBindOption";
|
||
import { SearchFilterOperatorPolicy } from "@/data/custom/searchFilterOperatorPolicy";
|
||
import { SearchFilterTypePolicy } from "@/data/custom/searchFilterTypePolicy";
|
||
import { notification } from "ant-design-vue";
|
||
import { SearchCriteriaResultData } from "@/data/auto/searchCriteriaResultData";
|
||
import dmsFolder from "./DmsFolderModal.vue";
|
||
import { useLoginProfileStore } from "@/store/modules/loginProfile";
|
||
import { WebSitePolicy } from "@/policy/custom/webSitePolicy";
|
||
import { orderBy } from "lodash-es";
|
||
import { Howl } from "howler";
|
||
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
||
import publishVideoService from "@/service/master/publishVideoService";
|
||
import { useWindowSize } from "@vueuse/core";
|
||
import { request } from "@/utils/request";
|
||
import fileTypePolicy from "@/policy/custom/fileTypePolicy";
|
||
import { PublishAudioEntity } from "@/data/auto/publishAudioEntity";
|
||
import { FamilyFolderFavoriteViewEntity } from "@/data/auto/familyFolderFavoriteViewEntity";
|
||
import { DmsFileEntity } from "@/data/auto/dmsFileEntity";
|
||
import { PublishData } from "@/data/auto/publishData";
|
||
import { PublishPhotoEntity } from "@/data/auto/publishPhotoEntity";
|
||
|
||
import MyComputer from "@/components/basic/MyComputer.vue";
|
||
import Toolbar from "@/components/basic/Toolbar.vue";
|
||
import OperatorStation from "@/components/basic/OperatorStation.vue";
|
||
import VideoPlayModal from "@/components/basic/VideoPlayModal.vue";
|
||
import type { VideoItem } from "@/components/basic/VideoPlayer.vue";
|
||
import { PublishVideoDetailDisplayData } from "@/data/auto/publishVideoDetailDisplayData";
|
||
|
||
interface BreadcrumbItem {
|
||
value: string;
|
||
displayName: string;
|
||
}
|
||
|
||
const { width } = useWindowSize();
|
||
|
||
const showModalShare = ref<boolean>(false);
|
||
const sharedFileRecords = ref<DmsFileUploadViewDisplayData[]>([]);
|
||
const showModalPublishPhoto = ref<boolean>(false);
|
||
const showModalPublishAudio = ref<boolean>(false);
|
||
const showModalPublishVideo = ref<boolean>(false);
|
||
const spinTip = ref<string>("加载中...");
|
||
const loading = ref<boolean>(false);
|
||
const canView = ref<boolean>(false);
|
||
const canAmend = ref<boolean>(false);
|
||
const canDelete = ref<boolean>(false);
|
||
const canCreate = ref<boolean>(false);
|
||
const rootPath = ref<string>("");
|
||
const imageSrc = ref<string>("");
|
||
const route = useRoute();
|
||
const router = useRouter();
|
||
const previousFilePath = ref<string>("");
|
||
|
||
/**
|
||
* 上传地址:
|
||
* 开发环境指向本地服务,生产环境指向同源根路径。
|
||
* 注意 WebApiRoot 生产环境为 "/",必须先去掉结尾斜杠再拼接,
|
||
* 否则会得到 "//DmsFile/UploadDmsFile",被浏览器当作协议相对地址(host = dmsfile)而导致解析失败。
|
||
*/
|
||
const uploadUrl = ref<string>(
|
||
`${(process.env.NODE_ENV === "development"
|
||
? WebSitePolicy.WebApiRootDev
|
||
: WebSitePolicy.WebApiRoot
|
||
).replace(/\/$/, "")
|
||
}/DmsFile/UploadDmsFile`
|
||
);
|
||
|
||
const currFilePath = ref<string>("");
|
||
|
||
const headers = ref({
|
||
Authorization: useLoginProfileStore().getToken(),
|
||
"Content-Type": "multipart/form-data",
|
||
FilePath: currFilePath.value,
|
||
});
|
||
|
||
const bindOptions = ref<BindOption[]>([]);
|
||
const datas = ref<DmsFileUploadViewDisplayData[]>([]);
|
||
const pagingParams = ref<PagingParams>({ pageSize: 999999, page: 1 });
|
||
const result = ref<SearchCriteriaResultData>(new SearchCriteriaResultData());
|
||
|
||
const currentFilter = ref<SearchFilter[]>([]);
|
||
const isSearched = ref<boolean>(false);
|
||
const currentSearchCriteria = ref<DmsFileSearchCriteria>(
|
||
new DmsFileSearchCriteria(),
|
||
);
|
||
|
||
const keys = ref<DmsFileUploadViewDisplayData[]>([]);
|
||
const dmsFolderModal = ref<boolean>(false);
|
||
const dmsFolderTitle = ref<string>("新建文件夹");
|
||
const dmsFolderIsRename = ref<boolean>(false);
|
||
const dmsFolderIsMove = ref<boolean>(false);
|
||
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
||
const videoPlayModal = ref<boolean>(false);
|
||
const videoPlayList = ref<VideoItem[]>([]);
|
||
const videoPlayIndex = ref<number>(0);
|
||
const videoPlayTitle = ref<string>("");
|
||
const visible = ref<boolean>(false);
|
||
|
||
const pathStack = ref<BreadcrumbItem[]>([]);
|
||
|
||
interface PublishPhotoEnquiry {
|
||
keys: PublishPhotoEntity[];
|
||
}
|
||
const publishPhotoEnquiry = ref<PublishPhotoEnquiry | null>(null);
|
||
|
||
interface PublishAudioEnquiry {
|
||
keys: PublishAudioEntity[];
|
||
}
|
||
const publishAudioEnquiry = ref<PublishAudioEnquiry | null>(null);
|
||
|
||
interface PublishVideoEnquiry {
|
||
keys: PublishVideoEntity[];
|
||
}
|
||
const publishVideoEnquiry = ref<PublishVideoEnquiry | null>(null);
|
||
|
||
interface ShareEnquiry {
|
||
keys: FamilyFolderFavoriteViewEntity[];
|
||
}
|
||
const shareEnquiry = ref<ShareEnquiry | null>(null);
|
||
|
||
const sound = ref();
|
||
|
||
const toUploadView = (r: Record<string, any>): DmsFileUploadViewDisplayData =>
|
||
r as DmsFileUploadViewDisplayData;
|
||
|
||
onUnmounted(() => {
|
||
sound.value?.stop();
|
||
clearRefreshTimers();
|
||
stopTranscodeTip();
|
||
});
|
||
|
||
const play = (src: string) => {
|
||
sound.value?.stop();
|
||
if (!src || src == undefined || src == "") {
|
||
return;
|
||
}
|
||
|
||
sound.value = new Howl({
|
||
src: src,
|
||
volume: 0.5,
|
||
autoplay: true,
|
||
loop: false,
|
||
html5: true,
|
||
preload: true,
|
||
onend: () => {
|
||
datas.value.forEach((element) => {
|
||
element.IsPlay = "";
|
||
});
|
||
},
|
||
});
|
||
|
||
sound.value.play();
|
||
};
|
||
|
||
const onPauseAudio = (record: DmsFileUploadViewDisplayData) => {
|
||
record.IsPause = "Y";
|
||
sound.value?.pause();
|
||
};
|
||
|
||
const onContinueAudio = (record: DmsFileUploadViewDisplayData) => {
|
||
record.IsPause = "";
|
||
sound.value?.play();
|
||
};
|
||
|
||
const onPlayAudio = (record: DmsFileUploadViewDisplayData) => {
|
||
datas.value.forEach((element) => {
|
||
if (element.FileId == record.FileId && element.IsPlay == "Y") {
|
||
element.IsPlay = "";
|
||
} else if (
|
||
element.FileId == record.FileId &&
|
||
(element.IsPlay == "" ||
|
||
element.IsPlay == null ||
|
||
element.IsPlay == undefined)
|
||
) {
|
||
element.IsPlay = "Y";
|
||
} else {
|
||
element.IsPlay = "";
|
||
}
|
||
record.IsPause = "";
|
||
});
|
||
|
||
if (record.IsPlay == "") {
|
||
sound.value?.stop();
|
||
return;
|
||
}
|
||
|
||
play(record.Url);
|
||
};
|
||
|
||
//================provide================
|
||
provide("dmsFolderModal", dmsFolderModal);
|
||
provide("dmsFolderTitle", dmsFolderTitle);
|
||
provide("dmsFolderIsRename", dmsFolderIsRename);
|
||
provide("dmsFolderIsMove", dmsFolderIsMove);
|
||
provide("DmsFileEntity", entity);
|
||
provide("isModalPublishVideo", showModalPublishVideo);
|
||
provide("isModalPublishAudio", showModalPublishAudio);
|
||
provide("isModalPublishPhoto", showModalPublishPhoto);
|
||
//================provide================
|
||
|
||
defineExpose({
|
||
keys,
|
||
});
|
||
|
||
onMounted(async () => {
|
||
let pContext: PermissionContext = usePermissionContext();
|
||
canView.value = pContext.canView(route.meta.permission as string);
|
||
canAmend.value = pContext.canAmend(route.meta.permission as string);
|
||
canDelete.value = pContext.canDelete(route.meta.permission as string);
|
||
canCreate.value = pContext.canCreate(route.meta.permission as string);
|
||
|
||
await initBindOption();
|
||
|
||
pathStack.value = [{ value: rootPath.value, displayName: "我的云盘" }];
|
||
|
||
onSearchByFilePath(rootPath.value);
|
||
});
|
||
|
||
/** 解析上传目标文件夹(DMS 当前路径) */
|
||
const resolveUploadFilePath = () => {
|
||
const bindOption = bindOptions.value.filter(
|
||
(x) => x.BindValue == DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
)[0];
|
||
return bindOption?.Value || currFilePath.value;
|
||
};
|
||
|
||
/** 本次上传的是否是视频:只有视频才需要转码/截图 */
|
||
const uploadingVideo = ref<boolean>(false);
|
||
|
||
/**
|
||
* "视频转码中 x%" 提示。
|
||
*
|
||
* 最后一片发出去后,服务端要先 ffmpeg 截封面(要解码一段视频,最多 25 秒)才返回,
|
||
* 这段时间前端进度停在 99%/100% 一动不动,看起来像卡死。
|
||
* 这里用一个按时间推进的估算进度(与后端 25 秒上限对齐,最高 99%)告诉用户还在处理。
|
||
*/
|
||
const TRANSCODE_MAX_MS = 25000;
|
||
let transcodeTimer = 0;
|
||
|
||
const startTranscodeTip = () => {
|
||
if (transcodeTimer) return;
|
||
const startAt = Date.now();
|
||
spinTip.value = "预览10秒视频转码中 0%";
|
||
transcodeTimer = window.setInterval(() => {
|
||
const ratio = Math.min(0.99, (Date.now() - startAt) / TRANSCODE_MAX_MS);
|
||
spinTip.value = `预览10秒视频转码中 ${Math.round(ratio * 100)}%`;
|
||
}, 300);
|
||
};
|
||
|
||
const stopTranscodeTip = () => {
|
||
if (!transcodeTimer) return;
|
||
clearInterval(transcodeTimer);
|
||
transcodeTimer = 0;
|
||
};
|
||
|
||
const onUploadStart = (file: File) => {
|
||
loading.value = true;
|
||
uploadingVideo.value = !!file && fileTypePolicy.isVideo(file?.name || "");
|
||
};
|
||
|
||
const onUploadProgress = (payload: { text?: string; percent?: number }) => {
|
||
// 99%/100% 之后就是服务端转码阶段,换成转码提示,别让用户以为卡住了
|
||
if (uploadingVideo.value && (payload?.percent ?? 0) >= 99) {
|
||
startTranscodeTip();
|
||
return;
|
||
}
|
||
// 进度回到低处说明开始传下一个文件了,转码提示到此为止
|
||
stopTranscodeTip();
|
||
spinTip.value = payload?.text || "上传中...";
|
||
};
|
||
|
||
/** 单个文件传完:这里不刷新,等一批都传完再统一刷,避免选了多个文件反复刷列表 */
|
||
const onUploadSuccess = () => {
|
||
// 字节已传完,服务端还在合并分片 + ffmpeg 截图/转码
|
||
if (uploadingVideo.value) {
|
||
startTranscodeTip();
|
||
return;
|
||
}
|
||
spinTip.value = "上传完成,等待服务端处理...";
|
||
};
|
||
|
||
/** 上传后延迟刷新的定时器,离开页面/重新开始时清掉,避免野刷新 */
|
||
let refreshTimers: number[] = [];
|
||
const clearRefreshTimers = () => {
|
||
refreshTimers.forEach((t) => clearTimeout(t));
|
||
refreshTimers = [];
|
||
};
|
||
|
||
/**
|
||
* 一批文件全部传完:给后端留点时间合并分片,文件越多等得越久。
|
||
* 视频封面(jpg)由 ffmpeg 生成、可能比合并更慢,所以首刷之后再补刷两次——
|
||
* 每次查询服务端都会重新拼 ?v=,src 变了 <img> 才会重新请求,封面就能补上来。
|
||
*/
|
||
const onUploadComplete = (payload: { count?: number }) => {
|
||
const count = payload?.count ?? 1;
|
||
const sec = 2500 + (count - 1) * 1000;
|
||
// 本次是不是视频:只有视频才需要补刷和转码提示
|
||
const isVideo = uploadingVideo.value;
|
||
// 视频场景由转码提示接管文案,等首刷完成后再切回"加载中..."
|
||
if (!isVideo) spinTip.value = "加载中...";
|
||
clearRefreshTimers();
|
||
|
||
refreshTimers.push(
|
||
window.setTimeout(() => {
|
||
// 列表已经刷出来了,转码提示到此为止
|
||
stopTranscodeTip();
|
||
uploadingVideo.value = false;
|
||
onReSearch();
|
||
loading.value = false;
|
||
}, sec),
|
||
);
|
||
|
||
// 只有视频才补刷:封面(jpg)是服务端 ffmpeg 异步生成的,首刷时可能还没落盘;
|
||
// 每次查询服务端都会重新拼 ?v=,src 变了 <img> 才会重新请求,封面就能补上来。
|
||
// 图片/音频/普通文件上传后文件已经就绪,一次刷新就够,多刷纯属浪费。
|
||
if (isVideo) {
|
||
refreshTimers.push(window.setTimeout(onReSearch, sec + 3000));
|
||
refreshTimers.push(window.setTimeout(onReSearch, sec + 6000));
|
||
}
|
||
};
|
||
|
||
/** 中断时的断点信息,弹窗里展示用 */
|
||
const interruptedInfo = ref<{ fileName: string; uploaded: number; total: number }>({
|
||
fileName: "",
|
||
uploaded: 0,
|
||
total: 0,
|
||
});
|
||
const showResumeModal = ref<boolean>(false);
|
||
const operatorStationRef = ref<any>(null);
|
||
|
||
/** 上传中断:断点还在内存里,弹窗问用户要不要接着传 */
|
||
const onUploadInterrupted = (payload: {
|
||
fileName?: string;
|
||
uploaded?: number;
|
||
total?: number;
|
||
}) => {
|
||
interruptedInfo.value = {
|
||
fileName: payload?.fileName || "",
|
||
uploaded: payload?.uploaded ?? 0,
|
||
total: payload?.total ?? 0,
|
||
};
|
||
stopTranscodeTip();
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
showResumeModal.value = true;
|
||
};
|
||
|
||
/** 继续上传:从断点那一批接着发 */
|
||
const onResumeUpload = () => {
|
||
showResumeModal.value = false;
|
||
loading.value = true;
|
||
spinTip.value = "继续上传中...";
|
||
operatorStationRef.value?.resumeUpload();
|
||
};
|
||
|
||
/** 放弃:清掉断点,已传的分片留在服务器上不会被合并 */
|
||
const onDiscardUpload = () => {
|
||
showResumeModal.value = false;
|
||
operatorStationRef.value?.discardUpload();
|
||
stopTranscodeTip();
|
||
uploadingVideo.value = false;
|
||
loading.value = false;
|
||
};
|
||
|
||
const onUploadError = () => {
|
||
stopTranscodeTip();
|
||
uploadingVideo.value = false;
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
};
|
||
|
||
const onSelectChange = (selected: DmsFileUploadViewDisplayData[]) => {
|
||
keys.value = selected;
|
||
};
|
||
|
||
const onViewPreviewPhoto = async (filePath: string) => {
|
||
router.push({ name: "Preview", params: { id: filePath, mode: "list" } });
|
||
};
|
||
|
||
const onViewPreviewAudio = async (filePath: string) => {
|
||
router.push({
|
||
name: "PreviewAudio",
|
||
params: { id: filePath, mode: "list" },
|
||
});
|
||
};
|
||
|
||
const onViewPreviewVideo = async (filePath: string) => {
|
||
router.push({
|
||
name: "PreviewVideo",
|
||
params: { id: filePath, mode: "list" },
|
||
});
|
||
};
|
||
|
||
const onChangeFolder = async (fvalue: string) => {
|
||
onSearchByFilePath(fvalue);
|
||
};
|
||
|
||
/** DMS 记录 → 播放列表项:Url=原码、FormattedM3u8=转码(10秒),封面用同名 png 兜底 */
|
||
const toVideoItem = (record: DmsFileUploadViewDisplayData): VideoItem => {
|
||
const item = new PublishVideoDetailDisplayData();
|
||
item.Title = record.OrgFileName;
|
||
item.Url = record.Url;
|
||
item.FormattedM3u8 = record.FormattedM3u8;
|
||
item.FormattedUrl = record.FormattedM3u8 || record.Url;
|
||
item.FormattedPic = (record.FormattedPic || "").replace(/\.m3u8$/, ".png");
|
||
return item;
|
||
};
|
||
|
||
/** 当前目录里的视频,作为弹窗播放器的播放列表 */
|
||
const buildVideoList = (
|
||
records: DmsFileUploadViewDisplayData[],
|
||
): VideoItem[] =>
|
||
records
|
||
.filter(
|
||
(x) =>
|
||
x.IsDirectoryIndc != "Y" &&
|
||
fileTypePolicy.isVideo(x.OrderKey || x.OrgFileName) &&
|
||
!!(x.FormattedM3u8 || x.Url),
|
||
)
|
||
.map(toVideoItem);
|
||
|
||
/** 打开视频弹窗 */
|
||
const openVideoPlay = (list: VideoItem[], index: number, title: string) => {
|
||
sound.value?.stop();
|
||
datas.value.forEach((element) => {
|
||
element.IsPlay = "";
|
||
});
|
||
videoPlayList.value = list;
|
||
videoPlayIndex.value = index < 0 ? 0 : index;
|
||
videoPlayTitle.value = title || "视频播放";
|
||
videoPlayModal.value = true;
|
||
};
|
||
|
||
const onPreviewFile = async (usernameOrRecord: any, orderKey?: string) => {
|
||
let username: string;
|
||
let fname: string;
|
||
if (typeof usernameOrRecord === "object") {
|
||
username = usernameOrRecord.CreatedBy;
|
||
fname = usernameOrRecord.OrderKey;
|
||
} else {
|
||
username = usernameOrRecord;
|
||
fname = orderKey!;
|
||
}
|
||
loading.value = true;
|
||
getPreviewFile(username, fname);
|
||
};
|
||
|
||
const onPreviewOrgFile = async (usernameOrRecord: any, orderKey?: string) => {
|
||
let fileId: number;
|
||
let orgFileName: string;
|
||
if (typeof usernameOrRecord === "object") {
|
||
fileId = usernameOrRecord.FileId;
|
||
orgFileName = usernameOrRecord.OrgFileName;
|
||
} else {
|
||
fileId = usernameOrRecord;
|
||
orgFileName = orderKey!;
|
||
}
|
||
loading.value = true;
|
||
onViewPictureFile(fileId, orgFileName);
|
||
};
|
||
|
||
const getPreviewFile = (username: string, fname: string) => {
|
||
let dms: DmsFileEntity = new DmsFileEntity();
|
||
dms.CreatedBy = username;
|
||
dms.OrderKey = fname;
|
||
dmsFileService
|
||
.DownloadFilePreview(dms)
|
||
.then((res) => {
|
||
const downloadUrl = window.URL.createObjectURL(new Blob([res]));
|
||
imageSrc.value = downloadUrl;
|
||
loading.value = false;
|
||
setPicVisible(true);
|
||
})
|
||
.catch(() => {
|
||
loading.value = false;
|
||
});
|
||
};
|
||
|
||
const DownloadFileCombine = (
|
||
fs: string[],
|
||
mergedData: Uint8Array,
|
||
index: number,
|
||
ttl: number,
|
||
total: number,
|
||
preview: boolean,
|
||
fname: string,
|
||
) => {
|
||
loading.value = true;
|
||
fs[fs.length - 2] = index.toString();
|
||
spinTip.value = "加载中(" + index + "/" + total + ")...";
|
||
dmsFileService
|
||
.DownloadFileCombine(fs.toString().replace(/,/g, "-"))
|
||
.then((res) => {
|
||
mergedData.set(new Uint8Array(res), ttl);
|
||
if (index < total) {
|
||
DownloadFileCombine(
|
||
fs,
|
||
mergedData,
|
||
index + 1,
|
||
ttl + res.byteLength,
|
||
total,
|
||
preview,
|
||
fname,
|
||
);
|
||
} else if (index == total) {
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
const downloadUrl = window.URL.createObjectURL(
|
||
new Blob([mergedData as unknown as BlobPart]),
|
||
);
|
||
imageSrc.value = downloadUrl;
|
||
if (!preview) {
|
||
const link = document.createElement("a");
|
||
link.href = downloadUrl;
|
||
link.setAttribute("download", fname);
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
} else {
|
||
setPicVisible(true);
|
||
}
|
||
}
|
||
})
|
||
.catch(() => {
|
||
spinTip.value = "加载中...";
|
||
loading.value = false;
|
||
});
|
||
};
|
||
|
||
const onLastFolder = async () => {
|
||
if (!datas.value || datas.value.length == 0) {
|
||
onSearchByFilePath(previousFilePath.value);
|
||
} else {
|
||
onPreviousFolder();
|
||
}
|
||
};
|
||
|
||
const onPreviousFolder = async () => {
|
||
let filePath: string = "";
|
||
if (datas.value && datas.value.length > 0) filePath = datas.value[0].FilePath;
|
||
dmsFileService.FindFolderNameParentByFolderName(filePath).then((res) => {
|
||
if (res && res.length > 0) onSearchByFilePath(res);
|
||
});
|
||
};
|
||
|
||
const onPublishPhoto = async () => {
|
||
showModalPublishPhoto.value = true;
|
||
};
|
||
|
||
const onPublishAudio = async () => {
|
||
showModalPublishAudio.value = true;
|
||
};
|
||
|
||
const onPublishVideo = async () => {
|
||
showModalPublishVideo.value = true;
|
||
};
|
||
|
||
const onShareFamily = async (records: DmsFileUploadViewDisplayData[]) => {
|
||
sharedFileRecords.value = records.map((r) => toUploadView(r));
|
||
showModalShare.value = true;
|
||
};
|
||
|
||
/** 按 URL 直接下载(视频走这条:Url 就是原码文件) */
|
||
const downloadByUrl = async (url: string, fileName: string) => {
|
||
if (!url) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "该文件没有可下载的地址",
|
||
placement: "topRight",
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
loading.value = true;
|
||
spinTip.value = "下载中...";
|
||
// 与 VideoPlayer 一致:先取回字节流,再用 Blob + <a download> 落盘
|
||
const res = await request<ArrayBuffer>({
|
||
url,
|
||
method: "get",
|
||
responseType: "arraybuffer",
|
||
});
|
||
const blobUrl = window.URL.createObjectURL(new Blob([res]));
|
||
const link = document.createElement("a");
|
||
link.href = blobUrl;
|
||
link.setAttribute("download", fileName);
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
link.remove();
|
||
// 立刻 revoke 部分浏览器会来不及触发下载,延后释放
|
||
setTimeout(() => window.URL.revokeObjectURL(blobUrl), 1000);
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "下载失败",
|
||
placement: "topRight",
|
||
});
|
||
} finally {
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
}
|
||
};
|
||
|
||
/** 下载一条记录:视频下原码,其它文件走原来的分片合并下载 */
|
||
const onDownloadFile = async (record: DmsFileUploadViewDisplayData) => {
|
||
if (fileTypePolicy.isVideo(record.OrgFileName) || fileTypePolicy.isVideo(record.OrderKey)) {
|
||
await downloadByUrl(record.Url, record.OrgFileName);
|
||
return;
|
||
}
|
||
GetOrgPictureFile(record.FileId, record.OrgFileName, false);
|
||
};
|
||
|
||
const GetOrgPictureFile = async (
|
||
fid: number,
|
||
fname: string,
|
||
preview: boolean,
|
||
) => {
|
||
if (fileTypePolicy.isVideo(fname)) {
|
||
return;
|
||
}
|
||
|
||
loading.value = true;
|
||
dmsFileService
|
||
.FindByKey(fid)
|
||
.then((res) => {
|
||
let fs: string[] = res.OrderKey.split("-");
|
||
let index: string = fs[fs.length - 2];
|
||
let total: string = fs[fs.length - 1].split(".")[0];
|
||
var mergedData = new Uint8Array((res.FileSize + 1) * 1024);
|
||
let ttl: number = 0;
|
||
fs[fs.length - 2] = "1";
|
||
spinTip.value = "加载中(1/" + total + ")...";
|
||
DownloadFileCombine(
|
||
fs,
|
||
mergedData,
|
||
1,
|
||
ttl,
|
||
parseInt(total),
|
||
preview,
|
||
fname,
|
||
);
|
||
})
|
||
.catch(() => {
|
||
loading.value = false;
|
||
});
|
||
};
|
||
|
||
const onViewPictureFile = async (fid: number, fname: string) => {
|
||
GetOrgPictureFile(fid, fname, true);
|
||
};
|
||
|
||
const onSearchByFilePath = async (fvalue: string) => {
|
||
setBindOptionValue(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
fvalue,
|
||
"",
|
||
[fvalue],
|
||
false,
|
||
);
|
||
previousFilePath.value = unref(currFilePath.value);
|
||
currFilePath.value = fvalue;
|
||
headers.value.FilePath = fvalue;
|
||
isSearched.value = true;
|
||
if (currentSearchCriteria.value && fvalue && fvalue.length > 0) {
|
||
currentSearchCriteria.value.Filter = [];
|
||
let filter: SearchFilter;
|
||
filter = new SearchFilter();
|
||
filter.Column = DmsFileUploadViewDisplayData.DB_FILE_PATH;
|
||
filter.Type = "SingleSelection";
|
||
filter.Operator = "single";
|
||
filter.Value = fvalue;
|
||
currentSearchCriteria.value.Filter.push(filter);
|
||
} else {
|
||
currentSearchCriteria.value.Filter = [];
|
||
}
|
||
|
||
await findBySearchCriteria(unref(currentSearchCriteria));
|
||
};
|
||
|
||
const onViewPic = () => {
|
||
if (keys.value.length == 0) return;
|
||
if (keys.value[0].IsDirectoryIndc == "Y") {
|
||
onChangeFolder(keys.value[0].FileName);
|
||
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
||
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
||
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
||
onUrlVideoPlayItem(keys.value[0]);
|
||
} else {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "未知格式无法预览",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
};
|
||
|
||
const setPicVisible = (value: boolean): void => {
|
||
visible.value = value;
|
||
};
|
||
|
||
const onCreate = () => {
|
||
dmsFolderTitle.value = "新增文件夹";
|
||
dmsFolderIsRename.value = false;
|
||
dmsFolderIsMove.value = false;
|
||
dmsFolderModal.value = true;
|
||
entity.value = new DmsFileEntity();
|
||
let bindOption: BindOption = bindOptions.value.filter(
|
||
(x) => x.BindValue == DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
)[0];
|
||
|
||
entity.value.FilePath = bindOption.SelectOptions.filter(
|
||
(x) => x.BindValue == bindOption.Value,
|
||
)[0].DisplayName;
|
||
entity.value.OrgFileName = bindOption.Value;
|
||
|
||
currFilePath.value = bindOption.Value;
|
||
};
|
||
|
||
const onAmend = () => {
|
||
if (keys.value[0].IsDirectoryIndc == "Y") {
|
||
dmsFolderTitle.value = "重命名文件夹";
|
||
} else {
|
||
dmsFolderTitle.value = "重命名文件";
|
||
}
|
||
dmsFolderIsRename.value = true;
|
||
dmsFolderModal.value = true;
|
||
dmsFolderIsMove.value = false;
|
||
entity.value = new DmsFileEntity();
|
||
|
||
entity.value.FileId = keys.value[0].FileId;
|
||
entity.value.FilePath = keys.value[0].FolderLocalName;
|
||
if (keys.value[0].CreatedBy == keys.value[0].FolderLocalName) {
|
||
entity.value.FilePath = "";
|
||
}
|
||
entity.value.FileName = keys.value[0].OrgFileName;
|
||
};
|
||
|
||
const onMove = () => {
|
||
if (keys.value[0].IsDirectoryIndc == "Y") {
|
||
dmsFolderTitle.value = "移动文件夹";
|
||
} else {
|
||
dmsFolderTitle.value = "移动文件";
|
||
}
|
||
dmsFolderIsRename.value = false;
|
||
dmsFolderIsMove.value = true;
|
||
dmsFolderModal.value = true;
|
||
|
||
entity.value = new DmsFileEntity();
|
||
|
||
entity.value.FileId = keys.value[0].FileId;
|
||
entity.value.FilePath = keys.value[0].FolderLocalName;
|
||
if (keys.value[0].CreatedBy == keys.value[0].FolderLocalName) {
|
||
entity.value.FilePath = "";
|
||
}
|
||
entity.value.FileName = keys.value[0].FileName;
|
||
entity.value.OrgFileName = keys.value[0].OrgFileName;
|
||
};
|
||
|
||
const onDelete = async () => {
|
||
try {
|
||
loading.value = true;
|
||
for (let i = 0; i < keys.value.length; i++) {
|
||
await dmsFileService.Delete(keys.value[i].FileId);
|
||
}
|
||
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "记录删除成功",
|
||
placement: "topRight",
|
||
});
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "记录删除失败",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
finally {
|
||
loading.value = false;
|
||
onReload();
|
||
}
|
||
};
|
||
|
||
const setBindOptionValue = (
|
||
bindValue: string,
|
||
value: string,
|
||
value1: string,
|
||
values: string[],
|
||
disabled: boolean,
|
||
) => {
|
||
let bindOption: BindOption = bindOptions.value.filter(
|
||
(x) => x.BindValue == bindValue,
|
||
)[0];
|
||
if (!bindOption) return;
|
||
bindOption.Value = value;
|
||
bindOption.Value1 = value1;
|
||
bindOption.Values = values;
|
||
bindOption.disabled = disabled;
|
||
};
|
||
|
||
const initBindOption = async () => {
|
||
let ubo = useBindOption();
|
||
bindOptions.value = [];
|
||
bindOptions.value.splice(0, bindOptions.value.length);
|
||
let bindOption: BindOption = ubo.getBindOption(
|
||
DmsFileUploadViewDisplayData.DB_ORG_FILE_NAME,
|
||
"名称",
|
||
SearchFilterTypePolicy.TEXT,
|
||
SearchFilterOperatorPolicy.CONTAIN,
|
||
);
|
||
bindOptions.value.push(bindOption);
|
||
|
||
let rps: SelectOption[] = await dmsFileService.FindDmsFolders();
|
||
if (rps && rps.length > 1) {
|
||
rootPath.value = rps[1].BindValue;
|
||
if (!currFilePath.value) {
|
||
currFilePath.value = rps[1].BindValue;
|
||
}
|
||
}
|
||
|
||
bindOption = ubo.getBindSelectOption(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
"当前目录",
|
||
SearchFilterTypePolicy.SINGLE_SELECTION,
|
||
SearchFilterOperatorPolicy.SINGLE,
|
||
rps,
|
||
);
|
||
|
||
bindOptions.value.push(bindOption);
|
||
|
||
setBindOptionValue(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
currFilePath.value,
|
||
"",
|
||
[currFilePath.value],
|
||
false,
|
||
);
|
||
};
|
||
|
||
result.value.Page = pagingParams.value.page ?? 1;
|
||
result.value.Limit = pagingParams.value.pageSize;
|
||
|
||
const onSubmit = async (filters: SearchFilter[]) => {
|
||
loading.value = true;
|
||
let c: DmsFileSearchCriteria = new DmsFileSearchCriteria();
|
||
currentFilter.value = filters;
|
||
|
||
c.Filter = filters;
|
||
c.limit = pagingParams.value.pageSize;
|
||
c.page = pagingParams.value.page ?? 1;
|
||
c.GridColumns = [];
|
||
currentSearchCriteria.value = c;
|
||
|
||
await findBySearchCriteria(c);
|
||
};
|
||
|
||
const findBySearchCriteria = async (c: DmsFileSearchCriteria) => {
|
||
keys.value = [];
|
||
try {
|
||
if (c.limit == 0) c.limit = pagingParams.value.pageSize;
|
||
if (c.page == 0) c.page = pagingParams.value.page ?? 1;
|
||
|
||
currentFilter.value = c.Filter;
|
||
let data = await dmsFileService.FindBySearchCriteria(c);
|
||
|
||
isSearched.value = true;
|
||
result.value.Total = data.Total;
|
||
result.value.Page = data.Page;
|
||
result.value.Limit = data.Limit;
|
||
const rawList = data.Datas ?? [];
|
||
// 始终排序,空数组orderBy也安全
|
||
datas.value = orderBy(
|
||
rawList,
|
||
(x: DmsFileUploadViewDisplayData) => x.IsDirectoryIndc,
|
||
"desc",
|
||
);
|
||
loading.value = false;
|
||
if (
|
||
data.Datas &&
|
||
data.Datas.length > 0 &&
|
||
fileTypePolicy.isAudio(data.Datas[0].OrderKey)
|
||
) {
|
||
onPlayAudio(data.Datas[0]);
|
||
onPauseAudio(data.Datas[0]);
|
||
} else {
|
||
sound.value?.stop();
|
||
}
|
||
} catch (error) {
|
||
loading.value = false;
|
||
console.log(error);
|
||
}
|
||
};
|
||
|
||
const onReSearch = async () => {
|
||
setBindOptionValue(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
currFilePath.value,
|
||
"",
|
||
[currFilePath.value],
|
||
false,
|
||
);
|
||
await findBySearchCriteria(unref(currentSearchCriteria));
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
};
|
||
|
||
const onReload = async () => {
|
||
let cfp: string = currFilePath.value;
|
||
await initBindOption();
|
||
setBindOptionValue(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
cfp,
|
||
"",
|
||
[cfp],
|
||
false,
|
||
);
|
||
await findBySearchCriteria(unref(currentSearchCriteria));
|
||
};
|
||
|
||
const handleSelectShare = async () => {
|
||
// 没选目标共享目录 / 没有待共享文件时直接提示,不发请求
|
||
if (!shareEnquiry.value) return;
|
||
if (shareEnquiry.value.keys.length === 0 || sharedFileRecords.value.length === 0) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "请选择一条记录",
|
||
placement: "topRight",
|
||
});
|
||
return;
|
||
}
|
||
|
||
try {
|
||
loading.value = true;
|
||
spinTip.value = "共享中...";
|
||
|
||
let fgps: FamilyGroupFolderEntity[] = [];
|
||
// 每个选中的目标共享目录 × 每个待共享的文件,各生成一条群组文件夹记录
|
||
shareEnquiry.value.keys.forEach((target) => {
|
||
sharedFileRecords.value.forEach((record) => {
|
||
let fgp: FamilyGroupFolderEntity = new FamilyGroupFolderEntity();
|
||
fgp.FamilyName = target.FamilyName;
|
||
fgp.TopFolderName = target.TopFolderName;
|
||
fgp.FolderName = record.FileName ?? "";
|
||
fgp.FolderLocalName = record.OrgFileName ?? "";
|
||
fgp.FilePath = target.FolderName;
|
||
|
||
fgps.push(fgp);
|
||
});
|
||
});
|
||
|
||
// 先关弹窗再发请求:遮罩盖在弹窗上会看不清,关掉后 loading 效果更明显。
|
||
// 注意 fgps 必须在关闭前组装好,弹窗销毁后就取不到选中的目标目录了
|
||
showModalShare.value = false;
|
||
|
||
await dmsFileService.CreateFamilyGroupFolder(fgps);
|
||
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "共享成功",
|
||
placement: "topRight",
|
||
});
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "共享失败",
|
||
placement: "topRight",
|
||
});
|
||
} finally {
|
||
loading.value = false;
|
||
spinTip.value = "加载中...";
|
||
}
|
||
};
|
||
|
||
const handleSelectPublishPhoto = async () => {
|
||
try {
|
||
loading.value = true;
|
||
if (publishPhotoEnquiry.value) {
|
||
if (publishPhotoEnquiry.value.keys.length > 0) {
|
||
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
|
||
const publishName = publishPhotoEnquiry.value.keys[0].PublishName;
|
||
// 先关弹窗再发请求,遮罩才看得清
|
||
showModalPublishPhoto.value = false;
|
||
|
||
let data: PublishData;
|
||
for (let i = 0; i < keys.value.length; i++) {
|
||
data = new PublishData();
|
||
data.FileId = keys.value[i].FileId;
|
||
data.PublishName = publishName;
|
||
|
||
await publishPhotoService.InsertPublishPhotoDetail(data);
|
||
}
|
||
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "作品发布成功",
|
||
placement: "topRight",
|
||
});
|
||
} else {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "请选择一条记录",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
}
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "作品发布失败",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
finally {
|
||
loading.value = false;
|
||
}
|
||
|
||
};
|
||
|
||
const handleSelectPublishAudio = async () => {
|
||
try {
|
||
loading.value = true;
|
||
if (publishAudioEnquiry.value) {
|
||
if (publishAudioEnquiry.value.keys.length > 0) {
|
||
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
|
||
const publishName = publishAudioEnquiry.value.keys[0].PublishName;
|
||
// 先关弹窗再发请求,遮罩才看得清
|
||
showModalPublishAudio.value = false;
|
||
|
||
let data: PublishData;
|
||
for (let i = 0; i < keys.value.length; i++) {
|
||
data = new PublishData();
|
||
data.FileId = keys.value[i].FileId;
|
||
data.PublishName = publishName;
|
||
|
||
await publishAudioService.InsertPublishAudioDetail(data);
|
||
}
|
||
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "专辑发布成功",
|
||
placement: "topRight",
|
||
});
|
||
} else {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "请选择一条记录",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
}
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "专辑发布失败",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
finally {
|
||
loading.value = false;
|
||
}
|
||
|
||
};
|
||
|
||
const handleSelectPublishVideo = async () => {
|
||
try {
|
||
loading.value = true;
|
||
|
||
if (publishVideoEnquiry.value) {
|
||
if (publishVideoEnquiry.value.keys.length > 0) {
|
||
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
|
||
const publishName = publishVideoEnquiry.value.keys[0].PublishName;
|
||
// 先关弹窗再发请求,遮罩才看得清
|
||
showModalPublishVideo.value = false;
|
||
|
||
let data: PublishData;
|
||
for (let i = 0; i < keys.value.length; i++) {
|
||
data = new PublishData();
|
||
data.FileId = keys.value[i].FileId;
|
||
data.PublishName = publishName;
|
||
|
||
await publishVideoService.InsertPublishVideoDetail(data);
|
||
}
|
||
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "专辑发布成功",
|
||
placement: "topRight",
|
||
});
|
||
} else {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "请选择一条记录",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
}
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "专辑发布失败",
|
||
placement: "topRight",
|
||
});
|
||
}
|
||
finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const onGoTop = () => {
|
||
pathStack.value = [{ value: rootPath.value, displayName: "我的云盘" }];
|
||
onSearchByFilePath(rootPath.value);
|
||
};
|
||
|
||
const onGoBack = () => {
|
||
if (pathStack.value.length > 1) {
|
||
pathStack.value.pop();
|
||
const prev = pathStack.value[pathStack.value.length - 1];
|
||
onSearchByFilePath(prev.value);
|
||
}
|
||
};
|
||
|
||
const onBreadcrumbClick = (item: BreadcrumbItem, index: number) => {
|
||
pathStack.value = pathStack.value.slice(0, index + 1);
|
||
onSearchByFilePath(item.value);
|
||
};
|
||
|
||
const onSearchByName = (keyword: string) => {
|
||
let c: DmsFileSearchCriteria = new DmsFileSearchCriteria();
|
||
let filters: SearchFilter[] = [];
|
||
|
||
let filePathFilter: SearchFilter = new SearchFilter();
|
||
filePathFilter.Column = DmsFileUploadViewDisplayData.DB_FILE_PATH;
|
||
filePathFilter.Type = "SingleSelection";
|
||
filePathFilter.Operator = "single";
|
||
filePathFilter.Value = currFilePath.value;
|
||
filters.push(filePathFilter);
|
||
|
||
if (keyword && keyword.trim()) {
|
||
let nameFilter: SearchFilter = new SearchFilter();
|
||
nameFilter.Column = DmsFileUploadViewDisplayData.DB_ORG_FILE_NAME;
|
||
nameFilter.Type = SearchFilterTypePolicy.TEXT;
|
||
nameFilter.Operator = SearchFilterOperatorPolicy.CONTAIN;
|
||
nameFilter.Value = keyword.trim();
|
||
filters.push(nameFilter);
|
||
}
|
||
|
||
c.Filter = filters;
|
||
c.limit = pagingParams.value.pageSize;
|
||
c.page = 1;
|
||
c.GridColumns = [];
|
||
|
||
currentSearchCriteria.value = c;
|
||
setBindOptionValue(
|
||
DmsFileUploadViewDisplayData.DB_FILE_PATH,
|
||
currFilePath.value,
|
||
"",
|
||
[currFilePath.value],
|
||
false,
|
||
);
|
||
pagingParams.value.page = 1;
|
||
findBySearchCriteria(c);
|
||
};
|
||
|
||
const onOpenFolder = (record: DmsFileUploadViewDisplayData) => {
|
||
if (record.IsDirectoryIndc == "Y") {
|
||
pathStack.value.push({
|
||
value: record.FileName,
|
||
displayName: record.OrgFileName,
|
||
});
|
||
onChangeFolder(record.FileName);
|
||
}
|
||
};
|
||
|
||
const onOpenFile = (record: DmsFileUploadViewDisplayData) => {
|
||
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
||
onPreviewFile(record.CreatedBy, record.OrderKey);
|
||
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
||
onUrlVideoPlayItem(record);
|
||
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
||
onPlayAudio(toUploadView(record));
|
||
} else {
|
||
onDownloadFile(record);
|
||
}
|
||
};
|
||
|
||
const onDownloadSelected = async (items: DmsFileUploadViewDisplayData[]) => {
|
||
// 逐个串行下载:并发触发多个 <a download> 浏览器会拦截后面的
|
||
for (const item of items) {
|
||
if (item.IsDirectoryIndc != "Y") {
|
||
await onDownloadFile(item);
|
||
}
|
||
}
|
||
};
|
||
|
||
const onShareSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
||
const files = items.filter((item) => item.IsDirectoryIndc != "Y");
|
||
// 只选中目录时原来什么都不发生,这里给个提示
|
||
if (files.length === 0) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "请选择要共享的文件",
|
||
placement: "topRight",
|
||
});
|
||
return;
|
||
}
|
||
onShareFamily(files);
|
||
};
|
||
|
||
const onPublishSelected = async (items: DmsFileUploadViewDisplayData[]) => {
|
||
const files = items.filter((item) => item.IsDirectoryIndc != "Y");
|
||
if (files.length === 0) return;
|
||
try {
|
||
loading.value = true;
|
||
const first = files[0];
|
||
const mediaKey = (item: DmsFileUploadViewDisplayData) =>
|
||
item.OrderKey || item.OrgFileName || "";
|
||
if (fileTypePolicy.isImage(mediaKey(first))) {
|
||
keys.value = files.filter((item) => fileTypePolicy.isImage(mediaKey(item)));
|
||
await onPublishPhoto();
|
||
} else if (fileTypePolicy.isVideo(mediaKey(first))) {
|
||
keys.value = files.filter((item) => fileTypePolicy.isVideo(mediaKey(item)));
|
||
await onPublishVideo();
|
||
} else if (fileTypePolicy.isAudio(mediaKey(first))) {
|
||
keys.value = files.filter((item) => fileTypePolicy.isAudio(mediaKey(item)));
|
||
await onPublishAudio();
|
||
}
|
||
} catch (error) {
|
||
notification.info({
|
||
message: "系统提示:",
|
||
description: "打开发布窗口失败",
|
||
placement: "topRight",
|
||
});
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const onViewPreviewSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
||
if (items.length === 0) return;
|
||
const first = items[0];
|
||
if (
|
||
fileTypePolicy.isImage(first.OrderKey) ||
|
||
fileTypePolicy.isImage(first.OrgFileName)
|
||
) {
|
||
onViewPreviewPhoto(first.FilePath);
|
||
} else if (
|
||
fileTypePolicy.isVideo(first.OrderKey) ||
|
||
fileTypePolicy.isVideo(first.OrgFileName)
|
||
) {
|
||
onViewPreviewVideo(first.FilePath);
|
||
} else if (
|
||
fileTypePolicy.isAudio(first.OrderKey) ||
|
||
fileTypePolicy.isAudio(first.OrgFileName)
|
||
) {
|
||
onViewPreviewAudio(first.FilePath);
|
||
}
|
||
};
|
||
|
||
/** 播放视频:把当前目录的视频串成播放列表,从点中的那一个开始 */
|
||
const onUrlVideoPlayItem = (record: DmsFileUploadViewDisplayData) => {
|
||
const list = buildVideoList(datas.value);
|
||
let index = list.findIndex((x) => x.Url === record.Url);
|
||
if (index < 0) {
|
||
list.unshift(toVideoItem(record));
|
||
index = 0;
|
||
}
|
||
openVideoPlay(list, index, record.OrgFileName);
|
||
};
|
||
|
||
const onPlayAudioItem = (record: DmsFileUploadViewDisplayData) => {
|
||
onPlayAudio(record);
|
||
};
|
||
|
||
const onPreviewSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
||
if (items.length > 0) {
|
||
keys.value = items;
|
||
onViewPic();
|
||
}
|
||
};
|
||
|
||
const onAmendSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
||
if (items.length === 1) {
|
||
keys.value = items;
|
||
onAmend();
|
||
}
|
||
};
|
||
|
||
const onMoveSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
||
if (items.length === 1) {
|
||
keys.value = items;
|
||
onMove();
|
||
}
|
||
};
|
||
|
||
const onDeleteSelected = () => {
|
||
onDelete();
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.dms-file-enquiry {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: calc(100vh - 120px);
|
||
}
|
||
</style>
|