Commit 6c5db609 by lijiabin

【需求 17679】 feat: 优化实名匿名部分等

parent db74b8dc
...@@ -9,10 +9,7 @@ ...@@ -9,10 +9,7 @@
import zhCn from 'element-plus/es/locale/lang/zh-cn' import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { initWxConfig } from '@/utils/wxUtil/initWXConfig' import { initWxConfig } from '@/utils/wxUtil/initWXConfig'
const locale = ref(zhCn) const locale = ref(zhCn)
// const userStore = useUserStore()
// userStore.fetchUserInfo().then((res) => {
// console.log(res)
// })
onMounted(() => { onMounted(() => {
if (import.meta.env.MODE === 'production') { if (import.meta.env.MODE === 'production') {
setTimeout(() => { setTimeout(() => {
......
...@@ -27,4 +27,7 @@ export interface LoginResponseDto { ...@@ -27,4 +27,7 @@ export interface LoginResponseDto {
accountNonLocked: boolean accountNonLocked: boolean
token: string token: string
userId: number userId: number
hiddenAvatar: string
hiddenName: string
signature: string
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class="bg-white backdrop-blur-sm rounded-lg shadow-sm border border-white/50 overflow-hidden" class="bg-white backdrop-blur-sm rounded-lg shadow-sm border border-white/50 overflow-hidden"
> >
<!-- 发布者信息 --> <!-- 发布者信息 -->
<div class="p-6 border-b border-gray-100"> <div class="p-6 border-b border-gray-100 pb-0">
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<div class="relative"> <div class="relative">
<img <img
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
<!-- 发表评论 --> <!-- 发表评论 -->
<div class="p-4 border-b border-gray-100"> <div class="p-4 border-b border-gray-100">
<div class="flex gap-3"> <div class="flex gap-3">
<img :src="userInfo?.avatar" alt="" class="w-10 h-10 rounded-full object-cover" /> <img :src="userAvatar" alt="" class="w-10 h-10 rounded-full object-cover" />
<div class="flex-1"> <div class="flex-1">
<div ref="commentInputRef"> <div ref="commentInputRef">
<el-input <el-input
...@@ -232,7 +232,7 @@ ...@@ -232,7 +232,7 @@
<!-- 展示 回复评论的输入框 --> <!-- 展示 回复评论的输入框 -->
<!-- <transition name="fade" mode="out-in"> --> <!-- <transition name="fade" mode="out-in"> -->
<div v-show="showCommentBox(item)" class="flex gap-3 mt-4"> <div v-show="showCommentBox(item)" class="flex gap-3 mt-4">
<img :src="userInfo?.avatar" alt="" class="w-10 h-10 rounded-full object-cover" /> <img :src="userAvatar" alt="" class="w-10 h-10 rounded-full object-cover" />
<div class="flex-1"> <div class="flex-1">
<el-input <el-input
v-model="comment" v-model="comment"
...@@ -313,6 +313,7 @@ const total = defineModel<number>('total', { required: true, default: 0 }) ...@@ -313,6 +313,7 @@ const total = defineModel<number>('total', { required: true, default: 0 })
const userStore = useUserStore() const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore) const { userInfo } = storeToRefs(userStore)
const userAvatar = computed(() => (isReal ? userInfo.value.avatar : userInfo.value.hiddenAvatar))
const commentRef = useTemplateRef<HTMLElement | null>('commentRef') const commentRef = useTemplateRef<HTMLElement | null>('commentRef')
const commentInputRef = useTemplateRef<HTMLElement | null>('commentInputRef') const commentInputRef = useTemplateRef<HTMLElement | null>('commentInputRef')
...@@ -480,7 +481,6 @@ const getCurrentChildrenList = (item: CommentItemDto) => { ...@@ -480,7 +481,6 @@ const getCurrentChildrenList = (item: CommentItemDto) => {
} }
const handleUserInfo = (item: CommentItemDto) => { const handleUserInfo = (item: CommentItemDto) => {
console.log(item)
router.push(`/otherUserPage/${item.userId}/${isReal}`) router.push(`/otherUserPage/${item.userId}/${isReal}`)
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<!-- 主输入区域 --> <!-- 主输入区域 -->
<div class="flex gap-3 mb-4 items-start"> <div class="flex gap-3 mb-4 items-start">
<!-- 用户头像 --> <!-- 用户头像 -->
<el-avatar :size="48" :src="userInfo.avatar" class="flex-shrink-0"> <el-avatar :size="48" :src="userAvatar" class="flex-shrink-0">
<el-icon><User /></el-icon> <el-icon><User /></el-icon>
</el-avatar> </el-avatar>
...@@ -156,12 +156,14 @@ import { useTagsStore } from '@/stores' ...@@ -156,12 +156,14 @@ import { useTagsStore } from '@/stores'
import { uploadFile } from '@/api' import { uploadFile } from '@/api'
import { Close } from '@element-plus/icons-vue' import { Close } from '@element-plus/icons-vue'
import { addOrUpdatePractice, addOrUpdateArticle } from '@/api' import { addOrUpdatePractice, addOrUpdateArticle } from '@/api'
import type { AddOrUpdatePracticeDto } from '@/api/practice/types' import type { AddOrUpdatePracticeDto } from '@/api'
import type { BooleanFlag } from '@/constants'
type ArticleType = ArticleTypeEnum.QUESTION | ArticleTypeEnum.PRACTICE type ArticleType = ArticleTypeEnum.QUESTION | ArticleTypeEnum.PRACTICE
const { type } = defineProps<{ const { type, isReal } = defineProps<{
type: ArticleType type: ArticleType
isReal: BooleanFlag
}>() }>()
const textMap: Record< const textMap: Record<
...@@ -185,6 +187,7 @@ const { tagList } = storeToRefs(tagsStore) ...@@ -185,6 +187,7 @@ const { tagList } = storeToRefs(tagsStore)
const userStore = useUserStore() const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore) const { userInfo } = storeToRefs(userStore)
const userAvatar = computed(() => (isReal ? userInfo.value.avatar : userInfo.value.hiddenAvatar))
const selectTagsDialogRef = const selectTagsDialogRef =
useTemplateRef<InstanceType<typeof SelectTagsDialog>>('selectTagsDialogRef') useTemplateRef<InstanceType<typeof SelectTagsDialog>>('selectTagsDialogRef')
......
...@@ -106,13 +106,18 @@ const formatSeconds = computed(() => { ...@@ -106,13 +106,18 @@ const formatSeconds = computed(() => {
onMounted(async () => { onMounted(async () => {
const { data } = await getTodayOnlineSeconds() const { data } = await getTodayOnlineSeconds()
heartbeat()
currentSeconds.value = data currentSeconds.value = data
}) })
setInterval(() => { const timer1 = setInterval(() => {
currentSeconds.value++ currentSeconds.value++
}, 1000) }, 1000)
setInterval(async () => { const timer2 = setInterval(async () => {
heartbeat() heartbeat()
}, 1000 * 30) }, 1000 * 30)
onUnmounted(() => {
clearInterval(timer1)
clearInterval(timer2)
})
</script> </script>
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
</div> </div>
</div> </div>
</div> </div>
<OnlineTime /> <OnlineTime v-if="showOnlineTime" />
<PublishDialog ref="PublishDialogRef" /> <PublishDialog ref="PublishDialogRef" />
</template> </template>
...@@ -145,6 +145,10 @@ const getSecondLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => { ...@@ -145,6 +145,10 @@ const getSecondLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => {
return key return key
} }
const showOnlineTime = computed(() => {
return !route.path.includes('/videoDetail') && !route.path.includes('/articleDetail')
})
const handlePost = async (type: ArticleTypeEnum) => { const handlePost = async (type: ArticleTypeEnum) => {
if (type === ArticleTypeEnum.VIDEO) { if (type === ArticleTypeEnum.VIDEO) {
router.push('/publishVideo') router.push('/publishVideo')
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<!-- 主要内容区域 --> <!-- 主要内容区域 -->
<div class="mx-auto pt-6"> <div class="mx-auto pt-6">
<PublishBox :type="ArticleTypeEnum.QUESTION" ref="publishBoxRef" /> <PublishBox :type="ArticleTypeEnum.QUESTION" ref="publishBoxRef" :isReal="0" />
<div v-loading="loading" v-if="list.length"> <div v-loading="loading" v-if="list.length">
<!-- 问题列表 --> <!-- 问题列表 -->
<div class="space-y-4"> <div class="space-y-4">
...@@ -298,9 +298,6 @@ const isOverThreeLine = (index: number) => { ...@@ -298,9 +298,6 @@ const isOverThreeLine = (index: number) => {
const handleExpand = (item: ArticleItemDto) => { const handleExpand = (item: ArticleItemDto) => {
item.isExpand = !item.isExpand item.isExpand = !item.isExpand
} }
setInterval(() => {
console.log(contentRefList.value)
}, 3000)
// 是否打开漫游 // 是否打开漫游
watch( watch(
......
<template> <template>
<div> <div>
<!-- 发布区域 --> <!-- 发布区域 -->
<PublishPractice :type="ArticleTypeEnum.PRACTICE" /> <PublishPractice :type="ArticleTypeEnum.PRACTICE" :isReal="1" />
<!-- 标签导航 --> <!-- 标签导航 -->
<div class="bg-white p-4 mb-6 rounded-lg shadow-sm"> <div class="bg-white p-4 mb-6 rounded-lg shadow-sm">
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<span class="mr-2"> <span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span> </span>
<span class="mr-2">评论 {{ item.collectionCount }}</span> <!-- <span class="mr-2">评论 {{ item.collectionCount }}</span> -->
</div> </div>
</div> </div>
......
...@@ -4,12 +4,30 @@ ...@@ -4,12 +4,30 @@
<div class="box relative h-200px bg-gradient-to-r from-purple-400 via-pink-300 to-blue-300"> <div class="box relative h-200px bg-gradient-to-r from-purple-400 via-pink-300 to-blue-300">
<!-- 顶部操作按钮 --> <!-- 顶部操作按钮 -->
<div class="absolute top-4 right-4 flex gap-2"> <div class="absolute top-4 right-4 flex gap-2">
<el-button v-if="!userInfo.isOfficialAccount" type="info" plain size="small" <el-button
@click="handleClearCache">清除缓存</el-button> v-if="!userInfo.isOfficialAccount"
<el-button v-if="officialAccountList.length" type="info" plain size="small" type="info"
@click="handleSwitchAccount">切换账号</el-button> plain
<el-button v-if="userInfo.isOfficialAccount" type="info" plain size="small" size="small"
@click="handleBackUser">返回个人账号</el-button> @click="handleClearCache"
>清除缓存</el-button
>
<el-button
v-if="officialAccountList.length"
type="info"
plain
size="small"
@click="handleSwitchAccount"
>切换账号</el-button
>
<el-button
v-if="userInfo.isOfficialAccount"
type="info"
plain
size="small"
@click="handleBackUser"
>返回个人账号</el-button
>
<!-- v-if="userInfo.isAdmin" 暂时不加权限 --> <!-- v-if="userInfo.isAdmin" 暂时不加权限 -->
<el-button type="primary" plain size="small" @click="handleAdmin">后台管理</el-button> <el-button type="primary" plain size="small" @click="handleAdmin">后台管理</el-button>
</div> </div>
...@@ -22,23 +40,40 @@ ...@@ -22,23 +40,40 @@
<div class="w-300px"> <div class="w-300px">
<!-- 个人信息卡片 --> <!-- 个人信息卡片 -->
<transition name="slide-fade" mode="out-in"> <transition name="slide-fade" mode="out-in">
<div
<div :key="isReal" class="bg-white rounded-lg shadow-sm p-6 mb-4 relative"> :key="isReal"
<!-- 右上角实时切换按钮 --> class="bg-white rounded-lg shadow-sm p-6 mb-4 relative overflow-hidden"
<el-link size="small" type="primary" :underline="false" plain class="absolute! right-4 top-4" >
@click="isReal = isReal ? 0 : 1"> <div
class="absolute -right-9 top-3 bg-blue-500 text-white text-xs px-10 py-1 rotate-45 cursor-pointer shadow-md hover:from-blue-600 hover:to-blue-700 transition-all"
@click="isReal = isReal ? 0 : 1"
>
切换{{ isReal ? '匿名' : '实名' }} 切换{{ isReal ? '匿名' : '实名' }}
</el-link> </div>
<!-- 卡片内容切换动画 -->
<!-- 内容区域 -->
<div class="flex items-start gap-4"> <div class="flex items-start gap-4">
<el-avatar :size="80" :src="userInfo?.avatar" class="border-4 border-white shadow-lg" /> <el-avatar
<div class="flex-1"> :size="80"
<h2 class="text-xl font-semibold text-gray-800 mb-1">{{ userInfo?.name }}</h2> :src="currentUserInfo.avatar"
<p class="text-gray-500 text-sm mb-2">{{ userInfo?.signature }}</p> class="border-4 border-white shadow-lg flex-shrink-0"
<el-button type="warning" size="small" plain @click="handleEdit"> />
<el-icon>
<Edit /> <div class="flex-1 min-w-0">
</el-icon> <el-tooltip :content="currentUserInfo.name" placement="top">
<span class="text-xl font-semibold text-gray-800 mb-1 truncate">
{{ currentUserInfo.name }}
</span>
</el-tooltip>
<el-tooltip :content="currentUserInfo.signature" placement="right">
<span class="text-gray-500 text-sm mb-3 line-clamp-2">
{{ currentUserInfo.signature }}
</span>
</el-tooltip>
<el-button v-if="!isReal" type="warning" size="small" plain @click="handleEdit">
<el-icon><Edit /></el-icon>
修改资料 修改资料
</el-button> </el-button>
</div> </div>
...@@ -48,12 +83,17 @@ ...@@ -48,12 +83,17 @@
<!-- 左侧菜单 ——个人菜单 --> <!-- 左侧菜单 ——个人菜单 -->
<div class="bg-white rounded-lg shadow-sm mb-4"> <div class="bg-white rounded-lg shadow-sm mb-4">
<div v-for="item in menuUserItems" :key="item.path" @click="changeMenu(item.path)" :class="[ <div
'flex items-center gap-3 px-4 py-3 cursor-pointer transition-colors border-b border-gray-100 last:border-b-0', v-for="item in menuUserItems"
activeMenu === item.path :key="item.path"
? 'bg-blue-50 text-blue-600 border-r-3 border-r-blue-600' @click="changeMenu(item.path)"
: 'text-gray-700 hover:bg-gray-50', :class="[
]"> 'flex items-center gap-3 px-4 py-3 cursor-pointer transition-colors border-b border-gray-100 last:border-b-0',
activeMenu === item.path
? 'bg-blue-50 text-blue-600 border-r-3 border-r-blue-600'
: 'text-gray-700 hover:bg-gray-50',
]"
>
<el-icon :size="16"> <el-icon :size="16">
<component :is="item.icon" /> <component :is="item.icon" />
</el-icon> </el-icon>
...@@ -62,12 +102,17 @@ ...@@ -62,12 +102,17 @@
</div> </div>
<!-- 左侧菜单 —— 官方账号菜单 审核操作等 --> <!-- 左侧菜单 —— 官方账号菜单 审核操作等 -->
<div class="bg-white rounded-lg shadow-sm"> <div class="bg-white rounded-lg shadow-sm">
<div v-for="item in menuOfficialItems" :key="item.path" @click="changeMenu(item.path)" :class="[ <div
'flex items-center gap-3 px-4 py-3 cursor-pointer transition-colors border-b border-gray-100 last:border-b-0', v-for="item in menuOfficialItems"
activeMenu === item.path :key="item.path"
? 'bg-blue-50 text-blue-600 border-r-3 border-r-blue-600' @click="changeMenu(item.path)"
: 'text-gray-700 hover:bg-gray-50', :class="[
]"> 'flex items-center gap-3 px-4 py-3 cursor-pointer transition-colors border-b border-gray-100 last:border-b-0',
activeMenu === item.path
? 'bg-blue-50 text-blue-600 border-r-3 border-r-blue-600'
: 'text-gray-700 hover:bg-gray-50',
]"
>
<el-icon :size="16"> <el-icon :size="16">
<component :is="item.icon" /> <component :is="item.icon" />
</el-icon> </el-icon>
...@@ -182,6 +227,19 @@ const menuOfficialItems = [ ...@@ -182,6 +227,19 @@ const menuOfficialItems = [
] ]
const isReal = ref(1) const isReal = ref(1)
const currentUserInfo = computed(() =>
isReal.value
? {
avatar: userInfo.value.avatar,
name: userInfo.value.name,
signature: '',
}
: {
avatar: userInfo.value.hiddenAvatar,
name: userInfo.value.hiddenName,
signature: userInfo.value.signature,
},
)
const changeMenu = (key: TabPaneName) => { const changeMenu = (key: TabPaneName) => {
router.push(`/userPage/${key}`) router.push(`/userPage/${key}`)
...@@ -190,9 +248,9 @@ const changeMenu = (key: TabPaneName) => { ...@@ -190,9 +248,9 @@ const changeMenu = (key: TabPaneName) => {
const handleEdit = () => { const handleEdit = () => {
console.log('修改资料') console.log('修改资料')
editUserInfoRef.value?.open({ editUserInfoRef.value?.open({
hiddenAvatar: userInfo.value.avatar, hiddenAvatar: userInfo.value.hiddenAvatar,
hiddenName: userInfo.value.name, hiddenName: userInfo.value.hiddenName,
signature: '', signature: userInfo.value.signature,
}) })
} }
...@@ -327,9 +385,9 @@ onMounted(() => { ...@@ -327,9 +385,9 @@ onMounted(() => {
.slide-fade-enter-active { .slide-fade-enter-active {
transition: transition:
opacity .6s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
transform .6s cubic-bezier(0.22, 1, 0.36, 1), transform 0.6s cubic-bezier(0.22, 1, 0.36, 1),
filter .6s ease; filter 0.6s ease;
transform-style: preserve-3d; transform-style: preserve-3d;
} }
...@@ -337,7 +395,7 @@ onMounted(() => { ...@@ -337,7 +395,7 @@ onMounted(() => {
opacity: 1; opacity: 1;
transform: translateY(0) rotateY(0deg) translateZ(0) scale(1); transform: translateY(0) rotateY(0deg) translateZ(0) scale(1);
filter: blur(0); filter: blur(0);
box-shadow: 0 15px 40px rgba(0, 0, 0, .18); /* box-shadow: 0 15px 40px rgba(0, 0, 0, 0.18); */
} }
.slide-fade-leave-from { .slide-fade-leave-from {
...@@ -348,9 +406,9 @@ onMounted(() => { ...@@ -348,9 +406,9 @@ onMounted(() => {
.slide-fade-leave-active { .slide-fade-leave-active {
transition: transition:
opacity .5s cubic-bezier(0.55, 0, 0.55, 0.2), opacity 0.5s cubic-bezier(0.55, 0, 0.55, 0.2),
transform .5s cubic-bezier(0.55, 0, 0.55, 0.2), transform 0.5s cubic-bezier(0.55, 0, 0.55, 0.2),
filter .4s; filter 0.4s;
transform-style: preserve-3d; transform-style: preserve-3d;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment