<template>
|
<div style="height: 70vh; overflow: auto">
|
<div v-for="(item, index) in groupedEmails" :key="index">
|
<span class="span-title">{{ `${item.name}(${item.data.length})` }}</span>
|
<vxe-table
|
ref="vxeTableRef"
|
style="margin: 10px 0"
|
:showHeader="false"
|
:data="item.data"
|
size="small"
|
min-height="40px"
|
:row-config="{ isCurrent: true, isHover: true }"
|
:menu-config="tableMenu"
|
@menu-click="contextMenuClickEvent"
|
@cell-click="cellClickEvent"
|
@checkbox-change="selectChangeEvent"
|
>
|
<vxe-column type="checkbox" width="30"></vxe-column>
|
<vxe-column field="sender" title="发件人" data-index="sender" min-width="300px">
|
<template #default="{ row }">
|
<div style="display: flex; align-items: center">
|
<div
|
v-if="row.mailType != 0"
|
class="dot"
|
:class="row.readFlag ? 'dot-color' : ''"
|
@click.stop="fnRowUpdateRead(row)"
|
></div>
|
<a-tooltip placement="bottom">
|
<template #title>
|
<span>陌生人</span>
|
</template>
|
<a-avatar size="small" style="margin-right: 8px" :src="row.avatar" />
|
</a-tooltip>
|
|
<a-popover placement="bottom">
|
<template #content>
|
<div
|
class="p-2"
|
style="
|
display: flex;
|
align-items: center;
|
border-bottom: 1px solid rgb(5 5 5 / 6%);
|
"
|
>
|
<a-avatar size="small" style="margin-right: 8px" :src="row.avatar" />
|
<span style="color: #000; font-weight: 700">{{ row.sender }}</span>
|
<CopyOutlined />
|
</div>
|
<div class="display-flex p-2">
|
<a-button type="link" size="small">新建客户</a-button>
|
<a-dropdown>
|
<a style="margin-right: 5px" class="ant-dropdown-link" @click.prevent>
|
<DownOutlined />
|
</a>
|
<template #overlay>
|
<a-menu>
|
<a-menu-item>
|
<a href="javascript:;">添加到已有客户</a>
|
</a-menu-item>
|
</a-menu>
|
</template>
|
</a-dropdown>
|
<a-button type="link" size="small">添加为线索</a-button>
|
|
<a-dropdown style="margin-right: 5px">
|
<a style="margin-right: 5px" class="ant-dropdown-link" @click.prevent>
|
<DownOutlined />
|
</a>
|
<template #overlay>
|
<a-menu>
|
<a-menu-item>
|
<a href="javascript:;">添加到通讯录</a>
|
</a-menu-item>
|
</a-menu>
|
</template>
|
</a-dropdown>
|
<a-button type="link" size="small">往来邮件</a-button></div
|
>
|
</template>
|
<div class="title-dot" :class="row.readFlag ? 'title-dot-color' : ''">
|
<span style="font-weight: 700">{{ row.senderName }}</span
|
><span style="padding: 0 8px">|</span>
|
<span style="font-weight: 500">{{ row.sender }}</span>
|
</div>
|
</a-popover>
|
</div>
|
</template>
|
</vxe-column>
|
<vxe-column show-overflow field="subject" title="表题" data-index="subject" min-width="250">
|
<template #default="{ row }">
|
<span
|
class="title-dot"
|
:class="row.readFlag ? 'title-dot-color' : ''"
|
style="font-weight: 500"
|
>{{ row.subject || '(无主题)' }}</span
|
>
|
-
|
<span style="color: #999">{{ row.subject }}</span>
|
</template>
|
</vxe-column>
|
<vxe-column field="action" title="Action" width="190">
|
<template #default="{ row, rowIndex }">
|
<span style="display: flex; justify-content: space-around">
|
<span>{{
|
row.mailType !== 0
|
? formatToDateDay(row.receiveTime)
|
: formatToDateDay(row.createTime)
|
}}</span>
|
|
<TooltipAndDropdown
|
:tooltipTitle="'待处理邮件'"
|
:initialDropdownOpen="false"
|
:initialTooltipOpen="false"
|
:showTooltip="!!row.handleTime"
|
:row="row"
|
:docCodeS="[row.docCode]"
|
/>
|
<span style="margin-left: 5px"><PushpinOutlined @click.stop="fnTagging" /></span>
|
</span>
|
</template>
|
</vxe-column>
|
</vxe-table>
|
</div>
|
<DrawerDetail
|
ref="drawerDetailRef"
|
v-model="openDrawerDetail"
|
:mailId="rowMailId"
|
:selectAllRow="selectRow"
|
:allList="dataSource"
|
/>
|
<a-dropdown :trigger="['click']" placement="bottomLeft" ref="dropdownRefs"> </a-dropdown>
|
</div>
|
</template>
|
|
<script lang="ts" setup>
|
name: 'ListPageTable';
|
import {
|
FieldTimeOutlined,
|
PushpinOutlined,
|
CopyOutlined,
|
DownOutlined,
|
} from '@ant-design/icons-vue';
|
|
import { ref, watch, defineProps, defineEmits, computed, defineExpose, inject } from 'vue';
|
|
// 定义属性
|
interface Props {
|
pageList: [];
|
}
|
const props = defineProps<Props>();
|
|
const groupedEmails = ref<GroupedDataItem[]>([]);
|
|
const dataSource = ref([]);
|
watch(
|
() => props.pageList,
|
(newValue) => {
|
dataSource.value = newValue;
|
groupedEmails.value = groupEmailsByDate(newValue);
|
},
|
);
|
import dayjs from 'dayjs';
|
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
|
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
import isoWeek from 'dayjs/plugin/isoWeek';
|
dayjs.extend(isSameOrAfter);
|
dayjs.extend(isSameOrBefore);
|
dayjs.extend(isoWeek);
|
|
interface EmailItem {
|
id: number;
|
subject: string;
|
}
|
|
// 确保 groupedData 的结构正确且 data 是 EmailItem 类型的数组
|
interface GroupedDataItem {
|
key: string;
|
data: EmailItem[];
|
name: string;
|
}
|
|
function groupEmailsByDate(dataSource) {
|
const today = dayjs();
|
const yesterday = dayjs().subtract(1, 'day');
|
const startOfWeek = dayjs().startOf('week');
|
const startOfMonth = dayjs().startOf('month');
|
const startOfLastMonth = dayjs().subtract(1, 'month').startOf('month');
|
const endOfLastMonth = dayjs().subtract(1, 'month').endOf('month');
|
|
const groupedData: GroupedDataItem[] = [
|
{
|
data: [],
|
name: '今天',
|
key: 'today',
|
},
|
{
|
data: [],
|
name: '昨天',
|
key: 'yesterday',
|
},
|
{
|
data: [],
|
name: '本周',
|
key: 'thisWeek',
|
},
|
{
|
data: [],
|
name: '这个月',
|
key: 'thisMonth',
|
},
|
{
|
data: [],
|
name: '上个月',
|
key: 'lastMonth',
|
},
|
{
|
data: [],
|
name: '更早',
|
key: 'earlier',
|
},
|
];
|
|
dataSource.forEach((item: any) => {
|
try {
|
const emailDate = dayjs(item.createTime);
|
if (emailDate.isSame(today, 'day')) {
|
groupedData[0].data.push(item);
|
} else if (emailDate.isSame(yesterday, 'day')) {
|
groupedData[1].data.push(item);
|
} else if (emailDate.isSameOrAfter(startOfWeek) && emailDate.isBefore(today, 'day')) {
|
groupedData[2].data.push(item);
|
} else if (emailDate.isSameOrAfter(startOfMonth) && emailDate.isBefore(today, 'day')) {
|
groupedData[3].data.push(item);
|
} else if (
|
emailDate.isSameOrAfter(startOfLastMonth) &&
|
emailDate.isSameOrBefore(endOfLastMonth)
|
) {
|
groupedData[4].data.push(item);
|
} else {
|
groupedData[5].data.push(item);
|
}
|
} catch (error) {
|
console.error(`Error processing item date: ${item.date}`, error);
|
}
|
});
|
// 将结果按中文映射进行返回
|
const result = <{ data: any; name: string; key: string }[]>[];
|
groupedData.forEach((group: { data: any; name: string; key: string }) => {
|
if (group.data.length > 0) {
|
result.push(group);
|
}
|
});
|
|
return result;
|
}
|
|
// 右键菜单
|
const tableMenu = {
|
className: 'my-menus',
|
body: {
|
options: [
|
[
|
{
|
code: 'reply',
|
name: '回复',
|
},
|
{ code: 'replyAll', name: '回复全部' },
|
{ code: 'replyWithAttachment', name: '带附件回复' },
|
{ code: 'replyAllWithAttachment', name: '带附件回复全部' },
|
{ code: 'forward', name: '转发' },
|
{ code: 'forwardAsAttachment', name: '作为附件转发' },
|
{ code: 'distribute', name: '分发' },
|
{ code: 'setRemark', name: '设置备注' },
|
],
|
[
|
{ code: 'toHandle', name: '待处理' },
|
{ code: 'markAsUnread', name: '标为未读' },
|
{ code: 'labelAs', name: '标注为' },
|
],
|
[
|
{ code: 'newRule', name: '新建收发件规则' },
|
{ code: 'moveTo', name: '移动到' },
|
],
|
[
|
{ code: 'exportEmail', name: '导出邮件' },
|
{ code: 'createFollowUp', name: '建为客户跟进' },
|
{ code: 'createSchedule', name: '新建日程' },
|
],
|
[
|
{ code: 'markAsSpam', name: '标为垃圾邮件' },
|
{ code: 'delete', name: '删除' },
|
],
|
],
|
},
|
};
|
|
function contextMenuClickEvent({ menu, row, column }) {
|
switch (menu.code) {
|
case 'copy':
|
if (row && column) {
|
}
|
break;
|
default:
|
}
|
}
|
const vxeTableRef = ref();
|
function fnSelectAll(is) {
|
vxeTableRef.value.forEach((row) => {
|
row.setAllCheckboxRow(is);
|
});
|
selectChangeEvent();
|
}
|
|
function selectChangeEvent() {
|
const isAll = getCheckboxRecords().length === dataSource.value.length;
|
const data = {
|
isAll,
|
records: getCheckboxRecords(),
|
};
|
emit('updateSelectAll', data);
|
}
|
function getCheckboxRecords() {
|
const list = new Set();
|
|
vxeTableRef.value.forEach((row) => {
|
const records = row.getCheckboxRecords(); // 假设该方法返回一个数组
|
if (Array.isArray(records)) {
|
// 确保 records 是数组
|
records.forEach((record) => list.add(record)); // 将记录添加到 Set 中
|
}
|
});
|
|
return Array.from(list); // 将 Set 转换回数组
|
}
|
// 操作row
|
function fnProcessingTime(row) {
|
console.log(row);
|
}
|
function fnTagging(row) {
|
console.log(row);
|
}
|
import DrawerDetail from './drawerDetail.vue';
|
// 详情内容
|
const openDrawerDetail = ref(false);
|
const rowMailId = ref('');
|
const selectRow = ref([]);
|
const cellClickEvent = (event) => {
|
selectRow.value = [];
|
rowMailId.value = event.row.docCode;
|
selectRow.value.push({ docCode: event.row.docCode });
|
openDrawerDetail.value = true;
|
};
|
|
// 更新祖父组件数据
|
const getDataList = inject('getDataList');
|
console.log(getDataList, '0000004');
|
|
import { updateReadApi, updateHandleAPi } from '@/api/email/userList';
|
// 标志未读/经读
|
function fnRowUpdateRead(row) {
|
const data = {
|
status: !row.readFlag,
|
list: [row.docCode],
|
};
|
pushReadApi(data);
|
}
|
function pushReadApi(params) {
|
updateReadApi(params).then((res) => {
|
if (res.code == 0) {
|
//
|
getDataList({});
|
}
|
});
|
}
|
const emit = defineEmits(['selectAll', 'updateSelectAll']);
|
defineExpose({
|
fnSelectAll,
|
});
|
|
import TooltipAndDropdown from './TooltipAndDropdown .vue';
|
import { formatToDateDay } from '@/utils/dateUtil';
|
</script>
|
<style scoped lang="less">
|
.display-flex {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
|
.head {
|
display: flex;
|
justify-content: space-between;
|
width: 100%;
|
border-bottom: 1px solid rgb(5 5 5 / 6%);
|
|
/* 增加选择器特异性 */
|
& .left {
|
width: 20%;
|
|
& .left-box {
|
display: flex;
|
align-items: center;
|
justify-content: space-flex-start;
|
width: 100%;
|
|
& .icon {
|
margin-right: 15px;
|
font-size: 16px;
|
}
|
}
|
}
|
|
& .right {
|
display: flex;
|
align-items: center;
|
}
|
}
|
|
.left-bt {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
padding-left: 27px;
|
background: #fffbe6;
|
}
|
|
.span-title {
|
padding: 20px;
|
color: #000;
|
font-weight: 700;
|
}
|
|
.table {
|
height: 80vh;
|
}
|
|
.my-menus {
|
background-color: #f8f8f9;
|
}
|
// 圆点
|
.dot {
|
display: inline-block;
|
width: 8px;
|
height: 8px;
|
margin-right: 10px;
|
border-radius: 50%;
|
background-color: #0a6aff;
|
}
|
|
.dot-color {
|
background-color: #d9d9d9;
|
color: #d9d9d9;
|
}
|
|
.title-dot {
|
color: #0a6aff;
|
}
|
|
.title-dot-color {
|
color: #999;
|
}
|
</style>
|