243 lines
7.7 KiB
Vue
243 lines
7.7 KiB
Vue
<template>
|
||
<div class="repo-info">
|
||
<d-row :gutter="64">
|
||
<d-col flex="1" class="min-w-0">
|
||
<div class="flex items-end flex-wrap gap-x-4 gap-y-1">
|
||
<div class="text-[20px]">
|
||
<span v-for="(path, index) in breadcrumb" :key="index">
|
||
<GLink :href="path.href" >
|
||
<span class="font-color-t1 font-semibold" :class="!index ? 'max-w-[200px] whitespace-nowrap table-cell overflow-ellipsis overflow-hidden' : 'break-all'">{{ path.label }}</span>
|
||
</GLink>
|
||
<span v-if="index !== breadcrumb.length - 1" class="breadcrumb-splitter font-color-t1"> / </span>
|
||
</span>
|
||
</div>
|
||
<template v-for="(item, index) in topicData.officialTopicList" :key="index">
|
||
<div class="official-topic mb-0.5">
|
||
<GIcon name="gt-plane-officialCertification" />
|
||
<span class="ml-1">{{ item.name }}</span>
|
||
</div>
|
||
</template>
|
||
<div v-if="repoInfo.visibility === 'private'" class="repo-visible font-color-t2 inline-flex items-center justify-center text-xs">
|
||
私有
|
||
</div>
|
||
</div>
|
||
<div class="mt-4 flex items-center flex-wrap gap-x-4 gap-y-1" v-if="repoInfo?.forked_from_project">
|
||
<span class="font-color-t2 cursor-pointer" :class="{'cursor-pointer': repoInfo.value?.forked_from_project?.web_url}" @click="toForkRepo">
|
||
fork 源:{{ repoInfo?.forked_from_project?.name_with_namespace }}
|
||
</span>
|
||
<div v-if="isAdminOperate" class="fork-btn" @click="handleSync()">
|
||
<GIcon name="gt-plane-synchronous" class="mr-1" />
|
||
同步源项目
|
||
<GIcon size="14" name="gt-line-right" class="ml-1" />
|
||
</div>
|
||
</div>
|
||
<template v-if="isPhone">
|
||
<RepoData class="mt-4" :widthType="widthType" @update-star="handleUpdateStarNumber" />
|
||
<RepoTopic :tagList="tagList" />
|
||
<RepoAction class="mt-3" />
|
||
<!-- 只在项目首页展示 -->
|
||
<DownloadChart v-if="route?.name === 'repoDashboard'" :repoId="repoId" class="mt-8" />
|
||
</template>
|
||
<template v-else>
|
||
<RepoTopic :tagList="tagList" />
|
||
</template>
|
||
</d-col>
|
||
<d-col v-if="!isPhone">
|
||
<RepoData :widthType="widthType" @update-star="handleUpdateStarNumber" />
|
||
</d-col>
|
||
</d-row>
|
||
|
||
<d-row align="middle" class="mt-32">
|
||
<d-col flex="1">
|
||
<NewNavTabs />
|
||
</d-col>
|
||
<d-col v-if="!isPhone">
|
||
<RepoAction />
|
||
</d-col>
|
||
</d-row>
|
||
<SyncFork ref="syncFork" :repoId="repoId" :repoInfo="repoInfo" />
|
||
</div>
|
||
</template>
|
||
<script lang="ts" setup>
|
||
import { ref, onUnmounted, watch, computed } from 'vue';
|
||
import RepoData from './RepoData.vue';
|
||
import RepoAction from './RepoAction.vue';
|
||
import DownloadChart from '@/components/Repo/DownloadChart.vue';
|
||
import NewNavTabs from '@/components/NavTabs/NewNavTabs.vue';
|
||
import RepoTopic from './RepoTopic.vue';
|
||
import SyncFork from './SyncFork.vue';
|
||
import { addEventListener, offEvent } from '@/utils/eventBus';
|
||
import { reqCatch } from '@/utils/catch';
|
||
import { storeToRefs } from 'pinia';
|
||
import { useRouter, useRoute } from 'vue-router';
|
||
import * as types from '@/api/org/types';
|
||
import { getCommunityInfo } from '@/api/org/index';
|
||
import { getOrgInfo } from '@/views/Org/hooks/orgInfo';
|
||
import { orgInfoStore } from '@/stores/Org/index';
|
||
import { useRepoHeaderInit } from '@/utils/hooks/useRepoHeaderInit';
|
||
import { useRepoId } from '@/utils/hooks/useRepoId';
|
||
import { useAccountStore } from '@/stores/user';
|
||
import { getSettingsValues } from '@/api/repo';
|
||
import { repoInfoStore } from '@/stores/Repo';
|
||
import { useOrgId } from '@/utils/hooks/useOrgId';
|
||
import setting from '@/setting';
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
widthType: string;
|
||
}>(),
|
||
{
|
||
widthType: 'md'
|
||
}
|
||
);
|
||
|
||
const { isLogin } = useAccountStore();
|
||
const { repoId } = useRepoId();
|
||
const { orgId } = useOrgId('/');
|
||
const route = useRoute();
|
||
const { access_level, repoInfo, isAdminOperate } = storeToRefs(repoInfoStore()); // pinia直接解构会失去响应式
|
||
const { setRepoInfo } = repoInfoStore();
|
||
// 获取组织namespace
|
||
const { namespace } = getOrgInfo();
|
||
|
||
const { initRepoDashboard, validLinks, topicData } = useRepoHeaderInit(isLogin);
|
||
initRepoDashboard();
|
||
|
||
const tagList = ref(validLinks.value);
|
||
const isPhone = computed(() => ['lg', 'sm'].includes(props.widthType));
|
||
|
||
const visiMap = new Map([
|
||
['public', '公开'],
|
||
['private', '私有'],
|
||
['internal', '内部']
|
||
]);
|
||
|
||
const toForkRepo = () => {
|
||
if (repoInfo.value?.forked_from_project?.web_url) {
|
||
location.href = repoInfo.value?.forked_from_project?.web_url;
|
||
}
|
||
};
|
||
|
||
const router = useRouter();
|
||
const breadcrumb = computed(() => {
|
||
const pathStrList = repoInfo.value.name_with_namespace?.split('/');
|
||
const pathList = pathStrList.map((item) => ({
|
||
label: item
|
||
}));
|
||
|
||
// 第一个路由带链接
|
||
if (pathList.length === 2) {
|
||
pathList[0].href = router.resolve({
|
||
name: 'homepage',
|
||
params: { namespace: orgId.value }
|
||
}).path;
|
||
pathList[1].href = router.resolve({
|
||
name: 'repoDashboard'
|
||
}).path;
|
||
}
|
||
return pathList;
|
||
});
|
||
|
||
// 获取仓库
|
||
const orgStore = orgInfoStore();
|
||
// 社区基本信息
|
||
const getCommunityInfoFun = async() => {
|
||
const params: types.commonGroupReqType = {
|
||
orgId: namespace.value
|
||
};
|
||
const { data, error } = await reqCatch(getCommunityInfo, params);
|
||
if (!error && data) {
|
||
orgStore.setCommunityUrl({
|
||
communityUrl: `https://${data.data.custom_domain}`,
|
||
communityactivityUrl: `https://${data.data.custom_domain}/activelist`
|
||
});
|
||
orgStore.setCommunityInfo(data.data);
|
||
}
|
||
};
|
||
|
||
async function getModuleState() {
|
||
const res = await getSettingsValues({
|
||
repoId: repoId.value,
|
||
group_id: namespace.value
|
||
});
|
||
if (res.data) {
|
||
const { modules } = res.data.data;
|
||
modules.forEach(({ key, value }) => {
|
||
if (key === 'COMMUNITY' && value === '1') {
|
||
getCommunityInfoFun();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
const handleUpdateStarNumber = (params:Record<string, any>) => {
|
||
setRepoInfo(params);
|
||
};
|
||
const syncFork = ref(null);
|
||
const handleSync = () => {
|
||
syncFork.value.handleOpen();
|
||
};
|
||
|
||
// @TODO 此处只用于repo切换时,读取项目模块配置信息。是否直接从repo详情获取?
|
||
watch(repoId, () => getModuleState(), { flush: 'post', immediate: true });
|
||
|
||
addEventListener('updateNaviBar', getModuleState);
|
||
onUnmounted(() => offEvent('updateNaviBar', getModuleState));
|
||
|
||
watch(() => topicData.userTopicList, val => {
|
||
if (val && val.length) {
|
||
tagList.value = validLinks.value.concat(topicData.userTopicList);
|
||
}
|
||
});
|
||
|
||
watch(() => validLinks.value, val => {
|
||
if (val && val.length) {
|
||
tagList.value = validLinks.value.concat(topicData.userTopicList);
|
||
}
|
||
}, { deep: true });
|
||
|
||
</script>
|
||
<style scoped lang="scss">
|
||
.repo-info {
|
||
.repo-visible {
|
||
border-radius: 14px;
|
||
border: 1px solid var(--devui-btn-common-border-color);
|
||
padding: 7px;
|
||
line-height: 16px;
|
||
height: 24px;
|
||
}
|
||
.official-topic {
|
||
background: rgba(#2951E0, 0.12);
|
||
border-radius: 4px;
|
||
padding: 0 8px;
|
||
height: 22px;
|
||
color: #2951E0;
|
||
font-weight: 600;
|
||
}
|
||
.status-btn-tag {
|
||
height: 24px;
|
||
border-radius: 12px;
|
||
border: 1px solid #e3e3ee;
|
||
padding: 0 8px;
|
||
font-size: 12px;
|
||
&:hover {
|
||
background: #f1f1f8;
|
||
color: #000 !important;
|
||
}
|
||
&:not(:last-of-type) {
|
||
margin-right: 4px;
|
||
}
|
||
}
|
||
.fork-btn {
|
||
border-radius: 4px;
|
||
border: 1px solid #E3E3EE;
|
||
background: #fff;
|
||
padding: 2px 8px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
&:hover {
|
||
background: linear-gradient(0deg, rgba(188, 188, 208, 0.1) 0%, rgba(188, 188, 208, 0.1) 100%), var(--White, #fff);
|
||
}
|
||
}
|
||
}
|
||
</style>
|