mirror of https://github.com/halo-dev/halo
Remove attachment thumbnails modal and related code
Deleted the AttachmentThumbnailsModal, related components, and composables for managing and displaying attachment thumbnails. Updated AttachmentList and AttachmentDetailModal to remove references to the thumbnails modal and related permissions. Simplified thumbnail display to show only available image thumbnails in the detail modal, and updated i18n files to remove unused thumbnail modal and status translations. Centralized thumbnail width mapping in utils/thumbnail.ts.
parent
4ff058eac2
commit
69f126efa4
|
@ -33,14 +33,12 @@ import { useRouteQuery } from "@vueuse/router";
|
|||
import type { Ref } from "vue";
|
||||
import { computed, onMounted, provide, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import RiMultiImageLine from "~icons/ri/multi-image-line";
|
||||
import AttachmentDetailModal from "./components/AttachmentDetailModal.vue";
|
||||
import AttachmentError from "./components/AttachmentError.vue";
|
||||
import AttachmentGroupList from "./components/AttachmentGroupList.vue";
|
||||
import AttachmentListItem from "./components/AttachmentListItem.vue";
|
||||
import AttachmentLoading from "./components/AttachmentLoading.vue";
|
||||
import AttachmentPoliciesModal from "./components/AttachmentPoliciesModal.vue";
|
||||
import AttachmentThumbnailsModal from "./components/AttachmentThumbnailsModal.vue";
|
||||
import AttachmentUploadModal from "./components/AttachmentUploadModal.vue";
|
||||
import { useAttachmentControl } from "./composables/use-attachment";
|
||||
import { useFetchAttachmentGroup } from "./composables/use-attachment-group";
|
||||
|
@ -230,9 +228,6 @@ watch(
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Thumbnails modal
|
||||
const thumbnailsVisible = ref(false);
|
||||
</script>
|
||||
<template>
|
||||
<AttachmentDetailModal
|
||||
|
@ -261,23 +256,11 @@ const thumbnailsVisible = ref(false);
|
|||
v-if="policyVisible"
|
||||
@close="policyVisible = false"
|
||||
/>
|
||||
<AttachmentThumbnailsModal
|
||||
v-if="thumbnailsVisible"
|
||||
@close="thumbnailsVisible = false"
|
||||
/>
|
||||
<VPageHeader :title="$t('core.attachment.title')">
|
||||
<template #icon>
|
||||
<IconFolder />
|
||||
</template>
|
||||
<template #actions>
|
||||
<HasPermission :permissions="['*']">
|
||||
<VButton size="sm" @click="thumbnailsVisible = true">
|
||||
<template #icon>
|
||||
<RiMultiImageLine />
|
||||
</template>
|
||||
{{ $t("core.attachment.actions.thumbnails") }}
|
||||
</VButton>
|
||||
</HasPermission>
|
||||
<VButton
|
||||
v-permission="['system:attachments:manage']"
|
||||
size="sm"
|
||||
|
|
|
@ -232,16 +232,15 @@ const showDisplayNameForm = ref(false);
|
|||
>
|
||||
<AttachmentPermalinkList :attachment="attachment" />
|
||||
</VDescriptionItem>
|
||||
<HasPermission
|
||||
v-if="!!attachment?.status?.thumbnails"
|
||||
:permissions="['*']"
|
||||
>
|
||||
<VDescriptionItem
|
||||
v-if="
|
||||
isImage(attachment?.spec.mediaType) &&
|
||||
!!attachment?.status?.thumbnails
|
||||
"
|
||||
:label="$t('core.attachment.detail_modal.fields.thumbnails')"
|
||||
>
|
||||
<AttachmentSingleThumbnailList :attachment="attachment" />
|
||||
</VDescriptionItem>
|
||||
</HasPermission>
|
||||
</VDescription>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { SIZE_MAP } from "../composables/use-thumbnail-detail";
|
||||
import { THUMBNAIL_WIDTH_MAP } from "@/utils/thumbnail";
|
||||
|
||||
const { size, permalink } = defineProps<{
|
||||
size: string;
|
||||
|
@ -19,9 +19,7 @@ const { size, permalink } = defineProps<{
|
|||
/>
|
||||
</a>
|
||||
<div class="flex min-w-0 flex-1 flex-col space-y-2 text-xs text-gray-900">
|
||||
<span class="font-semibold">
|
||||
{{ SIZE_MAP[size] }}
|
||||
</span>
|
||||
<span class="font-semibold"> {{ THUMBNAIL_WIDTH_MAP[size] }}w </span>
|
||||
<a
|
||||
:href="permalink"
|
||||
target="_blank"
|
||||
|
|
|
@ -38,7 +38,7 @@ const thumbnails = computed(() => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<ul class="flex flex-col space-y-2">
|
||||
<ul v-if="thumbnails.length" class="flex flex-col space-y-2">
|
||||
<AttachmentSingleThumbnailItem
|
||||
v-for="thumbnail in thumbnails"
|
||||
:key="thumbnail.size"
|
||||
|
@ -46,4 +46,7 @@ const thumbnails = computed(() => {
|
|||
:permalink="thumbnail.permalink"
|
||||
/>
|
||||
</ul>
|
||||
<span v-else>
|
||||
{{ $t("core.attachment.detail_modal.preview.not_support_thumbnail") }}
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { formatDatetime } from "@/utils/date";
|
||||
import {
|
||||
LocalThumbnailStatusPhaseEnum,
|
||||
type LocalThumbnail,
|
||||
} from "@halo-dev/api-client";
|
||||
import { VButton, VEntity, VEntityField } from "@halo-dev/components";
|
||||
import { toRefs } from "vue";
|
||||
import { useThumbnailControl } from "../composables/use-thumbnail-control";
|
||||
import {
|
||||
SIZE_MAP,
|
||||
useThumbnailDetail,
|
||||
} from "../composables/use-thumbnail-detail";
|
||||
|
||||
const props = defineProps<{
|
||||
thumbnail: LocalThumbnail;
|
||||
}>();
|
||||
|
||||
const { thumbnail } = toRefs(props);
|
||||
|
||||
const { phase } = useThumbnailDetail(thumbnail);
|
||||
const { handleRetry } = useThumbnailControl(thumbnail);
|
||||
</script>
|
||||
<template>
|
||||
<VEntity>
|
||||
<template #start>
|
||||
<VEntityField>
|
||||
<template #description>
|
||||
<a
|
||||
:href="thumbnail.spec.thumbnailUri"
|
||||
target="_blank"
|
||||
class="block flex-none"
|
||||
>
|
||||
<img
|
||||
v-if="
|
||||
thumbnail.status.phase ===
|
||||
LocalThumbnailStatusPhaseEnum.Succeeded
|
||||
"
|
||||
:src="thumbnail.spec.thumbnailUri"
|
||||
alt=""
|
||||
class="h-10 w-10 rounded-md object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-10 w-10 items-center justify-center rounded-md border"
|
||||
>
|
||||
<component
|
||||
:is="phase.icon"
|
||||
class="h-4.5 w-4.5"
|
||||
:class="phase.color"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField :title="SIZE_MAP[thumbnail.spec.size]">
|
||||
<template #description>
|
||||
<a
|
||||
:href="thumbnail.spec.thumbnailUri"
|
||||
target="_blank"
|
||||
class="truncate text-xs text-gray-500 hover:text-gray-900"
|
||||
>
|
||||
{{ thumbnail.spec.thumbnailUri }}
|
||||
</a>
|
||||
</template>
|
||||
</VEntityField>
|
||||
</template>
|
||||
<template #end>
|
||||
<VEntityField
|
||||
:description="formatDatetime(thumbnail.metadata.creationTimestamp)"
|
||||
/>
|
||||
<VEntityField>
|
||||
<template #description>
|
||||
<component
|
||||
:is="phase.icon"
|
||||
v-tooltip="$t(phase.label)"
|
||||
class="h-4.5 w-4.5"
|
||||
:class="phase.color"
|
||||
/>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField
|
||||
v-if="
|
||||
thumbnail.status.phase !== LocalThumbnailStatusPhaseEnum.Succeeded
|
||||
"
|
||||
>
|
||||
<template #description>
|
||||
<VButton size="sm" @click="handleRetry">
|
||||
{{ $t("core.common.buttons.retry") }}
|
||||
</VButton>
|
||||
</template>
|
||||
</VEntityField>
|
||||
</template>
|
||||
</VEntity>
|
||||
</template>
|
|
@ -1,216 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import FilterDropdown from "@/components/filter/FilterDropdown.vue";
|
||||
import { storageAnnotations } from "@/constants/annotations";
|
||||
import {
|
||||
coreApiClient,
|
||||
LocalThumbnailStatusPhaseEnum,
|
||||
} from "@halo-dev/api-client";
|
||||
import {
|
||||
Toast,
|
||||
VButton,
|
||||
VEmpty,
|
||||
VEntityContainer,
|
||||
VLoading,
|
||||
VModal,
|
||||
VPagination,
|
||||
VSpace,
|
||||
} from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { chunk } from "lodash-es";
|
||||
import { ref, useTemplateRef, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import AttachmentThumbnailItem from "./AttachmentThumbnailItem.vue";
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "close"): void;
|
||||
}>();
|
||||
|
||||
const modal = useTemplateRef<InstanceType<typeof VModal> | null>("modal");
|
||||
|
||||
const page = ref(1);
|
||||
const size = ref(20);
|
||||
const selectedStatus = ref<LocalThumbnailStatusPhaseEnum | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
watch(
|
||||
() => selectedStatus.value,
|
||||
() => {
|
||||
page.value = 1;
|
||||
}
|
||||
);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const {
|
||||
data: thumbnails,
|
||||
isLoading,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["core:attachments:thumbnails", page, size, selectedStatus],
|
||||
queryFn: async () => {
|
||||
const fieldSelector: string[] = [];
|
||||
if (selectedStatus.value) {
|
||||
fieldSelector.push(`status.phase=${selectedStatus.value}`);
|
||||
}
|
||||
|
||||
const { data } =
|
||||
await coreApiClient.storage.localThumbnail.listLocalThumbnail({
|
||||
page: page.value,
|
||||
size: size.value,
|
||||
fieldSelector,
|
||||
});
|
||||
return data;
|
||||
},
|
||||
refetchInterval: (data) => {
|
||||
const hasAbnormalData = data?.items?.some(
|
||||
(thumbnail) =>
|
||||
thumbnail.status.phase !== LocalThumbnailStatusPhaseEnum.Succeeded
|
||||
);
|
||||
|
||||
return hasAbnormalData ? 1000 : false;
|
||||
},
|
||||
});
|
||||
|
||||
async function handleRetryAllFailed() {
|
||||
try {
|
||||
const { data } =
|
||||
await coreApiClient.storage.localThumbnail.listLocalThumbnail({
|
||||
fieldSelector: [`status.phase=${LocalThumbnailStatusPhaseEnum.Failed}`],
|
||||
});
|
||||
const failedThumbnails = data.items;
|
||||
|
||||
if (!failedThumbnails.length) {
|
||||
Toast.info(
|
||||
t(
|
||||
"core.attachment.thumbnails_modal.operations.retry_all_failed.tips_empty"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const chunkedFailedThumbnails = chunk(failedThumbnails, 5);
|
||||
|
||||
for (const chunk of chunkedFailedThumbnails) {
|
||||
await Promise.all(
|
||||
chunk.map(async (thumbnail) => {
|
||||
await coreApiClient.storage.localThumbnail.patchLocalThumbnail({
|
||||
name: thumbnail.metadata.name,
|
||||
jsonPatchInner: [
|
||||
{
|
||||
op: "add",
|
||||
path: "/status/phase",
|
||||
value: LocalThumbnailStatusPhaseEnum.Pending,
|
||||
},
|
||||
{
|
||||
op: "add",
|
||||
path: "/metadata/annotations",
|
||||
value: {
|
||||
[storageAnnotations.RETRY_TIMESTAMP]: Date.now().toString(),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Toast.success(
|
||||
t(
|
||||
"core.attachment.thumbnails_modal.operations.retry_all_failed.tips_success"
|
||||
)
|
||||
);
|
||||
await refetch();
|
||||
} catch (error) {
|
||||
console.error("Failed to retry all failed thumbnails", error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<VModal
|
||||
ref="modal"
|
||||
:centered="false"
|
||||
:width="1000"
|
||||
:title="$t('core.attachment.thumbnails_modal.title')"
|
||||
:layer-closable="true"
|
||||
@close="emit('close')"
|
||||
>
|
||||
<div>
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<VSpace spacing="lg" class="flex-wrap">
|
||||
<FilterDropdown
|
||||
v-model="selectedStatus"
|
||||
:items="[
|
||||
{
|
||||
label: $t('core.common.filters.item_labels.all'),
|
||||
value: undefined,
|
||||
},
|
||||
{
|
||||
label: $t('core.attachment.thumbnails.phase.pending'),
|
||||
value: LocalThumbnailStatusPhaseEnum.Pending,
|
||||
},
|
||||
{
|
||||
label: $t('core.attachment.thumbnails.phase.succeeded'),
|
||||
value: LocalThumbnailStatusPhaseEnum.Succeeded,
|
||||
},
|
||||
{
|
||||
label: $t('core.attachment.thumbnails.phase.failed'),
|
||||
value: LocalThumbnailStatusPhaseEnum.Failed,
|
||||
},
|
||||
]"
|
||||
:label="$t('core.common.filters.labels.status')"
|
||||
/>
|
||||
</VSpace>
|
||||
<VButton size="sm" @click="handleRetryAllFailed">
|
||||
{{
|
||||
$t(
|
||||
"core.attachment.thumbnails_modal.operations.retry_all_failed.button"
|
||||
)
|
||||
}}
|
||||
</VButton>
|
||||
</div>
|
||||
<VLoading v-if="isLoading" />
|
||||
<VEmpty
|
||||
v-else-if="!thumbnails?.items?.length"
|
||||
:title="$t('core.attachment.thumbnails_modal.empty.title')"
|
||||
:message="$t('core.attachment.thumbnails_modal.empty.message')"
|
||||
>
|
||||
<template #actions>
|
||||
<VButton @click="refetch">
|
||||
{{ $t("core.common.buttons.refresh") }}
|
||||
</VButton>
|
||||
</template>
|
||||
</VEmpty>
|
||||
<div v-else class="overflow-hidden rounded-base border">
|
||||
<VEntityContainer>
|
||||
<AttachmentThumbnailItem
|
||||
v-for="thumbnail in thumbnails.items"
|
||||
:key="thumbnail.metadata.name"
|
||||
:thumbnail="thumbnail"
|
||||
/>
|
||||
</VEntityContainer>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<VPagination
|
||||
v-model:page="page"
|
||||
v-model:size="size"
|
||||
:page-label="$t('core.components.pagination.page_label')"
|
||||
:size-label="$t('core.components.pagination.size_label')"
|
||||
:total-label="
|
||||
$t('core.components.pagination.total_label', {
|
||||
total: thumbnails?.total || 0,
|
||||
})
|
||||
"
|
||||
:total="thumbnails?.total || 0"
|
||||
:size-options="[20, 30, 50, 100]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<VButton @click="modal?.close()">
|
||||
{{ $t("core.common.buttons.close") }}
|
||||
</VButton>
|
||||
</template>
|
||||
</VModal>
|
||||
</template>
|
|
@ -1,46 +0,0 @@
|
|||
import { storageAnnotations } from "@/constants/annotations";
|
||||
import {
|
||||
coreApiClient,
|
||||
LocalThumbnailStatusPhaseEnum,
|
||||
type LocalThumbnail,
|
||||
} from "@halo-dev/api-client";
|
||||
import { Toast } from "@halo-dev/components";
|
||||
import { useQueryClient } from "@tanstack/vue-query";
|
||||
import type { Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
export function useThumbnailControl(thumbnail: Ref<LocalThumbnail>) {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useI18n();
|
||||
|
||||
async function handleRetry() {
|
||||
await coreApiClient.storage.localThumbnail.patchLocalThumbnail({
|
||||
name: thumbnail.value.metadata.name,
|
||||
jsonPatchInner: [
|
||||
{
|
||||
op: "add",
|
||||
path: "/status/phase",
|
||||
value: LocalThumbnailStatusPhaseEnum.Pending,
|
||||
},
|
||||
{
|
||||
op: "add",
|
||||
path: "/metadata/annotations",
|
||||
value: {
|
||||
...thumbnail.value.metadata.annotations,
|
||||
[storageAnnotations.RETRY_TIMESTAMP]: Date.now().toString(),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["core:attachments:thumbnails"],
|
||||
});
|
||||
|
||||
Toast.success(t("core.common.toast.operation_success"));
|
||||
}
|
||||
|
||||
return {
|
||||
handleRetry,
|
||||
};
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
import {
|
||||
GetThumbnailByUriSizeEnum,
|
||||
LocalThumbnailStatusPhaseEnum,
|
||||
type LocalThumbnail,
|
||||
} from "@halo-dev/api-client";
|
||||
import { IconCheckboxCircle, IconErrorWarning } from "@halo-dev/components";
|
||||
import { computed, type Component, type Ref } from "vue";
|
||||
import RiTimeLine from "~icons/ri/time-line";
|
||||
|
||||
export const SIZE_MAP: Record<GetThumbnailByUriSizeEnum, string> = {
|
||||
XL: "1600w",
|
||||
L: "1200w",
|
||||
M: "800w",
|
||||
S: "400w",
|
||||
};
|
||||
|
||||
export const PHASE_MAP: Record<
|
||||
LocalThumbnailStatusPhaseEnum,
|
||||
{
|
||||
icon: Component;
|
||||
label: string;
|
||||
color: string;
|
||||
}
|
||||
> = {
|
||||
PENDING: {
|
||||
icon: RiTimeLine,
|
||||
label: "core.attachment.thumbnails.phase.pending",
|
||||
color: "text-gray-500",
|
||||
},
|
||||
SUCCEEDED: {
|
||||
icon: IconCheckboxCircle,
|
||||
label: "core.attachment.thumbnails.phase.succeeded",
|
||||
color: "text-green-500",
|
||||
},
|
||||
FAILED: {
|
||||
icon: IconErrorWarning,
|
||||
label: "core.attachment.thumbnails.phase.failed",
|
||||
color: "text-red-500",
|
||||
},
|
||||
};
|
||||
export function useThumbnailDetail(thumbnail: Ref<LocalThumbnail>) {
|
||||
const phase = computed(() => {
|
||||
return PHASE_MAP[
|
||||
thumbnail.value.status.phase || LocalThumbnailStatusPhaseEnum.Pending
|
||||
];
|
||||
});
|
||||
|
||||
return {
|
||||
phase,
|
||||
};
|
||||
}
|
|
@ -12,6 +12,7 @@ import {
|
|||
ExtensionColumn,
|
||||
ExtensionColumns,
|
||||
ExtensionCommands,
|
||||
ExtensionDetails,
|
||||
ExtensionDocument,
|
||||
ExtensionDraggable,
|
||||
ExtensionDropcursor,
|
||||
|
@ -44,7 +45,6 @@ import {
|
|||
ExtensionTrailingNode,
|
||||
ExtensionUnderline,
|
||||
ExtensionVideo,
|
||||
ExtensionDetails,
|
||||
RichTextEditor,
|
||||
useEditor,
|
||||
} from "../index";
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import ToolbarItem from "@/components/toolbar/ToolbarItem.vue";
|
||||
import { i18n } from "@/locales";
|
||||
import type { Editor, Range } from "@/tiptap/vue-3";
|
||||
import type { ExtensionOptions } from "@/types";
|
||||
import TiptapDetails, { type DetailsOptions } from "@tiptap/extension-details";
|
||||
import TiptapDetailsContent from "@tiptap/extension-details-content";
|
||||
import TiptapDetailsSummary from "@tiptap/extension-details-summary";
|
||||
import type { Editor, Range } from "@/tiptap/vue-3";
|
||||
import { markRaw } from "vue";
|
||||
import ToolbarItem from "@/components/toolbar/ToolbarItem.vue";
|
||||
import { i18n } from "@/locales";
|
||||
import MdiExpandHorizontal from "~icons/mdi/expand-horizontal";
|
||||
|
||||
const getRenderContainer = (node: HTMLElement) => {
|
||||
|
|
|
@ -10,6 +10,7 @@ import ExtensionBold from "./bold";
|
|||
import ExtensionBulletList from "./bullet-list";
|
||||
import ExtensionCode from "./code";
|
||||
import ExtensionColor from "./color";
|
||||
import ExtensionDetails from "./details";
|
||||
import ExtensionFontSize from "./font-size";
|
||||
import ExtensionHeading from "./heading";
|
||||
import ExtensionHighlight from "./highlight";
|
||||
|
@ -26,7 +27,6 @@ import ExtensionTable from "./table";
|
|||
import ExtensionTaskList from "./task-list";
|
||||
import ExtensionTextAlign from "./text-align";
|
||||
import ExtensionUnderline from "./underline";
|
||||
import ExtensionDetails from "./details";
|
||||
|
||||
// Custom extensions
|
||||
import {
|
||||
|
@ -124,6 +124,7 @@ export {
|
|||
ExtensionColumn,
|
||||
ExtensionColumns,
|
||||
ExtensionCommands,
|
||||
ExtensionDetails,
|
||||
ExtensionDocument,
|
||||
ExtensionDraggable,
|
||||
ExtensionDropcursor,
|
||||
|
@ -158,7 +159,6 @@ export {
|
|||
ExtensionTrailingNode,
|
||||
ExtensionUnderline,
|
||||
ExtensionVideo,
|
||||
ExtensionDetails,
|
||||
RangeSelection,
|
||||
};
|
||||
|
||||
|
|
|
@ -33,11 +33,3 @@ export enum patAnnotations {
|
|||
export enum secretAnnotations {
|
||||
DESCRIPTION = "secret.halo.run/description",
|
||||
}
|
||||
|
||||
// storage
|
||||
export enum storageAnnotations {
|
||||
URI = "storage.halo.run/uri",
|
||||
|
||||
// Frontend custom annotations, for retry operation
|
||||
RETRY_TIMESTAMP = "storage.halo.run/retry-timestamp",
|
||||
}
|
||||
|
|
|
@ -200,10 +200,6 @@ core:
|
|||
list:
|
||||
fields:
|
||||
private: Private
|
||||
reply_modal:
|
||||
fields:
|
||||
hidden:
|
||||
label: Private reply
|
||||
detail_modal:
|
||||
fields:
|
||||
owner: Commentator
|
||||
|
@ -221,8 +217,6 @@ core:
|
|||
original_comment: Original comment
|
||||
content: Reply content
|
||||
attachment:
|
||||
actions:
|
||||
thumbnails: Thumbnails
|
||||
filters:
|
||||
sort:
|
||||
items:
|
||||
|
@ -231,6 +225,8 @@ core:
|
|||
detail_modal:
|
||||
fields:
|
||||
thumbnails: Thumbnails
|
||||
preview:
|
||||
not_support_thumbnail: This image does not support generating thumbnails.
|
||||
permalink_list:
|
||||
relative: Relative path
|
||||
absolute: Absolute path
|
||||
|
@ -250,21 +246,6 @@ core:
|
|||
label: URL
|
||||
toast:
|
||||
success: Downloaded successfully
|
||||
thumbnails_modal:
|
||||
title: Thumbnail records
|
||||
empty:
|
||||
title: No thumbnail records
|
||||
message: There are currently no thumbnail records, thumbnails will be automatically generated after uploading image attachments.
|
||||
operations:
|
||||
retry_all_failed:
|
||||
button: Retry all failed records
|
||||
tips_empty: No failed thumbnail records
|
||||
tips_success: All failed records retried successfully
|
||||
thumbnails:
|
||||
phase:
|
||||
pending: Pending
|
||||
succeeded: Succeeded
|
||||
failed: Failed
|
||||
uc_attachment:
|
||||
empty:
|
||||
title: There are no attachments.
|
||||
|
|
|
@ -631,7 +631,6 @@ core:
|
|||
ungrouped: Ungrouped
|
||||
actions:
|
||||
storage_policies: Storage Policies
|
||||
thumbnails: Thumbnails
|
||||
empty:
|
||||
title: There are no attachments in the current group.
|
||||
message: >-
|
||||
|
@ -693,6 +692,7 @@ core:
|
|||
video_not_support: The current browser does not support video playback.
|
||||
audio_not_support: The current browser does not support audio playback.
|
||||
not_support: This file does not support preview.
|
||||
not_support_thumbnail: This image does not support generating thumbnails.
|
||||
permalink_list:
|
||||
relative: Relative path
|
||||
absolute: Absolute path
|
||||
|
@ -780,23 +780,6 @@ core:
|
|||
operations:
|
||||
select:
|
||||
result: ({count} items selected)
|
||||
thumbnails_modal:
|
||||
title: Thumbnail records
|
||||
empty:
|
||||
title: No thumbnail records
|
||||
message: >-
|
||||
There are currently no thumbnail records, thumbnails will be
|
||||
automatically generated after uploading image attachments.
|
||||
operations:
|
||||
retry_all_failed:
|
||||
button: Retry all failed records
|
||||
tips_empty: No failed thumbnail records
|
||||
tips_success: All failed records retried successfully
|
||||
thumbnails:
|
||||
phase:
|
||||
pending: Pending
|
||||
succeeded: Succeeded
|
||||
failed: Failed
|
||||
uc_attachment:
|
||||
empty:
|
||||
title: There are no attachments.
|
||||
|
|
|
@ -600,7 +600,6 @@ core:
|
|||
ungrouped: 未分组
|
||||
actions:
|
||||
storage_policies: 存储策略
|
||||
thumbnails: 缩略图
|
||||
empty:
|
||||
title: 当前分组没有附件
|
||||
message: 当前分组没有附件,你可以尝试刷新或者上传附件
|
||||
|
@ -660,6 +659,7 @@ core:
|
|||
video_not_support: 当前浏览器不支持该视频播放
|
||||
audio_not_support: 当前浏览器不支持该音频播放
|
||||
not_support: 此文件不支持预览
|
||||
not_support_thumbnail: 此图片不支持生成缩略图
|
||||
group_editing_modal:
|
||||
titles:
|
||||
create: 新增附件分组
|
||||
|
@ -737,21 +737,6 @@ core:
|
|||
permalink_list:
|
||||
relative: 相对路径
|
||||
absolute: 完整路径
|
||||
thumbnails_modal:
|
||||
title: 缩略图记录
|
||||
empty:
|
||||
title: 没有缩略图记录
|
||||
message: 当前没有缩略图记录,缩略图会在上传图片附件后自动生成。
|
||||
operations:
|
||||
retry_all_failed:
|
||||
button: 重试所有失败记录
|
||||
tips_empty: 没有失败记录
|
||||
tips_success: 重试所有失败记录成功
|
||||
thumbnails:
|
||||
phase:
|
||||
pending: 等待生成
|
||||
succeeded: 生成成功
|
||||
failed: 生成失败
|
||||
uc_attachment:
|
||||
empty:
|
||||
title: 当前没有附件
|
||||
|
|
|
@ -585,7 +585,6 @@ core:
|
|||
ungrouped: 未分組
|
||||
actions:
|
||||
storage_policies: 存儲策略
|
||||
thumbnails: 縮略圖
|
||||
empty:
|
||||
title: 當前分組沒有附件
|
||||
message: 當前分組沒有附件,你可以嘗試重整或者上傳附件
|
||||
|
@ -645,6 +644,7 @@ core:
|
|||
video_not_support: 當前瀏覽器不支援該影片播放
|
||||
audio_not_support: 當前瀏覽器不支援該音頻播放
|
||||
not_support: 此文件不支援預覽
|
||||
not_support_thumbnail: 此圖片不支持生成縮略圖
|
||||
group_editing_modal:
|
||||
titles:
|
||||
create: 新增附件分組
|
||||
|
@ -722,21 +722,6 @@ core:
|
|||
permalink_list:
|
||||
relative: 相對路徑
|
||||
absolute: 完整路徑
|
||||
thumbnails_modal:
|
||||
title: 縮略圖記錄
|
||||
empty:
|
||||
title: 沒有縮略圖記錄
|
||||
message: 當前沒有縮略圖記錄,縮略圖會在上傳圖片附件後自動生成。
|
||||
operations:
|
||||
retry_all_failed:
|
||||
button: 重試所有失敗記錄
|
||||
tips_empty: 沒有失敗記錄
|
||||
tips_success: 重試所有失敗記錄成功
|
||||
thumbnails:
|
||||
phase:
|
||||
pending: 等待生成
|
||||
succeeded: 生成成功
|
||||
failed: 生成失敗
|
||||
uc_attachment:
|
||||
empty:
|
||||
title: 當前沒有附件
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { GetThumbnailByUriSizeEnum } from "@halo-dev/api-client";
|
||||
|
||||
const THUMBNAIL_WIDTH_MAP: Record<GetThumbnailByUriSizeEnum, number> = {
|
||||
export const THUMBNAIL_WIDTH_MAP: Record<GetThumbnailByUriSizeEnum, number> = {
|
||||
XL: 1600,
|
||||
L: 1200,
|
||||
M: 800,
|
||||
|
|
Loading…
Reference in New Issue