feat: 修改样式
This commit is contained in:
+58
-127
@@ -1,85 +1,31 @@
|
||||
'use client';
|
||||
|
||||
import { Empty } from '@/components/empty';
|
||||
import { ProList } from '@/components/pro-list';
|
||||
import { queryAnnouncement } from '@/services/user/announcement';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
ColumnFiltersState,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
PaginationState,
|
||||
useReactTable,
|
||||
} from '@tanstack/react-table';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@workspace/airo-ui/components/dialog';
|
||||
import { Pagination } from '@workspace/airo-ui/custom-components/pro-table/pagination';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useImperativeHandle, useRef, useState } from 'react';
|
||||
import { Popup, PopupData, PopupRef } from './Popup';
|
||||
import { Popup } from './Popup';
|
||||
|
||||
export interface AnnouncementItem {
|
||||
id: number;
|
||||
title: string;
|
||||
content: string;
|
||||
pinned?: boolean;
|
||||
}
|
||||
|
||||
export interface DialogRef {
|
||||
export interface AnnouncementDialogRef {
|
||||
open: () => void;
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
interface DialogProps {
|
||||
ref?: React.Ref<DialogRef>;
|
||||
interface AnnouncementDialogProps {
|
||||
ref?: React.Ref<AnnouncementDialogRef>;
|
||||
}
|
||||
|
||||
export const AnnouncementDialog = ({ ref }: DialogProps) => {
|
||||
const t = useTranslations('dashboard');
|
||||
export const AnnouncementDialog = ({ ref }: AnnouncementDialogProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||
const popupRef = useRef<PopupRef>(null);
|
||||
|
||||
const { data: announcementData, isLoading } = useQuery({
|
||||
queryKey: ['queryAnnouncement', pagination.pageIndex + 1, pagination.pageSize],
|
||||
queryFn: async () => {
|
||||
const { data } = await queryAnnouncement({
|
||||
page: pagination.pageIndex + 1,
|
||||
size: pagination.pageSize,
|
||||
pinned: true,
|
||||
popup: true,
|
||||
});
|
||||
return {
|
||||
list: data.data?.announcements || [],
|
||||
total: data.data?.total || 0,
|
||||
};
|
||||
},
|
||||
enabled: open, // 只在弹窗打开时查询数据
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: announcementData?.list || [],
|
||||
columns: [],
|
||||
onPaginationChange: setPagination,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
state: {
|
||||
columnFilters,
|
||||
pagination,
|
||||
},
|
||||
manualPagination: true,
|
||||
manualFiltering: true,
|
||||
rowCount: announcementData?.total || 0,
|
||||
});
|
||||
const t = useTranslations('dashboard');
|
||||
const popupRef = useRef(null);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: () => {
|
||||
@@ -90,73 +36,58 @@ export const AnnouncementDialog = ({ ref }: DialogProps) => {
|
||||
},
|
||||
}));
|
||||
|
||||
const handleOpenPopup = (item: AnnouncementItem) => {
|
||||
const popupData: PopupData = {
|
||||
title: item.title,
|
||||
content: item.content,
|
||||
};
|
||||
popupRef.current?.open(popupData);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className='flex flex-col sm:grid sm:max-w-[600px]'>
|
||||
<DialogHeader>
|
||||
<DialogTitle className={'text-left text-2xl sm:text-4xl'}>
|
||||
{t('announcementTitle')}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className='overflow-y-auto sm:max-w-[800px]'>
|
||||
<DialogHeader>
|
||||
<DialogTitle className='text-left text-2xl sm:text-4xl'>
|
||||
{t('announcementTitle')}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className='space-y-4'>
|
||||
{isLoading ? (
|
||||
<div className='py-8 text-center'>{t('loading')}</div>
|
||||
) : (
|
||||
<>
|
||||
{announcementData?.list?.map((item: AnnouncementItem) => {
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className='flex items-center rounded-[20px] bg-[#B5C9E2] px-4 py-2 sm:p-4'
|
||||
<div className='mt-6'>
|
||||
<ProList<API.Announcement, Record<string, unknown>>
|
||||
request={async (pagination, filter) => {
|
||||
const response = await queryAnnouncement({
|
||||
...pagination,
|
||||
...filter,
|
||||
pinned: false,
|
||||
popup: false,
|
||||
});
|
||||
return {
|
||||
list: response.data.data?.announcements || [],
|
||||
total: response.data.data?.total || 0,
|
||||
};
|
||||
}}
|
||||
renderItem={(item) => {
|
||||
return (
|
||||
<div
|
||||
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2 shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)]`}
|
||||
>
|
||||
<p
|
||||
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
||||
>
|
||||
{item.pinned && (
|
||||
<span className={'text-[#225BA9]'}>{t('pinnedAnnouncement')}</span>
|
||||
)}
|
||||
<span>{item.content}</span>
|
||||
</p>
|
||||
<div className='ml-2 w-[65px] text-right'>
|
||||
<span
|
||||
className='cursor-pointer text-xs text-[#225BA9] sm:text-sm'
|
||||
onClick={() => popupRef.current?.open(item)}
|
||||
>
|
||||
<p className='line-clamp-2 flex-1 text-[10px] text-[#225BA9] sm:text-sm'>
|
||||
{item.pinned && t('pinnedAnnouncement')}{' '}
|
||||
<span className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'}`}>
|
||||
{item.content}
|
||||
</span>
|
||||
</p>
|
||||
<div className='ml-2 w-[65px] text-right'>
|
||||
<span
|
||||
className='cursor-pointer text-xs text-[#225BA9] sm:text-sm'
|
||||
onClick={() => handleOpenPopup(item)}
|
||||
>
|
||||
{t('viewDetails')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 使用 table 的分页器组件 */}
|
||||
{announcementData && announcementData.list && announcementData.list.length > 0 && (
|
||||
<div className='mt-6'>
|
||||
<Pagination
|
||||
table={table}
|
||||
text={{
|
||||
textRowsPerPage: t('rowsPerPage'),
|
||||
textPageOf: (pageIndex, pageCount) =>
|
||||
t('pageOf', { pageIndex: pageIndex, pageCount: pageCount }),
|
||||
}}
|
||||
/>
|
||||
{t('viewDetails')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Popup ref={popupRef} />
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
empty={<Empty />}
|
||||
/>
|
||||
</div>
|
||||
<Popup ref={popupRef} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -65,8 +65,8 @@ export default function Content() {
|
||||
const { data } = await queryAnnouncement({
|
||||
page: 1,
|
||||
size: 4,
|
||||
pinned: true,
|
||||
popup: true,
|
||||
pinned: false,
|
||||
popup: false,
|
||||
});
|
||||
return data.data?.announcements || [];
|
||||
},
|
||||
@@ -246,12 +246,16 @@ export default function Content() {
|
||||
{/* 置顶公告 */}
|
||||
{announcementData?.map((item) => {
|
||||
return (
|
||||
<div className='flex items-center rounded-[20px] bg-[#B5C9E2] px-4 py-2 sm:p-4'>
|
||||
<p className='line-clamp-2 flex-1 text-[10px] text-[#225BA9] sm:text-sm'>
|
||||
{item.pinned && t('pinnedAnnouncement')}{' '}
|
||||
<span className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'}`}>
|
||||
{item.content}
|
||||
</span>
|
||||
<div
|
||||
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2`}
|
||||
>
|
||||
<p
|
||||
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
||||
>
|
||||
{item.pinned && (
|
||||
<span className={'text-[#225BA9]'}>{t('pinnedAnnouncement')}</span>
|
||||
)}
|
||||
<span>{item.content}</span>
|
||||
</p>
|
||||
<div className='ml-2 w-[65px] text-right'>
|
||||
<span
|
||||
|
||||
@@ -41,8 +41,8 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
|
||||
const defaultMetadata = {
|
||||
title: {
|
||||
default: site?.site_name || `PPanel`,
|
||||
template: `%s | ${site?.site_name || 'PPanel'}`,
|
||||
default: site?.site_name || `airoPort`,
|
||||
template: `%s | ${site?.site_name || 'airoPort'}`,
|
||||
},
|
||||
description: site?.site_desc || '',
|
||||
keywords: site?.keywords || '',
|
||||
@@ -60,7 +60,6 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
],
|
||||
apple: site?.site_logo || '/apple-touch-icon.png',
|
||||
},
|
||||
manifest: '/site.webmanifest',
|
||||
};
|
||||
return defaultMetadata;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user