This commit is contained in:
owenchen committed 2026-09-07 16:54:19 +08:00
1 parent 599211b895
commit 9bbb8dfd67
9 files changed
+2889 -803

No files matched your search

@@ -17,6 +17,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Linq;
using static System.Net.Mime.MediaTypeNames;
using Image = SixLabors.ImageSharp.Image;
namespace CloudBuilder.Master.Service
@@ -255,8 +256,8 @@ namespace CloudBuilder.Master.Service
{
sqlWhere = sqlWhere + string.Format(" and {0} ='{1}' ", FamilyDmsFileViewEntity.DB_CREATED_BY, service.UserId);
}
if (string.IsNullOrEmpty(sqlWhere)) sqlWhere = " and 1=0 ";
//取了顶级目录
if (string.IsNullOrEmpty(sqlWhere)) sqlWhere = string.Format(" and {0} ={1} ", FamilyDmsFileViewEntity.DB_FAMILY_NAME, FamilyDmsFileViewEntity.DB_FILE_PATH);
FamilyDmsFileViewEntity entity = FamilyDmsFileViewEntity.GetInstance(repository.GetDbContext().Database.ProviderName);
string sql = entity.GetSelectTopFrom(criteria.limit, criteria.page, criteria.orderby.StringToDbField(), criteria.orderbytag, sqlWhere);
@@ -320,11 +321,16 @@ namespace CloudBuilder.Master.Service
{
item.Url = FileTypePolicy.PackUrl(service, item.CreatedBy, item.OrderKey, item.TranscodeIndc);
}
data.Families = list.Select(x => new FamilyDmsFileViewDisplayData(x)
{
FileType = FileTypePolicy.GetType(x.OrderKey),
FormattedPic = FileTypePolicy.PackUrl(service, x.CreatedBy, x.OrderKey, YesNoPolicy.YES)
}).ToArray();
}
data.Limit = criteria.limit;
data.Page = criteria.page;
data.Families = list.Select(x => new FamilyDmsFileViewDisplayData(x) { FileType = FileTypePolicy.GetType(x.OrderKey) }).ToArray();
data.Total = count;
//data.Sql = sql;
data.ErrorMessage = err;
@@ -1504,7 +1510,7 @@ namespace CloudBuilder.Master.Service
{
IRepository<FamilyGroupManagerUserViewEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerUserViewEntity>>();
FamilyGroupManagerUserViewEntity[] ents = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.UserName == service.UserId).ToArray();
FamilyGroupManagerUserViewEntity[] ents = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.UserName == service.UserId && x.ValidIndc=="Y").ToArray();
List<SelectOption> l = new List<SelectOption>();
SelectOption selectOption;
@@ -1530,7 +1536,7 @@ namespace CloudBuilder.Master.Service
IRepository<FamilyGroupEntity> repositoryFamilyGroup = repository.GetRepository<IRepository<FamilyGroupEntity>>();
FamilyGroupEntity group = repositoryFamilyGroup.DetachedEntities.Where(x => x.FamilyName == familyName).FirstOrDefault()!;
FamilyGroupEntity group = repositoryFamilyGroup.DetachedEntities.Where(x => x.FamilyName == familyName && x.ValidIndc==YesNoPolicy.YES).FirstOrDefault()!;
if (group == null) return l.ToArray();
selectOption = new SelectOption();
@@ -152,6 +152,19 @@ namespace CloudBuilder.Master.Service
IsSharePermission = true,
}).ToArray();
}
else
{
data.FamilyGroupManagers = null;
fgms = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.FamilyName == key && x.UserName == service.UserId).ToArray();
if (fgms != null && fgms.Length > 0)
{
data.FamilyGroupManagers = fgms.Where(x => x.ValidIndc == YesNoPolicy.YES)!.Select(x => new FamilyGroupManagerDisplayData(x)
{ UserLocalName = users!.Where(y => y.UserName == x.UserName).FirstOrDefault()!.UserLocalName }).ToArray();
data.FamilyGroupRequests = fgms.Where(x => x.ValidIndc == YesNoPolicy.NO)!.Select(x => new FamilyGroupManagerDisplayData(x)
{ UserLocalName = users!.Where(y => y.UserName == x.UserName).FirstOrDefault()!.UserLocalName }).ToArray();
}
}
data.IsManager = isManager;
@@ -570,7 +583,7 @@ namespace CloudBuilder.Master.Service
bool isManager = false;
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
FamilyGroupManagerEntity[] fgms = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.ManagerIndc == YesNoPolicy.YES && x.FamilyName == key && x.ValidIndc == YesNoPolicy.YES).ToArray();
FamilyGroupManagerEntity[] fgms = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.ManagerIndc == YesNoPolicy.YES && x.UserName == service.UserId && x.FamilyName == key && x.ValidIndc == YesNoPolicy.YES).ToArray();
if (fgms == null || fgms.Length == 0)
{
throw new ValidatedException("您不是管理员,不能解散");
@@ -588,7 +601,7 @@ namespace CloudBuilder.Master.Service
{
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
FamilyGroupManagerEntity org = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.FamilyName == manager.FamilyName && x.UserName == service.UserId).FirstOrDefault()!;
if (org != null) { return; }
if (org != null) { throw new ValidatedException("您已申请加入,耐心等待审核。"); }
org = new FamilyGroupManagerEntity();
org.FamilyName = manager.FamilyName;
@@ -623,6 +636,13 @@ namespace CloudBuilder.Master.Service
public void UpdateFamilyGroupManager(FamilyGroupManagerEntity manager)
{
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
FamilyGroupManagerEntity[] fgms = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.ManagerIndc == YesNoPolicy.YES && x.UserName == service.UserId && x.FamilyName == manager.FamilyName && x.ValidIndc == YesNoPolicy.YES).ToArray();
if (fgms == null || fgms.Length == 0)
{
throw new ValidatedException("您不是管理员");
}
FamilyGroupManagerEntity org = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.FamilyName == manager.FamilyName && x.UserName == manager.UserName).FirstOrDefault()!;
if (org == null) { return; }
@@ -636,6 +656,13 @@ namespace CloudBuilder.Master.Service
public void DeleteFamilyGroupManager(FamilyGroupManagerEntity manager)
{
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
FamilyGroupManagerEntity[] fgms = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.ManagerIndc == YesNoPolicy.YES && x.UserName == service.UserId && x.FamilyName == manager.FamilyName && x.ValidIndc == YesNoPolicy.YES).ToArray();
if (fgms == null || fgms.Length == 0)
{
throw new ValidatedException("您不是管理员");
}
FamilyGroupManagerEntity org = repositoryFamilyGroupManager.DetachedEntities.Where(x => x.FamilyName == manager.FamilyName && x.UserName == manager.UserName).FirstOrDefault()!;
if (org == null) { return; }
@@ -32,5 +32,7 @@ namespace CloudBuilder.Master.Data
public string? IsPlay { get; set; }
public string? IsPause { get; set; }
public string? FormattedPic { get; set; }
}
}
@@ -38,7 +38,7 @@
"Issuer": "Owen Chen",
"Audience": "Cloud Builder",
"Secret": "{8619F7C3-B53C-4B85-99F0-983D351ECD82}",
"AccessExpireMins": 120, //4小时过期
"AccessExpireMins": 480, //8小时过期
"RefreshExpireMins": 1440, // 1天
"IsRefreshAbsoluteExpired": false
},
@@ -0,0 +1,488 @@
<template>
<div class="my-computer" ref="containerRef">
<div class="my-computer-header">
<div class="view-toggles">
<a-tooltip title="列表视图">
<a-button
size="small"
:type="viewMode === 'list' ? 'primary' : 'default'"
@click="viewMode = 'list'"
>
<UnorderedListOutlined />
</a-button>
</a-tooltip>
<a-tooltip title="图标视图">
<a-button
size="small"
:type="viewMode === 'icon' ? 'primary' : 'default'"
@click="viewMode = 'icon'"
>
<AppstoreOutlined />
</a-button>
</a-tooltip>
</div>
</div>
<div class="my-computer-body" v-if="viewMode === 'icon'">
<div
v-for="record in datas"
:key="record.FileId + '-' + record.FileName"
class="file-card-wrapper"
@click="onCardClick(record)"
@dblclick="onCardDblClick(record)"
>
<!-- checkbox -->
<div class="file-checkbox-wrapper">
<a-checkbox
:checked="isSelected(record)"
@click.stop="toggleSelect(record)"
/>
</div>
<!-- 状态角标:右上角 -->
<div class="file-status-badge">
<LockOutlined
v-if="record.PermissionIndc === 'N'"
class="badge-lock"
/>
<template v-if="record.PermissionIndc === 'Y'">
<UnlockOutlined class="badge-unlock" />
<ShareAltOutlined
v-if="record.FavoriteIndc === 'Y'"
class="badge-share"
/>
</template>
</div>
<div class="file-content">
<template v-if="record.IsDirectoryIndc == 'Y'">
<div class="folder-icon">
<FolderOutlined />
</div>
<div class="file-name" :title="record.OrgFileName">
{{ record.OrgFileName }}
</div>
</template>
<template v-else-if="isImage(record.OrderKey)">
<div class="image-thumb">
<img
:src="record.Url"
:title="record.OrgFileName"
@click.stop="$emit('preview-image', record)"
/>
</div>
<div class="file-name" :title="record.OrgFileName">
{{ record.OrgFileName }}
</div>
</template>
<template v-else-if="isVideo(record.OrderKey)">
<div class="video-thumb">
<img
:src="record.FormattedPic.replace('.m3u8', '.png')"
:title="record.OrgFileName"
/>
<div class="play-overlay">
<PlayCircleOutlined />
</div>
</div>
<div class="file-name" :title="record.OrgFileName">
{{ record.OrgFileName }}
</div>
</template>
<template v-else-if="isAudio(record.OrderKey)">
<div
class="audio-icon"
:class="{
playing: record.IsPlay == 'Y' && record.IsPause != 'Y',
}"
>
<cust-icon-font
size="54"
type="icon-playmp3"
style="color: #ff7878"
/>
</div>
<div class="file-name" :title="record.OrgFileName">
{{ record.OrgFileName }}
</div>
</template>
<template v-else>
<div class="file-icon">
<FileOutlined />
</div>
<div class="file-name" :title="record.OrgFileName">
{{ record.OrgFileName }}
</div>
</template>
</div>
</div>
<a-empty v-if="!datas || datas.length === 0" description="暂无文件" />
</div>
<div class="my-computer-body list-body" v-else>
<div
v-for="record in datas"
:key="record.FileId + '-' + record.FileName"
class="list-item"
:class="{ selected: isSelected(record) }"
@click="onCardClick(record)"
@dblclick="onCardDblClick(record)"
>
<a-checkbox
:checked="isSelected(record)"
@click.stop="toggleSelect(record)"
/>
<div class="list-icon">
<template v-if="record.IsDirectoryIndc == 'Y'">
<FolderOutlined style="color: #faad14" />
</template>
<template v-else-if="isImage(record.OrderKey)">
<FileImageOutlined style="color: #52c41a" />
</template>
<template v-else-if="isVideo(record.OrderKey)">
<VideoCameraOutlined style="color: #1890ff" />
</template>
<template v-else-if="isAudio(record.OrderKey)">
<PlayCircleOutlined style="color: #eb2f96" />
</template>
<template v-else>
<FileOutlined style="color: #8c8c8c" />
</template>
</div>
<div class="list-name-wrap">
<span class="list-name" :title="record.OrgFileName">{{
record.OrgFileName
}}</span>
<span class="list-status-icon">
<LockOutlined
v-if="record.PermissionIndc === 'N'"
class="icon-lock"
/>
<template v-if="record.PermissionIndc === 'Y'">
<UnlockOutlined class="icon-unlock" />
<ShareAltOutlined
v-if="record.FavoriteIndc === 'Y'"
class="icon-share"
/>
</template>
</span>
</div>
<div class="list-size">{{ formatSize(record.FileSize) }}</div>
<div class="list-date">{{ formatDate(record.CreatedDatetime) }}</div>
</div>
<a-empty v-if="!datas || datas.length === 0" description="暂无文件" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import {
FolderOutlined,
FileOutlined,
FileImageOutlined,
VideoCameraOutlined,
PlayCircleOutlined,
UnorderedListOutlined,
AppstoreOutlined,
LockOutlined,
UnlockOutlined,
ShareAltOutlined,
} from "@ant-design/icons-vue";
import { FamilyDmsFileViewDisplayData } from "@/data/auto/familyDmsFileViewDisplayData";
import { notification } from "ant-design-vue";
const props = defineProps<{
datas: FamilyDmsFileViewDisplayData[];
selectedKeys: FamilyDmsFileViewDisplayData[];
}>();
const emit = defineEmits([
"update:selectedKeys",
"select-change",
"open-folder",
"open-file",
"preview-image",
]);
const viewMode = ref<"icon" | "list">("icon");
const isSelected = (record: FamilyDmsFileViewDisplayData) => {
return props.selectedKeys.some((s) => s.FileId === record.FileId);
};
/**
* 单选逻辑:
* 如果当前已经选中,则清空;否则选中当前这一项
*/
const toggleSelect = (record: FamilyDmsFileViewDisplayData) => {
let newKeys: FamilyDmsFileViewDisplayData[];
if (isSelected(record)) {
// 点击已选中项 → 取消选择
newKeys = [];
} else {
// 点击未选中项 → 只选中当前一个
newKeys = [record];
}
emit("update:selectedKeys", newKeys);
emit("select-change", newKeys);
};
const onCardClick = (record: FamilyDmsFileViewDisplayData) => {
toggleSelect(record);
};
const onCardDblClick = (record: FamilyDmsFileViewDisplayData) => {
if (record.IsDirectoryIndc == "Y") {
if (record.PermissionIndc == "Y") emit("open-folder", record);
else {
notification.info({
message: "系统提示:",
description: "你还没有权限访问该文件夹",
placement: "topRight",
});
}
} else {
emit("open-file", record);
}
};
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 formatSize = (size: number) => {
size = size * 1024;
if (!size) return "-";
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return (size / 1024).toFixed(1) + " KB";
if (size < 1024 * 1024 * 1024) return (size / 1024 / 1024).toFixed(1) + " MB";
return (size / 1024 / 1024 / 1024).toFixed(2) + " GB";
};
const formatDate = (date: any) => {
if (!date) return "-";
const d = new Date(date);
if (isNaN(d.getTime())) return "-";
return (
d.getFullYear() +
"-" +
String(d.getMonth() + 1).padStart(2, "0") +
"-" +
String(d.getDate()).padStart(2, "0") +
" " +
String(d.getHours()).padStart(2, "0") +
":" +
String(d.getMinutes()).padStart(2, "0")
);
};
</script>
<style scoped>
.my-computer {
padding: 8px;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
.my-computer-header {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 8px 4px;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 8px;
}
.view-toggles {
display: flex;
gap: 4px;
}
.my-computer-body {
flex: 1;
overflow-y: auto;
padding: 4px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
gap: 16px;
}
.my-computer-body.list-body {
flex-wrap: nowrap;
flex-direction: column;
gap: 0;
}
.file-card-wrapper {
width: 120px;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
padding: 8px;
border-radius: 6px;
transition: all 0.2s;
position: relative;
}
.file-card-wrapper:hover {
background: #f5f5f5;
}
.file-checkbox-wrapper {
position: absolute;
top: 2px;
left: 4px;
z-index: 1;
}
/* =========图标视图状态角标 右上角========= */
.file-status-badge {
position: absolute;
top: 2px;
right: 4px;
z-index: 1;
display: flex;
gap: 4px;
}
.badge-lock {
font-size: 16px;
color: #8c8c8c;
}
.badge-unlock {
font-size: 16px;
color: #52c41a;
}
.badge-share {
font-size: 16px;
color: #1890ff;
}
.file-content {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.folder-icon,
.file-icon,
.audio-icon {
font-size: 56px;
color: #faad14;
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 80px;
}
.file-icon {
color: #8c8c8c;
}
.audio-icon {
color: #eb2f96;
}
.audio-icon.playing {
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.image-thumb,
.video-thumb {
width: 100px;
height: 100px;
border-radius: 4px;
overflow: hidden;
position: relative;
background: #f0f0f0;
}
.image-thumb img,
.video-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.video-thumb .play-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.2);
font-size: 36px;
color: #fff;
opacity: 0;
transition: opacity 0.2s;
}
.video-thumb:hover .play-overlay {
opacity: 1;
}
.file-name {
font-size: 12px;
margin-top: 4px;
text-align: center;
max-width: 110px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.list-item {
display: flex;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
border-radius: 4px;
transition: background 0.15s;
gap: 12px;
}
.list-item:hover {
background: #f5f5f5;
}
.list-item.selected {
background: #e6f4ff;
}
.list-icon {
font-size: 20px;
width: 28px;
display: flex;
justify-content: center;
}
/* =========列表视图文件名+状态图标容器========= */
.list-name-wrap {
flex: 1;
display: flex;
align-items: center;
gap: 6px;
overflow: hidden;
}
.list-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.list-status-icon {
display: flex;
align-items: center;
gap: 4px;
}
.icon-lock {
font-size: 14px;
color: #8c8c8c;
}
.icon-unlock {
font-size: 14px;
color: #52c41a;
}
.icon-share {
font-size: 14px;
color: #1890ff;
}
.list-size,
.list-date {
color: #8c8c8c;
font-size: 13px;
width: 120px;
text-align: right;
}
.list-date {
width: 160px;
}
</style>
@@ -0,0 +1,287 @@
<template>
<div class="operator-station" v-if="!isDirectoryTop">
<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>
</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>
<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>
<template v-else-if="isDirectorySelected">
<a-tooltip :title="favorite">
<a-button type="text" :icon="h(ShareAltOutlined)" @click="$emit('set-share-folder')"
>{{favorite}}</a-button
>
</a-tooltip>
</template>
</div>
<a-divider type="vertical" v-if="hasSelection" />
<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 { FamilyDmsFileViewDisplayData } from "@/data/auto/familyDmsFileViewDisplayData";
import type { UploadProps } from "ant-design-vue";
interface BreadcrumbItem {
value: string;
displayName: string;
}
const props = defineProps<{
selectedItems: FamilyDmsFileViewDisplayData[];
pathStack: BreadcrumbItem[];
uploadUrl: string;
headers: any;
canCreate: boolean;
canAmend: boolean;
canDelete: boolean;
canView: boolean;
}>();
const emit = defineEmits([
"create-folder",
"set-share-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 favorite = computed(() => {
// 单选模式,取第一条选中
const record = props.selectedItems[0];
if (!record) return "";
// 无权限,不支持分享
if (record.PermissionIndc !== "Y") return "";
if (record.FavoriteIndc === "N") {
return "设置分享";
} else if (record.FavoriteIndc === "Y") {
return "取消分享";
}
return "";
});
const isDirectoryTop = computed(() => props.pathStack.length < 2);
const isSingleItem = computed(() => props.selectedItems.length === 1);
const selectedItem = computed(() => {
return props.selectedItems[0] || ({} as FamilyDmsFileViewDisplayData);
});
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>
@@ -223,7 +223,7 @@
</template>
</a-collapse-panel>
</a-collapse>
<a-collapse v-model:activeKey="activeKey" v-if="data.IsManager">
<a-collapse v-model:activeKey="activeKey">
<a-collapse-panel key="2" header="待审核成员名单">
<a-table
bordered
@@ -252,8 +252,8 @@
>
{{ datas.record.Notice }}
</template>
<template
v-else-if="datas.column.dataIndex === 'ok' && !isEdit"
<template
v-else-if="data.IsManager && datas.column.dataIndex === 'ok' && !isEdit"
>
<CheckCircleTwoTone
:style="{ fontSize: '24px', color: 'green' }"
@@ -266,7 +266,7 @@
/>
</template>
<template
v-else-if="datas.column.dataIndex === 'reject' && !isEdit"
v-else-if="data.IsManager && datas.column.dataIndex === 'reject' && !isEdit"
>
<CloseCircleOutlined
:style="{ fontSize: '24px', color: 'red' }"
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff