tijiao
This commit is contained in:
@@ -1,147 +1,432 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="crumbs">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item>
|
||||
<i class="el-icon-message"></i> Mailbox list
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="container">
|
||||
<el-tabs tab-position="left" style="height: 200px;">
|
||||
<el-tab-pane :label="'Mail received ( '+queryIn.num+' )'">
|
||||
<div style="margin: 5px 0 20px 10px;">
|
||||
<el-input v-model="queryIn.username" placeholder="Please enter name or email" style="width: 300px;margin: 0 15px 0 0;"></el-input>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearchIn" style="">Search</el-button>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" style="float: right;">Write Letter</el-button>
|
||||
</div>
|
||||
<div style="margin: 0 0 0 10px;">
|
||||
<el-table :data="tableData_in" border ref="multipleTable" header-cell-class-name="table-header" empty-text="New messages (0)">
|
||||
<el-table-column label="Email">
|
||||
<template slot-scope="scope">
|
||||
<img v-if="scope.row.state==0" src="../../assets/img/mes_op.png" alt="" style="vertical-align: text-bottom;margin: 0 6px 0 2px;">
|
||||
<img v-if="scope.row.state==1" src="../../assets/img/mes_ne.png" alt="" style="vertical-align: top;margin: 0 6px 0 0;">
|
||||
{{scope.row.email}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="account" label="Account"></el-table-column>
|
||||
<el-table-column prop="ctime" label="Time" width="100"></el-table-column>
|
||||
<el-table-column label=" " width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button plain type="primary" icon="el-icon-edit" @click="handleDetail(scope.row)">Look</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination">
|
||||
<el-pagination background layout="total, prev, pager, next" :current-page="queryIn.pageIndex" :page-size="queryIn.pageSize"
|
||||
:total="link_TotalIn" @current-change="handlePageChangeIn"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'Mail sent ( '+queryOut.num+' )'">
|
||||
<div style="margin: 5px 0 20px 10px;">
|
||||
<el-input v-model="queryOut.username" placeholder="Please enter name or email" style="width: 300px;margin: 0 15px 0 0;"></el-input>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearchOut" style="">Search</el-button>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" style="float: right;">Write Letter</el-button>
|
||||
</div>
|
||||
<div style="margin: 0 0 0 10px;">
|
||||
<el-table :data="tableData_out" border ref="multipleTable" header-cell-class-name="table-header" empty-text="New messages (0)">
|
||||
<el-table-column prop="email" label="Email"></el-table-column>
|
||||
<el-table-column prop="account" label="Account"></el-table-column>
|
||||
<el-table-column prop="ctime" label="Time" width="100"></el-table-column>
|
||||
<el-table-column label=" " width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button plain type="primary" icon="el-icon-edit" @click="handleDetail(scope.row)">Look</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination">
|
||||
<el-pagination background layout="total, prev, pager, next" :current-page="queryOut.pageIndex" :page-size="queryOut.pageSize"
|
||||
:total="link_TotalOut" @current-change="handlePageChangeIn"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mail-container">
|
||||
<div class="mail-sidebar">
|
||||
<div class="p-20">
|
||||
<el-button type="primary" icon="el-icon-plus" class="write-btn" @click="handleWrite">
|
||||
{{ $t('mailboxCollect.writeBtn') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<ul class="folder-list">
|
||||
<li :class="{ active: currentFolder === 'inbox' }" @click="switchFolder('inbox')">
|
||||
<i class="el-icon-message"></i> {{ $t('mailboxCollect.inboxTab') }}
|
||||
<span class="badge" v-if="queryIn.num > 0">{{ queryIn.num }}</span>
|
||||
</li>
|
||||
<li :class="{ active: currentFolder === 'sent' }" @click="switchFolder('sent')">
|
||||
<i class="el-icon-position"></i><span style="font-size: 14px;">{{ $t('mailboxCollect.outboxTab')}}</span>
|
||||
</li>
|
||||
<li @click="notImplemented"><i class="el-icon-document"></i> <span style="font-size: 14px;">{{ $t('mailboxCollect.draftsTab')}}</span> </li>
|
||||
<li @click="notImplemented"><i class="el-icon-delete"></i> <span style="font-size: 14px;">{{ $t('mailboxCollect.deletedTab')}}</span> </li>
|
||||
</ul>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="user-card">
|
||||
<el-avatar size="small" icon="el-icon-user-solid" class="user-avatar"></el-avatar>
|
||||
<div class="user-detail">
|
||||
<div class="user-name">{{ selectedAccount ? (selectedAccount.smtp_from_name || 'Nova Demo') : '-' }}</div>
|
||||
<div class="user-email" :title="selectedAccountEmail">{{ selectedAccountEmail }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="mini" type="text" @click="openAccountDialog" class="switch-btn">
|
||||
{{ $t('mailboxCollect.changeAccountBtn')}}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="mail-list-panel" :style="{ width: listWidth + 'px' }" v-if="selectedAccount">
|
||||
<div class="panel-header">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
prefix-icon="el-icon-search"
|
||||
:placeholder="$t('mailboxCollect.searchPlaceholder')"
|
||||
clearable
|
||||
@change="handleSearch"
|
||||
></el-input>
|
||||
<el-button icon="el-icon-refresh" circle :loading="syncLoading" @click="handleSyncInbox" style="margin-left: 10px;"></el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="list-scroll-area">
|
||||
<template v-if="displayList.length > 0">
|
||||
<div
|
||||
v-for="item in displayList"
|
||||
:key="item.id"
|
||||
:class="['mail-item-box', { active: activeMailId === item.id, unread: item.state === 1 }]"
|
||||
@click="selectMail(item)"
|
||||
>
|
||||
<div class="item-left">
|
||||
<el-avatar :size="32" icon="el-icon-user-solid" class="sender-avatar"></el-avatar>
|
||||
</div>
|
||||
|
||||
<div class="item-right">
|
||||
<div class="row-one">
|
||||
<span class="sender-name">{{ item.from_name || item.email }}</span>
|
||||
<span class="send-time">{{ formatDisplayTime(item.email_date) }}</span>
|
||||
</div>
|
||||
<div class="row-two">
|
||||
<span class="mail-subject">{{ item.subject || $t('mailboxCollect.noSubject') }}</span>
|
||||
</div>
|
||||
<div class="row-three">
|
||||
<p class="mail-excerpt">{{ stripHtml(item.content || '') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="empty-list-container">
|
||||
<div class="empty-wrapper">
|
||||
<i class="el-icon-message"></i>
|
||||
<p>{{ $t('mailboxCollect.emptyText') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="list-resizer" @mousedown="initResize" v-if="selectedAccount"></div>
|
||||
|
||||
<div class="mail-content-panel" v-if="selectedAccount" v-loading="detailLoading">
|
||||
<template v-if="activeMailId && !detailLoading">
|
||||
<div class="mail-page">
|
||||
<mail-detail
|
||||
v-if="detailMail"
|
||||
:mailData="detailMail"
|
||||
@close="closeDetail"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="empty-state">
|
||||
<div class="empty-wrapper">
|
||||
<i class="el-icon-message"></i>
|
||||
<p>{{ $t('mailboxCollect.selectMailTip') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog :title="$t('mailboxCollect.selectAccountTitle')" :visible.sync="accountDialogVisible" width="600px" append-to-body>
|
||||
<el-form inline style="margin-bottom: 10px;">
|
||||
<el-form-item :label="$t('mailboxCollect.journal')">
|
||||
<el-select v-model="accountJournalId" style="width: 260px;" @change="loadAccountsForJournal">
|
||||
<el-option v-for="item in journalList" :key="item.journal_id" :label="item.title" :value="item.journal_id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="accountList" v-loading="accountLoading" size="small">
|
||||
<el-table-column prop="smtp_user" :label="$t('mailboxCollect.accountColumn')" />
|
||||
<el-table-column prop="smtp_from_name" :label="$t('mailboxCollect.nameColumn')" />
|
||||
<el-table-column :label="$t('mailboxCollect.operation')" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="chooseAccount(scope.row)">
|
||||
{{ $t('mailboxCollect.useBtn') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseUrl: this.Common.baseUrl,
|
||||
mediaUrl: this.Common.mediaUrl,
|
||||
tableData_in: [{
|
||||
state:0,
|
||||
email: '123456',
|
||||
account: '123456',
|
||||
ctime: '123456',
|
||||
},{
|
||||
state:1,
|
||||
email: '123456',
|
||||
account: '123456',
|
||||
ctime: '123456',
|
||||
}],
|
||||
tableData_out: [],
|
||||
queryIn: {
|
||||
pageIndex: 1,
|
||||
pageSize: 15,
|
||||
username: '',
|
||||
num: 10
|
||||
},
|
||||
queryOut: {
|
||||
pageIndex: 1,
|
||||
pageSize: 15,
|
||||
username: '',
|
||||
num: 30
|
||||
},
|
||||
link_TotalIn: 0,
|
||||
link_TotalOut: 0,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getDate();
|
||||
},
|
||||
methods: {
|
||||
// 获取编辑列表数据
|
||||
getDate() {
|
||||
const API = {
|
||||
getInboxList: 'api/email_client/getInboxList',
|
||||
getEmailDetail: 'api/email_client/getEmailDetail',
|
||||
receiveMail: 'api/Mail/receiveMail',
|
||||
getAccounts: 'api/email_client/getAccounts',
|
||||
getOneEmail: 'api/email_client/getOneEmail',
|
||||
getAllJournal: 'api/Journal/getAllJournal',
|
||||
};
|
||||
import MailDetail from '../../components/page/components/email/MailDetail.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentFolder: 'inbox',
|
||||
searchKeyword: '',
|
||||
syncLoading: false,
|
||||
activeMailId: null,
|
||||
tableData_in: [],
|
||||
tableData_out: [],
|
||||
detailMail: {},
|
||||
queryIn: { num: 0 },
|
||||
listWidth: 350,
|
||||
minWidth: 260,
|
||||
maxWidth: 600,
|
||||
selectedAccount: null,
|
||||
accountDialogVisible: false,
|
||||
journalList: [],
|
||||
accountJournalId: null,
|
||||
accountList: [],
|
||||
accountLoading: false,
|
||||
detailLoading: false,
|
||||
};
|
||||
},
|
||||
components: { MailDetail },
|
||||
computed: {
|
||||
displayList() {
|
||||
return this.currentFolder === 'inbox' ? this.tableData_in : this.tableData_out;
|
||||
},
|
||||
selectedAccountEmail() {
|
||||
return this.selectedAccount ? this.selectedAccount.smtp_user : '';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initAccountSelection();
|
||||
},
|
||||
methods: {
|
||||
closeDetail() {
|
||||
this.activeMailId = null;
|
||||
this.detailMail = {};
|
||||
},
|
||||
// 拖拽逻辑
|
||||
initResize(e) {
|
||||
const startX = e.clientX;
|
||||
const startWidth = this.listWidth;
|
||||
const doDrag = (moveEvent) => {
|
||||
const newWidth = startWidth + (moveEvent.clientX - startX);
|
||||
if (newWidth >= this.minWidth && newWidth <= this.maxWidth) {
|
||||
this.listWidth = newWidth;
|
||||
}
|
||||
};
|
||||
const stopDrag = () => {
|
||||
document.removeEventListener('mousemove', doDrag);
|
||||
document.removeEventListener('mouseup', stopDrag);
|
||||
document.body.style.cursor = 'default';
|
||||
};
|
||||
document.addEventListener('mousemove', doDrag);
|
||||
document.addEventListener('mouseup', stopDrag);
|
||||
document.body.style.cursor = 'col-resize';
|
||||
},
|
||||
initAccountSelection() {
|
||||
const q = this.$route.query;
|
||||
if (q.j_email_id) {
|
||||
this.loadAccountById(q.j_email_id);
|
||||
} else {
|
||||
this.openAccountDialog();
|
||||
}
|
||||
},
|
||||
loadAccountById(jEmailId) {
|
||||
this.$api.post(API.getOneEmail, { j_email_id: jEmailId }).then(res => {
|
||||
const email = res.data.email;
|
||||
if (res.code === 0 && email) {
|
||||
this.selectedAccount = email;
|
||||
this.fetchData();
|
||||
} else {
|
||||
this.openAccountDialog();
|
||||
}
|
||||
}).catch(() => this.openAccountDialog());
|
||||
},
|
||||
openAccountDialog() {
|
||||
this.accountDialogVisible = true;
|
||||
this.loadJournals();
|
||||
if (this.selectedAccount.journal_id) {
|
||||
this.accountJournalId = this.selectedAccount.journal_id;
|
||||
this.loadAccountsForJournal(this.selectedAccount.journal_id);
|
||||
}
|
||||
},
|
||||
loadJournals() {
|
||||
this.$api.post(API.getAllJournal, {}).then(res => {
|
||||
this.journalList = (res.data.journals || res.data || []).map(i => ({
|
||||
journal_id: i.journal_id || i.id,
|
||||
title: i.title || i.name || ''
|
||||
}));
|
||||
});
|
||||
},
|
||||
loadAccountsForJournal(id) {
|
||||
this.accountLoading = true;
|
||||
this.$api.post(API.getAccounts, { journal_id: id }).then(res => {
|
||||
this.accountLoading = false;
|
||||
this.accountList = res.data || [];
|
||||
});
|
||||
},
|
||||
chooseAccount(row) {
|
||||
this.selectedAccount = row;
|
||||
this.accountDialogVisible = false;
|
||||
this.closeDetail();
|
||||
this.fetchData();
|
||||
},
|
||||
fetchData() {
|
||||
if (!this.selectedAccount) return;
|
||||
const params = {
|
||||
j_email_id: this.selectedAccount.j_email_id,
|
||||
journal_id: this.selectedAccount.journal_id,
|
||||
keyword: this.searchKeyword || ''
|
||||
};
|
||||
this.$api.post(API.getInboxList, params).then(res => {
|
||||
const list = (res && res.data && (res.data.list || res.data)) || [];
|
||||
this.tableData_in = (Array.isArray(list) ? list : []).map(item => ({
|
||||
id: item.inbox_id || item.id,
|
||||
inbox_id: item.inbox_id || item.id,
|
||||
email: item.from_email,
|
||||
from_name: item.from_name,
|
||||
subject: item.subject,
|
||||
email_date: item.email_date,
|
||||
content: item.content_html || item.content_text || '',
|
||||
state: item.is_read === 1 ? 0 : 1
|
||||
}));
|
||||
this.queryIn.num = this.tableData_in.length;
|
||||
});
|
||||
},
|
||||
switchFolder(f) { this.currentFolder = f; this.activeMailId = null; },
|
||||
selectMail(item) {
|
||||
this.activeMailId = item.id;
|
||||
this.detailLoading = true;
|
||||
const inboxId = item.inbox_id || item.id;
|
||||
this.$api.post(API.getEmailDetail, { inbox_id: inboxId }).then(res => {
|
||||
this.detailLoading = false;
|
||||
const d = res && res.data;
|
||||
if (res && res.code === 0 && d) {
|
||||
this.detailMail = {
|
||||
...d
|
||||
};
|
||||
item.state = 0;
|
||||
}
|
||||
}).catch(() => {
|
||||
this.detailLoading = false;
|
||||
});
|
||||
},
|
||||
handleSyncInbox() {
|
||||
this.syncLoading = true;
|
||||
this.$api.post(API.receiveMail, { j_email_id: this.selectedAccount.j_email_id }).then(() => {
|
||||
this.syncLoading = false;
|
||||
this.fetchData();
|
||||
}).catch(() => this.syncLoading = false);
|
||||
},
|
||||
/**
|
||||
* 格式化邮件显示时间
|
||||
* @param {Number|String} timestamp 后端返回的时间戳 (如: 1773110269)
|
||||
* @returns {String} 格式化后的字符串 (如: 15:57, 昨天, 3月8日, 2025-12-05)
|
||||
*/
|
||||
formatDisplayTime(timestamp) {
|
||||
if (!timestamp) return '';
|
||||
|
||||
},
|
||||
// 搜索-收件箱
|
||||
handleSearchIn() {
|
||||
this.getDate();
|
||||
},
|
||||
// 搜索-发件箱
|
||||
handleSearchOut() {
|
||||
this.getDate();
|
||||
},
|
||||
// 写邮件
|
||||
handleAdd() {
|
||||
// 1. 处理 10 位秒级时间戳,转为毫秒并实例化 Date 对象
|
||||
const date = new Date(Number(timestamp) * 1000);
|
||||
const now = new Date();
|
||||
|
||||
// 提取日期信息用于比较
|
||||
const dateYear = date.getFullYear();
|
||||
const dateMonth = date.getMonth() + 1;
|
||||
const dateDay = date.getDate();
|
||||
const nowYear = now.getFullYear();
|
||||
|
||||
// 获取昨天日期
|
||||
const yesterday = new Date(now);
|
||||
yesterday.setDate(now.getDate() - 1);
|
||||
|
||||
},
|
||||
// 邮箱信息
|
||||
handleDetail(e) {
|
||||
// 获取具体时分并补零 (例如 09:05)
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
const timePart = `${hours}:${minutes}`;
|
||||
|
||||
},
|
||||
// --- 按照图示规则判断返回 ---
|
||||
|
||||
// 分页导航-收件箱
|
||||
handlePageChangeIn(val) {
|
||||
this.$set(this.queryIn, 'pageIndex', val);
|
||||
this.getDate();
|
||||
},
|
||||
// 分页导航-发件箱
|
||||
handlePageChangeOut(val) {
|
||||
this.$set(this.queryOut, 'pageIndex', val);
|
||||
this.getDate();
|
||||
},
|
||||
}
|
||||
};
|
||||
// 1. 如果是今天:只显示时间,如 "15:57"
|
||||
if (date.toDateString() === now.toDateString()) {
|
||||
return timePart;
|
||||
}
|
||||
|
||||
// 2. 如果是昨天:只显示 "昨天"
|
||||
if (date.toDateString() === yesterday.toDateString()) {
|
||||
return '昨天';
|
||||
}
|
||||
|
||||
// 3. 如果是今年(非今天/昨天):显示 "月-日",如 "3月8日"
|
||||
if (dateYear === nowYear) {
|
||||
return `${dateMonth}月${dateDay}日`;
|
||||
}
|
||||
|
||||
// 4. 如果是往年:显示完整年月日,如 "2025-12-05"
|
||||
const fullMonth = dateMonth.toString().padStart(2, '0');
|
||||
const fullDay = dateDay.toString().padStart(2, '0');
|
||||
return `${dateYear}-${fullMonth}-${fullDay}`;
|
||||
},
|
||||
stripHtml(html) { return new DOMParser().parseFromString(html, 'text/html').body.textContent || ""; },
|
||||
handleWrite() {
|
||||
if (!this.selectedAccount) return;
|
||||
this.$router.push(
|
||||
'/mailboxSend?journal_id=' +
|
||||
this.selectedAccount.journal_id +
|
||||
'&j_email_id=' +
|
||||
this.selectedAccount.j_email_id
|
||||
);
|
||||
},
|
||||
handleSearch() { this.fetchData(); },
|
||||
notImplemented() { this.$message.info('开发中...'); }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mail-container {
|
||||
display: flex;
|
||||
height: calc(100vh - 120px);
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
/* 1. 左侧栏 */
|
||||
.mail-sidebar {
|
||||
width: 220px;
|
||||
background-color: #f8f9fa;
|
||||
border-right: 1px solid #eaeaea;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.p-20 { padding: 20px; }
|
||||
.write-btn { width: 100%; border-radius: 8px; font-weight: bold; }
|
||||
.folder-list { list-style: none; padding: 0; margin: 0; flex: 1; }
|
||||
.folder-list li {
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
color: #606266;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.folder-list li i { margin-right: 12px; font-size: 18px; }
|
||||
.folder-list li.active { background: #edeef0; color: #006699; font-weight: bold; border-right: 3px solid #006699; }
|
||||
.badge { margin-left: auto; background: #ddd; padding: 2px 8px; border-radius: 10px; font-size: 12px; }
|
||||
|
||||
.sidebar-footer { padding: 15px 20px; border-top: 1px solid #eee; background: #f8f9fa; }
|
||||
.user-card { display: flex; align-items: center; margin-bottom: 8px; overflow: hidden; }
|
||||
.user-avatar { flex-shrink: 0; background: #ffeded; color: #f56c6c; }
|
||||
.user-detail { margin-left: 10px; overflow: hidden; flex: 1; }
|
||||
.user-name { font-size: 14px; font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.user-email { font-size: 12px; color: #909399; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.switch-btn { padding: 0; font-size: 12px; color: #409eff; }
|
||||
|
||||
/* 2. 中间列表栏 - 参考 image_8649db.png */
|
||||
.mail-list-panel { display: flex; flex-direction: column; flex-shrink: 0; background: #fff; }
|
||||
.panel-header { padding: 15px; border-bottom: 1px solid #f5f5f5; display: flex; }
|
||||
.list-scroll-area { flex: 1; overflow-y: auto; }
|
||||
|
||||
.mail-item-box {
|
||||
display: flex;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mail-item-box:hover { background: #f5f7fa; }
|
||||
.mail-item-box.active { background: #eef1f6; border-left: 3px solid #006699; }
|
||||
.item-left { margin-right: 12px; display: flex; align-items: flex-start; padding-top: 4px; }
|
||||
.sender-avatar { background: #c0c4cc; }
|
||||
.item-right { flex: 1; overflow: hidden; }
|
||||
.row-one { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }
|
||||
.sender-name { font-size: 14px; color: #303133; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.send-time { font-size: 12px; color: #909399; flex-shrink: 0; }
|
||||
.row-two { margin-bottom: 4px; }
|
||||
.mail-subject { font-size: 13px; color: #6a7282; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.mail-excerpt { font-size: 12px; color: #606266; margin: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
|
||||
/* 拖拽条 */
|
||||
.list-resizer { width: 4px; cursor: col-resize; border-left: 1px solid #eaeaea; transition: background 0.2s; }
|
||||
.list-resizer:hover { background: #409eff; }
|
||||
|
||||
/* 3. 右侧详情 */
|
||||
.mail-content-panel { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
|
||||
.detail-toolbar { padding: 10px 20px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; }
|
||||
.detail-content { padding: 30px 40px; overflow-y: auto; }
|
||||
.mail-title { font-size: 24px; margin-bottom: 20px; }
|
||||
.mail-info { display: flex; align-items: center; }
|
||||
.info-main { margin-left: 15px; }
|
||||
.mail-body { line-height: 1.6; font-size: 15px; }
|
||||
.empty-state, .empty-list-container { flex: 1; display: flex; align-items: center; justify-content: center; color: #ccc; text-align: center; }
|
||||
.empty-state i, .empty-list-container i { font-size: 48px; margin-bottom: 10px; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user