Enhance PhpManager to support fetching and displaying PECL extension availability, including reasons for unavailability. Update UI in PhpManager.vue to show extension version and availability status, improving user experience with clearer installation options and error handling.

This commit is contained in:
ethanfly 2026-01-04 02:52:26 +08:00
parent 965bc618ee
commit 1189177568
2 changed files with 939 additions and 520 deletions

File diff suppressed because it is too large Load Diff

View File

@ -352,21 +352,34 @@
</div> </div>
<div v-else class="extensions-list"> <div v-else class="extensions-list">
<div class="extensions-count"> <div class="extensions-count">
找到 {{ availableExtensions.length }} 适用于 PHP {{ currentVersion }} 扩展 找到 {{ availableExtensions.length }} 扩展
</div> </div>
<div <div
v-for="ext in availableExtensions" v-for="ext in availableExtensions"
:key="ext.name" :key="ext.name"
class="extension-item" class="extension-item"
:class="{ 'not-available': ext.notAvailableReason }"
> >
<div class="ext-info"> <div class="ext-info">
<div class="ext-main"> <div class="ext-main">
<span class="ext-name" v-html="highlightKeyword(ext.name)"></span> <span class="ext-name" v-html="highlightKeyword(ext.name)"></span>
<el-tag type="warning" size="small">v{{ ext.version }}</el-tag> <el-tag type="info" size="small">{{ ext.version === 'latest' ? '最新版' : 'v' + ext.version }}</el-tag>
</div> </div>
<span class="ext-desc" v-if="ext.description">{{ ext.description }}</span> <span class="ext-desc" v-if="ext.description">{{ ext.description }}</span>
<span class="ext-not-available" v-if="ext.notAvailableReason">
<el-icon><Warning /></el-icon>
{{ ext.notAvailableReason }}
</span>
</div> </div>
<!-- 有明确不可用原因时显示不支持 -->
<el-tooltip v-if="ext.notAvailableReason" :content="ext.notAvailableReason" placement="top">
<el-button type="info" size="small" disabled>
不支持
</el-button>
</el-tooltip>
<!-- 否则显示安装按钮 -->
<el-button <el-button
v-else
type="primary" type="primary"
size="small" size="small"
@click="installExtension(ext)" @click="installExtension(ext)"
@ -415,7 +428,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, onUnmounted, onActivated } from 'vue' import { ref, reactive, computed, onMounted, onUnmounted, onActivated } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { FolderOpened, InfoFilled, VideoPlay, VideoPause, EditPen } from '@element-plus/icons-vue' import { FolderOpened, InfoFilled, VideoPlay, VideoPause, EditPen, Warning } from '@element-plus/icons-vue'
import { useServiceStore } from '@/stores/serviceStore' import { useServiceStore } from '@/stores/serviceStore'
import LogViewer from '@/components/LogViewer.vue' import LogViewer from '@/components/LogViewer.vue'
@ -451,6 +464,8 @@ interface AvailableExtension {
downloadUrl: string downloadUrl: string
description?: string description?: string
packageName?: string // Packagist PIE packageName?: string // Packagist PIE
supportedPhpVersions?: string[] // PHP
notAvailableReason?: string //
} }
const loading = ref(false) const loading = ref(false)
@ -1081,6 +1096,11 @@ onUnmounted(() => {
border-bottom: none; border-bottom: none;
} }
&.not-available {
opacity: 0.7;
background-color: rgba(0, 0, 0, 0.02);
}
.ext-info { .ext-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -1101,6 +1121,14 @@ onUnmounted(() => {
font-size: 12px; font-size: 12px;
color: var(--text-muted); color: var(--text-muted);
} }
.ext-not-available {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: var(--warning-color, #e6a23c);
}
} }
} }