Files
Situation-Awareness-Platfor…/src/components/CherryPick/index.vue

315 lines
8.6 KiB
Vue
Raw Normal View History

2025-03-12 18:41:20 +08:00
<template>
<GModal v-model="vModels" :showFooter="false" :title="addCherryPickItem.title">
<d-form layout="vertical" :data="addCherryPickModel" ref="addCherryPickFormRef" :rules="addCherryPickRules"
validate-on-rule-change="true">
<d-form-item field="baseName" :label="addCherryPickItem.baseName.label">
<div class="g-branch-compare-repo">
<div class="release-custom-icon">
<slot name="repo-prefix">
<Icon name="gt-branches" size="16px"></Icon>
</slot>
</div>
<d-editable-select class="release-branch-select" max-height="200" width="370" remote enable-lazy-load
placeholder="请选择分支" :loading="searching" :remote-method="getBranchList" v-model="addCherryPickModel.baseName"
:options="baseBranchOptions" :disabled="true">
<template #item="{ option, index }">
<div class="release-branch-option">
<slot name="source-option" :data="option" :index="index">
<Icon name="gt-branches" size="16px" />
<div class="release-branch-label">{{ option.label }}</div>
</slot>
</div>
</template>
</d-editable-select>
</div>
</d-form-item>
<d-form-item field="branchName" :label="addCherryPickItem.tagName.label">
<div class="g-branch-compare-repo">
<div class="release-custom-icon">
<slot name="repo-prefix">
<Icon name="gt-branches" size="16px"></Icon>
</slot>
</div>
<d-editable-select class="release-branch-select" max-height="200" width="370" remote enable-lazy-load
placeholder="请选择分支" :loading="searching" :remote-method="getBranchList" v-model="addCherryPickModel.branchName"
:options="targetBranchOptions">
<template #item="{ option, index }">
<div class="release-branch-option">
<slot name="source-option" :data="option" :index="index">
<Icon name="gt-branches" size="16px" />
<div class="release-branch-label">{{ option.label }}</div>
</slot>
</div>
</template>
</d-editable-select>
</div>
</d-form-item>
<div>
<d-checkbox v-model="addCherryPickModel.with_new_merge_request"
>是否使用新的Pull Request进行Cherry-Pick</d-checkbox
>
</div>
<gc-form-operation class="form-demo-form-operation mb-0">
<d-button :disabled="createTagBtnLoading" @click="cancelModel">{{ addCherryPickItem.cancel }}</d-button>
<d-button :disabled="isConfirm" :loading="createTagBtnLoading" color="primary" variant="solid"
@click="handleCreateTag">{{ addCherryPickItem.submit }}</d-button>
</gc-form-operation>
</d-form>
</GModal>
</template>
<script setup lang="ts">
import { reactive, ref, computed } from 'vue';
import { useModel } from '@/utils/hooks/useModel';
import { useRepoId } from '@/utils/hooks/useRepoId';
import { commitCherryPick } from '@/api/commit/index';
import { reqCatch } from '@/utils/catch';
import { getBranches } from '@/api/branch';
import { GModal } from '@/components/Setting/index';
import { useRouter } from 'vue-router';
const props = withDefaults(defineProps<{
modelValue?: boolean
'onUpdate:modelValue'?: Function
branches?: string[],
mergeRequest: any[],
options?: { name: string, value: string }[],
branch?: string;
repoIcon?: string;
branchIcon?: string;
repoIconSize?: string;
branchIconSize?: string;
repoReadonly?: boolean;
maxHeight?: number
}>(), {
data: () => {
return {
repoId: null,
sourceId: null,
targetId: null
};
},
branchList: () => [],
repoIcon: 'version-history',
branchIcon: 'gt-branches',
repoIconSize: '16px',
branchIconSize: '16px',
repoReadonly: true,
maxHeight: 250
});
const emits = defineEmits(['confirm', 'update:modelValue']);
const { vModels } = useModel(props, emits);
const searching = ref(false);
const addCherryPickRules = {
baseName: [{ required: true, message: '基于分支不能为空', trigger: 'blur' }],
branchName: [{ required: true, message: '分支名称不能为空', trigger: 'blur' }]
};
const { repoId } = useRepoId();
const baseBranchOptions = ref([]);
const targetBranchOptions = ref([]);
const createTagBtnLoading = ref(false);
const addCherryPickFormRef = ref(null);
const addCherryPickItem = {
title: 'Cherry-Pick',
baseName: {
label: 'Cherry-Pick',
helpTips: 'This is the plan name.',
ruleMsg: '',
placeholder: ''
},
tagName: {
label: '目标分支',
ruleMsg: '请选择目标分支',
placeholder: '请选择目标分支'
},
submit: '创建',
cancel: '取消'
};
const addCherryPickModel = reactive({
baseName: '',
tagName: '',
branchName: '',
description: '',
with_new_merge_request: false
});
const getBranchList = async(val?: string) => {
const params = val ? {
repoId: repoId.value,
search: val,
view: 'simple'
} : {
repoId: repoId.value,
view: 'simple',
page: 1,
per_page: 20
};
searching.value = true;
const res = await reqCatch(getBranches, params);
if (!res.error) {
baseBranchOptions.value = (res['data']['data']['data']['content'] || []).map((item: { name: any; default: boolean; }) => {
if (item.default) {
addCherryPickModel.baseName = item.name;
}
return {
label: item.name,
value: item.name
};
});
targetBranchOptions.value = (res['data']['data']['data']['content'] || []).map((item: { name: any; default: boolean; }) => {
if (item.default) {
addCherryPickModel.baseName = item.name;
}
return {
label: item.name,
value: item.name
};
});
if (props.branch) {
baseBranchOptions.value.push({ label: props.branch, value: props.branch });
addCherryPickModel.baseName = props.branch;
}
}
searching.value = false;
};
getBranchList();
const cancelModel = () => {
vModels.value = false;
addCherryPickModel.description = '';
addCherryPickModel.tagName = '';
addCherryPickModel.baseName = '';
};
const handleCreateTag = () => {
createTagReq();
};
const router = useRouter();
const createTagReq = async() => {
addCherryPickFormRef.value.validate(async(isValid: any, invalidFields: any) => {
if (!isValid) return;
createTagBtnLoading.value = true;
const param = {
branch: addCherryPickModel.branchName,
with_new_merge_request: addCherryPickModel.with_new_merge_request
};
commitCherryPick(repoId.value, addCherryPickModel.baseName, param)
.then((data: any) => {
if (!addCherryPickModel.with_new_merge_request) {
router.back();
} else {
emits('confirm', data.data.cherry_pick_branch_name, addCherryPickModel.branchName);
}
}).finally(() => {
createTagBtnLoading.value = false;
});
});
};
const isConfirm = computed(() => {
if (addCherryPickModel.baseName && addCherryPickModel.branchName) {
return false;
} else {
return true;
}
});
</script>
<style lang="scss" scoped>
.release {
margin: 20px 50px;
flex-direction: column;
&-branch {
&-select {
:deep(.devui-editable-select-input__inner) {
padding-left: 32px;
}
:deep(.devui-editable-select__inner) {
max-height: 400px;
}
:deep(.devui-editable-select__item) {
padding: 8px 4px;
}
}
&-option {
display: flex;
align-items: center;
}
&-label {
margin-left: 8px;
}
}
&-custom-icon {
position: absolute;
left: 0;
top: 0;
width: 32px;
height: 32px;
line-height: 38px;
padding-left: 16px;
padding-top: 4px;
z-index: 2;
display: flex;
:deep(.icon) {
align-self: center;
}
:deep(.devui-icon__container) {
align-self: center;
}
}
&-header {
display: flex;
justify-content: space-between;
&-left {
align-self: flex-start;
}
&-right {
align-self: flex-end;
}
}
}
:deep(.devui-form-operation.form-demo-form-operation) {
text-align: right;
padding-top: 20px;
button:first-child {
margin-right: 12px;
}
}
:deep(.devui-editable-select-input) {
height: 40px;
}
:deep(.devui-input) {
height: 40px;
}
:deep(.devui-form__control .devui-form__control-info .error-message) {
margin: 8px auto;
}
:deep(.g-rich-label) {
background: none;
border: none;
}
:deep(.g-rich-label-active) {
background: white;
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.09);
border-radius: 3px;
border: none;
font-weight: bold;
}
</style>