style: improve empty state display for inbox and sent box (#831)

- Add different messages based on mail count (empty vs select)
- Add semantic icons (InboxRound for inbox, SendRound for sent)
- Unify list container height to min-height: 60vh; max-height: 100vh
- Update CHANGELOG for v1.4.0

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Dream Hunter
2026-02-02 23:47:49 +08:00
committed by GitHub
co-authored by Claude Opus 4.5
parent 9583f0e1c5
commit 56351ed963
4 changed files with 22 additions and 7 deletions
+2
View File
@@ -14,6 +14,8 @@
### Improvements ### Improvements
- style: |邮件列表| 优化收件箱和发件箱空状态显示,根据邮件数量显示不同提示信息,添加语义化图标
## v1.3.0 ## v1.3.0
### Features ### Features
+2
View File
@@ -14,6 +14,8 @@
### Improvements ### Improvements
- style: |Mail List| Improve empty state display for inbox and sent box, show different messages based on mail count, add semantic icons
## v1.3.0 ## v1.3.0
### Features ### Features
+9 -4
View File
@@ -3,7 +3,7 @@ import { watch, onMounted, ref, onBeforeUnmount, computed } from "vue";
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../store' import { useGlobalState } from '../store'
import { CloudDownloadRound, ArrowBackIosNewFilled, ArrowForwardIosFilled } from '@vicons/material' import { CloudDownloadRound, ArrowBackIosNewFilled, ArrowForwardIosFilled, InboxRound } from '@vicons/material'
import { useIsMobile } from '../utils/composables' import { useIsMobile } from '../utils/composables'
import { processItem } from '../utils/email-parser' import { processItem } from '../utils/email-parser'
import { utcToLocalDate } from '../utils'; import { utcToLocalDate } from '../utils';
@@ -147,6 +147,7 @@ const { t } = useI18n({
attachments: 'Show Attachments', attachments: 'Show Attachments',
downloadMail: 'Download Mail', downloadMail: 'Download Mail',
pleaseSelectMail: "Please select mail", pleaseSelectMail: "Please select mail",
emptyInbox: "Your inbox is empty",
delete: 'Delete', delete: 'Delete',
deleteMailTip: 'Are you sure you want to delete mail?', deleteMailTip: 'Are you sure you want to delete mail?',
reply: 'Reply', reply: 'Reply',
@@ -171,6 +172,7 @@ const { t } = useI18n({
downloadMail: '下载邮件', downloadMail: '下载邮件',
attachments: '查看附件', attachments: '查看附件',
pleaseSelectMail: "请选择邮件", pleaseSelectMail: "请选择邮件",
emptyInbox: "收件箱为空",
delete: '删除', delete: '删除',
deleteMailTip: '确定要删除邮件吗?', deleteMailTip: '确定要删除邮件吗?',
reply: '回复', reply: '回复',
@@ -446,7 +448,7 @@ onBeforeUnmount(() => {
<n-split class="left" direction="horizontal" :max="0.75" :min="0.25" :default-size="mailboxSplitSize" <n-split class="left" direction="horizontal" :max="0.75" :min="0.25" :default-size="mailboxSplitSize"
:on-update:size="onSpiltSizeChange"> :on-update:size="onSpiltSizeChange">
<template #1> <template #1>
<div style="overflow: auto; min-height: 50vh; max-height: 100vh;"> <div style="overflow: auto; min-height: 60vh; max-height: 100vh;">
<n-list hoverable clickable> <n-list hoverable clickable>
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)" <n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"
:class="mailItemClass(row)"> :class="mailItemClass(row)">
@@ -506,7 +508,10 @@ onBeforeUnmount(() => {
:onDelete="deleteMail" :onReply="replyMail" :onForward="forwardMail" :onSaveToS3="saveToS3Proxy" /> :onDelete="deleteMail" :onReply="replyMail" :onForward="forwardMail" :onSaveToS3="saveToS3Proxy" />
</n-card> </n-card>
<n-card :bordered="false" embedded class="mail-item" v-else> <n-card :bordered="false" embedded class="mail-item" v-else>
<n-result status="info" :title="t('pleaseSelectMail')"> <n-result status="info" :title="count === 0 ? t('emptyInbox') : t('pleaseSelectMail')">
<template #icon>
<n-icon :component="InboxRound" :size="100" />
</template>
</n-result> </n-result>
</n-card> </n-card>
</template> </template>
@@ -531,7 +536,7 @@ onBeforeUnmount(() => {
<n-input v-model:value="localFilterKeyword" <n-input v-model:value="localFilterKeyword"
:placeholder="t('keywordQueryTip')" size="small" clearable /> :placeholder="t('keywordQueryTip')" size="small" clearable />
</div> </div>
<div style="overflow: auto; height: 80vh;"> <div style="overflow: auto; min-height: 60vh; max-height: 100vh;">
<n-list hoverable clickable> <n-list hoverable clickable>
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"> <n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)">
<n-thing :title="row.subject"> <n-thing :title="row.subject">
+9 -3
View File
@@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../store' import { useGlobalState } from '../store'
import { useIsMobile } from '../utils/composables' import { useIsMobile } from '../utils/composables'
import { utcToLocalDate } from '../utils'; import { utcToLocalDate } from '../utils';
import { SendRound } from '@vicons/material'
const message = useMessage() const message = useMessage()
const isMobile = useIsMobile() const isMobile = useIsMobile()
@@ -52,6 +53,7 @@ const { t } = useI18n({
refresh: 'Refresh', refresh: 'Refresh',
showCode: 'Change View Original Code', showCode: 'Change View Original Code',
pleaseSelectMail: "Please select a mail to view.", pleaseSelectMail: "Please select a mail to view.",
emptySent: "No sent emails",
delete: 'Delete', delete: 'Delete',
deleteMailTip: 'Are you sure you want to delete mail?', deleteMailTip: 'Are you sure you want to delete mail?',
multiAction: 'Multi Action', multiAction: 'Multi Action',
@@ -64,6 +66,7 @@ const { t } = useI18n({
refresh: '刷新', refresh: '刷新',
showCode: '切换查看元数据', showCode: '切换查看元数据',
pleaseSelectMail: "请选择一封邮件查看。", pleaseSelectMail: "请选择一封邮件查看。",
emptySent: "发件箱为空",
delete: '删除', delete: '删除',
deleteMailTip: '确定要删除邮件吗?', deleteMailTip: '确定要删除邮件吗?',
multiAction: '多选', multiAction: '多选',
@@ -239,7 +242,7 @@ onMounted(async () => {
<n-split direction="horizontal" :max="0.75" :min="0.25" :default-size="mailboxSplitSize" <n-split direction="horizontal" :max="0.75" :min="0.25" :default-size="mailboxSplitSize"
:on-update:size="onSpiltSizeChange"> :on-update:size="onSpiltSizeChange">
<template #1> <template #1>
<div style="overflow: auto; height: 80vh;"> <div style="overflow: auto; min-height: 60vh; max-height: 100vh;">
<n-list hoverable clickable> <n-list hoverable clickable>
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)" <n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"
:class="mailItemClass(row)"> :class="mailItemClass(row)">
@@ -297,7 +300,10 @@ onMounted(async () => {
<div v-else v-html="curMail.content" style="margin-top: 10px;"></div> <div v-else v-html="curMail.content" style="margin-top: 10px;"></div>
</n-card> </n-card>
<n-card :bordered="false" embedded class="mail-item" v-else> <n-card :bordered="false" embedded class="mail-item" v-else>
<n-result status="info" :title="t('pleaseSelectMail')"> <n-result status="info" :title="count === 0 ? t('emptySent') : t('pleaseSelectMail')">
<template #icon>
<n-icon :component="SendRound" :size="100" />
</template>
</n-result> </n-result>
</n-card> </n-card>
</template> </template>
@@ -312,7 +318,7 @@ onMounted(async () => {
{{ t('refresh') }} {{ t('refresh') }}
</n-button> </n-button>
</div> </div>
<div style="overflow: auto; height: 80vh;"> <div style="overflow: auto; min-height: 60vh; max-height: 100vh;">
<n-list hoverable clickable> <n-list hoverable clickable>
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"> <n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)">
<n-thing :title="row.subject"> <n-thing :title="row.subject">