179 lines
4.9 KiB
Vue
179 lines
4.9 KiB
Vue
|
|
<template>
|
|||
|
|
<user-info-card
|
|||
|
|
class="user-info"
|
|||
|
|
v-bind="userInfoData"
|
|||
|
|
:hideFollowData="hideFollowData"
|
|||
|
|
:profileLoading="profileLoading"
|
|||
|
|
:isPrivate="isPrivate"
|
|||
|
|
>
|
|||
|
|
<template v-if="!userInfoData.isSelf" #action>
|
|||
|
|
<div class="user-info-actions">
|
|||
|
|
<d-button :loading="loading" class="user-info-button" @click="onToggleStar">
|
|||
|
|
<Icon
|
|||
|
|
v-if="!loading"
|
|||
|
|
:name="userInfoData.hasFollowed ? 'gt-starred-c' : 'gt-star'"
|
|||
|
|
:color="userInfoData.hasFollowed ? 'var(--color-Y500)' : ''"
|
|||
|
|
size="16px"
|
|||
|
|
/>
|
|||
|
|
<span class="ml-2">
|
|||
|
|
{{ userInfoData.hasFollowed ? '已关注' : '关注' }}
|
|||
|
|
</span>
|
|||
|
|
</d-button>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
</user-info-card>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script lang="ts">
|
|||
|
|
export default {
|
|||
|
|
name: 'user-info'
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { ref, onMounted, watch } from 'vue';
|
|||
|
|
import { useUserInfo } from '@/views/User/hooks/useUserInfo';
|
|||
|
|
import UserInfoCard from '@/components/UserInfoCard/index.vue';
|
|||
|
|
import { getUserProfile } from '@/api/user';
|
|||
|
|
import { reqCatch } from '@/utils/catch';
|
|||
|
|
import { otherAccountStore } from '@/stores/user';
|
|||
|
|
import type { UserProfile } from '@/api/user/types';
|
|||
|
|
import type { AxiosResponse } from 'axios';
|
|||
|
|
import { useStarFollow } from '@/views/User/hooks/useStarFollow';
|
|||
|
|
import { useRouter } from 'vue-router';
|
|||
|
|
import { xssPurify } from '@/utils';
|
|||
|
|
import { useIsPrivate } from '@/views/User/hooks/useIsPrivate';
|
|||
|
|
const { isPrivate } = useIsPrivate();
|
|||
|
|
|
|||
|
|
const router = useRouter();
|
|||
|
|
|
|||
|
|
// 状态仓库
|
|||
|
|
const otherStore = otherAccountStore();
|
|||
|
|
const emits = defineEmits<{(e: 'updateBanner', image: string): void; (e: 'updateInfo', data: any): void }>();
|
|||
|
|
|
|||
|
|
const profileLoading = ref(true);
|
|||
|
|
// 用户信息
|
|||
|
|
const userInfoData = ref({
|
|||
|
|
name: '',
|
|||
|
|
namespace: '',
|
|||
|
|
avatarUrl: '',
|
|||
|
|
description: '',
|
|||
|
|
fansCount: 0,
|
|||
|
|
followCount: 0,
|
|||
|
|
tenant: '',
|
|||
|
|
location: '',
|
|||
|
|
email: '',
|
|||
|
|
github: '',
|
|||
|
|
blog: '',
|
|||
|
|
username: '',
|
|||
|
|
profile: {},
|
|||
|
|
isFollow: false,
|
|||
|
|
isSelf: false,
|
|||
|
|
hasFollowed: false
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const { isSelf, userInfo, namespace } = useUserInfo();
|
|||
|
|
const { followCount, fanCount, hasFollowed, loading, hideFollowData, toggleStar, getAllCounts, checkFollowedUser } =
|
|||
|
|
useStarFollow(
|
|||
|
|
{
|
|||
|
|
namespace,
|
|||
|
|
username: userInfo.username
|
|||
|
|
},
|
|||
|
|
false
|
|||
|
|
);
|
|||
|
|
checkFollowedUser();
|
|||
|
|
watch(() => [fanCount.value, followCount.value], () => {
|
|||
|
|
userInfoData.value.fansCount = fanCount.value;
|
|||
|
|
userInfoData.value.followCount = followCount.value;
|
|||
|
|
userInfoData.value.hasFollowed = hasFollowed.value;
|
|||
|
|
});
|
|||
|
|
watch(
|
|||
|
|
() => hasFollowed.value,
|
|||
|
|
(val, oldVal) => {
|
|||
|
|
getAllCounts();
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
watch(
|
|||
|
|
() => otherStore.accountInfo.isFollow,
|
|||
|
|
(val) => {
|
|||
|
|
hasFollowed.value = val || false;
|
|||
|
|
otherStore.saveFollowed(val);
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const onToggleStar = () => {
|
|||
|
|
if (loading.value) return false;
|
|||
|
|
toggleStar(userInfo.username || '', namespace, !hasFollowed.value);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
onMounted(async() => {
|
|||
|
|
let userData = userInfo;
|
|||
|
|
if (!isSelf) userData = {};
|
|||
|
|
const username = namespace;
|
|||
|
|
const res = await reqCatch(getUserProfile, { username });
|
|||
|
|
if (!res.data) {
|
|||
|
|
// 审核未通过,跳404页
|
|||
|
|
router.replace('/404');
|
|||
|
|
}
|
|||
|
|
const infoData = (res.data as AxiosResponse<UserProfile>).data || { avatar: '', profile: {}};
|
|||
|
|
const $name = infoData.nickname || '';
|
|||
|
|
userInfoData.value = {
|
|||
|
|
name: $name ? xssPurify($name) : '',
|
|||
|
|
namespace: infoData.username ? `@${infoData.username}` : `@${namespace}`,
|
|||
|
|
avatarUrl: infoData.avatar || '',
|
|||
|
|
description: infoData.profile.description || '',
|
|||
|
|
fansCount: infoData.fans || 0,
|
|||
|
|
followCount: infoData.concerns || 0,
|
|||
|
|
tenant: infoData.profile.company || '',
|
|||
|
|
location: infoData.profile.location || '',
|
|||
|
|
email: !infoData.profile.email_private ? infoData.profile.show_email : '',
|
|||
|
|
github: infoData.profile.github_account.replace(/(https?:\/\/)?github\.com\//, ''),
|
|||
|
|
blog: infoData.profile.website || '',
|
|||
|
|
username: infoData.username || namespace,
|
|||
|
|
profile: infoData.profile,
|
|||
|
|
isFollow: hasFollowed.value,
|
|||
|
|
isSelf
|
|||
|
|
};
|
|||
|
|
profileLoading.value = false;
|
|||
|
|
sessionStorage.setItem('curName', userInfoData.value.name);
|
|||
|
|
emits('updateBanner', infoData.profile.bg_image);
|
|||
|
|
emits('updateInfo', infoData);
|
|||
|
|
|
|||
|
|
otherStore.saveAccountInfo(userInfoData.value);
|
|||
|
|
|
|||
|
|
if (isSelf || !infoData?.profile?.setting_private) getAllCounts();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
defineExpose({
|
|||
|
|
getAllCounts
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.user-info {
|
|||
|
|
&-actions {
|
|||
|
|
margin: 24px 0;
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
&-button {
|
|||
|
|
display: block;
|
|||
|
|
width: 180px;
|
|||
|
|
padding: 8px 16px;
|
|||
|
|
line-height: 1 !important;
|
|||
|
|
background-color: white;
|
|||
|
|
border-color: var(--devui-line, #d7d8da);
|
|||
|
|
color: var(--color-text);
|
|||
|
|
:deep(.button-content) {
|
|||
|
|
display: inline-flex;
|
|||
|
|
align-items: center;
|
|||
|
|
line-height: 1;
|
|||
|
|
}
|
|||
|
|
&:active,
|
|||
|
|
&:hover {
|
|||
|
|
color: var(--color-text) !important;
|
|||
|
|
border-color: var(--devui-line, #d7d8da);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|