133 lines
3.3 KiB
Vue
133 lines
3.3 KiB
Vue
<template>
|
|
<a-spin style="display: block" :loading="loading">
|
|
<a-tabs v-model:activeKey="messageType" type="rounded" destroy-on-hide>
|
|
<a-tab-pane v-for="item in tabList" :key="item.key">
|
|
<template #title>
|
|
<span> {{ item.title }}{{ formatUnreadLength(item.key) }} </span>
|
|
</template>
|
|
<a-result v-if="!renderList.length" status="404">
|
|
<template #subtitle> {{ $t('messageBox.noContent') }} </template>
|
|
</a-result>
|
|
<List
|
|
:render-list="renderList"
|
|
:unread-count="unreadCount"
|
|
@item-click="handleItemClick"
|
|
/>
|
|
</a-tab-pane>
|
|
<template #extra>
|
|
<a-button type="text" @click="emptyList">
|
|
{{ $t('messageBox.tab.button') }}
|
|
</a-button>
|
|
</template>
|
|
</a-tabs>
|
|
</a-spin>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, reactive, toRefs, computed } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import {
|
|
queryMessageList,
|
|
setMessageStatus,
|
|
MessageRecord,
|
|
MessageListType,
|
|
} from '@/api/message';
|
|
import useLoading from '@/hooks/loading';
|
|
import List from './list.vue';
|
|
|
|
interface TabItem {
|
|
key: string;
|
|
title: string;
|
|
avatar?: string;
|
|
}
|
|
const { loading, setLoading } = useLoading(true);
|
|
const messageType = ref('message');
|
|
const { t } = useI18n();
|
|
const messageData = reactive<{
|
|
renderList: MessageRecord[];
|
|
messageList: MessageRecord[];
|
|
}>({
|
|
renderList: [],
|
|
messageList: [],
|
|
});
|
|
toRefs(messageData);
|
|
const tabList: TabItem[] = [
|
|
{
|
|
key: 'message',
|
|
title: t('messageBox.tab.title.message'),
|
|
},
|
|
{
|
|
key: 'notice',
|
|
title: t('messageBox.tab.title.notice'),
|
|
},
|
|
{
|
|
key: 'todo',
|
|
title: t('messageBox.tab.title.todo'),
|
|
},
|
|
];
|
|
async function fetchSourceData() {
|
|
setLoading(true);
|
|
try {
|
|
const { data } = await queryMessageList();
|
|
messageData.messageList = data;
|
|
} catch (err) {
|
|
// you can report use errorHandler or other
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
async function readMessage(data: MessageListType) {
|
|
const ids = data.map((item) => item.id);
|
|
await setMessageStatus({ ids });
|
|
fetchSourceData();
|
|
}
|
|
const renderList = computed(() => {
|
|
return messageData.messageList.filter(
|
|
(item) => messageType.value === item.type
|
|
);
|
|
});
|
|
const unreadCount = computed(() => {
|
|
return renderList.value.filter((item) => !item.status).length;
|
|
});
|
|
const getUnreadList = (type: string) => {
|
|
const list = messageData.messageList.filter(
|
|
(item) => item.type === type && !item.status
|
|
);
|
|
return list;
|
|
};
|
|
const formatUnreadLength = (type: string) => {
|
|
const list = getUnreadList(type);
|
|
return list.length ? `(${list.length})` : ``;
|
|
};
|
|
const handleItemClick = (items: MessageListType) => {
|
|
if (renderList.value.length) readMessage([...items]);
|
|
};
|
|
const emptyList = () => {
|
|
messageData.messageList = [];
|
|
};
|
|
fetchSourceData();
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
:deep(.arco-popover-popup-content) {
|
|
padding: 0;
|
|
}
|
|
|
|
:deep(.arco-list-item-meta) {
|
|
align-items: flex-start;
|
|
}
|
|
|
|
:deep(.arco-tabs-nav) {
|
|
padding: 14px 0 12px 16px;
|
|
border-bottom: 1px solid var(--color-neutral-3);
|
|
}
|
|
|
|
:deep(.arco-tabs-content) {
|
|
padding-top: 0;
|
|
|
|
.arco-result-subtitle {
|
|
color: rgb(var(--gray-6));
|
|
}
|
|
}
|
|
</style>
|