mirror of https://github.com/halo-dev/halo
172 lines
4.2 KiB
Vue
172 lines
4.2 KiB
Vue
<script lang="ts" setup>
|
|
import { usePluginModuleStore } from "@/stores/plugin";
|
|
import { VButton, VModal, VSpace, VTabbar } from "@halo-dev/components";
|
|
import type {
|
|
AttachmentLike,
|
|
AttachmentSelectProvider,
|
|
} from "@halo-dev/console-shared";
|
|
import { computed, markRaw, onMounted, ref } from "vue";
|
|
import { useI18n } from "vue-i18n";
|
|
import CoreSelectorProvider from "./selector-providers/CoreSelectorProvider.vue";
|
|
|
|
const { t } = useI18n();
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
visible: boolean;
|
|
accepts?: string[];
|
|
min?: number;
|
|
max?: number;
|
|
}>(),
|
|
{
|
|
visible: false,
|
|
accepts: () => ["*/*"],
|
|
min: undefined,
|
|
max: undefined,
|
|
}
|
|
);
|
|
|
|
const emit = defineEmits<{
|
|
(event: "update:visible", visible: boolean): void;
|
|
(event: "close"): void;
|
|
(event: "select", attachments: AttachmentLike[]): void;
|
|
}>();
|
|
|
|
const selected = ref<AttachmentLike[]>([] as AttachmentLike[]);
|
|
|
|
const attachmentSelectProviders = ref<AttachmentSelectProvider[]>([
|
|
{
|
|
id: "core",
|
|
label: t("core.attachment.select_modal.providers.default.label"),
|
|
component: markRaw(CoreSelectorProvider),
|
|
},
|
|
]);
|
|
|
|
// resolve plugin extension points
|
|
const { pluginModules } = usePluginModuleStore();
|
|
|
|
onMounted(async () => {
|
|
for (const pluginModule of pluginModules) {
|
|
try {
|
|
const callbackFunction =
|
|
pluginModule?.extensionPoints?.["attachment:selector:create"];
|
|
|
|
if (typeof callbackFunction !== "function") {
|
|
continue;
|
|
}
|
|
|
|
const providers = await callbackFunction();
|
|
attachmentSelectProviders.value.push(...providers);
|
|
} catch (error) {
|
|
console.error(`Error processing plugin module:`, pluginModule, error);
|
|
}
|
|
}
|
|
});
|
|
|
|
const activeId = ref(attachmentSelectProviders.value[0].id);
|
|
|
|
const onVisibleChange = (visible: boolean) => {
|
|
emit("update:visible", visible);
|
|
if (!visible) {
|
|
emit("close");
|
|
}
|
|
};
|
|
|
|
const onChangeProvider = (providerId: string) => {
|
|
const provider = attachmentSelectProviders.value.find(
|
|
(provider) => provider.id === providerId
|
|
);
|
|
|
|
if (!provider) {
|
|
return;
|
|
}
|
|
|
|
activeId.value = providerId;
|
|
};
|
|
|
|
const handleConfirm = () => {
|
|
emit("select", Array.from(selected.value));
|
|
onVisibleChange(false);
|
|
};
|
|
|
|
const confirmDisabled = computed(() => {
|
|
if (props.min === undefined) {
|
|
return false;
|
|
}
|
|
return selected.value.length < props.min;
|
|
});
|
|
|
|
const confirmCountMessage = computed(() => {
|
|
if (!props.min && !props.max) {
|
|
return selected.value.length;
|
|
}
|
|
return `${selected.value.length} / ${props.max || props.min}`;
|
|
});
|
|
</script>
|
|
<template>
|
|
<VModal
|
|
:visible="visible"
|
|
:width="1240"
|
|
:mount-to-body="true"
|
|
:layer-closable="true"
|
|
:title="$t('core.attachment.select_modal.title')"
|
|
height="calc(100vh - 20px)"
|
|
@update:visible="onVisibleChange"
|
|
>
|
|
<VTabbar
|
|
v-model:active-id="activeId"
|
|
:items="
|
|
attachmentSelectProviders.map((provider) => ({
|
|
id: provider.id,
|
|
label: provider.label,
|
|
}))
|
|
"
|
|
class="w-full"
|
|
type="outline"
|
|
></VTabbar>
|
|
|
|
<div v-if="visible" class="mt-2">
|
|
<template
|
|
v-for="(provider, index) in attachmentSelectProviders"
|
|
:key="index"
|
|
>
|
|
<Suspense>
|
|
<component
|
|
:is="provider.component"
|
|
v-if="activeId === provider.id"
|
|
v-model:selected="selected"
|
|
:accepts="accepts"
|
|
:min="min"
|
|
:max="max"
|
|
@change-provider="onChangeProvider"
|
|
></component>
|
|
<template #fallback>
|
|
{{ $t("core.common.status.loading") }}
|
|
</template>
|
|
</Suspense>
|
|
</template>
|
|
</div>
|
|
<template #footer>
|
|
<VSpace>
|
|
<VButton
|
|
type="secondary"
|
|
:disabled="confirmDisabled"
|
|
@click="handleConfirm"
|
|
>
|
|
{{ $t("core.common.buttons.confirm") }}
|
|
<span v-if="selected.length || props.min || props.max">
|
|
{{
|
|
$t("core.attachment.select_modal.operations.select.result", {
|
|
count: confirmCountMessage,
|
|
})
|
|
}}
|
|
</span>
|
|
</VButton>
|
|
<VButton @click="onVisibleChange(false)">
|
|
{{ $t("core.common.buttons.cancel") }}
|
|
</VButton>
|
|
</VSpace>
|
|
</template>
|
|
</VModal>
|
|
</template>
|