fix: streamline release deploy ui
This commit is contained in:
parent
2d81e98b3b
commit
3cf7f6656d
@ -616,11 +616,6 @@ body.auth-page {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-section-nav {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.taskbar-context {
|
.taskbar-context {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -668,43 +663,6 @@ body.auth-page {
|
|||||||
transition: color 180ms ease, opacity 180ms ease, border-color 180ms ease, background 180ms ease;
|
transition: color 180ms ease, opacity 180ms ease, border-color 180ms ease, background 180ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-step-link {
|
|
||||||
border-color: color-mix(in oklab, var(--line) 86%, var(--panel-strong));
|
|
||||||
background: color-mix(in oklab, var(--panel-strong) 90%, var(--panel-muted));
|
|
||||||
}
|
|
||||||
|
|
||||||
.release-step-index {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
border: 1px solid var(--line);
|
|
||||||
border-radius: 999px;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 9px;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.release-step-link.tone-ok .release-step-index {
|
|
||||||
border-color: color-mix(in oklab, var(--ok) 34%, var(--line));
|
|
||||||
background: color-mix(in oklab, var(--ok-soft) 46%, var(--panel-strong));
|
|
||||||
color: color-mix(in oklab, var(--ok) 70%, var(--text));
|
|
||||||
}
|
|
||||||
|
|
||||||
.release-step-link.tone-warn .release-step-index {
|
|
||||||
border-color: color-mix(in oklab, var(--warn) 38%, var(--line));
|
|
||||||
background: color-mix(in oklab, var(--warn-soft) 56%, var(--panel-strong));
|
|
||||||
color: color-mix(in oklab, var(--warn) 82%, var(--text));
|
|
||||||
}
|
|
||||||
|
|
||||||
.release-step-link.tone-bad .release-step-index {
|
|
||||||
border-color: color-mix(in oklab, var(--bad) 42%, var(--line));
|
|
||||||
background: color-mix(in oklab, var(--bad-soft) 58%, var(--panel-strong));
|
|
||||||
color: color-mix(in oklab, var(--bad) 82%, var(--text));
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-link:hover {
|
.section-link:hover {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-color: color-mix(in oklab, var(--accent) 18%, var(--line));
|
border-color: color-mix(in oklab, var(--accent) 18%, var(--line));
|
||||||
@ -715,10 +673,6 @@ body.auth-page {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-kind-select {
|
|
||||||
min-width: 98px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-group-spread {
|
.control-group-spread {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
@ -3191,9 +3145,9 @@ body.auth-page {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 8px;
|
margin-top: 0;
|
||||||
padding-top: 8px;
|
padding-top: 0;
|
||||||
border-top: 1px solid color-mix(in oklab, var(--line) 92%, var(--panel-strong));
|
border-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-command-actions .refresh {
|
.release-command-actions .refresh {
|
||||||
@ -3307,23 +3261,24 @@ body.auth-page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.release-service-title-line {
|
.release-service-title-line {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
flex-wrap: nowrap;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-service-title strong {
|
.release-service-title strong {
|
||||||
overflow: hidden;
|
grid-column: 1 / -1;
|
||||||
flex: 1 1 auto;
|
overflow: visible;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.3;
|
line-height: 1.25;
|
||||||
text-overflow: ellipsis;
|
overflow-wrap: anywhere;
|
||||||
white-space: nowrap;
|
text-overflow: clip;
|
||||||
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-service-title-line .badge {
|
.release-service-title-line .badge {
|
||||||
flex: 0 0 auto;
|
width: fit-content;
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
font-size: 9.5px;
|
font-size: 9.5px;
|
||||||
@ -4035,17 +3990,6 @@ body.auth-page {
|
|||||||
background: linear-gradient(180deg, color-mix(in oklab, var(--panel-muted) 98%, var(--panel-strong)) 0%, var(--panel-muted) 100%);
|
background: linear-gradient(180deg, color-mix(in oklab, var(--panel-muted) 98%, var(--panel-strong)) 0%, var(--panel-muted) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.release-section-nav {
|
|
||||||
display: flex;
|
|
||||||
gap: 6px;
|
|
||||||
align-items: center;
|
|
||||||
padding: 4px;
|
|
||||||
border: 1px solid color-mix(in oklab, var(--line) 92%, var(--panel-strong));
|
|
||||||
border-radius: 14px;
|
|
||||||
background: linear-gradient(180deg, color-mix(in oklab, var(--panel-muted) 96%, var(--panel-strong)) 0%, var(--panel-strong) 100%);
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mongo-admin-layout {
|
.mongo-admin-layout {
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
@ -4736,6 +4680,20 @@ body.auth-page {
|
|||||||
box-shadow: 0 24px 64px rgba(29, 42, 68, 0.24);
|
box-shadow: 0 24px 64px rgba(29, 42, 68, 0.24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.build-params-dialog {
|
||||||
|
grid-template-rows: auto auto auto;
|
||||||
|
width: min(900px, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-params-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-params-toggle {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.log-viewer-head {
|
.log-viewer-head {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@ -56,12 +56,6 @@ const PRIMARY_FILTERS = [
|
|||||||
{ id: "infra", label: "基础设施" },
|
{ id: "infra", label: "基础设施" },
|
||||||
];
|
];
|
||||||
const BUSINESS_GROUPS = new Set(["gateway", "app", "pay"]);
|
const BUSINESS_GROUPS = new Set(["gateway", "app", "pay"]);
|
||||||
const RELEASE_SECTIONS = [
|
|
||||||
{ id: "release-build", label: "构建参数" },
|
|
||||||
{ id: "release-targets", label: "更新目标" },
|
|
||||||
{ id: "release-log", label: "执行日志" },
|
|
||||||
{ id: "release-restart", label: "滚动重启" },
|
|
||||||
];
|
|
||||||
const CONFIG_TABS = [
|
const CONFIG_TABS = [
|
||||||
{ id: "nacos", label: "Nacos" },
|
{ id: "nacos", label: "Nacos" },
|
||||||
{ id: "go", label: "Go Env" },
|
{ id: "go", label: "Go Env" },
|
||||||
@ -420,7 +414,6 @@ createApp({
|
|||||||
: DATABASE_ENGINES.filter((engine) => engine.id === "mongo"),
|
: DATABASE_ENGINES.filter((engine) => engine.id === "mongo"),
|
||||||
commonToolTabs: COMMON_TOOL_TABS,
|
commonToolTabs: COMMON_TOOL_TABS,
|
||||||
primaryFilters: PRIMARY_FILTERS,
|
primaryFilters: PRIMARY_FILTERS,
|
||||||
releaseSections: RELEASE_SECTIONS,
|
|
||||||
configTabs: CONFIG_TABS,
|
configTabs: CONFIG_TABS,
|
||||||
infraTabs: INFRA_TABS,
|
infraTabs: INFRA_TABS,
|
||||||
mongoAdminTabs: MONGO_ADMIN_TABS,
|
mongoAdminTabs: MONGO_ADMIN_TABS,
|
||||||
@ -436,7 +429,7 @@ createApp({
|
|||||||
keyword: "",
|
keyword: "",
|
||||||
infraKeyword: "",
|
infraKeyword: "",
|
||||||
releaseKeyword: "",
|
releaseKeyword: "",
|
||||||
releaseKindFilter: "all",
|
buildParamsOpen: false,
|
||||||
configTab: "nacos",
|
configTab: "nacos",
|
||||||
configEditorMode: "diff",
|
configEditorMode: "diff",
|
||||||
goEditorMode: "diff",
|
goEditorMode: "diff",
|
||||||
@ -1743,9 +1736,6 @@ createApp({
|
|||||||
const keyword = this.normalizedReleaseKeyword;
|
const keyword = this.normalizedReleaseKeyword;
|
||||||
return this.allReleaseTargetRows
|
return this.allReleaseTargetRows
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
if (this.releaseKindFilter !== "all" && item.kind !== this.releaseKindFilter) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (keyword && !item.searchText.includes(keyword)) {
|
if (keyword && !item.searchText.includes(keyword)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1766,9 +1756,6 @@ createApp({
|
|||||||
].join(" ").toLowerCase(),
|
].join(" ").toLowerCase(),
|
||||||
}))
|
}))
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
if (this.releaseKindFilter !== "all" && item.kind !== this.releaseKindFilter) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (keyword && !item.searchText.includes(keyword)) {
|
if (keyword && !item.searchText.includes(keyword)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2385,14 +2372,6 @@ createApp({
|
|||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
scrollToSection(sectionId) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
const node = document.getElementById(sectionId);
|
|
||||||
if (node) {
|
|
||||||
node.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
imageMeta(imageRef) {
|
imageMeta(imageRef) {
|
||||||
const raw = String(imageRef || "").trim();
|
const raw = String(imageRef || "").trim();
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
@ -2490,36 +2469,30 @@ createApp({
|
|||||||
return this.copiedToken === token;
|
return this.copiedToken === token;
|
||||||
},
|
},
|
||||||
runReleasePrecheck() {
|
runReleasePrecheck() {
|
||||||
|
const selectedKinds = new Set(
|
||||||
|
(this.updateOps.items || [])
|
||||||
|
.filter((item) => this.updateOps.selectedServices.includes(item.service))
|
||||||
|
.map((item) => item.kind)
|
||||||
|
);
|
||||||
const checks = [
|
const checks = [
|
||||||
{
|
{
|
||||||
label: "更新目标",
|
|
||||||
ok: this.updateOps.items.length > 0,
|
ok: this.updateOps.items.length > 0,
|
||||||
detail: this.updateOps.items.length > 0 ? `${this.updateOps.items.length} 项可更新服务` : this.explainError(this.updateOps.error) || "暂无更新目标",
|
detail: this.updateOps.items.length > 0 ? `${this.updateOps.items.length} 项可更新服务` : this.explainError(this.updateOps.error) || "暂无可更新服务",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "更新选择",
|
|
||||||
ok: this.updateOps.selectedServices.length > 0,
|
ok: this.updateOps.selectedServices.length > 0,
|
||||||
detail: this.updateOps.selectedServices.length > 0 ? this.updateOps.selectedServices.join(", ") : "未选择更新服务",
|
detail: this.updateOps.selectedServices.length > 0 ? this.updateOps.selectedServices.join(", ") : "未选择更新服务",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "滚动重启目标",
|
|
||||||
ok: this.restartOps.items.length > 0,
|
ok: this.restartOps.items.length > 0,
|
||||||
detail: this.restartOps.items.length > 0 ? `${this.restartOps.items.length} 项可重启服务` : (this.restartOps.error || "暂无重启目标"),
|
detail: this.restartOps.items.length > 0 ? `${this.restartOps.items.length} 项可重启服务` : (this.restartOps.error || "暂无重启目标"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "构建参数",
|
ok: (
|
||||||
ok: (() => {
|
(!selectedKinds.has("java") || Boolean(this.updateOps.javaGitRef.trim()))
|
||||||
const selectedKinds = new Set(
|
&& (!selectedKinds.has("golang") || Boolean(this.updateOps.goGitRef.trim()))
|
||||||
(this.updateOps.items || [])
|
&& (!selectedKinds.has("frontend") || Boolean(this.updateOps.adminGitRef.trim()))
|
||||||
.filter((item) => this.updateOps.selectedServices.includes(item.service))
|
),
|
||||||
.map((item) => item.kind)
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
(!selectedKinds.has("java") || Boolean(this.updateOps.javaGitRef.trim()))
|
|
||||||
&& (!selectedKinds.has("golang") || Boolean(this.updateOps.goGitRef.trim()))
|
|
||||||
&& (!selectedKinds.has("frontend") || Boolean(this.updateOps.adminGitRef.trim()))
|
|
||||||
);
|
|
||||||
})(),
|
|
||||||
detail: `Java ${this.updateOps.javaGitRef || "-"} / Go ${this.updateOps.goGitRef || "-"} / Admin ${this.updateOps.adminGitRef || "-"}`,
|
detail: `Java ${this.updateOps.javaGitRef || "-"} / Go ${this.updateOps.goGitRef || "-"} / Admin ${this.updateOps.adminGitRef || "-"}`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -2529,9 +2502,9 @@ createApp({
|
|||||||
ranAt: new Date().toISOString(),
|
ranAt: new Date().toISOString(),
|
||||||
tone: ok ? "ok" : "warn",
|
tone: ok ? "ok" : "warn",
|
||||||
title: ok ? "预检查通过" : "预检查未通过",
|
title: ok ? "预检查通过" : "预检查未通过",
|
||||||
checks,
|
checks: [],
|
||||||
};
|
};
|
||||||
this.recordReleaseHistory("precheck", this.releasePrecheck.title, checks.map((item) => `${item.label}: ${item.detail}`).join(" | "), ok ? "ok" : "warn");
|
this.recordReleaseHistory("precheck", this.releasePrecheck.title, checks.map((item) => item.detail).join(" | "), ok ? "ok" : "warn");
|
||||||
},
|
},
|
||||||
async refreshReleaseTargets() {
|
async refreshReleaseTargets() {
|
||||||
await this.ensureReleaseWorkbenchLoaded({ force: true });
|
await this.ensureReleaseWorkbenchLoaded({ force: true });
|
||||||
@ -3319,33 +3292,6 @@ createApp({
|
|||||||
}
|
}
|
||||||
return this.releaseIsRunning() ? `上次${this.releasePrecheck.title}` : this.releasePrecheck.title;
|
return this.releaseIsRunning() ? `上次${this.releasePrecheck.title}` : this.releasePrecheck.title;
|
||||||
},
|
},
|
||||||
releaseStepTone(sectionId) {
|
|
||||||
if (sectionId === "release-build") {
|
|
||||||
return this.updateOps.selectedServices.length > 0 || this.updateOps.status ? "ok" : "neutral";
|
|
||||||
}
|
|
||||||
if (sectionId === "release-targets") {
|
|
||||||
return this.updateOps.selectedServices.length > 0 || this.restartOps.selectedServices.length > 0 ? "ok" : "neutral";
|
|
||||||
}
|
|
||||||
if (sectionId === "release-log") {
|
|
||||||
if (this.updateOps.error || this.updateOps.status === "failed") {
|
|
||||||
return "bad";
|
|
||||||
}
|
|
||||||
if (this.updateOps.running || this.updateOps.status === "queued" || this.updateOps.status === "running") {
|
|
||||||
return "warn";
|
|
||||||
}
|
|
||||||
return this.updateOps.status === "success" ? "ok" : "neutral";
|
|
||||||
}
|
|
||||||
if (sectionId === "release-restart") {
|
|
||||||
if (this.restartOps.error) {
|
|
||||||
return "bad";
|
|
||||||
}
|
|
||||||
if (this.restartOps.running) {
|
|
||||||
return "warn";
|
|
||||||
}
|
|
||||||
return this.restartOps.result?.ok || this.restartOps.selectedServices.length > 0 ? "ok" : "neutral";
|
|
||||||
}
|
|
||||||
return "neutral";
|
|
||||||
},
|
|
||||||
syncRefreshSettings() {
|
syncRefreshSettings() {
|
||||||
const settings = this.payload.settings || {};
|
const settings = this.payload.settings || {};
|
||||||
const options = Array.isArray(settings.refreshIntervalOptions)
|
const options = Array.isArray(settings.refreshIntervalOptions)
|
||||||
@ -5995,10 +5941,10 @@ createApp({
|
|||||||
this.restartOps.items = Array.isArray(payload.items) ? payload.items : [];
|
this.restartOps.items = Array.isArray(payload.items) ? payload.items : [];
|
||||||
const available = new Set(this.restartOps.items.map((item) => item.service));
|
const available = new Set(this.restartOps.items.map((item) => item.service));
|
||||||
this.restartOps.selectedServices = this.restartOps.selectedServices.filter((service) => available.has(service));
|
this.restartOps.selectedServices = this.restartOps.selectedServices.filter((service) => available.has(service));
|
||||||
this.recordReleaseHistory("restart", "刷新滚动重启目标", `${this.restartOps.items.length} 项`, "neutral");
|
this.recordReleaseHistory("restart", "刷新重启列表", `${this.restartOps.items.length} 项`, "neutral");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.restartOps.error = error instanceof Error ? error.message : String(error);
|
this.restartOps.error = error instanceof Error ? error.message : String(error);
|
||||||
this.recordReleaseHistory("restart", "刷新滚动重启目标失败", this.explainError(this.restartOps.error), "bad");
|
this.recordReleaseHistory("restart", "刷新重启列表失败", this.explainError(this.restartOps.error), "bad");
|
||||||
} finally {
|
} finally {
|
||||||
this.restartOps.loaded = true;
|
this.restartOps.loaded = true;
|
||||||
this.restartOps.loading = false;
|
this.restartOps.loading = false;
|
||||||
@ -6041,10 +5987,10 @@ createApp({
|
|||||||
|
|
||||||
const available = new Set(this.updateOps.items.map((item) => item.service));
|
const available = new Set(this.updateOps.items.map((item) => item.service));
|
||||||
this.updateOps.selectedServices = this.updateOps.selectedServices.filter((service) => available.has(service));
|
this.updateOps.selectedServices = this.updateOps.selectedServices.filter((service) => available.has(service));
|
||||||
this.recordReleaseHistory("update", "刷新更新目标", `${this.updateOps.items.length} 项`, "neutral");
|
this.recordReleaseHistory("update", "刷新服务列表", `${this.updateOps.items.length} 项`, "neutral");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.updateOps.error = error instanceof Error ? error.message : String(error);
|
this.updateOps.error = error instanceof Error ? error.message : String(error);
|
||||||
this.recordReleaseHistory("update", "刷新更新目标失败", this.explainError(this.updateOps.error), "bad");
|
this.recordReleaseHistory("update", "刷新服务列表失败", this.explainError(this.updateOps.error), "bad");
|
||||||
} finally {
|
} finally {
|
||||||
this.updateOps.loaded = true;
|
this.updateOps.loaded = true;
|
||||||
this.updateOps.loading = false;
|
this.updateOps.loading = false;
|
||||||
|
|||||||
@ -305,38 +305,6 @@
|
|||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="activeView === 'release'">
|
|
||||||
<section class="control-bar task-control-bar">
|
|
||||||
<div class="taskbar-context">
|
|
||||||
<strong>发布</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group release-section-nav">
|
|
||||||
<button
|
|
||||||
v-for="(section, index) in releaseSections"
|
|
||||||
:key="section.id"
|
|
||||||
:class="['section-link', 'release-step-link', `tone-${releaseStepTone(section.id)}`]"
|
|
||||||
@click="scrollToSection(section.id)"
|
|
||||||
>
|
|
||||||
<span class="release-step-index">{{ index + 1 }}</span>
|
|
||||||
<span>{{ section.label }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group control-group-spread">
|
|
||||||
<label class="interval-field">
|
|
||||||
<span>类型</span>
|
|
||||||
<select v-model="releaseKindFilter" class="interval-select release-kind-select">
|
|
||||||
<option value="all">全部</option>
|
|
||||||
<option value="java">Java</option>
|
|
||||||
<option value="golang">Golang</option>
|
|
||||||
<option value="frontend">前端</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<p v-if="error" class="toolbar-error">加载失败:{{ error }}</p>
|
<p v-if="error" class="toolbar-error">加载失败:{{ error }}</p>
|
||||||
|
|
||||||
<template v-if="!showLoadingSkeleton && (activeView === 'overview' || activeView === 'services')">
|
<template v-if="!showLoadingSkeleton && (activeView === 'overview' || activeView === 'services')">
|
||||||
@ -3134,13 +3102,6 @@
|
|||||||
|
|
||||||
<template v-if="!showLoadingSkeleton && activeView === 'release'">
|
<template v-if="!showLoadingSkeleton && activeView === 'release'">
|
||||||
<section class="panel release-status-strip sticky-release-strip">
|
<section class="panel release-status-strip sticky-release-strip">
|
||||||
<div class="release-task-head">
|
|
||||||
<div class="release-task-context">
|
|
||||||
<strong>发布工作台</strong>
|
|
||||||
<span>构建参数 → 更新目标 → 执行日志 → 滚动重启</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="release-command-row" aria-label="发布操作">
|
<div class="release-command-row" aria-label="发布操作">
|
||||||
<div class="release-action-summary compact">
|
<div class="release-action-summary compact">
|
||||||
<span :class="['badge', releasePrimaryStatusTone()]">{{ releasePrimaryStatusLabel() }}</span>
|
<span :class="['badge', releasePrimaryStatusTone()]">{{ releasePrimaryStatusLabel() }}</span>
|
||||||
@ -3151,6 +3112,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-group release-command-actions">
|
<div class="action-group release-command-actions">
|
||||||
|
<button class="refresh ghost" @click="buildParamsOpen = true">构建参数</button>
|
||||||
<template v-if="releaseIsRunning()">
|
<template v-if="releaseIsRunning()">
|
||||||
<button class="refresh" @click="openUpdateLogViewer" :disabled="!updateOps.operationId && !updateOps.logs.length">查看日志</button>
|
<button class="refresh" @click="openUpdateLogViewer" :disabled="!updateOps.operationId && !updateOps.logs.length">查看日志</button>
|
||||||
<button class="refresh ghost" @click="fetchUpdateOperationStatus(updateOps.operationId)" :disabled="!updateOps.operationId || updateOps.statusRequestInFlight">
|
<button class="refresh ghost" @click="fetchUpdateOperationStatus(updateOps.operationId)" :disabled="!updateOps.operationId || updateOps.statusRequestInFlight">
|
||||||
@ -3197,63 +3159,12 @@
|
|||||||
<div v-if="releasePrecheck.ranAt" class="precheck-strip release-check-strip">
|
<div v-if="releasePrecheck.ranAt" class="precheck-strip release-check-strip">
|
||||||
<span :class="['badge', releasePrecheck.tone]">{{ releasePrecheckBadgeLabel() }}</span>
|
<span :class="['badge', releasePrecheck.tone]">{{ releasePrecheckBadgeLabel() }}</span>
|
||||||
<span class="badge neutral">执行于 {{ formatDateTime(releasePrecheck.ranAt) }}</span>
|
<span class="badge neutral">执行于 {{ formatDateTime(releasePrecheck.ranAt) }}</span>
|
||||||
<span
|
|
||||||
v-for="check in releasePrecheck.checks"
|
|
||||||
:key="'precheck-' + check.label"
|
|
||||||
:class="['badge', check.ok ? 'ok' : 'warn']"
|
|
||||||
:title="check.detail"
|
|
||||||
>
|
|
||||||
{{ check.label }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p v-if="updateOps.error" class="metric-error">{{ explainError(updateOps.error) }}</p>
|
<p v-if="updateOps.error" class="metric-error">{{ explainError(updateOps.error) }}</p>
|
||||||
<p v-else-if="updateOps.message" :class="updateOps.running ? 'warn-text' : updateOps.result && updateOps.result.ok ? 'ok-text' : 'metric-error'">{{ updateOps.message }}</p>
|
<p v-else-if="updateOps.message" :class="updateOps.running ? 'warn-text' : updateOps.result && updateOps.result.ok ? 'ok-text' : 'metric-error'">{{ updateOps.message }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="release-build" class="panel infra-panel">
|
|
||||||
<header class="panel-header">
|
|
||||||
<div class="panel-title">
|
|
||||||
<h2>构建参数</h2>
|
|
||||||
</div>
|
|
||||||
<span class="badge neutral">平台 {{ updateOps.defaults.dockerPlatform }}</span>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="metadata-strip">
|
|
||||||
<span class="mono">Harbor {{ updateOps.builder.harborRegistry }} / {{ updateOps.builder.harborProject }}</span>
|
|
||||||
<span class="mono">Java {{ truncateMiddle(updateOps.builder.javaRepoRoot, 16, 12) }}</span>
|
|
||||||
<span class="mono">Go {{ truncateMiddle(updateOps.builder.golangRepoRoot, 16, 12) }}</span>
|
|
||||||
<span class="mono">Admin {{ truncateMiddle(updateOps.builder.frontendRepoRoot || updateOps.builder.frontendRepoUrl, 16, 12) }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="update-form-grid">
|
|
||||||
<label class="update-field">
|
|
||||||
<span>Java Git Ref</span>
|
|
||||||
<input v-model.trim="updateOps.javaGitRef" class="search" placeholder="main / branch / tag / commit" />
|
|
||||||
</label>
|
|
||||||
<label class="update-field">
|
|
||||||
<span>Go Git Ref</span>
|
|
||||||
<input v-model.trim="updateOps.goGitRef" class="search" placeholder="main / branch / tag / commit" />
|
|
||||||
</label>
|
|
||||||
<label class="update-field">
|
|
||||||
<span>Admin Git Ref</span>
|
|
||||||
<input v-model.trim="updateOps.adminGitRef" class="search" placeholder="main / branch / tag / commit" />
|
|
||||||
</label>
|
|
||||||
<label class="update-field">
|
|
||||||
<span>Image Tag</span>
|
|
||||||
<input v-model.trim="updateOps.imageTag" class="search" placeholder="可选,不填则自动生成" />
|
|
||||||
</label>
|
|
||||||
<div class="update-field update-field-toggle">
|
|
||||||
<span>构建选项</span>
|
|
||||||
<label class="update-check">
|
|
||||||
<input v-model="updateOps.skipMavenBuild" type="checkbox" />
|
|
||||||
<strong>跳过 Maven</strong>
|
|
||||||
<small>仅影响 Java 构建阶段</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="release-targets" class="panel infra-panel">
|
<section id="release-targets" class="panel infra-panel">
|
||||||
<header class="panel-header">
|
<header class="panel-header">
|
||||||
<div class="panel-title">
|
<div class="panel-title">
|
||||||
@ -3323,7 +3234,7 @@
|
|||||||
</header>
|
</header>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="empty-panel compact">{{ updateOps.loading ? '加载更新目标中...' : '当前没有可展示的更新目标' }}</div>
|
<div v-else class="empty-panel compact">{{ updateOps.loading ? '加载服务中...' : '当前没有可展示的服务' }}</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="release-log" class="panel infra-panel">
|
<section id="release-log" class="panel infra-panel">
|
||||||
@ -3531,6 +3442,54 @@
|
|||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<div v-if="buildParamsOpen" class="log-viewer-overlay" @click.self="buildParamsOpen = false">
|
||||||
|
<section class="log-viewer build-params-dialog" role="dialog" aria-modal="true" aria-labelledby="build-params-title">
|
||||||
|
<header class="log-viewer-head">
|
||||||
|
<div class="panel-title">
|
||||||
|
<h2 id="build-params-title">构建参数</h2>
|
||||||
|
</div>
|
||||||
|
<div class="action-group">
|
||||||
|
<span class="badge neutral">平台 {{ updateOps.defaults.dockerPlatform }}</span>
|
||||||
|
<button class="refresh ghost" @click="buildParamsOpen = false">关闭</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="metadata-strip">
|
||||||
|
<span class="mono">Harbor {{ updateOps.builder.harborRegistry }} / {{ updateOps.builder.harborProject }}</span>
|
||||||
|
<span class="mono">Java {{ truncateMiddle(updateOps.builder.javaRepoRoot, 18, 14) }}</span>
|
||||||
|
<span class="mono">Go {{ truncateMiddle(updateOps.builder.golangRepoRoot, 18, 14) }}</span>
|
||||||
|
<span class="mono">Admin {{ truncateMiddle(updateOps.builder.frontendRepoRoot || updateOps.builder.frontendRepoUrl, 18, 14) }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="update-form-grid build-params-grid">
|
||||||
|
<label class="update-field">
|
||||||
|
<span>Java Git Ref</span>
|
||||||
|
<input v-model.trim="updateOps.javaGitRef" class="search" placeholder="main / branch / tag / commit" />
|
||||||
|
</label>
|
||||||
|
<label class="update-field">
|
||||||
|
<span>Go Git Ref</span>
|
||||||
|
<input v-model.trim="updateOps.goGitRef" class="search" placeholder="main / branch / tag / commit" />
|
||||||
|
</label>
|
||||||
|
<label class="update-field">
|
||||||
|
<span>Admin Git Ref</span>
|
||||||
|
<input v-model.trim="updateOps.adminGitRef" class="search" placeholder="main / branch / tag / commit" />
|
||||||
|
</label>
|
||||||
|
<label class="update-field">
|
||||||
|
<span>Image Tag</span>
|
||||||
|
<input v-model.trim="updateOps.imageTag" class="search" placeholder="可选,不填则自动生成" />
|
||||||
|
</label>
|
||||||
|
<div class="update-field update-field-toggle build-params-toggle">
|
||||||
|
<span>构建选项</span>
|
||||||
|
<label class="update-check">
|
||||||
|
<input v-model="updateOps.skipMavenBuild" type="checkbox" />
|
||||||
|
<strong>跳过 Maven</strong>
|
||||||
|
<small>仅影响 Java 构建阶段</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="logViewer.open" class="log-viewer-overlay" @click.self="closeLogViewer">
|
<div v-if="logViewer.open" class="log-viewer-overlay" @click.self="closeLogViewer">
|
||||||
<section class="log-viewer" role="dialog" aria-modal="true" :aria-labelledby="'log-viewer-title'">
|
<section class="log-viewer" role="dialog" aria-modal="true" :aria-labelledby="'log-viewer-title'">
|
||||||
<header class="log-viewer-head">
|
<header class="log-viewer-head">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user