mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
feat(pluginInstall): enhance repository link display and update cautionary messages for third-party plugins
This commit is contained in:
@@ -50,6 +50,43 @@
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.repoLink {
|
||||||
|
display: inline-flex;
|
||||||
|
max-width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
margin: 0;
|
||||||
|
font-family: $font-mono;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
span {
|
||||||
|
min-width: 0;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--accent-color);
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
color: currentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--focus-ring-color, var(--accent-color));
|
||||||
|
outline-offset: 3px;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.source {
|
.source {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
import { Input } from '@/components/ui/Input';
|
import { Input } from '@/components/ui/Input';
|
||||||
import { Modal } from '@/components/ui/Modal';
|
import { Modal } from '@/components/ui/Modal';
|
||||||
import { IconAlertTriangle, IconPlug } from '@/components/ui/icons';
|
import { IconAlertTriangle, IconExternalLink, IconPlug } from '@/components/ui/icons';
|
||||||
import { useAuthStore } from '@/stores';
|
import { useAuthStore } from '@/stores';
|
||||||
import type { PluginStoreEntry } from '@/types';
|
import type { PluginStoreEntry } from '@/types';
|
||||||
import {
|
import {
|
||||||
|
buildRepositoryURL,
|
||||||
getPluginConfirmToken,
|
getPluginConfirmToken,
|
||||||
getPluginRepositorySlug,
|
getPluginRepositorySlug,
|
||||||
isDefaultPluginStoreSource,
|
isDefaultPluginStoreSource,
|
||||||
@@ -60,6 +61,8 @@ export function PluginInstallGateModal({
|
|||||||
|
|
||||||
const title = entry.name || entry.id;
|
const title = entry.name || entry.id;
|
||||||
const repoSlug = getPluginRepositorySlug(entry.repository);
|
const repoSlug = getPluginRepositorySlug(entry.repository);
|
||||||
|
const repositoryURL = buildRepositoryURL(entry.repository);
|
||||||
|
const repoLabel = repoSlug || entry.id;
|
||||||
const token = getPluginConfirmToken(entry);
|
const token = getPluginConfirmToken(entry);
|
||||||
const logo = resolvePluginAssetURL(entry.logo, apiBase);
|
const logo = resolvePluginAssetURL(entry.logo, apiBase);
|
||||||
const rawSourceText = entry.sourceName || entry.sourceUrl;
|
const rawSourceText = entry.sourceName || entry.sourceUrl;
|
||||||
@@ -87,7 +90,21 @@ export function PluginInstallGateModal({
|
|||||||
<GateLogo src={logo} />
|
<GateLogo src={logo} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className={styles.name}>{title}</h3>
|
<h3 className={styles.name}>{title}</h3>
|
||||||
<p className={styles.slug}>{repoSlug || entry.id}</p>
|
{repositoryURL ? (
|
||||||
|
<a
|
||||||
|
className={styles.repoLink}
|
||||||
|
href={repositoryURL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title={t('plugin_store.open_repository')}
|
||||||
|
aria-label={t('plugin_store.open_repository')}
|
||||||
|
>
|
||||||
|
<span>{repoLabel}</span>
|
||||||
|
<IconExternalLink size={12} />
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<p className={styles.slug}>{repoLabel}</p>
|
||||||
|
)}
|
||||||
{sourceText ? (
|
{sourceText ? (
|
||||||
<p className={styles.source}>{t('plugin_store.source_name', { source: sourceText })}</p>
|
<p className={styles.source}>{t('plugin_store.source_name', { source: sourceText })}</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -1223,8 +1223,8 @@
|
|||||||
"gate_title": "Install {{name}}",
|
"gate_title": "Install {{name}}",
|
||||||
"gate_title_update": "Update {{name}}",
|
"gate_title_update": "Update {{name}}",
|
||||||
"gate_warning": "Unexpected and harmful things can happen if you don't read this.",
|
"gate_warning": "Unexpected and harmful things can happen if you don't read this.",
|
||||||
"gate_effect_runs_code": "This plugin runs untrusted code inside your proxy backend, with access to credentials, requests, and responses.",
|
"gate_effect_runs_code": "This plugin will run uncertified third-party code inside your proxy backend. The system cannot isolate or audit its behavior, and it may have access to your sensitive credentials, network requests, and response data.",
|
||||||
"gate_effect_no_review": "It is not published or reviewed by the official router-for-me organization and may behave differently in future versions.",
|
"gate_effect_no_review": "This plugin is not published or reviewed by the official router-for-me organization. The official organization makes no express or implied warranty for this plugin's stability, security, compliance, or any behavior changes in future versions.",
|
||||||
"gate_effect_restart": "Installing it changes the local plugin directory and may require a service restart to take effect.",
|
"gate_effect_restart": "Installing it changes the local plugin directory and may require a service restart to take effect.",
|
||||||
"gate_untrusted_alert": "This plugin is not from the official router-for-me organization. Only continue if you fully trust its author and source.",
|
"gate_untrusted_alert": "This plugin is not from the official router-for-me organization. Only continue if you fully trust its author and source.",
|
||||||
"gate_repository_label": "Repository",
|
"gate_repository_label": "Repository",
|
||||||
|
|||||||
@@ -1210,8 +1210,8 @@
|
|||||||
"gate_title": "Установка {{name}}",
|
"gate_title": "Установка {{name}}",
|
||||||
"gate_title_update": "Обновление {{name}}",
|
"gate_title_update": "Обновление {{name}}",
|
||||||
"gate_warning": "Если вы не прочитаете это, могут произойти неожиданные и опасные последствия.",
|
"gate_warning": "Если вы не прочитаете это, могут произойти неожиданные и опасные последствия.",
|
||||||
"gate_effect_runs_code": "Этот плагин выполняет недоверенный код внутри вашего прокси-бэкенда с доступом к учётным данным, запросам и ответам.",
|
"gate_effect_runs_code": "Этот плагин будет выполнять несертифицированный сторонний код внутри вашего прокси-бэкенда. Система не может изолировать или аудировать его поведение, и он может получить доступ к вашим конфиденциальным учётным данным, сетевым запросам и данным ответов.",
|
||||||
"gate_effect_no_review": "Он не опубликован и не проверен официальной организацией router-for-me и может вести себя иначе в будущих версиях.",
|
"gate_effect_no_review": "Этот плагин не опубликован и не проверен официальной организацией router-for-me. Официальная организация не предоставляет никаких явных или подразумеваемых гарантий стабильности, безопасности, соответствия требованиям или любых изменений поведения в последующих версиях этого плагина.",
|
||||||
"gate_effect_restart": "Установка изменяет локальный каталог плагинов и может потребовать перезапуска сервиса.",
|
"gate_effect_restart": "Установка изменяет локальный каталог плагинов и может потребовать перезапуска сервиса.",
|
||||||
"gate_untrusted_alert": "Этот плагин не от официальной организации router-for-me. Продолжайте, только если полностью доверяете его автору и источнику.",
|
"gate_untrusted_alert": "Этот плагин не от официальной организации router-for-me. Продолжайте, только если полностью доверяете его автору и источнику.",
|
||||||
"gate_repository_label": "Репозиторий",
|
"gate_repository_label": "Репозиторий",
|
||||||
|
|||||||
@@ -1223,8 +1223,8 @@
|
|||||||
"gate_title": "安装 {{name}}",
|
"gate_title": "安装 {{name}}",
|
||||||
"gate_title_update": "更新 {{name}}",
|
"gate_title_update": "更新 {{name}}",
|
||||||
"gate_warning": "如果你不阅读以下内容,可能会发生意料之外的危险后果。",
|
"gate_warning": "如果你不阅读以下内容,可能会发生意料之外的危险后果。",
|
||||||
"gate_effect_runs_code": "该插件会在你的代理后端内运行不受信任的代码,并可访问凭据、请求与响应。",
|
"gate_effect_runs_code": "该插件将在您的代理后端内运行第三方未认证代码。系统无法对其行为进行隔离或审计,其具备访问您的敏感凭据、网络请求与响应数据的潜在权限。",
|
||||||
"gate_effect_no_review": "它并非由官方组织 router-for-me 发布或审核,且在后续版本中行为可能发生变化。",
|
"gate_effect_no_review": "本插件并非由官方组织 router-for-me 发布或审核。官方不对该插件的稳定性、安全性、合规性以及后续版本的任意行为变更承担任何明示或暗示的担保责任。",
|
||||||
"gate_effect_restart": "安装会修改本地插件目录,并可能需要重启服务才能生效。",
|
"gate_effect_restart": "安装会修改本地插件目录,并可能需要重启服务才能生效。",
|
||||||
"gate_untrusted_alert": "该插件并非来自官方组织 router-for-me。请仅在你完全信任其作者与来源时继续。",
|
"gate_untrusted_alert": "该插件并非来自官方组织 router-for-me。请仅在你完全信任其作者与来源时继续。",
|
||||||
"gate_repository_label": "仓库",
|
"gate_repository_label": "仓库",
|
||||||
|
|||||||
@@ -1249,8 +1249,8 @@
|
|||||||
"gate_title": "安裝 {{name}}",
|
"gate_title": "安裝 {{name}}",
|
||||||
"gate_title_update": "更新 {{name}}",
|
"gate_title_update": "更新 {{name}}",
|
||||||
"gate_warning": "如果你不閱讀以下內容,可能會發生意料之外的危險後果。",
|
"gate_warning": "如果你不閱讀以下內容,可能會發生意料之外的危險後果。",
|
||||||
"gate_effect_runs_code": "該插件會在你的代理後端內執行不受信任的程式碼,並可存取憑證、請求與回應。",
|
"gate_effect_runs_code": "該插件將在您的代理後端內執行第三方未認證程式碼。系統無法對其行為進行隔離或稽核,其具備存取您的敏感憑證、網路請求與回應資料的潛在權限。",
|
||||||
"gate_effect_no_review": "它並非由官方組織 router-for-me 發布或審核,且在後續版本中行為可能發生變化。",
|
"gate_effect_no_review": "本插件並非由官方組織 router-for-me 發布或審核。官方不對該插件的穩定性、安全性、合規性以及後續版本的任意行為變更承擔任何明示或暗示的擔保責任。",
|
||||||
"gate_effect_restart": "安裝會修改本機插件目錄,並可能需要重新啟動服務才能生效。",
|
"gate_effect_restart": "安裝會修改本機插件目錄,並可能需要重新啟動服務才能生效。",
|
||||||
"gate_untrusted_alert": "該插件並非來自官方組織 router-for-me。請僅在你完全信任其作者與來源時繼續。",
|
"gate_untrusted_alert": "該插件並非來自官方組織 router-for-me。請僅在你完全信任其作者與來源時繼續。",
|
||||||
"gate_repository_label": "儲存庫",
|
"gate_repository_label": "儲存庫",
|
||||||
|
|||||||
Reference in New Issue
Block a user