jcloud/dashboard/src2/components/group/PatchAppDialog.vue
2025-04-12 17:39:38 +08:00

312 lines
6.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Dialog v-if="show" :options="{ title, position: 'top' }" v-model="show">
<template v-slot:body-content>
<div class="flex flex-col gap-4">
<p class="text-base text-gray-600">
您可以通过输入补丁URL或选择补丁文件来选择应用程序补丁
</p>
<div class="flex flex-col gap-2">
<FormControl
v-if="!app"
class="w-full"
v-model="applyToApp"
label="选择应用"
placeholder="选择要打补丁的应用"
type="select"
variant="outline"
:options="$resources.apps.data"
/>
<!-- 补丁选择器URL或文件 -->
<div class="flex w-full items-end gap-1">
<FormControl
v-if="!patch"
class="w-full"
label="补丁URL"
type="data"
v-model="patchURL"
variant="outline"
placeholder="输入补丁URL"
/>
<FormControl
v-else
class="w-full"
label="补丁文件名"
type="data"
variant="outline"
v-model="patchFileName"
placeholder="设置补丁文件名"
/>
<!-- 文件选择器 -->
<input
ref="fileSelector"
type="file"
:accept="['text/x-patch', 'text/x-diff', 'application/x-patch']"
class="hidden"
@change="onPatchFileSelect"
/>
<Button
@click="$refs.fileSelector.click()"
title="选择补丁文件"
>
<FeatherIcon name="file-text" class="h-5 w-5 text-gray-600" />
</Button>
<!-- 清除补丁文件 -->
<Button @click="clear" v-if="patch" title="清除补丁文件">
<FeatherIcon name="x" class="h-5 w-5 text-gray-600" />
</Button>
</div>
</div>
<ErrorMessage class="-mt-2 w-full" :message="error" />
<h3 class="mt-4 text-base font-semibold">补丁配置</h3>
<FormControl
v-if="!applyToAllBenches"
v-model="applyToBench"
label="选择部署"
type="select"
variant="outline"
:options="$resources.benches.data"
/>
<FormControl
label="将补丁应用到所有活动部署"
type="checkbox"
v-model="applyToAllBenches"
/>
<FormControl
label="应用补丁后构建资源"
type="checkbox"
v-model="buildAssets"
/>
</div>
</template>
<template v-slot:actions>
<Button variant="solid" class="w-full" @click="applyPatch">
应用补丁
</Button>
</template>
</Dialog>
</template>
<script>
import {
Button,
Dialog,
ErrorMessage,
FeatherIcon,
FileUploader,
FormControl
} from 'jingrow-ui';
export default {
name: 'PatchAppDialog',
props: {
app: [null, String],
group: String
},
components: {
Dialog,
FormControl,
ErrorMessage,
FileUploader,
Button,
FeatherIcon
},
watch: {
app(value) {
this.show = !!value;
this.applyToApp = value || '';
},
show(value) {
this.error = '';
if (value) {
return;
}
setTimeout(this.clearApp, 150);
}
},
data() {
return {
show: true,
error: '',
patch: '',
patchURL: '',
patchFileName: '',
buildAssets: false,
applyToApp: '',
applyToBench: '',
applyToAllBenches: false
};
},
computed: {
title() {
const app = this.app || this.applyToApp;
if (app) {
return `应用补丁到 ${app}`;
}
return '应用补丁';
}
},
methods: {
clearApp() {
this.$emit('clear-app-to-patch');
},
validate() {
if (!this.$resources.benches.data.length) {
this.error =
'此部署组没有部署,无法应用补丁。';
return false;
}
if (this.patch && !this.patchFileName) {
this.error = '请输入补丁文件名。';
return false;
}
if (!this.patch && !this.patchURL) {
this.error = '请输入补丁URL或选择一个补丁文件。';
return false;
}
if (!this.applyToAllBenches && !this.applyToBench) {
this.error =
'请选择一个部署或勾选“将补丁应用到所有活动部署”。';
return false;
}
if (!this.app && !this.applyToApp) {
this.error = '请选择要打补丁的应用。';
return false;
}
if (this.patchURL && !this.patchURL.endsWith('.patch')) {
this.error =
'补丁URL没有`.patch`扩展名。请输入有效的URL。';
return false;
}
return true;
},
applyPatch() {
if (!this.validate()) {
return;
}
if (!this.patchFileName && this.patchURL) {
this.patchFileName = this.patchURL.split('/').at(-1);
}
if (!this.patchFileName.endsWith('.patch')) {
this.patchFileName += '.patch';
}
const app = this.app || this.applyToApp;
const args = {
release_group: this.group,
app,
patch_config: {
patch: this.patch,
filename: this.patchFileName,
patch_url: this.patchURL,
build_assets: this.buildAssets,
patch_bench: this.applyToBench,
patch_all_benches: this.applyToAllBenches
}
};
this.$resources.applyPatch.submit(args);
},
async onPatchFileSelect(e) {
this.error = '';
const file = e.target.files?.[0];
if (!file) {
return;
}
this.patch = await file.text();
this.patchFileName = file.name;
},
clear() {
this.error = '';
this.patch = '';
this.patchFileName = '';
},
close() {
this.show = false;
this.clear();
}
},
resources: {
apps() {
return {
type: 'list',
pagetype: 'Release Group App',
parent: 'Release Group',
auto: true,
filters: {
parenttype: 'Release Group',
parent: this.group
},
onSuccess(data) {
if (data.length === 1) {
this.applyToApp = data[0].value;
}
},
onError(data) {
this.error = data;
},
transform(data) {
return data.map(({ name }) => ({ value: name, label: name }));
}
};
},
benches() {
return {
type: 'list',
pagetype: 'Bench',
fields: ['name'],
filters: {
group: this.group,
status: 'Active'
},
auto: true,
onSuccess(data) {
if (data.length > 0) {
this.applyToBench = data.at(-1).value;
return;
}
this.error =
'此部署组没有部署,无法应用补丁。';
},
onError(data) {
this.error = data;
},
transform(data) {
return data.map(({ name }) => ({ value: name, label: name }));
}
};
},
applyPatch() {
return {
url: 'jcloud.api.bench.apply_patch',
onSuccess() {
this.close();
this.$router.push({
name: 'Release Group Detail Jobs',
params: { name: this.group }
});
},
onError(error) {
if (error.messages.length) {
this.error = error.messages.join('\n');
} else {
this.error = error.message;
}
}
};
}
}
};
</script>