添加自定义构建参数功能

This commit is contained in:
hukdoesn
2025-06-30 15:45:29 +08:00
parent fa52e9e571
commit 0348cc2f4e
5 changed files with 320 additions and 13 deletions

View File

@@ -134,6 +134,84 @@
</div>
</div>
<!-- 构建参数配置 -->
<a-divider>构建参数</a-divider>
<div class="parameters-list">
<div v-for="(param, index) in formState.parameters" :key="index" class="parameter-item">
<div class="parameter-header">
<span class="parameter-number">
<TagOutlined /> 参数 {{ index + 1 }}
</span>
<a-space>
<a-tooltip title="删除">
<a-button
v-if="formState.parameters.length > 0"
type="text"
danger
@click="removeParameter(index)"
>
<DeleteOutlined />
</a-button>
</a-tooltip>
</a-space>
</div>
<a-row :gutter="16">
<a-col :span="8">
<a-form-item
label="参数名称"
:name="['parameters', index, 'name']"
:rules="[
{ required: true, message: '请输入参数名称' },
{ pattern: /^[A-Z_][A-Z0-9_]*$/, message: '参数名只能包含大写字母、数字和下划线,且必须以字母或下划线开头' }
]"
>
<a-input v-model:value="param.name" placeholder="例如MY_SERVICES">
<template #prefix>
<KeyOutlined />
</template>
</a-input>
<div class="form-item-help">参数名只能包含大写字母数字和下划线</div>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="参数描述">
<a-input v-model:value="param.description" placeholder="参数用途说明" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="默认值">
<a-input v-model:value="param.defaultValuesText" placeholder="多个值用逗号分隔" @blur="updateDefaultValues(param, index)" />
<div class="form-item-help">多个默认值用英文逗号分隔</div>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="24">
<a-form-item
label="可选值"
:name="['parameters', index, 'choicesText']"
:rules="[{ required: true, message: '请输入可选值' }]"
>
<a-textarea
v-model:value="param.choicesText"
placeholder="每行一个选项值,例如:&#10;user-service&#10;payment-service"
:rows="3"
@blur="updateChoices(param, index)"
/>
<div class="form-item-help">每行输入一个选项值</div>
</a-form-item>
</a-col>
</a-row>
</div>
</div>
<div class="parameter-actions">
<a-button type="dashed" block @click="addParameter">
<PlusOutlined /> 添加构建参数
</a-button>
</div>
<a-divider>构建阶段</a-divider>
<div class="stages-list">
<div v-for="(stage, index) in formState.stages" :key="index" class="stage-item">
<div class="stage-header">
@@ -404,6 +482,7 @@ const formState = reactive({
script: '',
}
],
parameters: [],
notification_channels: [],
});
@@ -509,6 +588,51 @@ const removeStage = (index) => {
formState.stages.splice(index, 1);
};
// 添加构建参数
const addParameter = () => {
formState.parameters.push({
name: '',
description: '',
choices: [],
choicesText: '',
choiceOptions: [],
default_values: [],
defaultValuesText: '',
});
};
const removeParameter = (index) => {
formState.parameters.splice(index, 1);
};
// 更新选项
const updateChoices = (param, index) => {
if (param.choicesText) {
const choices = param.choicesText.split('\n').filter(line => line.trim()).map(line => line.trim());
param.choices = choices;
param.choiceOptions = choices.map(choice => ({
label: choice,
value: choice
}));
param.default_values = param.default_values.filter(value => choices.includes(value));
} else {
param.choices = [];
param.choiceOptions = [];
param.default_values = [];
}
};
// 更新默认值
const updateDefaultValues = (param, index) => {
if (param.defaultValuesText) {
const values = param.defaultValuesText.split(',').filter(val => val.trim()).map(val => val.trim());
param.default_values = values;
} else {
param.default_values = [];
}
};
// 处理返回
const handleBack = () => {
router.back();
@@ -526,6 +650,14 @@ const handleSubmit = async () => {
// 构建提交数据
const submitData = { ...formState };
// 处理参数数据
submitData.parameters = formState.parameters.map(param => ({
name: param.name,
description: param.description,
choices: param.choices,
default_values: param.default_values
}));
if (!submitData.use_external_script) {
submitData.external_script_repo_url = '';
submitData.external_script_directory = '';
@@ -589,6 +721,25 @@ const loadTaskDetail = async (taskId) => {
script: '',
});
}
// 加载参数配置
const parameters = response.data.data.parameters || [];
formState.parameters = parameters.map(param => {
const choicesText = (param.choices || []).join('\n');
const defaultValuesText = (param.default_values || []).join(',');
return {
name: param.name || '',
description: param.description || '',
choices: param.choices || [],
choicesText: choicesText,
choiceOptions: (param.choices || []).map(choice => ({
label: choice,
value: choice
})),
default_values: param.default_values || [],
defaultValuesText: defaultValuesText,
};
});
formState.notification_channels = response.data.data.notification_channels || [];
@@ -790,6 +941,38 @@ onMounted(async () => {
margin-top: 16px;
}
.parameters-list {
margin-top: 16px;
}
.parameter-item {
padding: 16px;
background: transparent;
border-radius: 4px;
margin-bottom: 16px;
border: 1px solid #e8e8e8;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.parameter-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #e8e8e8;
}
.parameter-number {
font-size: 14px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
.parameter-actions {
margin-top: 16px;
}
.form-footer {
margin-top: 24px;
text-align: center;

View File

@@ -362,6 +362,21 @@
</div>
</a-form-item>
<!-- 构建参数选择 -->
<div v-if="selectedTask?.parameters?.length > 0" class="build-parameters">
<a-divider>构建参数</a-divider>
<div v-for="param in selectedTask.parameters" :key="param.name" class="parameter-group">
<a-form-item :label="param.name">
<a-checkbox-group
v-model:value="buildForm.parameterValues[param.name]"
:options="param.choiceOptions"
/>
<div class="parameter-help" v-if="param.description">{{ param.description }}</div>
</a-form-item>
</div>
</div>
<a-form-item label="构建需求描述" required>
<a-textarea
v-model:value="buildForm.requirement"
@@ -429,6 +444,7 @@ const buildForm = reactive({
commit_id: '',
requirement: '',
version: '',
parameterValues: {},
});
// SSE相关状态
@@ -706,6 +722,21 @@ const handleBuild = async (record) => {
buildForm.commit_id = '';
buildForm.requirement = '';
buildForm.version = '';
buildForm.parameterValues = {};
// 初始化参数默认值
if (record.parameters && record.parameters.length > 0) {
record.parameters.forEach(param => {
// 处理参数选项
param.choiceOptions = (param.choices || []).map(choice => ({
label: choice,
value: choice
}));
// 设置默认值
buildForm.parameterValues[param.name] = [...(param.default_values || [])];
});
}
// 显示构建对话框
buildModalVisible.value = true;
@@ -1213,7 +1244,8 @@ const confirmBuild = async () => {
// 构建请求参数
const requestData = {
task_id: selectedTask.value.task_id,
requirement: buildForm.requirement
requirement: buildForm.requirement,
parameter_values: buildForm.parameterValues
};
if (isDevOrTestEnv.value) {
@@ -1326,14 +1358,6 @@ const isStagingOrProdEnv = computed(() => {
// 构建对话框标题
const buildModalTitle = computed(() => {
if (!selectedTask.value) return '构建配置';
const envType = selectedTask.value.environment?.type;
if (envType === 'development') return '开发环境构建配置';
if (envType === 'testing') return '测试环境构建配置';
if (envType === 'staging') return '预发布环境构建配置';
if (envType === 'production') return '生产环境构建配置';
return '构建配置';
});
@@ -1698,4 +1722,18 @@ const handleViewBuildDetail = (record) => {
font-size: 12px;
color: #999;
}
.build-parameters {
margin: 16px 0;
}
.parameter-group {
margin-bottom: 16px;
}
.parameter-help {
font-size: 12px;
color: rgba(0, 0, 0, 0.45);
margin-top: 4px;
}
</style>