Commit 76422e6d by lijiabin

【需求 20331】 styles: 基本上是一些样式优化

parent e5a127c9
// 企业文化接口 // 企业文化接口
export * from './task' export * from './task'
export * from './sign' export * from './sign'
export * from './article'
export * from './shop' export * from './shop'
export * from './tag' export * from './tag'
export * from './article'
export * from './user' export * from './user'
export * from './case' export * from './case'
export * from './home' export * from './home'
...@@ -19,7 +17,6 @@ export * from './dailyLottery' ...@@ -19,7 +17,6 @@ export * from './dailyLottery'
// 导出类型 // 导出类型
export * from './task/types' export * from './task/types'
export * from './shop/types' export * from './shop/types'
export * from './article/types'
export * from './tag/types' export * from './tag/types'
export * from './article/types' export * from './article/types'
export * from './user/types' export * from './user/types'
......
...@@ -76,6 +76,10 @@ export const articleTypeListOptionsForReal: { label: string; value: ArticleTypeE ...@@ -76,6 +76,10 @@ export const articleTypeListOptionsForReal: { label: string; value: ArticleTypeE
label: '专访', label: '专访',
value: ArticleTypeEnum.INTERVIEW, value: ArticleTypeEnum.INTERVIEW,
}, },
{
label: '问吧',
value: ArticleTypeEnum.QUESTION,
},
] ]
export const articleTypeListOptionsForNotReal: { label: string; value: ArticleTypeEnum }[] = [ export const articleTypeListOptionsForNotReal: { label: string; value: ArticleTypeEnum }[] = [
...@@ -88,11 +92,6 @@ export const articleTypeListOptionsForNotReal: { label: string; value: ArticleTy ...@@ -88,11 +92,6 @@ export const articleTypeListOptionsForNotReal: { label: string; value: ArticleTy
value: ArticleTypeEnum.VIDEO, value: ArticleTypeEnum.VIDEO,
}, },
{ {
label: '问吧',
value: ArticleTypeEnum.QUESTION,
},
{
label: '专栏', label: '专栏',
value: ArticleTypeEnum.COLUMN, value: ArticleTypeEnum.COLUMN,
}, },
......
<template> <template>
<Draggable <Draggable
v-show="showOnlineTime"
:initial-value="{ x: x, y: y }" :initial-value="{ x: x, y: y }"
storage-key="vueuse-draggable" storage-key="vueuse-draggable"
storage-type="session" storage-type="session"
class="fixed" class="fixed z-2"
> >
<div class="cursor-pointer online-time flex flex-col items-center z-10050"> <div
<!-- 图片容器 --> class="group flex items-center gap-2.5 py-2.5 pr-4 pl-3 bg-#fff rounded-xl shadow-[inset_0_2px_6px_rgba(0,0,0,0.08)] cursor-pointer transition-all duration-250 relative shadow-[inset_0_2px_8px_rgba(0,0,0,0.12)]"
>
<!-- 在线指示灯 -->
<div <div
class="mb-4 w-24 h-24 bg-white rounded-full shadow-xl flex items-center justify-center hover:scale-110 transition-transform cursor-pointer" class="w-1.5 h-1.5 rounded-full bg-green-500 shrink-0 animate-pulse shadow-[0_0_6px_rgba(34,197,94,0.4)]"
> ></div>
<img src="@/assets/img/culture/ask.png" draggable="false" alt="吉祥物" class="w-20 h-20" />
<!-- 如果没有图片,用emoji代替 --> <!-- 时长内容 -->
<!-- <span class="text-6xl">🎯</span> --> <div class="flex flex-col leading-tight">
<span class="text-base text-gray-400 tracking-wider font-medium">今日在线时长</span>
<span class="text-base font-bold text-blue-600 tabular-nums tracking-wider">
{{ formatSeconds }}
</span>
</div> </div>
<!-- 时长显示卡片 --> <!-- 关闭按钮 -->
<div <div
class="w-24 md:w-28 lg:w-32 h-16 md:h-18 lg:h-20 rounded-lg bg-gradient-to-br from-white via-blue-50 to-purple-50 shadow-lg hover:shadow-xl border border-white/50 flex flex-col justify-center items-center transition-all duration-300 ease-out hover:scale-105 hover:-translate-y-1 backdrop-blur-sm relative overflow-hidden group transform-gpu backface-hidden will-change-transform" class="absolute -top-1.5 -right-1.5 w-4 h-4 rounded-full bg-white text-gray-400 shadow-sm flex items-center justify-center opacity-0 scale-60 transition-all duration-200 cursor-pointer group-hover:opacity-100 group-hover:scale-100 hover:!bg-red-500 hover:!text-white"
title="关闭"
@click.stop="showOnlineTime = false"
> >
<!-- 其他内容保持不变 --> <svg viewBox="0 0 12 12" class="w-2.5 h-2.5">
<div <path
class="absolute inset-0 bg-gradient-to-r from-blue-400/5 via-purple-400/5 to-pink-400/5 opacity-0 group-hover:opacity-100 transition-opacity duration-500" d="M1.5.4L6 4.9 10.5.4l1.1 1.1L7.1 6l4.5 4.5-1.1 1.1L6 7.1 1.5 11.6.4 10.5 4.9 6 .4 1.5z"
></div> fill="currentColor"
/>
<div </svg>
class="absolute top-0 left-0 right-0 h-2 bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 opacity-80"
></div>
<div
class="absolute top-1 left-0 right-0 h-1 bg-gradient-to-r from-blue-300 via-purple-300 to-pink-300 opacity-60"
></div>
<div class="text-center px-3 relative">
<div class="text-xs md:text-sm text-gray-700 font-medium mb-1 tracking-wide">
今日在线时长
</div>
<div
class="text-center text-2xl font-bold bg-gradient-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent"
>
{{ formatSeconds }}
</div>
</div>
<div class="absolute bottom-2 left-3 right-3 h-1 bg-gray-200 rounded-full overflow-hidden">
<div
class="h-full bg-gradient-to-r from-blue-400 to-purple-400 rounded-full animate-pulse"
:style="{
width: widthRate + '%',
}"
></div>
</div>
<div class="absolute top-3 right-3 w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
<div
class="absolute bottom-3 left-3 w-1.5 h-1.5 bg-blue-400 rounded-full animate-pulse"
style="animation-delay: 0.8s"
></div>
<div
class="absolute left-0 top-4 bottom-4 w-0.5 bg-gradient-to-b from-transparent via-purple-300 to-transparent opacity-50"
></div>
<div
class="absolute right-0 top-4 bottom-4 w-0.5 bg-gradient-to-b from-transparent via-blue-300 to-transparent opacity-50"
></div>
</div> </div>
</div> </div>
</Draggable> </Draggable>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { UseDraggable as Draggable } from '@vueuse/components' import { UseDraggable as Draggable } from '@vueuse/components'
import { useWindowSize } from '@vueuse/core' import { useWindowSize } from '@vueuse/core'
import { getTodayOnlineSeconds, heartbeat } from '@/api' import { getTodayOnlineSeconds, heartbeat } from '@/api'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc' import utc from 'dayjs/plugin/utc'
import { useOnlineTimeStore } from '@/stores'
import { storeToRefs } from 'pinia'
dayjs.extend(utc) dayjs.extend(utc)
const onlineTimeStore = useOnlineTimeStore()
const { showOnlineTime } = storeToRefs(onlineTimeStore)
const { height } = useWindowSize() const { height } = useWindowSize()
const CONTAINER_HEIGHT = 170, const CONTAINER_HEIGHT = 170,
GAP = 30 GAP = 30
// CONTAINER_WIDTH = 130
const maxSeconds = 60 * 30 // 半小时
const x = GAP const x = GAP
const y = height.value - CONTAINER_HEIGHT - GAP const y = height.value - CONTAINER_HEIGHT - GAP
const currentSeconds = ref(0) const currentSeconds = ref(0)
// 进度条的比例
const widthRate = computed(() => {
if (currentSeconds.value >= maxSeconds) {
return 100
} else {
return (currentSeconds.value / maxSeconds) * 100
}
})
// 在线时长格式化 将秒级 格式化为 00:00
// 如果大于一个小时的话,则显示小时:分钟:秒
const formatSeconds = computed(() => { const formatSeconds = computed(() => {
if (currentSeconds.value >= 60 * 60) { if (currentSeconds.value >= 60 * 60) {
return dayjs.utc(currentSeconds.value * 1000).format('hh:mm:ss') return dayjs.utc(currentSeconds.value * 1000).format('hh:mm:ss')
......
...@@ -5,3 +5,4 @@ export * from './interview' ...@@ -5,3 +5,4 @@ export * from './interview'
export * from './video' export * from './video'
export * from './question' export * from './question'
export * from './yabi' export * from './yabi'
export * from './onlineTime'
import { defineStore } from 'pinia'
export const useOnlineTimeStore = defineStore('onlineTime', () => {
const showOnlineTime = ref(true)
return {
showOnlineTime,
}
})
...@@ -47,7 +47,7 @@ export const useUserStore = defineStore('user', () => { ...@@ -47,7 +47,7 @@ export const useUserStore = defineStore('user', () => {
const { data } = await refreshTokenApi(refreshToken.value) const { data } = await refreshTokenApi(refreshToken.value)
setUserInfoAndToken(data) setUserInfoAndToken(data)
} }
const setUserInfoAndToken = async (data: LoginResponseDto) => { const setUserInfoAndToken = (data: LoginResponseDto) => {
setUserInfo(data) setUserInfo(data)
setToken(data.token) setToken(data.token)
setRefreshToken(data.refreshToken) setRefreshToken(data.refreshToken)
......
import { app_config } from '@/config' import { app_config } from '@/config'
import Axois from './axios' import Axios from './axios'
// 'http://192.168.2.168:8089' // 'http://192.168.2.168:8089'
const baseUrl = app_config[import.meta.env.MODE]?.baseUrl const baseUrl = app_config[import.meta.env.MODE]?.baseUrl
console.log('baseUrl', baseUrl) console.log('baseUrl', baseUrl)
export default new Axois({ export default new Axios({
baseURL: baseUrl, baseURL: baseUrl,
timeout: 1000 * 60, timeout: 1000 * 60,
}) })
...@@ -100,49 +100,69 @@ const onBid = async (item: AuctionItemDto) => { ...@@ -100,49 +100,69 @@ const onBid = async (item: AuctionItemDto) => {
console.log(data, 'data') console.log(data, 'data')
const val = ref(0) const val = ref(0)
ElMessageBox.confirm('确定参与竞拍吗?', { ElMessageBox.confirm('确定参与竞拍吗?', {
confirmButtonText: '确', confirmButtonText: '确认出价',
cancelButtonText: '取消', cancelButtonText: '取消',
customClass: 'auction-bid-dialog',
message: () => ( message: () => (
<div class="space-y-12px text-gray-700"> <div class="space-y-16px">
{/* 作品名称 */} {/* 商品名称 */}
<div class="text-16px font-600 text-gray-900">{item.name}</div> <div class="flex items-center gap-3">
<img src={item.imageUrl} class="w-12 h-12 rounded-lg object-cover shadow-sm" />
<div>
<div class="text-15px font-600 text-gray-800 line-clamp-1">{item.name}</div>
<div class="text-12px text-gray-400 mt-1">{item.specification}</div>
</div>
</div>
{/* 规则说明 */} {/* 规则说明 */}
<div class="text-12px leading-18px text-gray-500 bg-gray-50 rounded-6px p-10px"> <div class="text-12px leading-18px text-indigo-500 bg-indigo-50 rounded-8px px-12px py-8px flex items-start gap-6px">
竞拍后将暂时扣除您出价的 YA 币,若您的出价被超越,YA 币将自动退回 <span class="mt-2px shrink-0">💡</span>
<span>竞拍后将暂时扣除您出价的 YA 币,若您的出价被超越,YA 币将自动退回</span>
</div> </div>
{/* 当前竞拍信息 */} {/* 当前竞拍信息 */}
<div class="space-y-6px"> <div class="bg-gray-50 rounded-10px p-12px space-y-8px">
{data.currentPrice ? ( {data.currentPrice ? (
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<span class="text-gray-500">当前最高出价</span> <span class="text-13px text-gray-500">当前最高出价</span>
<span class="text-orange-500 font-600">{data.currentPrice} YA</span> <span class="text-16px text-orange-500 font-700">
{data.currentPrice} <span class="text-12px font-400">YA</span>
</span>
</div> </div>
) : ( ) : (
<div class="text-gray-500">当前暂未有人出价</div> <div class="flex items-center justify-between">
<span class="text-13px text-gray-500">当前最高出价</span>
<span class="text-13px text-gray-400">暂无人出价</span>
</div>
)} )}
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<span class="text-gray-500">单人出价上限</span> <span class="text-13px text-gray-500">起拍价</span>
<span class="text-gray-700">{item.bidLimit} </span> <span class="text-13px text-gray-700 font-500">{data.startingPrice} YA</span>
</div>
<div class="flex items-center justify-between">
<span class="text-13px text-gray-500">最低加价</span>
<span class="text-13px text-gray-700 font-500">{data.minIncrement} YA</span>
</div>
<div class="flex items-center justify-between">
<span class="text-13px text-gray-500">出价次数上限</span>
<span class="text-13px text-gray-700 font-500">{item.bidLimit} </span>
</div> </div>
</div> </div>
{/* 出价输入 */} {/* 出价输入 */}
<div class="space-y-6px flex items-center justify-between"> <div class="space-y-8px">
<div class="text-gray-500">您的出价</div> <div class="text-13px text-gray-700 font-500">您的出价 (YA)</div>
<el-input-number <el-input-number
v-model={val.value} v-model={val.value}
controls-position="right" controls-position="right"
class="w-50%!" class="w-full!"
placeholder="请输入 YA 币数量" min={0}
placeholder="请输入出价金额"
/> />
</div> <div class="flex items-center justify-end text-12px text-gray-400">
可用余额:<span class="text-indigo-500 font-500">{yabiData.value.currentValue}</span>{' '}
{/* 余额提示 */} YA
<div class="flex items-center justify-end text-12px text-gray-500 rounded-6px p-8px"> </div>
<span>当前可用 {yabiData.value.currentValue} YA</span>
</div> </div>
</div> </div>
), ),
...@@ -221,52 +241,52 @@ const onBid = async (item: AuctionItemDto) => { ...@@ -221,52 +241,52 @@ const onBid = async (item: AuctionItemDto) => {
</button> </button>
</div> </div>
<template v-if="list.length"> <template v-if="list.length">
<!-- 卡片网格 --> <div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-5">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-6">
<div <div
v-for="item in list" v-for="item in list"
:key="item.id" :key="item.id"
class="card group relative bg-white rounded-xl overflow-hidden border-2 border-solid border-transparent shadow-lg hover:border-blue-500 hover:shadow-xl transition-all duration-300 cursor-pointer transform hover:-translate-y-1" class="card group relative bg-white rounded-xl overflow-hidden border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer hover:-translate-y-0.5"
:class="{ 'filter-grayscale-30': item.status === AuctionStatusEnum.AUCTION_FAILED }" :class="{ 'filter-grayscale-30': item.status === AuctionStatusEnum.AUCTION_FAILED }"
> >
<!-- 状态角标 --> <!-- 图片区 -->
<div <div class="card-img-wrap relative aspect-4/3 overflow-hidden bg-gray-100">
class="absolute top-2 left-2 z-2 text-xs font-semibold px-2.5 py-1 rounded-full tracking-wide"
:class="getBadgeClass(item.status)"
>
{{ tabs.find((option) => option.value === item.status)?.label }}
</div>
<!-- 图片容器 -->
<div
class="card-img-wrap w-full aspect-6/5 bg-gradient-to-br from-blue-50 to-purple-50 flex items-center justify-center relative overflow-hidden"
>
<img <img
:src="item.imageUrl" :src="item.imageUrl"
class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/> />
<!-- 悬浮层 --> <!-- 状态角标 -->
<!-- <div <div
class="absolute inset-0 bg-black/0 group-hover:bg-black/15 transition-all duration-300 flex items-center justify-center opacity-0 group-hover:opacity-100" class="absolute top-2.5 left-2.5 text-11px font-semibold px-2.5 py-1 rounded-md tracking-wide shadow-sm"
:class="getBadgeClass(item.status)"
>
{{ tabs.find((option) => option.value === item.status)?.label }}
</div>
<!-- 倒计时条 -->
<div
v-if="item.status === AuctionStatusEnum.AUCTIONING"
class="absolute bottom-0 inset-x-0 bg-black/60 backdrop-blur-sm text-white text-11px py-1.5 px-3 flex items-center gap-1.5"
> >
<span <span
class="bg-white px-4 py-2 rounded-full text-sm font-medium text-blue-600 shadow-md transition-all duration-300" class="inline-block w-1.5 h-1.5 rounded-full bg-red-400 animate-pulse"
> ></span>
查看详情 {{ item.remainingTime }}
</span> </div>
</div> -->
</div> </div>
<!-- 内容区 --> <!-- 内容区 -->
<div class="card-body p-5 flex flex-col gap-2"> <div class="p-4 flex flex-col gap-2">
<!-- 标题 --> <!-- 标题 + 规格 -->
<h3 class="text-[15px] font-semibold text-gray-900 leading-snug line-clamp-1"> <div class="flex items-center justify-between gap-2">
{{ item.name }} <h3 class="text-sm font-semibold text-gray-800 line-clamp-1">
</h3> {{ item.name }}
</h3>
<span class="text-11px text-gray-400 shrink-0">{{ item.specification }}</span>
</div>
<!-- 描述 --> <!-- 描述 -->
<p class="text-xs text-gray-500 leading-relaxed line-clamp-1"> <p class="text-xs text-gray-400 line-clamp-1">
<el-popover :content="item.description" placement="top-start" width="300"> <el-popover :content="item.description" placement="top-start" width="300">
<template #reference> <template #reference>
{{ item.description }} {{ item.description }}
...@@ -274,47 +294,45 @@ const onBid = async (item: AuctionItemDto) => { ...@@ -274,47 +294,45 @@ const onBid = async (item: AuctionItemDto) => {
</el-popover> </el-popover>
</p> </p>
<!-- 规格 --> <!-- 分隔线 -->
<div class="flex items-center gap-1 text-xs text-gray-600"> <div class="border-t border-dashed border-gray-100 my-1"></div>
<span class="text-gray-400">规格</span>
<span class="text-gray-700 font-medium">{{ item.specification }}</span>
</div>
<!-- 剩余时间(单独一行,重要) -->
<div
class="text-xs text-gray-500 mt-1"
:style="{
opacity: item.status === AuctionStatusEnum.AUCTIONING ? 1 : 0,
}"
>
⏱ 拍卖剩余:{{ item.remainingTime }}
</div>
<!-- 底部价格 + 按钮 --> <!-- 价格区 -->
<div class="flex items-end justify-between gap-2"> <div class="flex items-end justify-between gap-2">
<div class="flex flex-col"> <div class="flex flex-col gap-0.5">
<div v-if="item.currentPrice" class="flex items-baseline gap-1">
<span class="text-11px text-gray-400">当前出价</span>
<span class="text-lg font-bold text-orange-500">{{
item.currentPrice
}}</span>
<span class="text-11px text-gray-400">YA币</span>
</div>
<div class="flex items-baseline gap-1"> <div class="flex items-baseline gap-1">
<span class="text-xs text-gray-400">起拍</span> <span class="text-11px text-gray-400">起拍价</span>
<span class="text-lg font-bold text-red-500"> <span
class="font-semibold"
:class="
item.currentPrice
? 'text-xs text-gray-400 line-through'
: 'text-lg text-orange-500'
"
>
{{ item.startingPrice }} {{ item.startingPrice }}
</span> </span>
<span class="text-xs text-gray-500">YA币</span> <span v-if="!item.currentPrice" class="text-11px text-gray-400">YA币</span>
</div> </div>
<div class="text-xs text-gray-400"> <div class="text-11px text-gray-400">
最低加价 加价幅度 ≥ {{ item.minIncrement }} YA币
<span class="text-gray-600 font-medium">{{ item.minIncrement }}</span> YA币
</div> </div>
</div> </div>
<el-button <button
v-if="item.status === AuctionStatusEnum.AUCTIONING" v-if="item.status === AuctionStatusEnum.AUCTIONING"
type="primary" class="shrink-0 px-4 py-1.5 rounded-lg text-xs font-medium bg-gradient-to-r from-indigo-500 to-purple-500 text-white shadow-sm shadow-indigo-500/20 hover:shadow-md hover:shadow-indigo-500/30 active:scale-95 transition-all duration-200 cursor-pointer"
size="small"
class="bg-gradient-to-r from-indigo-500 to-purple-600 text-white border-none px-4 py-2 rounded-lg shadow-md hover:shadow-lg transition-all"
@click.stop="onBid(item)" @click.stop="onBid(item)"
> >
参与竞拍 🔨 出价
</el-button> </button>
</div> </div>
</div> </div>
</div> </div>
...@@ -402,44 +420,46 @@ const onBid = async (item: AuctionItemDto) => { ...@@ -402,44 +420,46 @@ const onBid = async (item: AuctionItemDto) => {
</template> </template>
<style scoped> <style scoped>
/* 已结束卡片置灰 */
.card.filter-grayscale-30 { .card.filter-grayscale-30 {
filter: grayscale(30%); filter: grayscale(30%);
} }
</style>
/* 图片光圈装饰 (UnoCSS 复杂渐变伪元素不易直接实现,保留为 scoped CSS) */ <style>
.card-img-wrap::before { .auction-bid-dialog .el-message-box__header {
content: ''; display: none;
position: absolute;
width: 120px;
height: 120px;
border-radius: 50%;
background: radial-gradient(circle, rgba(139, 92, 246, 0.12) 0%, transparent 70%);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: transform 0.3s ease;
z-index: 0; /* 确保在图片下方 */
} }
/* 悬浮时光圈放大效果 */ .auction-bid-dialog .el-message-box__content {
.card:hover .card-img-wrap::before { padding: 24px 24px 8px;
transform: translate(-50%, -50%) scale(1.1);
} }
.bid-btn.el-button.is-disabled { .auction-bid-dialog .el-message-box__btns {
--el-button-bg-color: #d1d5db !important; /* gray-300 */ padding: 12px 24px 20px;
--el-button-text-color: #6b7280 !important; /* gray-500 */
background: #d1d5db !important; /* fallback */
color: #6b7280 !important; /* fallback */
box-shadow: none !important;
cursor: not-allowed !important;
transform: none !important;
} }
.bid-btn.el-button.is-disabled:hover {
transform: none !important; .auction-bid-dialog .el-message-box__btns .el-button--primary {
box-shadow: none !important; background: linear-gradient(to right, #6366f1, #8b5cf6);
background: #d1d5db !important; border: none;
color: #6b7280 !important; border-radius: 8px;
padding: 8px 24px;
}
.auction-bid-dialog .el-message-box__btns .el-button--primary:hover {
opacity: 0.9;
}
.auction-bid-dialog .el-message-box__btns .el-button:not(.el-button--primary) {
border-radius: 8px;
padding: 8px 24px;
}
.auction-bid-dialog {
border-radius: 16px !important;
overflow: hidden;
}
.auction-bid-dialog .el-message-box__status {
display: none !important;
} }
</style> </style>
...@@ -13,6 +13,15 @@ ...@@ -13,6 +13,15 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="自动关闭" prop="autoCloseWeekend"> <el-form-item label="自动关闭" prop="autoCloseWeekend">
<!-- 加一个tips -->
<template #label>
<div class="flex items-center gap-1">
<span>自动关闭</span>
<el-tooltip content="如果开启,则会在周末自动关闭抽奖" placement="top">
<el-icon size="16"><IEpInfoFilled /></el-icon>
</el-tooltip>
</div>
</template>
<el-switch <el-switch
v-model="form.autoCloseWeekend" v-model="form.autoCloseWeekend"
:active-value="1" :active-value="1"
......
...@@ -17,93 +17,79 @@ ...@@ -17,93 +17,79 @@
<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">
<el-card <div
v-for="(item, index) in list" v-for="(item, index) in list"
:key="item.id" :key="item.id"
class="question-card !rounded-lg mb-4 transition-all duration-300 relative" class="relative group bg-white rounded-lg p-5 cursor-pointer transition-all duration-300 hover:shadow-lg hover:shadow-gray-100 border border-gray-100 hover:border-gray-200 mb-3 sm:mb-4"
shadow="hover"
> >
<div <!-- 推荐标签 -->
v-if="item.isRecommend" <div v-if="item.isRecommend" class="absolute left-0 top-5">
class="absolute top-0 left-0 w-13 h-6 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg" <div
> class="h-5.5 pl-2 pr-2.5 flex items-center gap-1 bg-gradient-to-r from-#6366f1 to-#818cf8 rounded-r-full text-white text-11px font-medium shadow-sm"
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" /> >
<div class="text-12px text-#000 line-height-12px">推荐</div> <svg viewBox="0 0 16 16" class="w-3 h-3 fill-current">
<path
d="M8 1.3l2 4.1 4.5.7-3.2 3.1.8 4.5L8 11.5l-4.1 2.2.8-4.5L1.5 6.1l4.5-.7z"
/>
</svg>
推荐
</div>
</div> </div>
<!-- 问题标题 -->
<h2 <h2
class="text-xl line-clamp-1 font-semibold text-gray-900 mb-2 leading-relaxed cursor-pointer hover:text-blue-600 transition-colors" class="text-xl line-clamp-1 font-semibold text-gray-900 mb-3 leading-tight hover:text-blue-600 transition-colors"
:class="{ 'pl-14': item.isRecommend }"
@click="openNewPage(`/questionDetail/${item.id}`)" @click="openNewPage(`/questionDetail/${item.id}`)"
> >
{{ item.title }} {{ item.title }}
</h2> </h2>
<div class="flex gap-4 mb-2">
<!-- 问吧暂时先不展示图片 --> <div class="mb-3">
<!-- <el-image <p
v-if="item.faceUrl && !item.cultureCommentListVo?.hiddenName" :ref="(e) => (contentRefList[index] = e as HTMLElement)"
:src="item.faceUrl" class="text-gray-600 text-sm sm:text-base leading-relaxed transition-all duration-300"
fit="cover" :class="{ 'line-clamp-3': !item.isExpand }"
class="w-50 h-25 rounded-lg" >
/> --> <template v-if="item.cultureCommentListVo?.hiddenName">
<!-- 问题内容 --> {{ item.cultureCommentListVo?.hiddenName }}
<div> <span v-html="parseEmoji(item.cultureCommentListVo?.content)"></span>
<p </template>
:ref="(e) => (contentRefList[index] = e as HTMLElement)" <template v-else>
class="text-gray-600 text-base leading-relaxed transition-all duration-300" <span v-html="parseEmoji(item.content)"></span>
:class="{ 'line-clamp-3': !item.isExpand }" </template>
> </p>
<!-- 如果有评论的话 就展示 最热的 没有的话 说明没有评论 就展示内容 --> <div class="flex justify-end" v-if="isOverThreeLine(index)">
<template v-if="item.cultureCommentListVo?.hiddenName"> <el-button @click.stop="handleExpand(item)" type="primary" text size="small">
{{ item.cultureCommentListVo?.hiddenName }} {{ item.isExpand ? '收起' : '阅读全文' }}
<span v-html="parseEmoji(item.cultureCommentListVo?.content)"></span> <el-icon class="ml-1" :class="{ 'rotate-180': item.isExpand }">
</template> <IEpArrowDown />
<template v-else> </el-icon>
<p v-html="parseEmoji(item.content)"></p> </el-button>
</template>
</p>
<!-- 展开/收起按钮 靠右边布局 -->
<div class="flex justify-end">
<el-button
v-if="isOverThreeLine(index)"
@click.stop="handleExpand(item)"
type="primary"
text
size="small"
class="text-blue-500"
>
{{ item.isExpand ? '收起' : '阅读全文' }}
<el-icon class="ml-1" :class="{ 'rotate-180': item.isExpand }">
<IEpArrowDown />
</el-icon>
</el-button>
</div>
</div> </div>
</div> </div>
<!-- 底部信息栏 -->
<div class="flex items-center justify-between border-t border-gray-100"> <div class="flex items-center justify-between pt-3 border-t border-gray-100/80">
<!-- 左侧:发布人信息 --> <div class="flex items-center gap-2 xl:gap-3 flex-wrap">
<div class="flex items-center gap-2 lg:gap-4">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="text-orange-500 text-sm font-medium hidden lg:block">发布人</span> <el-avatar :size="22" :src="item.showAvatar" />
<div class="flex items-center gap-2"> <span class="text-sm text-gray-600">{{ item.showName }}</span>
<el-avatar :size="20" :src="item.showAvatar"> </el-avatar>
<span class="text-sm text-gray-700 font-medium">{{ item.showName }}</span>
</div>
</div> </div>
<span class="text-xs text-gray-400 hidden sm:inline">{{
<span class="text-xs text-gray-400">{{
dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm') dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm')
}}</span> }}</span>
<div class="hidden sm:block w-1 h-1 bg-gray-300 rounded-full"></div>
<!-- 操作按钮组 --> <div class="flex items-center gap-1">
<div class="flex items-center">
<el-button <el-button
size="small" size="small"
plain plain
:class="{ 'opacity-50': item.hasAddQuestion }" class="rounded-lg"
:class="{
'!text-blue-500 !border-blue-200 !bg-blue-50': item.hasAddQuestion,
}"
@click.stop="handleAddQuestion(item)" @click.stop="handleAddQuestion(item)"
> >
<el-icon> <el-icon class="mr-0.5">
<IEpCircleCheckFilled v-show="item.hasAddQuestion" /> <IEpCircleCheckFilled v-show="item.hasAddQuestion" />
<IEpPlus v-show="!item.hasAddQuestion" /> <IEpPlus v-show="!item.hasAddQuestion" />
</el-icon> </el-icon>
...@@ -113,62 +99,33 @@ ...@@ -113,62 +99,33 @@
<el-button <el-button
size="small" size="small"
plain plain
:class="{ 'opacity-50': item.hasCollect }" class="rounded-lg"
:class="{ '!text-amber-500 !border-amber-200 !bg-amber-50': item.hasCollect }"
@click.stop="handleCollect(item)" @click.stop="handleCollect(item)"
> >
<el-icon> <el-icon class="mr-0.5">
<IEpStarFilled v-show="item.hasCollect" /> <IEpStarFilled v-show="item.hasCollect" />
<IEpStar v-show="!item.hasCollect" /> <IEpStar v-show="!item.hasCollect" />
</el-icon> </el-icon>
{{ item.hasCollect ? '已关注' : '关注' }} {{ item.hasCollect ? '已关注' : '关注' }}
</el-button> </el-button>
<!-- 回答按钮保持不变 --> <el-button
<!-- 当前最热评论的评论有几条 --> size="small"
<el-button size="small" plain @click.stop="handleComment(item, index)"> plain
<el-icon><IEpEdit /></el-icon> class="rounded-lg"
@click.stop="handleComment(item, index)"
>
<el-icon class="mr-0.5"><IEpEdit /></el-icon>
<template v-if="item.cultureCommentListVo?.childNum"> <template v-if="item.cultureCommentListVo?.childNum">
{{ item.cultureCommentListVo?.childNum }}条评论 {{ item.cultureCommentListVo?.childNum }}条评论
</template> </template>
<template v-else> <template v-else>写评论</template>
<span>写评论</span>
</template>
</el-button> </el-button>
<ActionMore class="ml-4" :articleDetail="item" /> <ActionMore class="ml-1" :articleDetail="item" />
</div> </div>
</div> </div>
<!-- 右侧:统计信息 -->
<div class="flex items-center">
<!-- 浏览量 -->
<!-- <el-button text class="flex items-center gap-2 text-gray-500">
<el-icon><IEpView /></el-icon>
<span class="text-sm">{{ item.viewCount || 0 }}</span>
</el-button> -->
<!-- 收藏 -->
<!-- <el-button
text
class="flex items-center gap-2 text-gray-500 transition-colors"
@click.stop="handleCollect(item)"
>
<el-icon :color="item.hasCollect ? '#409EFF' : '#999'"><IEpStar /></el-icon>
<span class="text-sm" :class="{ 'text-blue-500': item.hasCollect }">{{
item.collectionCount || 0
}}</span>
</el-button> -->
<!-- 评论 -->
<!-- <el-button
text
class="flex items-center gap-2 text-gray-500 transition-colors"
@click.stop="handleComment(item, index)"
>
<el-icon><IEpChatDotRound /></el-icon>
<span class="text-sm">{{ item.cultureCommentListVo?.childNum || 0 }}</span>
</el-button> -->
</div>
</div> </div>
<Transition name="fadeCommentBox" mode="out-in"> <Transition name="fadeCommentBox" mode="out-in">
<Comment <Comment
...@@ -184,7 +141,7 @@ ...@@ -184,7 +141,7 @@
@commentSuccess="() => handleCommentSuccess(item)" @commentSuccess="() => handleCommentSuccess(item)"
/> />
</Transition> </Transition>
</el-card> </div>
</div> </div>
<!-- 底部分页 --> <!-- 底部分页 -->
<div class="bottom-pagination backdrop-blur-8 border-t border-gray-200"> <div class="bottom-pagination backdrop-blur-8 border-t border-gray-200">
......
...@@ -5,27 +5,30 @@ ...@@ -5,27 +5,30 @@
<div <div
v-for="item in list" v-for="item in list"
:key="item.id" :key="item.id"
class="relative group bg-white rounded-lg p-6 cursor-pointer transition-all duration-300 hover:shadow-lg hover:shadow-gray-100 hover:-translate-y-1 border border-gray-100 hover:border-gray-200 mb-3 sm:mb-4" class="relative group bg-white rounded-lg p-4 cursor-pointer transition-all duration-300 hover:shadow-lg hover:shadow-gray-100 hover:-translate-y-1 border border-gray-100 hover:border-gray-200 mb-3 sm:mb-4"
@click="jumpToArticleDetailPage({ type: item.type, id: item.id })" @click="jumpToArticleDetailPage({ type: item.type, id: item.id })"
> >
<div class="flex gap-3 justify-between"> <!-- 推荐标签 -->
<div v-if="item.isRecommend" class="absolute left-0 top-5">
<div <div
v-if="item.isRecommend" class="h-5.5 pl-2 pr-2.5 flex items-center gap-1 bg-gradient-to-r from-#6366f1 to-#818cf8 rounded-r-full text-white text-11px font-medium shadow-sm"
class="absolute top-0 left-0 w-13 h-6 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
> >
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" /> <svg viewBox="0 0 16 16" class="w-3 h-3 fill-current">
<div class="text-12px text-#000 line-height-12px">推荐</div> <path d="M8 1.3l2 4.1 4.5.7-3.2 3.1.8 4.5L8 11.5l-4.1 2.2.8-4.5L1.5 6.1l4.5-.7z" />
</svg>
推荐
</div> </div>
<!-- 内容区域 --> </div>
<div class="flex gap-3 justify-between">
<div class="flex-1 min-w-0 flex flex-col justify-between h-24"> <div class="flex-1 min-w-0 flex flex-col justify-between h-24">
<!-- 标题 -->
<h2 <h2
class="text-xl font-semibold text-gray-900 line-clamp-1 group-hover:text-blue-600 transition-colors duration-200 leading-tight" class="text-xl font-semibold text-gray-900 line-clamp-1 group-hover:text-blue-600 transition-colors duration-200 leading-tight"
:class="{ 'pl-12': item.isRecommend }"
> >
{{ item.title }} {{ item.title }}
</h2> </h2>
<!-- 内容摘要 -->
<div v-if="!item.content?.includes('</')" class="my-2 space-y-1"> <div v-if="!item.content?.includes('</')" class="my-2 space-y-1">
<p <p
class="text-gray-600 text-sm sm:text-base leading-relaxed line-clamp-1 break-all" class="text-gray-600 text-sm sm:text-base leading-relaxed line-clamp-1 break-all"
...@@ -34,14 +37,11 @@ ...@@ -34,14 +37,11 @@
</p> </p>
</div> </div>
<!-- 统计信息 -->
<div class="flex items-center gap-2 xl:gap-4 text-gray-500 text-xs lg:text-sm"> <div class="flex items-center gap-2 xl:gap-4 text-gray-500 text-xs lg:text-sm">
<!-- 发布人名称和头像 -->
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<el-avatar :size="24" :src="item.showAvatar" /> <el-avatar :size="24" :src="item.showAvatar" />
<span class="text-sm text-gray-500">{{ item.showName }}</span> <span class="text-sm text-gray-500">{{ item.showName }}</span>
</div> </div>
<!-- 时间 -->
<span class="text-gray-500 font-medium ml-0"> <span class="text-gray-500 font-medium ml-0">
<span class="hidden sm:inline">{{ <span class="hidden sm:inline">{{
dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm') dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm')
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
<span class="text-sm text-gray-500">{{ <span class="text-sm text-gray-500">{{
articleTypeListOptions.find((i) => i.value === item.type)?.label articleTypeListOptions.find((i) => i.value === item.type)?.label
}}</span> }}</span>
<!-- 分隔符 -->
<div class="hidden sm:block w-1 h-1 bg-gray-300 rounded-full"></div> <div class="hidden sm:block w-1 h-1 bg-gray-300 rounded-full"></div>
<div class="flex items-center gap-1 hover:text-blue-500 transition-colors"> <div class="flex items-center gap-1 hover:text-blue-500 transition-colors">
<el-icon class="text-sm"><IEpView /></el-icon> <el-icon class="text-sm"><IEpView /></el-icon>
...@@ -71,7 +70,6 @@ ...@@ -71,7 +70,6 @@
</div> </div>
</div> </div>
<!-- 图片区域 -->
<div v-show="item.faceUrl" class="relative flex-shrink-0 w-30 h-20 xl:w-36 xl:h-24"> <div v-show="item.faceUrl" class="relative flex-shrink-0 w-30 h-20 xl:w-36 xl:h-24">
<el-image <el-image
:src="item.faceUrl + '?x-oss-process=image/format,webp'" :src="item.faceUrl + '?x-oss-process=image/format,webp'"
...@@ -81,7 +79,6 @@ ...@@ -81,7 +79,6 @@
class="w-full h-full object-cover rounded-lg sm:rounded-lg group-hover:scale-105 transition-transform duration-300" class="w-full h-full object-cover rounded-lg sm:rounded-lg group-hover:scale-105 transition-transform duration-300"
loading="lazy" loading="lazy"
/> />
<!-- 图片遮罩效果 -->
<div <div
class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-5 rounded-lg sm:rounded-lg transition-all duration-300" class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-5 rounded-lg sm:rounded-lg transition-all duration-300"
></div> ></div>
...@@ -94,12 +91,10 @@ ...@@ -94,12 +91,10 @@
<div class="bottom-pagination backdrop-blur-8 border-t border-gray-200"> <div class="bottom-pagination backdrop-blur-8 border-t border-gray-200">
<div class="max-w-7xl mx-auto py-4"> <div class="max-w-7xl mx-auto py-4">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<!-- 左侧:回到顶部按钮 -->
<div class="left"> <div class="left">
<ScrollTopComp /> <ScrollTopComp />
</div> </div>
<!-- 右侧:分页器 -->
<div class="right"> <div class="right">
<div <div
class="pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-2" class="pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-2"
......
...@@ -5,94 +5,91 @@ ...@@ -5,94 +5,91 @@
<div <div
v-for="(item, index) in list" v-for="(item, index) in list"
:key="index" :key="index"
class="bg-white rounded-lg shadow-sm mb-6 overflow-hidden" class="bg-white rounded-xl shadow-sm mb-6 overflow-hidden border border-gray-100"
:style="{ '--dynamic-color': item.color }" :style="{ '--dynamic-color': item.color }"
> >
<!-- 专栏标题栏 -->
<div <div
class="flex items-center justify-between pr-4 pl-4 pt-2 pb-2 bg-green-50 border-b border-green-100" class="flex items-center justify-between px-5 py-3"
:style="{ backgroundColor: item.color, '--dynamic-color': item.color }" :style="{ backgroundColor: item.color }"
> >
<h3 class="text-lg font-medium text-gray-800 flex items-center"> <h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 mr-2 bg-#444"></span> <span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }} {{ item.title }}
</h3> </h3>
<div <div
class="flex items-center cursor-pointer" class="flex items-center cursor-pointer text-13px text-gray-500 hover:text-indigo-500 transition-colors duration-200"
@click=" @click="
router.push({ router.push({
path: `/columnSearchList/${item.id}`, path: `/columnSearchList/${item.id}`,
query: { query: { columnTitle: item.title },
columnTitle: item.title,
},
}) })
" "
> >
<span class="mr-1 text-14px color-#606266">查看更多 >></span> 查看更多 >>
</div> </div>
</div> </div>
<div class="p-4"> <!-- 内容区 -->
<div class="p-5">
<div <div
v-if="item.yaColumnVoList.length" v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-2 lg:grid-cols-3 gap-4" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5"
> >
<div <div
v-for="i in item.yaColumnVoList" v-for="i in item.yaColumnVoList"
:key="i.articleId" :key="i.articleId"
class="group cursor-pointer" class="group cursor-pointer rounded-lg overflow-hidden border border-transparent hover:border-gray-200 hover:shadow-md transition-all duration-300"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })" @click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
> >
<div class="relative mb-3 overflow-hidden rounded-lg"> <!-- 封面图 -->
<div class="relative overflow-hidden">
<img <img
:src="i.faceUrl" :src="i.faceUrl"
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300" class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/> />
<!-- 推荐角标 -->
<div <div
v-if="i.isRecommend" v-if="i.isRecommend"
class="absolute top--1 left--1 w-15 h-7 z-1000 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg" class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
> >
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" /> <img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div> <div class="text-12px text-#000 line-height-12px">推荐</div>
</div> </div>
<!-- 底部渐变遮罩 -->
<div
class="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
></div>
</div> </div>
<!-- 屏幕变小 标题变小 -->
<div <!-- 文字信息 -->
class="font-medium text-gray-800 mb-2 transition-colors line-clamp-1 text-sm xl:text-lg" <div class="p-3">
> <div
{{ i.title }} class="font-semibold text-gray-800 mb-2.5 line-clamp-1 text-base group-hover:text-indigo-600 transition-colors duration-200"
</div> >
<!-- 因为是富文本 暂时不显示 --> {{ i.title }}
<!-- <p class="text-sm text-gray-500 mb-3 line-clamp-1">
{{ i.content }}
</p> -->
<div class="flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center gap-2">
<span class="flex items-center">
<el-icon class="mr-1">
<IEpView />
</el-icon>
{{ i.viewCount }}
</span>
<span class="flex items-center">
<el-icon class="mr-1">
<IEpChatDotRound />
</el-icon>
{{ i.replyCount }}
</span>
<span class="flex items-center">
<el-icon class="mr-1">
<IEpStar />
</el-icon>
{{ i.collectCount }}
</span>
</div> </div>
<span> <div class="flex items-center justify-between text-xs text-gray-500">
{{ <div class="flex items-center gap-3">
<span class="flex items-center gap-0.5">
<el-icon><IEpView /></el-icon>
{{ i.viewCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpChatDotRound /></el-icon>
{{ i.replyCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpStar /></el-icon>
{{ i.collectCount }}
</span>
</div>
<span class="text-gray-400">{{
smallerThanXl smallerThanXl
? dayjs(i.createTime * 1000).format('YYYY-MM-DD') ? dayjs(i.createTime * 1000).format('YYYY-MM-DD')
: dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') : dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm:ss')
}} }}</span>
</span> </div>
</div> </div>
</div> </div>
</div> </div>
...@@ -151,7 +148,6 @@ import dayjs from 'dayjs' ...@@ -151,7 +148,6 @@ import dayjs from 'dayjs'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { jumpToArticleDetailPage } from '@/utils' import { jumpToArticleDetailPage } from '@/utils'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core' import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
console.log(breakpointsTailwind, 'breakpointsTailwind')
const breakpoints = useBreakpoints(breakpointsTailwind) const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl') const smallerThanXl = breakpoints.smaller('xl')
......
...@@ -5,46 +5,39 @@ ...@@ -5,46 +5,39 @@
<div <div
v-for="(item, index) in list" v-for="(item, index) in list"
:key="index" :key="index"
class="bg-white rounded-lg shadow-sm mb-6 overflow-hidden" class="bg-white rounded-xl shadow-sm mb-6 overflow-hidden border border-gray-100"
:style="{ '--dynamic-color': item.color }" :style="{ '--dynamic-color': item.color }"
> >
<!-- 专栏标题栏 -->
<div <div
class="flex items-center justify-between pr-4 pl-4 pt-2 pb-2 bg-green-50 border-b border-green-100" class="flex items-center justify-between px-5 py-3"
:style="{ backgroundColor: item.color, '--dynamic-color': item.color }" :style="{ backgroundColor: item.color }"
> >
<h3 class="text-lg font-medium text-gray-800 flex items-center"> <h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 mr-2 bg-#444"></span> <span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }} {{ item.title }}
</h3> </h3>
<div
class="flex items-center cursor-pointer hover:text-[var(--dynamic-color)]"
@click="
router.push({
path: '/searchPage',
query: {
type: ArticleTypeEnum.INTERVIEW,
},
})
"
></div>
</div> </div>
<div class="p-4"> <!-- 内容区 -->
<div class="p-5">
<div <div
v-if="item.yaColumnVoList.length" v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-2 lg:grid-cols-3 gap-4" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5"
> >
<div <div
v-for="i in item.yaColumnVoList" v-for="i in item.yaColumnVoList"
:key="i.articleId" :key="i.articleId"
class="group cursor-pointer" class="group cursor-pointer rounded-lg overflow-hidden border border-transparent hover:border-gray-200 hover:shadow-md transition-all duration-300"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })" @click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
> >
<div class="relative mb-3 overflow-hidden rounded-lg"> <!-- 封面图 -->
<div class="relative overflow-hidden">
<img <img
:src="i.faceUrl" :src="i.faceUrl"
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300" class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/> />
<!-- 推荐角标 -->
<div <div
v-if="i.isRecommend" v-if="i.isRecommend"
class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg" class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
...@@ -52,42 +45,40 @@ ...@@ -52,42 +45,40 @@
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" /> <img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div> <div class="text-12px text-#000 line-height-12px">推荐</div>
</div> </div>
<!-- 底部渐变遮罩 -->
<div
class="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
></div>
</div> </div>
<div
class="font-medium text-gray-800 mb-2 transition-colors line-clamp-1 text-sm xl:text-lg" <!-- 文字信息 -->
> <div class="p-3">
{{ i.title }} <div
</div> class="font-semibold text-gray-800 mb-2.5 line-clamp-1 text-base group-hover:text-indigo-600 transition-colors duration-200"
<!-- 因为是富文本 暂时不显示 --> >
<!-- <p class="text-xs text-gray-500 mb-3 line-clamp-1"> {{ i.title }}
{{ i.content }} </div>
</p> --> <div class="flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center justify-between text-xs text-gray-400"> <div class="flex items-center gap-3">
<div class="flex items-center space-x-4"> <span class="flex items-center gap-0.5">
<span class="flex items-center"> <el-icon><IEpView /></el-icon>
<el-icon class="mr-1"> {{ i.viewCount }}
<IEpView /> </span>
</el-icon> <span class="flex items-center gap-0.5">
{{ i.viewCount }} <el-icon><IEpChatDotRound /></el-icon>
</span> {{ i.replyCount }}
<span class="flex items-center"> </span>
<el-icon class="mr-1"> <span class="flex items-center gap-0.5">
<IEpChatDotRound /> <el-icon><IEpStar /></el-icon>
</el-icon> {{ i.collectCount }}
{{ i.replyCount }} </span>
</span> </div>
<span class="flex items-center"> <span class="text-gray-400">{{
<el-icon class="mr-1"> smallerThanXl
<IEpStar /> ? dayjs(i.createTime * 1000).format('YYYY-MM-DD')
</el-icon> : dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm:ss')
{{ i.collectCount }} }}</span>
</span>
</div> </div>
<span>{{
smallerThanXl
? dayjs(i.createTime * 1000).format('YYYY-MM-DD')
: dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm:ss')
}}</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -142,14 +133,12 @@ ...@@ -142,14 +133,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { getInterviewList } from '@/api' import { getInterviewList } from '@/api'
import { usePageSearch, useScrollTop } from '@/hooks' import { usePageSearch, useScrollTop } from '@/hooks'
import { TABS_REF_KEY, ArticleTypeEnum } from '@/constants' import { TABS_REF_KEY } from '@/constants'
import { useRouter } from 'vue-router'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { jumpToArticleDetailPage } from '@/utils' import { jumpToArticleDetailPage } from '@/utils'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core' import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind) const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl') const smallerThanXl = breakpoints.smaller('xl')
const router = useRouter()
const tabsRef = inject(TABS_REF_KEY) const tabsRef = inject(TABS_REF_KEY)
const { handleBackTop, ScrollTopComp } = useScrollTop(tabsRef!) const { handleBackTop, ScrollTopComp } = useScrollTop(tabsRef!)
......
...@@ -101,9 +101,11 @@ ...@@ -101,9 +101,11 @@
</div> </div>
</div> </div>
<!-- 内容区域 --> <!-- 内容区域 -->
<div class="bg-white rounded-lg shadow-sm"> <div class="bg-gray-50/80 rounded-lg shadow-sm border border-gray-100">
<!-- 最新标题 --> <!-- 最新标题 -->
<div class="flex items-center justify-between p-4 border-b border-gray-100"> <div
class="flex items-center justify-between p-4 bg-white rounded-t-lg border-b border-gray-100"
>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<div class="w-1 h-6 bg-red-500 rounded"></div> <div class="w-1 h-6 bg-red-500 rounded"></div>
<h2 class="text-lg font-medium"> <h2 class="text-lg font-medium">
...@@ -126,66 +128,59 @@ ...@@ -126,66 +128,59 @@
查看更多 >> 查看更多 >>
</div> </div>
</div> </div>
<div class="divide-y bg-#fff"> <div class="space-y-3 p-4">
<div <div
@click="jumpToArticleDetailPage({ type: ArticleTypeEnum.PRACTICE, id: item.id })"
v-for="item in list" v-for="item in list"
:key="item.id" :key="item.id"
class="p-4 hover:bg-gray-50 transition-colors cursor-pointer pl-8" class="group bg-white rounded-lg p-5 cursor-pointer transition-all duration-300 shadow-sm hover:shadow-lg hover:shadow-gray-100 hover:-translate-y-1 border border-gray-100 hover:border-gray-200"
@click="jumpToArticleDetailPage({ type: ArticleTypeEnum.PRACTICE, id: item.id })"
> >
<div class="flex gap-3 items-center h-100%" style="border-bottom: 1.5px solid #ddd"> <div class="flex gap-4 justify-between">
<!-- 左侧内容 --> <div class="flex-1 min-w-0">
<div class="flex-1"> <h2
<h1 class="font-medium text-gray-800 mb-2 leading-relaxed line-clamp-1 text-lg"> class="text-lg font-semibold text-gray-900 line-clamp-1 group-hover:text-blue-600 transition-colors duration-200 mb-2"
>
{{ item.title }} {{ item.title }}
</h1> </h2>
<!-- 带图片的内容 --> <div class="flex gap-3 mb-3">
<div class="flex gap-3 mb-2 align-center"> <el-image
<img
v-if="item.faceUrl" v-if="item.faceUrl"
:src="item.faceUrl" :src="item.faceUrl"
:alt="item.title" :alt="item.title"
class="w-40 h-25 object-cover rounded-lg flex-shrink-0" fit="cover"
:lazy="true"
class="w-36 h-22 rounded-lg flex-shrink-0 object-cover group-hover:scale-105 transition-transform duration-300 overflow-hidden"
loading="lazy"
/> />
<div class="flex-1 mr-4"> <p class="text-gray-500 text-sm leading-relaxed line-clamp-3 flex-1">
<div class="text-gray-500 text-base leading-relaxed line-clamp-3"> {{ item.content }}
{{ item.content }} </p>
</div>
</div>
</div> </div>
<!-- 互动数据 --> <div class="flex items-center gap-2 xl:gap-4 text-gray-500 text-xs lg:text-sm">
<div class="flex items-center gap-5 text-gray-400 text-sm mb-2"> <div class="flex items-center gap-2">
<div class="flex items-center gap-1"> <el-avatar :size="22" :src="item.showAvatar" />
<el-icon class="text-sm"> <span class="text-sm text-gray-500">{{ item.showName }}</span>
<IEpView />
</el-icon>
<span>{{ item.viewCount }}</span>
</div> </div>
<div class="flex items-center gap-1"> <span class="hidden sm:inline text-gray-400">
<el-icon class="text-sm"> {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm') }}
<IEpChatDotRound /> </span>
</el-icon> <div class="hidden sm:block w-1 h-1 bg-gray-300 rounded-full"></div>
<span>{{ item.replyCount }}</span> <div class="flex items-center gap-1 hover:text-blue-500 transition-colors">
<el-icon class="text-sm"><IEpView /></el-icon>
<span class="font-medium">{{ item.viewCount }}</span>
</div> </div>
<div class="flex items-center gap-1 mr-2"> <div class="flex items-center gap-1 hover:text-red-500 transition-colors">
<el-icon class="text-sm"> <el-icon class="text-sm"><IEpChatDotRound /></el-icon>
<IEpStar /> <span class="font-medium">{{ item.replyCount }}</span>
</el-icon> </div>
<span>{{ item.praiseCount }}</span> <div class="flex items-center gap-1 hover:text-yellow-500 transition-colors">
<el-icon class="text-sm"><IEpStar /></el-icon>
<span class="font-medium">{{ item.praiseCount }}</span>
</div> </div>
<div>{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm') }}</div>
</div> </div>
</div> </div>
<!-- 加一个el-divider -->
<el-divider class="my-1! h-100%!" direction="vertical" />
<!-- 右侧头像 -->
<div class="flex flex-col items-center gap-1 flex-shrink-0 pr-8">
<el-avatar :size="45" :src="item.showAvatar" />
<div class="text-xs text-gray-600 mt-2">{{ item.showName }}</div>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -17,43 +17,35 @@ export default function ExchangeContent( ...@@ -17,43 +17,35 @@ export default function ExchangeContent(
{ item, modelValue }: ExchangeContentProps, { item, modelValue }: ExchangeContentProps,
context: SetupContext<ExchangeContentEvents>, context: SetupContext<ExchangeContentEvents>,
) { ) {
const totalPrice = computed(() => item.price * (modelValue.num || 1))
return ( return (
<div class="exchange-content py-6 px-4"> <div class="py-4">
{/* 商品图片区域 */} {/* 商品信息卡片 */}
<div class="flex justify-center mb-8"> <div class="flex gap-4 p-4 bg-gray-50 rounded-xl mb-5">
<div class="relative"> <div class="w-24 h-24 bg-white rounded-xl overflow-hidden shadow-sm shrink-0
<div class="w-32 h-32 bg-gradient-to-br from-orange-100 to-pink-100 rounded-3xl flex items-center justify-center shadow-lg"> flex items-center justify-center p-2">
<div class="w-20 h-20 bg-white rounded-lg flex items-center justify-center shadow-sm"> <img src={item.imageUrl} alt={item.name}
<img src={item.imageUrl} alt={item.name} class="w-16 h-16 object-contain" /> class="max-w-full max-h-full object-contain rounded-lg" />
</div> </div>
<div class="flex flex-col justify-center min-w-0 gap-1.5">
<div class="text-base font-semibold text-gray-800 line-clamp-2">{item.name}</div>
<div class="flex items-baseline gap-1">
<span class="text-xs text-orange-400">¥</span>
<span class="text-2xl font-bold text-orange-500">{item.price}</span>
<span class="text-xs text-gray-400 ml-1">积分/件</span>
</div> </div>
<div class="absolute -top-2 -right-2 w-7 h-7 bg-blue-500 rounded-full flex items-center justify-center shadow-md"> <div class="text-12px text-gray-400">
<span class="text-white text-sm font-medium">{item.stock}</span> 剩余库存:<span class="text-gray-600 font-medium">{item.stock}</span>
</div> </div>
</div> </div>
</div> </div>
{/* 商品信息 */} {/* 表单区域 */}
<div class="space-y-3 mb-8">
<div class="flex items-center gap-3 px-4">
<div class="w-1.5 h-1.5 bg-gray-400 rounded-full flex-shrink-0"></div>
<span class="text-gray-600 text-sm min-w-12">名称:</span>
<span class="font-medium text-gray-900 flex-1">{item.name}</span>
</div>
<div class="flex items-center gap-3 px-4">
<div class="w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0"></div>
<span class="text-gray-600 text-sm min-w-12">积分:</span>
<span class="font-semibold text-orange-500 text-lg">{item.price}YA币</span>
</div>
</div>
{/* 办公点选择和数量 */}
{item.itemType === ShopGoodsTypeEnum.REAL_GOODS && ( {item.itemType === ShopGoodsTypeEnum.REAL_GOODS && (
<div class=" rounded-lg px-5 mx-2 space-y-4"> <div class="space-y-4 mb-5">
{/* 办公点选择 */}
<div> <div>
<label class="text-gray-700 text-sm font-medium mb-2 block">办公点</label> <label class="text-13px text-gray-600 font-medium mb-2 block">配送办公点</label>
<el-select <el-select
modelValue={modelValue.deliveryInfo} modelValue={modelValue.deliveryInfo}
onUpdate:modelValue={(value: string) => onUpdate:modelValue={(value: string) =>
...@@ -68,9 +60,8 @@ export default function ExchangeContent( ...@@ -68,9 +60,8 @@ export default function ExchangeContent(
</el-select> </el-select>
</div> </div>
{/* 数量选择 */}
<div> <div>
<label class="text-gray-700 text-sm font-medium mb-2 block">选择数量</label> <label class="text-13px text-gray-600 font-medium mb-2 block">兑换数量</label>
<el-input-number <el-input-number
min={1} min={1}
max={item.stock} max={item.stock}
...@@ -78,12 +69,29 @@ export default function ExchangeContent( ...@@ -78,12 +69,29 @@ export default function ExchangeContent(
onUpdate:modelValue={(value: number) => onUpdate:modelValue={(value: number) =>
context.emit('update:modelValue', { ...modelValue, num: value }) context.emit('update:modelValue', { ...modelValue, num: value })
} }
class="w-full" class="w-full!"
controls-position="right" controls-position="right"
/> />
</div> </div>
</div> </div>
)} )}
{/* 费用汇总 */}
<div class="border-t border-dashed border-gray-200 pt-4 mt-4">
<div class="flex items-center justify-between">
<span class="text-sm text-gray-500">
合计扣除
{modelValue.num > 1 && (
<span class="text-gray-400 text-xs ml-1">({item.price} × {modelValue.num})</span>
)}
</span>
<div class="flex items-baseline gap-0.5">
<span class="text-sm text-orange-400">¥</span>
<span class="text-2xl font-bold text-orange-500">{totalPrice.value}</span>
<span class="text-xs text-gray-400 ml-1">积分</span>
</div>
</div>
</div>
</div> </div>
) )
} }
......
...@@ -15,30 +15,40 @@ ...@@ -15,30 +15,40 @@
</div> </div>
<template v-if="virtualGoodsList.length"> <template v-if="virtualGoodsList.length">
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4"> <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
<div <div
v-for="item in virtualGoodsList" v-for="item in virtualGoodsList"
:key="item.id" :key="item.id"
class="group bg-white rounded-lg p-4 flex flex-col items-center shadow-md transition-all duration-200 cursor-pointer border border-gray-200 hover:border-blue-300" class="goods-card group relative bg-white rounded-xl overflow-hidden cursor-pointer border border-gray-200/80 shadow-sm hover:shadow-lg hover:-translate-y-1 transition-all duration-300"
@click="onExchangeGoods(item)" @click="onExchangeGoods(item)"
> >
<div <div
class="w-20 h-20 mb-3 flex items-center justify-center bg-blue-50/50 rounded-lg p-2" class="aspect-square bg-gradient-to-br from-gray-50 to-gray-100/80 overflow-hidden p-5 flex items-center justify-center"
> >
<img <img
:src="item.imageUrl" :src="item.imageUrl"
alt="" alt=""
class="rounded-lg w-full h-full object-contain" class="max-w-full max-h-full object-contain rounded-lg transition-transform duration-300 group-hover:scale-110"
/> />
</div> </div>
<div <div class="p-3.5 border-t border-gray-100">
class="text-sm text-gray-700 mb-3 font-medium text-center line-clamp-2 min-h-[40px]" <div
> class="text-13px text-gray-800 font-medium line-clamp-2 min-h-[36px] leading-snug"
{{ item.name }} >
</div> {{ item.name }}
<div class="bg-blue-600 text-white text-xs px-4 py-1.5 rounded font-medium"> </div>
{{ item.price }} 积分 <div class="mt-2.5 flex items-center justify-between">
<div class="flex items-baseline gap-0.5">
<span class="text-xs text-orange-400 font-medium">¥</span>
<span class="text-xl font-bold text-orange-500">{{ item.price }}</span>
<span class="text-11px text-gray-400 ml-0.5">积分</span>
</div>
<span class="text-11px text-gray-300">库存 {{ item.stock }}</span>
</div>
</div> </div>
<div
class="absolute inset-x-0 bottom-0 h-0.75 bg-gradient-to-r from-indigo-400 to-purple-400 scale-x-0 group-hover:scale-x-100 transition-transform duration-300 origin-left"
></div>
</div> </div>
</div> </div>
...@@ -91,30 +101,40 @@ ...@@ -91,30 +101,40 @@
</div> </div>
<template v-if="realGoodsList.length"> <template v-if="realGoodsList.length">
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4"> <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
<div <div
v-for="item in realGoodsList" v-for="item in realGoodsList"
:key="item.id" :key="item.id"
class="group bg-white rounded-lg p-4 flex flex-col items-center shadow-md transition-all duration-200 cursor-pointer border border-gray-200 hover:border-blue-300" class="goods-card group relative bg-white rounded-xl overflow-hidden cursor-pointer border border-gray-200/80 shadow-sm hover:shadow-lg hover:-translate-y-1 transition-all duration-300"
@click="onExchangeGoods(item)" @click="onExchangeGoods(item)"
> >
<div <div
class="w-20 h-20 mb-3 flex items-center justify-center bg-blue-50/50 rounded-lg p-2" class="aspect-square bg-gradient-to-br from-gray-50 to-gray-100/80 overflow-hidden p-5 flex items-center justify-center"
> >
<img <img
:src="item.imageUrl" :src="item.imageUrl"
alt="" alt=""
class="rounded-lg w-full h-full object-contain" class="max-w-full max-h-full object-contain rounded-lg transition-transform duration-300 group-hover:scale-110"
/> />
</div> </div>
<div <div class="p-3.5 border-t border-gray-100">
class="text-sm text-gray-700 mb-3 font-medium text-center line-clamp-2 min-h-[40px]" <div
> class="text-13px text-gray-800 font-medium line-clamp-2 min-h-[36px] leading-snug"
{{ item.name }} >
</div> {{ item.name }}
<div class="bg-blue-600 text-white text-xs px-4 py-1.5 rounded font-medium"> </div>
{{ item.price }} 积分 <div class="mt-2.5 flex items-center justify-between">
<div class="flex items-baseline gap-0.5">
<span class="text-xs text-orange-400 font-medium">¥</span>
<span class="text-xl font-bold text-orange-500">{{ item.price }}</span>
<span class="text-11px text-gray-400 ml-0.5">积分</span>
</div>
<span class="text-11px text-gray-300">库存 {{ item.stock }}</span>
</div>
</div> </div>
<div
class="absolute inset-x-0 bottom-0 h-0.75 bg-gradient-to-r from-indigo-400 to-purple-400 scale-x-0 group-hover:scale-x-100 transition-transform duration-300 origin-left"
></div>
</div> </div>
</div> </div>
...@@ -287,17 +307,14 @@ const onExchangeGoods = async (item: BackendShopItemDto) => { ...@@ -287,17 +307,14 @@ const onExchangeGoods = async (item: BackendShopItemDto) => {
await ElMessageBox({ await ElMessageBox({
title: 'YA币兑换', title: 'YA币兑换',
customStyle: { customClass: 'exchange-dialog',
width: '1000px',
},
message: () => ( message: () => (
// @ts-ignore // @ts-ignore
<ExchangeContent item={item} v-model={form.value}></ExchangeContent> <ExchangeContent item={item} v-model={form.value}></ExchangeContent>
), ),
confirmButtonText: '确认兑换', confirmButtonText: '确认兑换',
cancelButtonText: '取消', cancelButtonText: '再想想',
showCancelButton: true, showCancelButton: true,
center: true,
beforeClose: async (action, instance, done) => { beforeClose: async (action, instance, done) => {
if (action === 'cancel') return done() if (action === 'cancel') return done()
if (yabiData.value.currentValue < item.price * form.value.num) if (yabiData.value.currentValue < item.price * form.value.num)
...@@ -320,3 +337,44 @@ const onExchangeGoods = async (item: BackendShopItemDto) => { ...@@ -320,3 +337,44 @@ const onExchangeGoods = async (item: BackendShopItemDto) => {
}) })
} }
</script> </script>
<style>
.exchange-dialog {
border-radius: 16px !important;
width: 320px !important;
overflow: hidden;
}
.exchange-dialog .el-message-box__header {
padding: 20px 24px 0;
}
.exchange-dialog .el-message-box__title {
font-size: 16px;
font-weight: 600;
}
.exchange-dialog .el-message-box__content {
padding: 8px 24px;
}
.exchange-dialog .el-message-box__btns {
padding: 8px 24px 20px;
}
.exchange-dialog .el-message-box__btns .el-button--primary {
background: linear-gradient(to right, #6366f1, #8b5cf6);
border: none;
border-radius: 8px;
padding: 8px 28px;
}
.exchange-dialog .el-message-box__btns .el-button--primary:hover {
opacity: 0.9;
}
.exchange-dialog .el-message-box__btns .el-button:not(.el-button--primary) {
border-radius: 8px;
padding: 8px 28px;
}
</style>
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
@click="handleClearCache" @click="handleClearCache"
>清除缓存</el-button >清除缓存</el-button
> >
<el-button type="info" plain size="small" @click="showOnlineTime = !showOnlineTime"
>展示/隐藏在线时长</el-button
>
<el-button <el-button
v-if="officialAccountList.length" v-if="officialAccountList.length"
type="info" type="info"
...@@ -153,7 +156,6 @@ ...@@ -153,7 +156,6 @@
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import EditUserInfo from './components/editUserInfo.vue' import EditUserInfo from './components/editUserInfo.vue'
import { generateLoginKey, hasOfficialAccount } from '@/api' import { generateLoginKey, hasOfficialAccount } from '@/api'
...@@ -162,6 +164,9 @@ import { wxLogin } from '@/utils/wxUtil' ...@@ -162,6 +164,9 @@ import { wxLogin } from '@/utils/wxUtil'
import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router' import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router'
import type { TabPaneName } from 'element-plus' import type { TabPaneName } from 'element-plus'
import { IS_REAL_KEY } from '@/constants/symbolKey' import { IS_REAL_KEY } from '@/constants/symbolKey'
import { useOnlineTimeStore, useUserStore } from '@/stores'
const { showOnlineTime } = storeToRefs(useOnlineTimeStore())
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
......
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