feat(ai): hide coding plan providers in intl mode (#12090)

This commit is contained in:
ssongliu
2026-03-05 10:47:38 +00:00
committed by GitHub
parent 735cf3cc71
commit 78eef15f5b
16 changed files with 99 additions and 47 deletions
+8 -4
View File
@@ -287,7 +287,11 @@ type noteDetailHelper struct {
func (u *UpgradeService) LoadRelease() ([]dto.ReleasesNotes, error) {
var notes []dto.ReleasesNotes
resp, err := req_helper.HandleGet("https://1panel.cn/docs/v2/search/search_index.json")
url := "https://docs.1panel.pro/v2/search/search_index.json"
if global.CONF.Base.Edition != "intl" {
url = "https://1panel.cn/docs/v2/search/search_index.json"
}
resp, err := req_helper.HandleGet(url)
if err != nil {
return notes, err
}
@@ -321,13 +325,13 @@ func analyzeDoc(version, content string) dto.ReleasesNotes {
}
item.CreatedAt = strings.ReplaceAll(strings.TrimSpace(parts[1]), "</p>", "")
for i := 1; i < len(parts); i++ {
if strings.Contains(parts[i], "问题修复") {
if strings.Contains(parts[i], "问题修复") || strings.Contains(parts[i], "Bug Fixes") {
item.FixCount = strings.Count(parts[i], "<li>")
}
if strings.Contains(parts[i], "新增功能") {
if strings.Contains(parts[i], "新增功能") || strings.Contains(parts[i], "New Features") {
item.NewCount = strings.Count(parts[i], "<li>")
}
if strings.Contains(parts[i], "功能优化") {
if strings.Contains(parts[i], "功能优化") || strings.Contains(parts[i], "Improvements") {
item.OptimizationCount = strings.Count(parts[i], "<li>")
}
}
@@ -106,7 +106,8 @@ const toLxware = () => {
};
const to1Panel = () => {
window.open('https://1panel.cn', '_blank', 'noopener,noreferrer');
let url = globalStore.isIntl ? 'https://1panel.pro' : 'https://1panel.cn';
window.open(url, '_blank', 'noopener,noreferrer');
};
const toDoc = () => {
@@ -117,7 +118,7 @@ const toForum = () => {
let url = globalStore.isIntl
? 'https://github.com/1Panel-dev/1Panel/discussions'
: 'https://bbs.fit2cloud.com/c/1p/7';
window.open(url, '_blank');
window.open(url, '_blank', 'noopener,noreferrer');
};
const toGithub = () => {
@@ -2,21 +2,28 @@
<DrawerPro v-model="drawerVisible" :header="$t('setting.release')" @close="handleClose" size="large">
<div class="note" v-loading="loading">
<el-form ref="formRef" :model="form" :rules="rules">
<el-form-item :label="$t('setting.versionItem')" prop="version">
<el-input class="p-w-200" disabled v-model="form.version">
<template #append>
<CopyButton class="w-16" :isIcon="false" :content="form.version" type="primary" />
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('setting.backupCopies')" prop="backupCopies">
<el-input class="p-w-200" type="number" v-model.number="form.backupCopies">
<template #append>
<el-button @click="onSave(formRef)" class="w-16">{{ $t('commons.button.save') }}</el-button>
</template>
</el-input>
<span class="input-help">{{ $t('setting.backupCopiesHelper') }}</span>
</el-form-item>
<div class="release-settings">
<el-form-item :label="$t('setting.versionItem')" prop="version" class="compact-form-item">
<div class="setting-control">
<el-input disabled v-model="form.version" />
<CopyButton
class="setting-action-btn"
:isIcon="false"
:content="form.version"
type="primary"
/>
</div>
</el-form-item>
<el-form-item :label="$t('setting.backupCopies')" prop="backupCopies" class="compact-form-item">
<div class="setting-control">
<el-input-number v-model="form.backupCopies" :min="0" controls-position="right" />
<el-button @click="onSave(formRef)" class="setting-action-btn" type="primary">
{{ $t('commons.button.save') }}
</el-button>
</div>
<span class="input-help">{{ $t('setting.backupCopiesHelper') }}</span>
</el-form-item>
</div>
</el-form>
<el-collapse v-if="notes && notes.length !== 0" v-model="currentVersion" :accordion="true">
<div v-for="(item, index) in notes" :key="index">
@@ -183,4 +190,31 @@ defineExpose({
margin-left: 5px;
margin-top: -4px;
}
.release-settings {
margin-bottom: 16px;
padding: 14px 14px 10px;
border: 1px solid var(--el-border-color-light);
border-radius: 10px;
}
.compact-form-item {
margin-bottom: 12px;
}
.compact-form-item :deep(.el-form-item__label) {
padding-bottom: 6px;
}
.setting-control {
display: flex;
align-items: center;
gap: 8px;
max-width: 340px;
width: 100%;
}
.setting-control :deep(.el-input),
.setting-control :deep(.el-input-number) {
flex: 1;
width: 100%;
}
.setting-action-btn {
min-width: 64px;
}
</style>
+2 -2
View File
@@ -2196,7 +2196,7 @@ const message = {
about: 'About',
versionItem: 'Current Version',
backupCopies: 'Number of Copies to Keep',
backupCopies: 'Backup Copies',
backupCopiesHelper: 'Set the number of upgrade backup copies to keep for version rollback. 0 means keep all.',
backupCopiesRule: 'Please keep at least 3 upgrade backup records',
release: 'Release Notes',
@@ -3858,7 +3858,7 @@ const message = {
masterBackup: 'Master Node Backup',
backupNode: 'Backup Node',
backupFrequency: 'Backup Frequency (hours)',
backupCopies: 'Backup Retention Copies',
backupCopies: 'Backup Copies',
noBackupNode: 'The backup node is currently empty. Select a backup node to save and try again!',
masterBackupAlert:
'Master node backup is not currently configured. To ensure data security, please set up a backup node as soon as possible to facilitate manual switching to a new master node in case of failure.',
+2 -2
View File
@@ -2223,7 +2223,7 @@ const message = {
about: 'Acerca de',
versionItem: 'Versión Actual',
backupCopies: 'Número de Copias a Conservar',
backupCopies: 'Copias de Respaldo',
backupCopiesHelper:
'Establezca el número de copias de respaldo de actualización para conservar para la reversión de versión. 0 significa conservar todas.',
backupCopiesRule: 'Conserve al menos 3 registros de respaldo de actualización',
@@ -3843,7 +3843,7 @@ const message = {
masterBackup: 'Respaldo del Nodo Principal',
backupNode: 'Nodo de Respaldo',
backupFrequency: 'Frecuencia de Respaldo (horas)',
backupCopies: 'Copias de Retención de Respaldo',
backupCopies: 'Copias de Respaldo',
noBackupNode: 'Actualmente no hay nodo de respaldo configurado. Selecciona uno y vuelve a intentarlo.',
masterBackupAlert:
'No se ha configurado un respaldo del nodo principal. Para garantizar la seguridad de los datos, configura un nodo de respaldo lo antes posible y así facilitar el cambio manual en caso de fallo.',
+2 -2
View File
@@ -2145,7 +2145,7 @@ const message = {
about: 'について',
versionItem: '現在のバージョン',
backupCopies: '保持するバックアップ数',
backupCopies: 'バックアップ数',
backupCopiesHelper:
'バージョンロールバック用に保持するアップグレードバックアップの数を設定します。0はすべて保持を意味します。',
backupCopiesRule: '少なくとも3つのアップグレードバックアップ記録を保持してください',
@@ -3781,7 +3781,7 @@ const message = {
masterBackup: 'マスターノードバックアップ',
backupNode: 'バックアップノード',
backupFrequency: 'バックアップ頻度(時間)',
backupCopies: 'バックアップ保持数',
backupCopies: 'バックアップ数',
noBackupNode: '現在バックアップノードが空です。保存するバックアップノードを選択して再試行してください!',
masterBackupAlert:
'現在マスターノードのバックアップが設定されていません。データセキュリティを確保するため、障害時に新しいマスターノードに手動で切り替えられるよう、速やかにバックアップノードを設定してください。',
+2 -2
View File
@@ -2108,7 +2108,7 @@ const message = {
about: '정보',
versionItem: '현재 버전',
backupCopies: '보관할 백업 복사본 수',
backupCopies: '백업 수',
backupCopiesHelper:
'버전 롤백을 위해 보관할 업그레이드 백업 복사본 수를 설정합니다. 0은 모두 보관을 의미합니다.',
backupCopiesRule: '최소 3개의 업그레이드 백업 기록을 보관하세요',
@@ -3708,7 +3708,7 @@ const message = {
masterBackup: '마스터 노드 백업',
backupNode: '백업 노드',
backupFrequency: '백업 주기(시간)',
backupCopies: '백업 기록 보관 수',
backupCopies: '백업 수',
noBackupNode: '현재 백업 노드가 비어 있습니다. 저장할 백업 노드를 선택한 후 다시 시도하십시오!',
masterBackupAlert:
'현재 마스터 노드 백업이 구성되지 않았습니다. 데이터 보안을 위해 장애 시 새로운 마스터 노드로 수동 전환이 가능하도록 가능한 빨리 백업 노드를 설정하십시오.',
+2 -2
View File
@@ -2203,7 +2203,7 @@ const message = {
about: 'Mengenai',
versionItem: 'Versi Semasa',
backupCopies: 'Bilangan Salinan untuk Disimpan',
backupCopies: 'Salinan Sandaran',
backupCopiesHelper:
'Tetapkan bilangan salinan sandaran naik taraf untuk disimpan untuk pemulihan versi. 0 bermakna simpan semua.',
backupCopiesRule: 'Sila simpan sekurang-kurangnya 3 rekod sandaran naik taraf',
@@ -3848,7 +3848,7 @@ const message = {
masterBackup: 'Sandaran Nod Master',
backupNode: 'Nod Sandaran',
backupFrequency: 'Kekerapan Sandaran (jam)',
backupCopies: 'Bilangan salinan sandaran yang disimpan',
backupCopies: 'Salinan Sandaran',
noBackupNode: 'Nod sandaran kosong. Sila pilih nod sandaran untuk disimpan dan cuba lagi!',
masterBackupAlert:
'Sandaran nod master belum dikonfigurasikan. Untuk memastikan keselamatan data, sila sediakan nod sandaran secepat mungkin untuk memudahkan pertukaran manual ke nod master baru sekiranya berlaku kegagalan.',
+2 -2
View File
@@ -2192,7 +2192,7 @@ const message = {
about: 'Sobre',
versionItem: 'Versão Atual',
backupCopies: 'Número de Cópias a Manter',
backupCopies: 'Cópias de Backup',
backupCopiesHelper:
'Defina o número de cópias de backup de atualização para manter para reversão de versão. 0 significa manter todas.',
backupCopiesRule: 'Mantenha pelo menos 3 registros de backup de atualização',
@@ -3867,7 +3867,7 @@ const message = {
masterBackup: 'Backup do Nó Mestre',
backupNode: 'Nó de Backup',
backupFrequency: 'Frequência de Backup (horas)',
backupCopies: 'Número de cópias de backup a reter',
backupCopies: 'Cópias de Backup',
noBackupNode:
'O nó de backup está vazio atualmente. Selecione um nó de backup para salvar e tente novamente!',
masterBackupAlert:
+2 -2
View File
@@ -2189,7 +2189,7 @@ const message = {
about: 'О программе',
versionItem: 'Текущая Версия',
backupCopies: 'Количество Копий для Сохранения',
backupCopies: 'Копии Бэкапа',
backupCopiesHelper:
'Установите количество копий резервных копий обновления для сохранения для отката версии. 0 означает сохранить все.',
backupCopiesRule: 'Пожалуйста, сохраните как минимум 3 записи резервных копий обновления',
@@ -3852,7 +3852,7 @@ const message = {
masterBackup: 'Резервная копия главного узла',
backupNode: 'Резервный узел',
backupFrequency: 'Частота резервного копирования (часы)',
backupCopies: 'Количество сохраняемых резервных копий',
backupCopies: 'Копии Бэкапа',
noBackupNode:
'Резервный узел в настоящее время пуст. Выберите резервный узел для сохранения и повторите попытку!',
masterBackupAlert:
+2 -2
View File
@@ -2228,7 +2228,7 @@ const message = {
about: 'Hakkında',
versionItem: 'Mevcut Sürüm',
backupCopies: 'Saklanacak Kopya Sayısı',
backupCopies: 'Yedek Kopya',
backupCopiesHelper:
'Sürüm geri alma için saklanacak yükseltme yedek kopya sayısını ayarlayın. 0, tümünü sakla anlamına gelir.',
backupCopiesRule: 'Lütfen en az 3 yükseltme yedek kaydı saklayın',
@@ -3911,7 +3911,7 @@ const message = {
masterBackup: 'Ana Düğüm Yedekleme',
backupNode: 'Yedek Düğüm',
backupFrequency: 'Yedekleme Sıklığı (saat)',
backupCopies: 'Saklanacak yedek kopya sayısı',
backupCopies: 'Yedek Kopya',
noBackupNode: 'Yedek düğüm şu anda boş. Lütfen kaydetmek için bir yedek düğüm seçin ve tekrar deneyin!',
masterBackupAlert:
'Ana düğüm yedeklemesi şu anda yapılandırılmamış. Veri güvenliği için, lütfen arıza durumunda yeni bir ana düğüme manuel geçiş yapabilmek amacıyla en kısa sürede bir yedek düğüm ayarlayın.',
+2 -2
View File
@@ -2062,7 +2062,7 @@ const message = {
about: '關於',
versionItem: '當前版本',
backupCopies: '保留份數',
backupCopies: '備份份數',
backupCopiesHelper: '設定用於版本回滾的升級備份保留份數。0 表示保留所有。',
backupCopiesRule: '請至少儲存 3 份升級備份記錄',
release: '版本更新日誌',
@@ -3580,7 +3580,7 @@ const message = {
masterBackup: '主節點備份',
backupNode: '備份節點',
backupFrequency: '備份頻率(小時)',
backupCopies: '備份記錄保留份數',
backupCopies: '備份份數',
noBackupNode: '目前備份節點為空,請選擇備份節點儲存後重試',
masterBackupAlert:
'目前未設定主節點備份,為保障資料安全,請盡快設定備份節點,便於主節點故障時可人工切換新主節點。',
+2 -2
View File
@@ -2032,7 +2032,7 @@ const message = {
about: '关于',
versionItem: '当前版本',
backupCopies: '保留份数',
backupCopies: '备份份数',
backupCopiesHelper: '设置用于版本回滚的升级备份保留份数,为 0 则保留所有。',
backupCopiesRule: '请至少保存 3 份升级备份记录',
release: '版本更新日志',
@@ -3534,7 +3534,7 @@ const message = {
masterBackup: '主节点备份',
backupNode: '备份节点',
backupFrequency: '备份频率(小时)',
backupCopies: '备份记录保留份数',
backupCopies: '备份份数',
noBackupNode: '当前备份节点为空,请选择备份节点保存后重试!',
masterBackupAlert:
'当前未配置主节点备份,为保障数据安全,请尽快设置备份节点,便于主节点故障时可人工切换新主节点。',
@@ -108,6 +108,7 @@ import { getAgentProviderDisplayName } from '@/utils/agent';
import { App } from '@/api/interface/app';
import AdvancedSetting from '@/components/advanced-setting/index.vue';
import AccountAddDialog from '@/views/ai/agents/model/add/index.vue';
import { useGlobalStore } from '@/composables/useGlobalStore';
const emit = defineEmits(['search', 'task']);
@@ -121,6 +122,7 @@ const providerAccountCount = ref<Record<string, number>>({});
const manualModel = ref(false);
const appInfo = ref<App.AppDTO>();
const accountAddRef = ref();
const { isIntl } = useGlobalStore();
const form = reactive({
name: '',
@@ -215,11 +217,13 @@ const loadProviders = async () => {
}
const res = await getAgentProviders();
const data = res.data || [];
providerOptions.value = data.map((item) => ({
const blockedProviders = new Set(['ark-coding-plan', 'bailian-coding-plan']);
const filteredData = isIntl.value ? data.filter((item) => !blockedProviders.has(item.provider)) : data;
providerOptions.value = filteredData.map((item) => ({
value: item.provider,
label: getAgentProviderDisplayName(item.provider, item.displayName),
}));
providerModels.value = data.reduce((acc, item) => {
providerModels.value = filteredData.reduce((acc, item) => {
acc[item.provider] = item.models || [];
return acc;
}, {} as Record<string, AI.ProviderModelInfo[]>);
@@ -35,6 +35,7 @@ import { AI } from '@/api/interface/ai';
import { getAgentProviders, pageAgentAccounts, updateAgentModelConfig } from '@/api/modules/ai';
import { Rules } from '@/global/form-rules';
import { MsgSuccess } from '@/utils/message';
import { useGlobalStore } from '@/composables/useGlobalStore';
const emit = defineEmits(['updated']);
const { t } = useI18n();
@@ -42,6 +43,8 @@ const { t } = useI18n();
const loading = ref(false);
const saving = ref(false);
const formRef = ref<FormInstance>();
const { isIntl } = useGlobalStore();
const blockedProviders = new Set(['ark-coding-plan', 'bailian-coding-plan']);
const agentId = ref(0);
const providerModels = ref<Record<string, AI.ProviderModelInfo[]>>({});
@@ -81,7 +84,8 @@ const loadProviders = async () => {
}
const res = await getAgentProviders();
const data = res.data || [];
providerModels.value = data.reduce((acc, item) => {
const filteredData = isIntl.value ? data.filter((item) => !blockedProviders.has(item.provider)) : data;
providerModels.value = filteredData.reduce((acc, item) => {
acc[item.provider] = item.models || [];
return acc;
}, {} as Record<string, AI.ProviderModelInfo[]>);
@@ -94,7 +98,8 @@ const loadAccounts = async () => {
provider: '',
name: '',
});
accountOptions.value = res.data.items || [];
const items = res.data.items || [];
accountOptions.value = isIntl.value ? items.filter((item) => !blockedProviders.has(item.provider)) : items;
};
const setModelsByProvider = (provider: string) => {
@@ -76,6 +76,7 @@ import { Rules } from '@/global/form-rules';
import { createAgentAccount, getAgentProviders, updateAgentAccount } from '@/api/modules/ai';
import i18n from '@/lang';
import { getAgentProviderDisplayName } from '@/utils/agent';
import { useGlobalStore } from '@/composables/useGlobalStore';
const emit = defineEmits(['search']);
@@ -85,6 +86,7 @@ const providerOptions = ref<Array<{ label: string; value: string }>>([]);
const providerBaseURL = ref<Record<string, string>>({});
const loading = ref(false);
const editableBaseURLProviders = ['ollama', 'custom', 'zai'];
const { isIntl } = useGlobalStore();
const form = reactive({
id: 0,
@@ -225,11 +227,13 @@ const openDrawer = async (params?: OpenParams) => {
const loadProviders = async () => {
const res = await getAgentProviders();
const data = res.data || [];
providerOptions.value = data.map((item) => ({
const blockedProviders = new Set(['ark-coding-plan', 'bailian-coding-plan']);
const filteredData = isIntl.value ? data.filter((item) => !blockedProviders.has(item.provider)) : data;
providerOptions.value = filteredData.map((item) => ({
value: item.provider,
label: getAgentProviderDisplayName(item.provider, item.displayName),
}));
providerBaseURL.value = data.reduce((acc, item) => {
providerBaseURL.value = filteredData.reduce((acc, item) => {
acc[item.provider] = item.baseUrl || '';
return acc;
}, {} as Record<string, string>);