Merge pull request #1907 from IGCrystal/Branch-2

🐞 fix(WebUI): 修复安装插件按钮不可见
This commit is contained in:
Soulter
2025-06-26 23:28:37 +08:00
committed by GitHub
3 changed files with 104 additions and 11 deletions
@@ -31,7 +31,8 @@
"saveAndClose": "Save and Close",
"cancel": "Cancel",
"actions": "Actions",
"back": "Back"
"back": "Back",
"selectFile": "Select File"
},
"status": {
"enabled": "Enabled",
@@ -106,6 +107,11 @@
"uninstall": {
"title": "Confirm Deletion",
"message": "Are you sure you want to delete this extension?"
},
"install": {
"title": "Install Extension",
"fromFile": "Install from File",
"fromUrl": "Install from URL"
}
},
"messages": {
@@ -127,7 +133,8 @@
"hasUpdate": "New version available:",
"confirmDelete": "Are you sure you want to delete this extension?",
"fillUrlOrFile": "Please fill in extension URL or upload extension file",
"dontFillBoth": "Please don't fill in both extension URL and upload file"
"dontFillBoth": "Please don't fill in both extension URL and upload file",
"supportedFormats": "Supports .zip extension files"
},
"upload": {
"fromFile": "Install from File",
@@ -31,7 +31,8 @@
"saveAndClose": "保存并关闭",
"cancel": "取消",
"actions": "操作",
"back": "返回"
"back": "返回",
"selectFile": "选择文件"
},
"status": {
"enabled": "启用",
@@ -106,6 +107,11 @@
"uninstall": {
"title": "删除确认",
"message": "你确定要删除当前插件吗?"
},
"install": {
"title": "安装插件",
"fromFile": "从文件安装",
"fromUrl": "从链接安装"
}
},
"messages": {
@@ -127,7 +133,8 @@
"hasUpdate": "有新版本:",
"confirmDelete": "确定要删除插件吗?",
"fillUrlOrFile": "请填写插件链接或上传插件文件",
"dontFillBoth": "请不要同时填写插件链接和上传插件文件"
"dontFillBoth": "请不要同时填写插件链接和上传文件",
"supportedFormats": "支持 .zip 格式的插件文件"
},
"upload": {
"fromFile": "从文件安装",
+86 -7
View File
@@ -13,6 +13,7 @@ import { ref, computed, onMounted, reactive } from 'vue';
const commonStore = useCommonStore();
const { t } = useI18n();
const { tm } = useModuleI18n('features/extension');
const fileInput = ref(null);
const activeTab = ref('installed');
const extension_data = reactive({
data: [],
@@ -61,6 +62,7 @@ const loading_ = ref(false);
const extension_url = ref("");
const dialog = ref(false);
const upload_file = ref(null);
const uploadTab = ref('file');
const showPluginFullName = ref(false);
const marketSearch = ref("");
const filterKeys = ['name', 'desc', 'author'];
@@ -629,16 +631,20 @@ onMounted(async () => {
</v-btn>
</v-btn-group>
<v-btn @click="toggleShowReserved" prepend-icon="mdi-eye-settings-outline"
:color="showReserved ? 'primary' : undefined" :variant="showReserved ? 'flat' : 'outlined'"
class="flex-shrink-0">
<v-btn class="ml-2" variant="tonal" @click="toggleShowReserved">
<v-icon>{{ showReserved ? 'mdi-eye-off' : 'mdi-eye' }}</v-icon>
{{ showReserved ? tm('buttons.hideSystemPlugins') : tm('buttons.showSystemPlugins') }}
</v-btn>
<v-btn prepend-icon="mdi-tune-vertical" color="primary" variant="outlined"
@click="getPlatformEnableConfig" class="flex-shrink-0">
<v-btn class="ml-2" variant="tonal" @click="getPlatformEnableConfig">
<v-icon>mdi-cog</v-icon>
{{ tm('buttons.platformConfig') }}
</v-btn>
<v-btn class="ml-2" color="primary" variant="tonal" @click="dialog = true">
<v-icon>mdi-plus</v-icon>
{{ tm('buttons.install') }}
</v-btn>
</v-col>
<v-col cols="12" sm="auto" md="6" class="ml-auto">
@@ -808,12 +814,16 @@ onMounted(async () => {
<!-- <small style="color: var(--v-theme-secondaryText);">每个插件都是作者无偿提供的的劳动成果如果您喜欢某个插件 Star</small> -->
<v-btn icon="mdi-plus" size="x-large" style="position: fixed; right: 52px; bottom: 52px;" @click="dialog = true"
color="darkprimary">
</v-btn>
<div v-if="pinnedPlugins.length > 0" class="mt-4">
<h2>{{ tm('market.recommended') }}</h2>
<v-row style="margin-top: 8px;">
<v-col cols="12" md="6" lg="6" v-for="plugin in pinnedPlugins" :key="plugin.name">
<ExtensionCard :extension="plugin" class="h-120 rounded-lg" market-mode="true" :highlight="true"
@install="extension_url = plugin.repo; newExtension()" @view-readme="open(plugin.repo)">
@install="extension_url = plugin.repo; dialog = true; uploadTab = 'url'" @view-readme="open(plugin.repo)">
</ExtensionCard>
</v-col>
</v-row>
@@ -866,7 +876,7 @@ onMounted(async () => {
</template>
<template v-slot:item.actions="{ item }">
<v-btn v-if="!item.installed" class="text-none mr-2" size="x-small" variant="flat"
@click="extension_url = item.repo; newExtension()">
@click="extension_url = item.repo; dialog = true; uploadTab = 'url'">
<v-icon>mdi-download</v-icon></v-btn>
<v-btn v-else class="text-none mr-2" size="x-small" variant="flat" border
disabled><v-icon>mdi-check</v-icon></v-btn>
@@ -1067,6 +1077,75 @@ onMounted(async () => {
<ReadmeDialog v-model:show="readmeDialog.show" :plugin-name="readmeDialog.pluginName"
:repo-url="readmeDialog.repoUrl" />
<!-- 上传插件对话框 -->
<v-dialog v-model="dialog" width="500">
<v-card>
<v-card-title class="text-h5">{{ tm('dialogs.install.title') }}</v-card-title>
<v-card-text>
<v-tabs v-model="uploadTab">
<v-tab value="file">{{ tm('dialogs.install.fromFile') }}</v-tab>
<v-tab value="url">{{ tm('dialogs.install.fromUrl') }}</v-tab>
</v-tabs>
<v-window v-model="uploadTab" class="mt-4">
<v-window-item value="file">
<div class="d-flex flex-column align-center justify-center pa-4">
<v-file-input
ref="fileInput"
v-model="upload_file"
:label="tm('upload.selectFile')"
accept=".zip"
hide-details
hide-input
class="d-none"
></v-file-input>
<v-btn
color="primary"
size="large"
prepend-icon="mdi-upload"
@click="$refs.fileInput.click()"
>
{{ tm('buttons.selectFile') }}
</v-btn>
<div class="text-body-2 text-medium-emphasis mt-2">
{{ tm('messages.supportedFormats') }}
</div>
<div v-if="upload_file" class="mt-4 text-center">
<v-chip color="primary" size="large" closable @click:close="upload_file = null">
{{ upload_file.name }}
<template v-slot:append>
<span class="text-caption ml-2">({{ (upload_file.size / 1024).toFixed(1) }}KB)</span>
</template>
</v-chip>
</div>
</div>
</v-window-item>
<v-window-item value="url">
<div class="pa-4">
<v-text-field
v-model="extension_url"
:label="tm('upload.enterUrl')"
variant="outlined"
prepend-inner-icon="mdi-link"
hide-details
placeholder="https://github.com/username/repo"
></v-text-field>
</div>
</v-window-item>
</v-window>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="grey" variant="text" @click="dialog = false">{{ tm('buttons.cancel') }}</v-btn>
<v-btn color="primary" variant="text" @click="newExtension">{{ tm('buttons.install') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<style scoped>