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

243 lines
7.7 KiB
Vue
Raw Normal View History

2025-03-12 18:41:20 +08:00
<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>