refactor(admin): удалить мёртвый updater/config-write API и его UI

Маршруты, операциями которых продукт не владеет, отвечали заглушкой
"managed by orchestrator" или пустым списком:

  POST /hysteria2ChangeVersion
  GET  /listRelease
  POST /config/updateHysteria2Config
  POST /config/importHysteria2Config
  POST /config/restartServer
  POST /config/uploadCertFile
  GET  /config/hysteria2AcmePath   (не имел потребителя вовсе)

Они удалены, а не оставлены заглушками. Причины две. API-контракт не
должен обещать updater, которого у продукта принципиально нет:
маршрут, всегда возвращающий отказ, вводит в заблуждение. И это лишняя
attack surface плюс технический мусор от прежней архитектуры.

Вместе с маршрутами убраны мёртвые сервисы (StartHysteria2,
StopHysteria2, RestartHysteria2, SetHysteria2Config,
UpdateHysteria2Config, GetAuthHttpUrl, Hysteria2AcmePath), неиспользуемые
типы и клиентские функции фронтенда.

Отдельно - кнопки. "Перезапустить панель" и загрузка сертификатов
обращались к заглушкам, то есть гарантированно возвращали ошибку.
Кнопка, которая всегда падает, - не точка расширения на будущее, а
дефект UX. Удалены вместе со строками i18n.

Конфигурация Hysteria остаётся доступной панели на чтение и на
выгрузку: getHysteria2Config и exportHysteria2Config.
This commit is contained in:
2026-08-27 12:15:53 +05:00
parent 10d2c48cf0
commit 19ffc80130
15 changed files with 20 additions and 357 deletions
+4 -44
View File
@@ -5,10 +5,13 @@ import {
ConfigsDto,
ConfigUpdateDto,
ConfigVo,
Hysteria2AcmePathVo,
Hysteria2ServerConfig,
} from "@/api/config/types";
// Серверный конфиг Hysteria доступен панели только на чтение и на выгрузку:
// им владеет install-оркестратор. Клиентов записи, импорта, перезапуска и
// загрузки сертификатов здесь нет — соответствующих маршрутов не существует.
export function getHysteria2ConfigApi(): AxiosPromise<Hysteria2ServerConfig> {
return request({
url: "/config/getHysteria2Config",
@@ -16,16 +19,6 @@ export function getHysteria2ConfigApi(): AxiosPromise<Hysteria2ServerConfig> {
});
}
export function updateHysteria2ConfigApi(
data: Hysteria2ServerConfig
): AxiosPromise {
return request({
url: "/config/updateHysteria2Config",
method: "post",
data: data,
});
}
export function getConfigApi(data: ConfigDto): AxiosPromise<ConfigVo> {
return request({
url: "/config/getConfig",
@@ -77,36 +70,3 @@ export function exportHysteria2ConfigApi(): AxiosPromise {
});
}
export function importHysteria2ConfigApi(data: FormData): AxiosPromise {
return request({
url: "/config/importHysteria2Config",
method: "post",
headers: {
"Content-Type": "multipart/form-data",
},
data: data,
});
}
export function hysteria2AcmePathApi(): AxiosPromise<Hysteria2AcmePathVo> {
return request({
url: "/config/hysteria2AcmePath",
method: "get",
});
}
export function restartServerApi(): AxiosPromise {
return request({
url: "/config/restartServer",
method: "post",
});
}
export function uploadCertFileApi(data: FormData): AxiosPromise<string> {
return request({
url: "/config/uploadCertFile",
method: "post",
data,
headers: { "Content-Type": "multipart/form-data" },
});
}
-5
View File
@@ -340,8 +340,3 @@ export interface Tab {
name: string;
desc: string;
}
export interface Hysteria2AcmePathVo {
crtPath: string;
keyPath: string;
}
-5
View File
@@ -185,10 +185,6 @@ export default {
hysteria2TrafficTime: "Hysteria2 Traffic Time",
huiCrtPath: "HY2XS admin CRT File Path",
huiKeyPath: "HY2XS admin KEY File Path",
uploadCrtFile: "Upload CRT File",
uploadKeyFile: "Upload KEY File",
restartServer: "Restart Panel",
restartTip: "Restarting, please refresh",
useHysteria2Cert: "Use Hysteria2 cert",
huiHttps: "Open https on the panel",
resetTrafficCron: "Reset traffic schedule task",
@@ -237,7 +233,6 @@ export default {
addConfigItem: "Add Config Item",
hysteria2Version: "Hysteria2 Version",
hysteria2Running: "Hysteria2 Status",
hysteria2ChangeVersion: "Change",
addOutbound: "Add Outbound",
extension: "Extension",
listen: "Listen",
-5
View File
@@ -181,10 +181,6 @@ export default {
hysteria2TrafficTime: "Период учёта трафика Hysteria2",
huiCrtPath: "Путь к CRT HY2XS admin",
huiKeyPath: "Путь к KEY HY2XS admin",
uploadCrtFile: "Загрузить CRT",
uploadKeyFile: "Загрузить KEY",
restartServer: "Перезапустить панель",
restartTip: "Перезапуск, обновите страницу",
useHysteria2Cert: "Использовать сертификат Hysteria2",
huiHttps: "Включить HTTPS панели",
resetTrafficCron: "Расписание сброса трафика",
@@ -233,7 +229,6 @@ export default {
addConfigItem: "Добавить параметр",
hysteria2Version: "Версия Hysteria2",
hysteria2Running: "Статус Hysteria2",
hysteria2ChangeVersion: "Сменить",
addOutbound: "Добавить outbound",
extension: "Расширение",
listen: "Адрес прослушивания",
@@ -7,14 +7,6 @@
{{ $t("common.save") }}
</el-button>
</el-form-item>
<el-form-item>
<el-button @click="handleRestartServer">
<template #icon>
<i-ep-refreshRight />
</template>
{{ $t("config.restartServer") }}
</el-button>
</el-form-item>
<el-form-item>
<el-upload
v-model:file-list="fileList"
@@ -166,7 +158,6 @@ import {
exportConfigApi,
importConfigApi,
listConfigApi,
restartServerApi,
updateConfigsApi,
} from "@/api/config";
import { ConfigsUpdateDto } from "@/api/config/types";
@@ -352,21 +343,6 @@ const handleExport = async () => {
}
};
const handleRestartServer = async () => {
try {
ElMessageBox.confirm(t("config.restartTip"), t("common.warning"), {
confirmButtonText: t("common.confirm"),
cancelButtonText: t("common.cancel"),
type: "warning",
}).then(() => {
restartServerApi();
ElMessage.success(t("config.restartTip"));
});
} catch (e) {
/* empty */
}
};
onMounted(() => {
setConfig();
if (route.query.focus === "huiHttps") {
@@ -95,28 +95,9 @@
<el-form-item label="cert" prop="tls.cert">
<el-input
v-model="dataForm.tls.cert"
style="width: 50%"
style="width: 100%"
clearable
/>
<el-upload
style="height: 32px"
ref="uploadCrtFile"
action=""
:file-list="crtFileList"
:http-request="uploadCertFile"
accept=".crt"
:before-upload="
() => {
crtFileList = [];
}
"
:show-file-list="false"
:limit="1"
>
<template #trigger>
<el-button>{{ t("config.uploadCrtFile") }}</el-button>
</template>
</el-upload>
</el-form-item>
</el-tooltip>
<el-tooltip
@@ -127,28 +108,9 @@
<el-form-item label="key" prop="tls.key">
<el-input
v-model="dataForm.tls.key"
style="width: 50%"
style="width: 100%"
clearable
/>
<el-upload
style="height: 32px"
ref="uploadKeyFile"
action=""
:file-list="keyFileList"
:http-request="uploadCertFile"
accept=".key"
:before-upload="
() => {
keyFileList = [];
}
"
:show-file-list="false"
:limit="1"
>
<template #trigger>
<el-button>{{ t("config.uploadKeyFile") }}</el-button>
</template>
</el-upload>
</el-form-item>
</el-tooltip>
<el-tooltip
@@ -1104,13 +1066,10 @@ import {
exportHysteria2ConfigApi,
getHysteria2ConfigApi,
listConfigApi,
uploadCertFileApi,
} from "@/api/config";
import { useI18n } from "vue-i18n";
import { assignWith, deepCopy } from "@/utils/copy";
import { UploadRequestOptions } from "element-plus";
import { dashboardSummaryApi } from "@/api/dashboard";
import { UploadUserFile } from "element-plus";
const { t } = useI18n();
@@ -1181,8 +1140,6 @@ const state = reactive({
version: "",
running: false,
},
crtFileList: [] as UploadUserFile[],
keyFileList: [] as UploadUserFile[],
});
const {
@@ -1203,8 +1160,6 @@ const {
outbounds,
masquerade,
hysteria2Monitor,
crtFileList,
keyFileList,
} = toRefs(state);
const handleExport = async () => {
@@ -1287,33 +1242,6 @@ const setHysteria2Monitor = async () => {
state.hysteria2Monitor.running = data.hysteria.running;
};
const uploadCertFile = async (params: UploadRequestOptions) => {
try {
if (!state.dataForm.tls) {
return;
}
if (
!params.file.name.endsWith(".crt") &&
!params.file.name.endsWith(".key")
) {
ElMessage.error(t("common.fileFormatUnsupported"));
}
if (params.file.size > 1024 * 1024) {
ElMessage.error(t("common.fileTooLarge"));
}
let formData = new FormData();
formData.append("file", params.file);
const { data } = await uploadCertFileApi(formData);
if (params.file.name.endsWith(".crt")) {
state.dataForm.tls.cert = data;
} else if (params.file.name.endsWith(".key")) {
state.dataForm.tls.key = data;
}
} catch (e) {
/* empty */
}
};
onMounted(() => {
setConfig();
setHysteria2Monitor();