This commit is contained in:
itcsx committed 2026-09-23 07:25:47 +08:00
1 parent adcf94df4a
commit 428c94951b
9 files changed
+622 -263

No files matched your search

@@ -19,13 +19,19 @@
</div>
<div v-else class="vap-body">
<!-- 收起 -->
<button class="vap-collapse" type="button" title="收起播放器" @click="emit('close')">
<!-- 收起(控制区收起时换成下面的"显示控制区",右上角同一位置只放一个) -->
<button v-if="controlsVisible" class="vap-collapse" type="button" title="收起播放器" @click="emit('close')">
<DownOutlined />
</button>
<!-- 控制区收起后的恢复入口:整页用法没有弹窗右上角按钮,否则收起就点不回来了 -->
<button v-if="!controlsVisible" class="vap-restore" type="button" title="显示控制区"
@click.stop="toggleControls">
<EyeOutlined />
</button>
<!-- 唱片 + 唱臂 -->
<div class="vap-stage">
<!-- 唱片 + 唱臂:整片区域单击即可暂停/播放,
这样页内全屏(控制区已收起)时也还能控制播放 -->
<div class="vap-stage" :title="isPlaying ? '单击暂停' : '单击播放'" @click="toggle">
<div class="vap-turntable">
<div class="vap-disc" :class="{ 'is-spinning': isPlaying }">
<img v-if="current.cover && !coverError" class="vap-disc-cover" :src="current.cover" alt=""
@@ -66,10 +72,12 @@
</div>
<!-- 功能图标行 -->
<div class="vap-actions">
<button class="vap-act" :class="{ 'is-fav': isFaved }" type="button" title="喜欢" @click="onFav">
<HeartFilled v-if="isFaved" />
<HeartOutlined v-else />
<div v-if="controlsVisible" class="vap-actions">
<!-- 隐藏/显示控制区:整页用法时父组件会顺带藏掉 layout 顶栏,做到整页全屏 -->
<button class="vap-act" type="button" :class="{ 'is-on': !controlsVisible }"
:title="controlsVisible ? '隐藏控制区' : '显示控制区'" @click.stop="toggleControls">
<EyeInvisibleOutlined v-if="controlsVisible" />
<EyeOutlined v-else />
</button>
<button class="vap-act" type="button" title="下载" @click="onDownload">
<DownloadOutlined />
@@ -117,8 +125,8 @@
</div>
<!-- 进度 -->
<div class="vap-progress" ref="barRef" @pointerdown="onBarDown" @pointermove="onBarMove" @pointerup="onBarUp"
@pointercancel="onBarUp">
<div v-if="controlsVisible" class="vap-progress" ref="barRef" @pointerdown="onBarDown"
@pointermove="onBarMove" @pointerup="onBarUp" @pointercancel="onBarUp">
<div class="vap-bar">
<span class="vap-bar-fill" :style="{ width: displayRatio * 100 + '%' }"></span>
<span class="vap-bar-thumb" :style="{ left: displayRatio * 100 + '%' }"></span>
@@ -130,7 +138,7 @@
</div>
<!-- 主控制 -->
<div class="vap-controls">
<div v-if="controlsVisible" class="vap-controls">
<button class="vap-ctl" type="button" :title="modeTitle" @click="cycleMode">
<RetweetOutlined v-if="mode !== 'random'" />
<SwapOutlined v-else />
@@ -180,12 +188,13 @@
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from "vue";
import { message } from "ant-design-vue";
import { request } from "@/utils/request";
import { useVModel } from "@vueuse/core";
import {
DownOutlined, HeartOutlined, HeartFilled, DownloadOutlined, FieldTimeOutlined,
DownOutlined, DownloadOutlined, FieldTimeOutlined,
AudioOutlined, AudioMutedOutlined, EllipsisOutlined, InfoCircleOutlined,
RetweetOutlined, SwapOutlined, StepBackwardFilled, StepForwardFilled,
CaretRightFilled, PauseOutlined, UnorderedListOutlined, CloseOutlined,
CustomerServiceOutlined,
CustomerServiceOutlined, EyeOutlined, EyeInvisibleOutlined,
} from "@ant-design/icons-vue";
/** 一首歌 */
@@ -202,8 +211,31 @@ export interface VinylTrack {
lrc?: string;
}
const props = withDefaults(defineProps<{ tracks?: VinylTrack[] }>(), { tracks: () => [] });
const emit = defineEmits<{ (e: "close"): void }>();
const props = withDefaults(
defineProps<{
tracks?: VinylTrack[];
/** 控制区(功能图标行 / 进度 / 主控制)是否显示;页面可用它做「整页全屏」 */
controls?: boolean;
}>(),
{ tracks: () => [], controls: true }
);
const emit = defineEmits<{
(e: "close"): void;
(e: "update:controls", visible: boolean): void;
}>();
/**
* 控制区是否显示:由功能图标行的眼睛图标切换。
* 收起后唱片与歌词吃掉这部分空间;父组件可用 v-model:controls 拿到状态做整页全屏。
* passive: true(与 VideoPlayer / PhotoSlidePlayer 一致):父组件不绑 v-model 时
* 按钮也不会"点了没反应"。
*/
const controlsVisible = useVModel(props, "controls", emit, { passive: true });
const toggleControls = () => {
menu.value = ""; // 顺手收起可能打开的弹层(定时 / 音量 / 倍速)
controlsVisible.value = !controlsVisible.value;
};
/* ---------------- 基础状态 ---------------- */
const audioARef = ref<HTMLAudioElement | null>(null);
@@ -580,25 +612,7 @@ const onSleep = (v: number) => {
menu.value = "";
};
/* ---------------- 喜欢 / 下载 / 信息 ---------------- */
const FAV_KEY = "vap-favs";
const loadFavs = (): Set<string> => {
try {
return new Set<string>(JSON.parse(localStorage.getItem(FAV_KEY) || "[]"));
} catch {
return new Set<string>();
}
};
const favs = ref<Set<string>>(loadFavs());
const isFaved = computed(() => !!current.value && favs.value.has(current.value.url));
const onFav = () => {
if (!current.value) return;
const s = new Set(favs.value);
if (s.has(current.value.url)) s.delete(current.value.url);
else s.add(current.value.url);
favs.value = s;
localStorage.setItem(FAV_KEY, JSON.stringify([...s]));
};
/* ---------------- 下载 / 信息 ---------------- */
const onDownload = async () => {
if (!current.value) return;
// 参考 DmsFileEnquiry.vue:先取回字节流,再用 Blob + <a download> 落盘
@@ -781,7 +795,33 @@ onBeforeUnmount(() => {
padding: 6px;
}
/* 控制区收起后的恢复入口:与"收起"按钮同一位置(右上角),整页用法下没有弹窗右上角按钮 */
.vap-restore {
position: absolute;
top: 14px;
right: 14px;
z-index: 30;
display: flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
font-size: 18px;
color: #fff;
background: rgba(0, 0, 0, 0.38);
border: 0;
border-radius: 10px;
cursor: pointer;
opacity: 0.55;
transition: opacity 0.2s;
}
.vap-restore:hover {
opacity: 1;
}
/* ---------- 唱片区 ---------- */
/* 单击整片区域即可暂停/播放(全屏收起控制区后唯一的播放开关),所以给可点的光标 */
.vap-stage {
position: relative;
flex: 1 1 auto;
@@ -789,6 +829,7 @@ onBeforeUnmount(() => {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
/* 唱盘方框:唱片与唱臂共用同一坐标系(尺寸即唱片直径) */
@@ -1040,10 +1081,6 @@ onBeforeUnmount(() => {
color: #7ff3e8;
}
.vap-act.is-fav {
color: #ff5b7f;
}
.vap-act.is-muted {
opacity: 0.55;
}
+23 -2
View File
@@ -33,7 +33,17 @@ input[type=radio][readonly]:not([disabled]) {
容器高度是行内样式(bsInfo.height - 120)、Preview 还用了负外边距,只能用 !important 覆盖。 */
body.pv-fullscreen .layout-header,
body.pv-fullscreen .layout-page-header {
display: none !important;
/* 注意:这里不能用 display:none。
.layout-header 里的 a-menu(mode=horizontal) 靠容器宽度判断溢出折叠,
display:none 时宽度归零会把所有菜单项收进折叠区,退出全屏后也不再展开,
表现就是"退出全屏后右上角菜单不见了"。
改成移出视口:元素仍然有正常尺寸(不会触发折叠),但看不见、也不占位。 */
position: fixed !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
transform: translateY(-100%) !important;
pointer-events: none !important;
}
body.pv-fullscreen .layout-content-view {
@@ -41,7 +51,18 @@ body.pv-fullscreen .layout-content-view {
padding: 0 !important;
}
body.pv-fullscreen .pv-page {
/* 退出全屏的那一瞬:鼠标通常正停在顶栏菜单上方,会让下拉菜单立刻 hover 展开
(也可能把 click 落到菜单项上)。这里让顶栏短暂不响应指针,
避开这次误触;指针事件照常落到内容区,不影响看图/看片。
.pv-settling 由页面在退出全屏时挂 400ms 后自动移除。 */
body.pv-settling .layout-header,
body.pv-settling .layout-page-header {
pointer-events: none !important;
}
/* 影视厅 / 图片预览用 .pv-page,音乐厅用 .pa-page,全屏时都要铺满整屏 */
body.pv-fullscreen .pv-page,
body.pv-fullscreen .pa-page {
width: 100% !important;
height: 100vh !important;
padding: 0 !important;
+166 -87
View File
@@ -822,114 +822,186 @@ const onReload = async () => {
};
const handleSelectShare = async () => {
if (shareEnquiry.value) {
if (shareEnquiry.value.keys.length > 0) {
let fgps: FamilyGroupFolderEntity[] = [];
let fgp: FamilyGroupFolderEntity;
shareEnquiry.value.keys.forEach((element) => {
fgp = new FamilyGroupFolderEntity();
fgp.FamilyName = element.FamilyName;
fgp.TopFolderName = element.TopFolderName;
fgp.FolderName = sharedFileRecord.value?.FileName ?? "";
fgp.FolderLocalName = sharedFileRecord.value?.OrgFileName ?? "";
fgp.FilePath = element.FolderName;
// 没选目标共享目录时直接提示,不发请求
if (!shareEnquiry.value) return;
if (shareEnquiry.value.keys.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
return;
}
fgps.push(fgp);
});
try {
loading.value = true;
spinTip.value = "共享中...";
await dmsFileService.CreateFamilyGroupFolder(fgps);
showModalShare.value = false;
} else {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
}
let fgps: FamilyGroupFolderEntity[] = [];
let fgp: FamilyGroupFolderEntity;
shareEnquiry.value.keys.forEach((element) => {
fgp = new FamilyGroupFolderEntity();
fgp.FamilyName = element.FamilyName;
fgp.TopFolderName = element.TopFolderName;
fgp.FolderName = sharedFileRecord.value?.FileName ?? "";
fgp.FolderLocalName = sharedFileRecord.value?.OrgFileName ?? "";
fgp.FilePath = element.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 () => {
if (publishPhotoEnquiry.value) {
if (publishPhotoEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishPhotoEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishPhotoEnquiry.value) {
if (publishPhotoEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishPhotoEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishPhoto.value = false;
await publishPhotoService.InsertPublishPhotoDetail(data);
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",
});
}
showModalPublishPhoto.value = false;
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;
spinTip.value = "加载中...";
}
};
const handleSelectPublishAudio = async () => {
if (publishAudioEnquiry.value) {
if (publishAudioEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishAudioEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishAudioEnquiry.value) {
if (publishAudioEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishAudioEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishAudio.value = false;
await publishAudioService.InsertPublishAudioDetail(data);
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",
});
}
showModalPublishAudio.value = false;
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;
spinTip.value = "加载中...";
}
};
const handleSelectPublishVideo = async () => {
if (publishVideoEnquiry.value) {
if (publishVideoEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishVideoEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishVideoEnquiry.value) {
if (publishVideoEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishVideoEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishVideo.value = false;
await publishVideoService.InsertPublishVideoDetail(data);
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",
});
}
showModalPublishVideo.value = false;
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;
spinTip.value = "加载中...";
}
};
@@ -1022,9 +1094,16 @@ const onDownloadSelected = async (
};
const onShareSelected = (items: DmsFileUploadDeleteLogViewDisplayData[]) => {
if (items.length > 0) {
onShareFamily(items[0]);
// 没选中文件时原来什么都不发生,这里给个提示
if (items.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择要共享的文件",
placement: "topRight",
});
return;
}
onShareFamily(items[0]);
};
const onPublishSelected = (items: DmsFileUploadDeleteLogViewDisplayData[]) => {
+99 -37
View File
@@ -843,7 +843,11 @@ const onDelete = async () => {
placement: "topRight",
});
} catch (error) {
notification.info({
message: "系统提示:",
description: "记录删除失败",
placement: "topRight",
});
}
finally {
loading.value = false;
@@ -988,32 +992,56 @@ const onReload = async () => {
};
const handleSelectShare = async () => {
if (shareEnquiry.value) {
if (shareEnquiry.value.keys.length > 0 && sharedFileRecords.value.length > 0) {
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;
// 没选目标共享目录 / 没有待共享文件时直接提示,不发请求
if (!shareEnquiry.value) return;
if (shareEnquiry.value.keys.length === 0 || sharedFileRecords.value.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
return;
}
fgps.push(fgp);
});
});
try {
loading.value = true;
spinTip.value = "共享中...";
await dmsFileService.CreateFamilyGroupFolder(fgps);
showModalShare.value = false;
} else {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
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 = "加载中...";
}
};
@@ -1022,15 +1050,19 @@ const handleSelectPublishPhoto = async () => {
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 = publishPhotoEnquiry.value.keys[0].PublishName;
data.PublishName = publishName;
await publishPhotoService.InsertPublishPhotoDetail(data);
}
showModalPublishPhoto.value = false;
notification.info({
message: "系统提示:",
@@ -1046,7 +1078,11 @@ const handleSelectPublishPhoto = async () => {
}
}
} catch (error) {
notification.info({
message: "系统提示:",
description: "作品发布失败",
placement: "topRight",
});
}
finally {
loading.value = false;
@@ -1059,15 +1095,19 @@ const handleSelectPublishAudio = async () => {
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 = publishAudioEnquiry.value.keys[0].PublishName;
data.PublishName = publishName;
await publishAudioService.InsertPublishAudioDetail(data);
}
showModalPublishAudio.value = false;
notification.info({
message: "系统提示:",
@@ -1083,7 +1123,11 @@ const handleSelectPublishAudio = async () => {
}
}
} catch (error) {
notification.info({
message: "系统提示:",
description: "专辑发布失败",
placement: "topRight",
});
}
finally {
loading.value = false;
@@ -1097,15 +1141,19 @@ const handleSelectPublishVideo = async () => {
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 = publishVideoEnquiry.value.keys[0].PublishName;
data.PublishName = publishName;
await publishVideoService.InsertPublishVideoDetail(data);
}
showModalPublishVideo.value = false;
notification.info({
message: "系统提示:",
@@ -1121,7 +1169,11 @@ const handleSelectPublishVideo = async () => {
}
}
} catch (error) {
notification.info({
message: "系统提示:",
description: "专辑发布失败",
placement: "topRight",
});
}
finally {
loading.value = false;
@@ -1216,9 +1268,16 @@ const onDownloadSelected = async (items: DmsFileUploadViewDisplayData[]) => {
const onShareSelected = (items: DmsFileUploadViewDisplayData[]) => {
const files = items.filter((item) => item.IsDirectoryIndc != "Y");
if (files.length > 0) {
onShareFamily(files);
// 只选中目录时原来什么都不发生,这里给个提示
if (files.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择要共享的文件",
placement: "topRight",
});
return;
}
onShareFamily(files);
};
const onPublishSelected = async (items: DmsFileUploadViewDisplayData[]) => {
@@ -1240,11 +1299,14 @@ const onPublishSelected = async (items: DmsFileUploadViewDisplayData[]) => {
await onPublishAudio();
}
} catch (error) {
loading.value = false;
notification.info({
message: "系统提示:",
description: "打开发布窗口失败",
placement: "topRight",
});
} finally {
loading.value = false;
}
};
const onViewPreviewSelected = (items: DmsFileUploadViewDisplayData[]) => {
+166 -87
View File
@@ -922,114 +922,186 @@ const onReload = async () => {
};
const handleSelectShare = async () => {
if (shareEnquiry.value) {
if (shareEnquiry.value.keys.length > 0) {
let fgps: FamilyGroupFolderEntity[] = [];
let fgp: FamilyGroupFolderEntity;
shareEnquiry.value.keys.forEach((element) => {
fgp = new FamilyGroupFolderEntity();
fgp.FamilyName = element.FamilyName;
fgp.TopFolderName = element.TopFolderName;
fgp.FolderName = sharedFileRecord.value?.FileName ?? "";
fgp.FolderLocalName = sharedFileRecord.value?.OrgFileName ?? "";
fgp.FilePath = element.FolderName;
// 没选目标共享目录时直接提示,不发请求
if (!shareEnquiry.value) return;
if (shareEnquiry.value.keys.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
return;
}
fgps.push(fgp);
});
try {
loading.value = true;
spinTip.value = "共享中...";
await dmsFileService.CreateFamilyGroupFolder(fgps);
showModalShare.value = false;
} else {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
}
let fgps: FamilyGroupFolderEntity[] = [];
let fgp: FamilyGroupFolderEntity;
shareEnquiry.value.keys.forEach((element) => {
fgp = new FamilyGroupFolderEntity();
fgp.FamilyName = element.FamilyName;
fgp.TopFolderName = element.TopFolderName;
fgp.FolderName = sharedFileRecord.value?.FileName ?? "";
fgp.FolderLocalName = sharedFileRecord.value?.OrgFileName ?? "";
fgp.FilePath = element.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 () => {
if (publishPhotoEnquiry.value) {
if (publishPhotoEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishPhotoEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishPhotoEnquiry.value) {
if (publishPhotoEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishPhotoEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishPhoto.value = false;
await publishPhotoService.InsertPublishPhotoDetail(data);
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",
});
}
showModalPublishPhoto.value = false;
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;
spinTip.value = "加载中...";
}
};
const handleSelectPublishAudio = async () => {
if (publishAudioEnquiry.value) {
if (publishAudioEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishAudioEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishAudioEnquiry.value) {
if (publishAudioEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishAudioEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishAudio.value = false;
await publishAudioService.InsertPublishAudioDetail(data);
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",
});
}
showModalPublishAudio.value = false;
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;
spinTip.value = "加载中...";
}
};
const handleSelectPublishVideo = async () => {
if (publishVideoEnquiry.value) {
if (publishVideoEnquiry.value.keys.length > 0) {
let data: PublishData;
for (let i = 0; i < keys.value.length; i++) {
data = new PublishData();
data.FileId = keys.value[i].FileId;
data.PublishName = publishVideoEnquiry.value.keys[0].PublishName;
try {
loading.value = true;
if (publishVideoEnquiry.value) {
if (publishVideoEnquiry.value.keys.length > 0) {
// 先把选中的专辑名取出来:关掉弹窗后组件可能被销毁,就取不到了
const publishName = publishVideoEnquiry.value.keys[0].PublishName;
// 先关弹窗再发请求,遮罩才看得清
showModalPublishVideo.value = false;
await publishVideoService.InsertPublishVideoDetail(data);
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",
});
}
showModalPublishVideo.value = false;
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;
spinTip.value = "加载中...";
}
};
@@ -1121,9 +1193,16 @@ const onDownloadSelected = async (items: FamilyDmsFileViewDisplayData[]) => {
};
const onShareSelected = (items: FamilyDmsFileViewDisplayData[]) => {
if (items.length > 0) {
onShareFamily(items[0]);
// 没选中文件时原来什么都不发生,这里给个提示
if (items.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择要共享的文件",
placement: "topRight",
});
return;
}
onShareFamily(items[0]);
};
const onPublishSelected = (items: FamilyDmsFileViewDisplayData[]) => {
@@ -251,23 +251,44 @@ const onSelectChange = (selected: FamilyFolderFavoriteViewEntity[]) => {
};
const onDelete = async () => {
let fgfs: FamilyFolderFavoriteEntity[] = [];
let fgf: FamilyFolderFavoriteEntity;
keys.value.forEach((element) => {
fgf = new FamilyFolderFavoriteEntity();
fgf.UserName = element.UserName;
fgf.FolderName = element.FolderName;
fgfs.push(fgf);
});
if (keys.value.length === 0) {
notification.info({
message: "系统提示:",
description: "请选择一条记录",
placement: "topRight",
});
return;
}
try {
loading.value = true;
let fgfs: FamilyFolderFavoriteEntity[] = [];
let fgf: FamilyFolderFavoriteEntity;
keys.value.forEach((element) => {
fgf = new FamilyFolderFavoriteEntity();
fgf.UserName = element.UserName;
fgf.FolderName = element.FolderName;
fgfs.push(fgf);
});
await familyGroupService.DeleteFamilyFolderFavorites(fgfs);
await familyGroupService.DeleteFamilyFolderFavorites(fgfs).then(() => {
notification.info({
message: "系统提示:",
description: "记录删除成功",
placement: "topRight",
});
onReload();
});
} catch (error) {
notification.info({
message: "系统提示:",
description: "记录删除失败",
placement: "topRight",
});
} finally {
loading.value = false;
}
};
const onReset = () => {
+15
View File
@@ -44,12 +44,27 @@ const mode = ref<string>(route.params.mode as string)
*/
const controlsVisible = ref(true);
/** 退出全屏后让顶栏短暂不响应指针的定时器 */
let settleTimer = 0;
watch(controlsVisible, (visible) => {
document.body.classList.toggle("pv-fullscreen", !visible);
// 退出全屏时鼠标往往正好停在右上角(恢复按钮的位置,也是顶栏菜单的位置),
// 顶栏一恢复显示就会被 hover 展开下拉。让它先"冷静" 400ms,避开这次误触。
if (visible) {
window.clearTimeout(settleTimer);
document.body.classList.add("pv-settling");
settleTimer = window.setTimeout(() => {
document.body.classList.remove("pv-settling");
}, 400);
}
});
onUnmounted(() => {
document.body.classList.remove("pv-fullscreen");
document.body.classList.remove("pv-settling");
window.clearTimeout(settleTimer);
});
const toIndex = ref<number>(0)
+32 -2
View File
@@ -2,12 +2,12 @@
<div class="pa-page" :style="{
height: bsInfo.height - 120 + 'px',
}">
<VinylAudioPlayer :tracks="audios" @close="onClose" />
<VinylAudioPlayer v-model:controls="controlsVisible" :tracks="audios" @close="onClose" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { ref, onMounted, onUnmounted, watch } from "vue";
import VinylAudioPlayer from "@/components/basic/VinylAudioPlayer.vue";
import type { VinylTrack } from "@/components/basic/VinylAudioPlayer.vue";
import publishAudioService from "@/service/master/publishAudioService";
@@ -32,6 +32,36 @@ const mode = ref<string>(route.params.mode as string)
// 播放器曲目(VinylAudioPlayer 负责界面与播放)
const audios = ref<VinylTrack[]>([]);
/**
* 控制区显隐:与影视厅 PreviewVideo / 图片页 Preview 同一套机制——
* 收起控制区时给 body 挂 .pv-fullscreen,藏掉 layout 顶部的两条栏
* (标题栏 + 页面头)并把内容区撑到整屏,音乐厅真正占满全屏。
*/
const controlsVisible = ref(true);
/** 退出全屏后让顶栏短暂不响应指针的定时器 */
let settleTimer = 0;
watch(controlsVisible, (visible) => {
document.body.classList.toggle("pv-fullscreen", !visible);
// 退出全屏时鼠标往往正好停在右上角(恢复按钮的位置,也是顶栏菜单的位置),
// 顶栏一恢复显示就会被 hover 展开下拉。让它先"冷静" 400ms,避开这次误触。
if (visible) {
window.clearTimeout(settleTimer);
document.body.classList.add("pv-settling");
settleTimer = window.setTimeout(() => {
document.body.classList.remove("pv-settling");
}, 400);
}
});
onUnmounted(() => {
document.body.classList.remove("pv-fullscreen");
document.body.classList.remove("pv-settling");
window.clearTimeout(settleTimer);
});
onMounted(async () => {
// 加载歌曲信息
loadAudios()
+15
View File
@@ -39,12 +39,27 @@ const videos = ref<VideoItem[]>([]);
*/
const controlsVisible = ref(true);
/** 退出全屏后让顶栏短暂不响应指针的定时器 */
let settleTimer = 0;
watch(controlsVisible, (visible) => {
document.body.classList.toggle("pv-fullscreen", !visible);
// 退出全屏时鼠标往往正好停在右上角(恢复按钮的位置,也是顶栏菜单的位置),
// 顶栏一恢复显示就会被 hover 展开下拉。让它先"冷静" 400ms,避开这次误触。
if (visible) {
window.clearTimeout(settleTimer);
document.body.classList.add("pv-settling");
settleTimer = window.setTimeout(() => {
document.body.classList.remove("pv-settling");
}, 400);
}
});
onUnmounted(() => {
document.body.classList.remove("pv-fullscreen");
document.body.classList.remove("pv-settling");
window.clearTimeout(settleTimer);
});
onMounted(async () => {