179 lines
5.3 KiB
Vue
179 lines
5.3 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="mt-20">
|
|||
|
|
<div class="w-[1200px]">
|
|||
|
|
<h1 class="mr-title">新建Pull Request</h1>
|
|||
|
|
<div class="text-CG600 text-xs mt-[16px]">
|
|||
|
|
你可以选择两个内容存在差异的分支,比较并查看它们的更改,并创建一个新的Pull Request。
|
|||
|
|
</div>
|
|||
|
|
<DataPanel :loading="loading" skeleton="true" class="mt-20" :card="false">
|
|||
|
|
<BranchCompare
|
|||
|
|
v-model:repoId="branchCompareData.repoId"
|
|||
|
|
v-model:targetRepoId="branchCompareData.targetRepoId"
|
|||
|
|
v-model:sourceId="branchCompareData.originId"
|
|||
|
|
v-model:targetId="branchCompareData.targetId"
|
|||
|
|
:repoList="originRepoList"
|
|||
|
|
:targetRepoList="targetRepoList"
|
|||
|
|
:branchList="originBranchList"
|
|||
|
|
:targetBranchList="targetBranchList"
|
|||
|
|
:showRepo="isFork"
|
|||
|
|
:isFork="isFork"
|
|||
|
|
@onSwitch="onSwitch"
|
|||
|
|
>
|
|||
|
|
</BranchCompare>
|
|||
|
|
<div class="mt-20 text-right">
|
|||
|
|
<d-button @click="toNext" variant="solid">下一步</d-button>
|
|||
|
|
</div>
|
|||
|
|
</DataPanel>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { reactive, ref, watch } from 'vue';
|
|||
|
|
import BranchCompare from '@/components/BranchCompareFork/index.vue';
|
|||
|
|
import getRepoId from '@/utils/getRepoId';
|
|||
|
|
import { getRepo } from '@/api/repo';
|
|||
|
|
import { getBranches } from '@/api/branch';
|
|||
|
|
import { useRouter } from 'vue-router';
|
|||
|
|
import { Message } from 'vue-devui/message';
|
|||
|
|
const router = useRouter();
|
|||
|
|
const loading = ref(false);
|
|||
|
|
|
|||
|
|
const branchCompareData = reactive({
|
|||
|
|
repoId: getRepoId('/'), // 源项目
|
|||
|
|
targetRepoId: getRepoId('/'), // 目标项目
|
|||
|
|
originId: '', // 源分支
|
|||
|
|
targetId: '' // 目标分支
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const onSwitch = () => {
|
|||
|
|
[branchCompareData.originId, branchCompareData.targetId] = [
|
|||
|
|
branchCompareData.targetId,
|
|||
|
|
branchCompareData.originId
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const isFork = ref(false); // 是否为fork项目
|
|||
|
|
const originRepoList = ref([{ label: getRepoId('/'), value: getRepoId('/') }]);
|
|||
|
|
const targetRepoList = ref([{ label: getRepoId('/'), value: getRepoId('/') }]);
|
|||
|
|
const targetRepos = ref([]); // 最后获取目标项目id使用(等接口支持path后可去掉)
|
|||
|
|
const originBranchList = ref([
|
|||
|
|
{ label: '', value: '' } // 有初始值,可以撑开select下拉框
|
|||
|
|
]);
|
|||
|
|
const targetBranchList = ref([{ label: '', value: '' }]);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取源分支或目标分支列表
|
|||
|
|
* @param {*} type origin | target
|
|||
|
|
* @param {*} repoId
|
|||
|
|
*/
|
|||
|
|
const getBranchList = async (type = 'origin', repoId = getRepoId()) => {
|
|||
|
|
loading.value = true;
|
|||
|
|
const params = {
|
|||
|
|
repoId,
|
|||
|
|
sort: type === 'origin' ? 'mr_source' : 'mr_target',
|
|||
|
|
per_page: 100 // TODO: 加下拉加载
|
|||
|
|
};
|
|||
|
|
const res = await getBranches(params);
|
|||
|
|
if (!res.error) {
|
|||
|
|
const repoData = res?.data?.data;
|
|||
|
|
const branchId = type === 'origin' ? 'originId' : 'targetId';
|
|||
|
|
const branchList = [];
|
|||
|
|
repoData.content.forEach((item) => {
|
|||
|
|
branchList.push({
|
|||
|
|
label: item.name,
|
|||
|
|
value: item.name
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
if (type === 'origin') {
|
|||
|
|
originBranchList.value = branchList;
|
|||
|
|
} else {
|
|||
|
|
targetBranchList.value = branchList;
|
|||
|
|
}
|
|||
|
|
branchCompareData[branchId] =
|
|||
|
|
type === 'origin' ? originBranchList.value[0].value : targetBranchList.value[0].value;
|
|||
|
|
}
|
|||
|
|
loading.value = false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const getTargetRepo = async (targetId) => {
|
|||
|
|
const params = { repoId: targetId };
|
|||
|
|
const res = await getRepo(params);
|
|||
|
|
if (!res.error) {
|
|||
|
|
const repoData = res?.data?.data;
|
|||
|
|
targetRepos.value.unshift({ ...repoData });
|
|||
|
|
targetRepoList.value.unshift({
|
|||
|
|
label: repoData.path_with_namespace,
|
|||
|
|
value: repoData.path_with_namespace
|
|||
|
|
});
|
|||
|
|
branchCompareData.targetRepoId = repoData.path_with_namespace;
|
|||
|
|
getBranchList('target', repoData.id);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const getOriginRepo = async (repoId = getRepoId()) => {
|
|||
|
|
loading.value = true;
|
|||
|
|
const params = { repoId };
|
|||
|
|
const res = await getRepo(params);
|
|||
|
|
if (!res.error) {
|
|||
|
|
const repoData = res?.data?.data;
|
|||
|
|
targetRepos.value.unshift({ ...repoData });
|
|||
|
|
isFork.value = !!repoData.forked_from_project;
|
|||
|
|
if (isFork.value) {
|
|||
|
|
getTargetRepo(repoData.forked_from_project.id);
|
|||
|
|
} else {
|
|||
|
|
getBranchList('target', repoId);
|
|||
|
|
}
|
|||
|
|
getBranchList();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
getOriginRepo();
|
|||
|
|
|
|||
|
|
watch(
|
|||
|
|
() => branchCompareData.repoId,
|
|||
|
|
(val) => {
|
|||
|
|
getBranchList('origin', encodeURIComponent(val));
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
watch(
|
|||
|
|
() => branchCompareData.targetRepoId,
|
|||
|
|
(val) => {
|
|||
|
|
getBranchList('target', encodeURIComponent(val));
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const toNext = () => {
|
|||
|
|
const { repoId, targetRepoId, originId, targetId } = branchCompareData;
|
|||
|
|
const originPath = `${repoId}${originId}`;
|
|||
|
|
const targetPath = `${targetRepoId}${targetId}`;
|
|||
|
|
if (!originId) return Message.warning('请选择源分支');
|
|||
|
|
if (!targetId) return Message.warning('请选择目标分支');
|
|||
|
|
if (originPath === targetPath) {
|
|||
|
|
return Message.warning('目标分支和源分支不能相同');
|
|||
|
|
}
|
|||
|
|
const selectTargetRepo = targetRepos.value.filter(
|
|||
|
|
(item) => item.path_with_namespace === targetRepoId
|
|||
|
|
);
|
|||
|
|
router.push({
|
|||
|
|
name: 'repoMergeCompare',
|
|||
|
|
query: {
|
|||
|
|
originRepo: repoId,
|
|||
|
|
targetRepo: targetRepoId,
|
|||
|
|
targetProjectId: selectTargetRepo[0].id,
|
|||
|
|
originBranch: originId,
|
|||
|
|
targetBranch: targetId
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.mr-title {
|
|||
|
|
margin: 24px 0 16px 0;
|
|||
|
|
font-size: var(--text-2xl);
|
|||
|
|
color: var(--color-G900);
|
|||
|
|
font-weight: 500;
|
|||
|
|
line-height: 32px;
|
|||
|
|
}
|
|||
|
|
</style>
|