Merge pull request #894 from nagisa77/codex/migrate-components-to-iconpark

refactor: migrate placeholders to IconPark
This commit is contained in:
Tim
2025-09-06 02:02:51 +08:00
committed by GitHub
8 changed files with 31 additions and 24 deletions

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="base-placeholder"> <div class="base-placeholder">
<i :class="['base-placeholder-icon', icon]" /> <component :is="icon" class="base-placeholder-icon" theme="outline" size="48" />
<div class="base-placeholder-text"> <div class="base-placeholder-text">
<slot>{{ text }}</slot> <slot>{{ text }}</slot>
</div> </div>
@@ -12,7 +12,7 @@ export default {
name: 'BasePlaceholder', name: 'BasePlaceholder',
props: { props: {
text: { type: String, default: '' }, text: { type: String, default: '' },
icon: { type: String, default: 'fas fa-inbox' }, icon: { type: String, default: 'Inbox' },
}, },
} }
</script> </script>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="user-list"> <div class="user-list">
<BasePlaceholder v-if="users.length === 0" text="暂无用户" icon="fas fa-inbox" /> <BasePlaceholder v-if="users.length === 0" text="暂无用户" icon="Inbox" />
<div v-for="u in users" :key="u.id" class="user-item" @click="handleUserClick(u)"> <div v-for="u in users" :key="u.id" class="user-item" @click="handleUserClick(u)">
<BaseImage :src="u.avatar" alt="avatar" class="user-avatar" /> <BaseImage :src="u.avatar" alt="avatar" class="user-avatar" />
<div class="user-info"> <div class="user-info">

View File

@@ -56,7 +56,7 @@
<BasePlaceholder <BasePlaceholder
v-if="messages.length === 0" v-if="messages.length === 0"
text="暂无会话,发送消息试试 🎉" text="暂无会话,发送消息试试 🎉"
icon="fas fa-inbox" icon="Inbox"
/> />
</div> </div>
</template> </template>
@@ -351,9 +351,9 @@ onMounted(async () => {
}) })
const subscribeToConversation = () => { const subscribeToConversation = () => {
if (!currentUser.value) return; if (!currentUser.value) return
const destination = `/topic/conversation/${conversationId}` const destination = `/topic/conversation/${conversationId}`
subscribe(destination, async (message) => { subscribe(destination, async (message) => {
try { try {
const parsedMessage = JSON.parse(message.body) const parsedMessage = JSON.parse(message.body)
@@ -370,12 +370,12 @@ const subscribeToConversation = () => {
await markConversationAsRead() await markConversationAsRead()
await nextTick() await nextTick()
if (isUserNearBottom.value) { if (isUserNearBottom.value) {
scrollToBottomSmooth() scrollToBottomSmooth()
} }
} catch (e) { } catch (e) {
console.error("Failed to parse websocket message", e) console.error('Failed to parse websocket message', e)
} }
}) })
} }
@@ -394,7 +394,7 @@ onActivated(async () => {
await nextTick() await nextTick()
scrollToBottomSmooth() scrollToBottomSmooth()
updateNearBottom() updateNearBottom()
if (isConnected.value) { if (isConnected.value) {
// 如果已连接,重新订阅 // 如果已连接,重新订阅
subscribeToConversation() subscribeToConversation()

View File

@@ -22,7 +22,7 @@
</div> </div>
<div v-if="!loading && conversations.length === 0" class="empty-container"> <div v-if="!loading && conversations.length === 0" class="empty-container">
<BasePlaceholder v-if="conversations.length === 0" text="暂无会话" icon="fas fa-inbox" /> <BasePlaceholder v-if="conversations.length === 0" text="暂无会话" icon="Inbox" />
</div> </div>
<div <div
@@ -73,7 +73,7 @@
</div> </div>
<div v-else> <div v-else>
<div v-if="channels.length === 0" class="empty-container"> <div v-if="channels.length === 0" class="empty-container">
<BasePlaceholder text="暂无频道" icon="fas fa-inbox" /> <BasePlaceholder text="暂无频道" icon="Inbox" />
</div> </div>
<div <div
v-for="ch in channels" v-for="ch in channels"
@@ -273,9 +273,9 @@ onActivated(async () => {
}) })
const subscribeToUserMessages = () => { const subscribeToUserMessages = () => {
if (!currentUser.value) return; if (!currentUser.value) return
const destination = `/topic/user/${currentUser.value.id}/messages` const destination = `/topic/user/${currentUser.value.id}/messages`
subscribe(destination, (message) => { subscribe(destination, (message) => {
if (activeTab.value === 'messages') { if (activeTab.value === 'messages') {
fetchConversations() fetchConversations()

View File

@@ -14,8 +14,12 @@
<div class="message-control-container"> <div class="message-control-container">
<div class="message-control-title">通知设置</div> <div class="message-control-title">通知设置</div>
<div class="message-control-item-container"> <div class="message-control-item-container">
<template v-for="pref in notificationPrefs"> <template v-for="pref in notificationPrefs">
<div v-if="canShowNotification(pref.type)" :key="pref.type" class="message-control-item"> <div
v-if="canShowNotification(pref.type)"
:key="pref.type"
class="message-control-item"
>
<div class="message-control-item-label">{{ formatType(pref.type) }}</div> <div class="message-control-item-label">{{ formatType(pref.type) }}</div>
<BaseSwitch <BaseSwitch
:model-value="pref.enabled" :model-value="pref.enabled"
@@ -47,7 +51,7 @@
<BasePlaceholder <BasePlaceholder
v-else-if="notifications.length === 0" v-else-if="notifications.length === 0"
text="暂时没有消息 :)" text="暂时没有消息 :)"
icon="fas fa-inbox" icon="Inbox"
/> />
<div class="timeline-container" v-if="notifications.length > 0"> <div class="timeline-container" v-if="notifications.length > 0">
@@ -757,7 +761,12 @@ const formatType = (t) => {
const isAdmin = computed(() => authState.role === 'ADMIN') const isAdmin = computed(() => authState.role === 'ADMIN')
const needAdminSet = new Set(['POST_REVIEW_REQUEST','REGISTER_REQUEST', 'POINT_REDEEM', 'ACTIVITY_REDEEM']) const needAdminSet = new Set([
'POST_REVIEW_REQUEST',
'REGISTER_REQUEST',
'POINT_REDEEM',
'ACTIVITY_REDEEM',
])
const canShowNotification = (type) => { const canShowNotification = (type) => {
return !needAdminSet.has(type) || isAdmin.value return !needAdminSet.has(type) || isAdmin.value

View File

@@ -63,11 +63,7 @@
<div class="loading-points-container" v-if="historyLoading"> <div class="loading-points-container" v-if="historyLoading">
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch> <l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
</div> </div>
<BasePlaceholder <BasePlaceholder v-else-if="histories.length === 0" text="暂无积分记录" icon="Inbox" />
v-else-if="histories.length === 0"
text="暂无积分记录"
icon="fas fa-inbox"
/>
<div class="timeline-container" v-else> <div class="timeline-container" v-else>
<BaseTimeline :items="histories"> <BaseTimeline :items="histories">
<template #item="{ item }"> <template #item="{ item }">

View File

@@ -207,7 +207,7 @@
<BasePlaceholder <BasePlaceholder
v-if="filteredTimelineItems.length === 0" v-if="filteredTimelineItems.length === 0"
text="暂无时间线" text="暂无时间线"
icon="fas fa-inbox" icon="Inbox"
/> />
<div class="timeline-list"> <div class="timeline-list">
<BaseTimeline :items="filteredTimelineItems"> <BaseTimeline :items="filteredTimelineItems">
@@ -305,7 +305,7 @@
</BaseTimeline> </BaseTimeline>
</div> </div>
<div v-else> <div v-else>
<BasePlaceholder text="暂无收藏文章" icon="fas fa-inbox" /> <BasePlaceholder text="暂无收藏文章" icon="Inbox" />
</div> </div>
</div> </div>

View File

@@ -36,6 +36,7 @@ import {
MessageOne, MessageOne,
AlarmClock, AlarmClock,
Bookmark, Bookmark,
Inbox,
LoadingFour, LoadingFour,
Mail, Mail,
Lock, Lock,
@@ -79,6 +80,7 @@ export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('MessageOne', MessageOne) nuxtApp.vueApp.component('MessageOne', MessageOne)
nuxtApp.vueApp.component('AlarmClock', AlarmClock) nuxtApp.vueApp.component('AlarmClock', AlarmClock)
nuxtApp.vueApp.component('Bookmark', Bookmark) nuxtApp.vueApp.component('Bookmark', Bookmark)
nuxtApp.vueApp.component('Inbox', Inbox)
nuxtApp.vueApp.component('LoadingFour', LoadingFour) nuxtApp.vueApp.component('LoadingFour', LoadingFour)
nuxtApp.vueApp.component('UserIcon', User) nuxtApp.vueApp.component('UserIcon', User)
nuxtApp.vueApp.component('Mail', Mail) nuxtApp.vueApp.component('Mail', Mail)