Feat(webui): support pinning and dragging for installed plugins (#6649) (#6776)

* refactor(persona): replace local folder components with shared folder components

* feat(webui): implement draggable reordering with animation for pinned plugins

* refactor(webui): extract PinnedPluginItem into a standalone component
This commit is contained in:
M1LKT
2026-03-22 14:55:02 +08:00
committed by GitHub
parent 554c9cecfa
commit a2dae0fc5e
11 changed files with 603 additions and 314 deletions

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, inject, watch } from "vue";
import { ref, computed, inject, watch, useAttrs } from "vue";
import { useCustomizerStore } from "@/stores/customizer";
import { useModuleI18n } from "@/i18n/composables";
import { getPlatformDisplayName, getPlatformIcon } from "@/utils/platformUtils";
@@ -13,6 +13,10 @@ const props = defineProps({
type: Object,
required: true,
},
pinned: {
type: Boolean,
default: false,
},
marketMode: {
type: Boolean,
default: false,
@@ -31,6 +35,7 @@ const emit = defineEmits([
"install",
"uninstall",
"toggle-activation",
"toggle-pin",
"view-handlers",
"view-readme",
"view-changelog",
@@ -39,6 +44,8 @@ const emit = defineEmits([
const reveal = ref(false);
const showUninstallDialog = ref(false);
const attrs = useAttrs();
// 国际化
const { tm } = useModuleI18n("features/extension");
@@ -114,6 +121,11 @@ const toggleActivation = () => {
emit("toggle-activation", props.extension);
};
const togglePin = (e?: Event) => {
if (e) e.stopPropagation();
emit("toggle-pin", props.extension);
};
const viewHandlers = () => {
emit("view-handlers", props.extension);
};
@@ -130,6 +142,7 @@ const viewChangelog = () => {
<template>
<v-card
v-bind="attrs"
class="mx-auto d-flex flex-column h-100"
elevation="0"
height="100%"
@@ -203,16 +216,34 @@ const viewChangelog = () => {
<template v-if="!marketMode">
<v-tooltip location="left">
<template v-slot:activator="{ props: tooltipProps }">
<div v-bind="tooltipProps" class="extension-switch-wrap" @click.stop>
<v-switch
:model-value="extension.activated"
color="success"
density="compact"
hide-details
inset
@update:model-value="toggleActivation"
></v-switch>
</div>
<div class="extension-switch-wrap" @click.stop>
<div v-bind="tooltipProps" style="display:inline-flex; align-items:center;">
<v-switch
:model-value="extension.activated"
color="success"
density="compact"
hide-details
inset
@update:model-value="toggleActivation"
></v-switch>
</div>
<v-tooltip location="top" :text="pinned ? tm('buttons.unpin') : tm('buttons.pin')">
<template #activator="{ props: pinProps }">
<v-btn
v-bind="pinProps"
icon
size="small"
variant="tonal"
:color="pinned ? 'primary' : 'secondary'"
class="ml-2"
@click.stop="togglePin"
>
<v-icon size="18">{{ pinned ? 'mdi-pin' : 'mdi-pin-outline' }}</v-icon>
</v-btn>
</template>
</v-tooltip>
</div>
</template>
<span>{{
extension.activated ? tm("buttons.disable") : tm("buttons.enable")