feat: 修改样式
125
README.zh-CN.md
@ -1,125 +0,0 @@
|
||||
<a name="readme-top"></a>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img width="160" src="https://raw.githubusercontent.com/perfect-panel/ppanel-assets/refs/heads/main/logo.svg">
|
||||
|
||||
<h1>PPanel 前端</h1>
|
||||
|
||||
这是由 PPanel 提供支持的前端
|
||||
|
||||
[英文](./README.md)
|
||||
·
|
||||
中文
|
||||
·
|
||||
[更新日志](./CHANGELOG.md)
|
||||
·
|
||||
[报告问题][issues-link]
|
||||
·
|
||||
[请求功能][issues-link]
|
||||
|
||||
<!-- SHIELD GROUP -->
|
||||
|
||||
[![][github-release-shield]][github-release-link]
|
||||
[![][github-releasedate-shield]][github-releasedate-link]
|
||||
[![][github-action-test-shield]][github-action-test-link]
|
||||
[![][github-action-release-shield]][github-action-release-link]<br/>
|
||||
[![][github-contributors-shield]][github-contributors-link]
|
||||
[![][github-forks-shield]][github-forks-link]
|
||||
[![][github-stars-shield]][github-stars-link]
|
||||
[![][github-issues-shield]][github-issues-link]
|
||||
[![][github-license-shield]][github-license-link]
|
||||
|
||||
![][split]
|
||||
|
||||
</div>
|
||||
|
||||
## 📦 Application List
|
||||
|
||||
| 📦 Application | 🖼️ Preview |
|
||||
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------- |
|
||||
| [**PPanel User Web**][ppanel-user-web-github]<br/>Developed with modern frontend technologies (Next.js, TypeScript, TailwindCSS), providing basic user features with support for multiple languages and themes.<br/>[][ppanel-user-web-deploy] | [![Preview][ppanel-user-web-cover]][ppanel-user-web-github] |
|
||||
| [**PPanel Admin Web**][ppanel-admin-web-github]<br/>Developed with modern frontend technologies, this admin web provides basic data management features with support for multiple languages and themes.<br/>[][ppanel-admin-web-deploy] | [![Preview][ppanel-admin-web-cover]][ppanel-admin-web-preview] |
|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
您可以使用 Github Codespaces 进行在线开发:
|
||||
|
||||
[![][codespaces-shield]][codespaces-link]
|
||||
|
||||
您可以使用 Gitpod 进行在线开发:
|
||||
|
||||
[][gitpod-link]
|
||||
|
||||
或者克隆项目进行本地开发:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/perfect-panel/ppanel-web.git
|
||||
cd ppanel-web
|
||||
|
||||
# 安装依赖
|
||||
bun install
|
||||
```
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
欢迎各种类型的贡献,
|
||||
如果您有兴趣贡献代码,请随时查看我们的 GitHub
|
||||
[问题][github-issues-link] 来展示您的能力。
|
||||
|
||||
[![][pr-welcome-shield]][pr-welcome-link]
|
||||
|
||||
[![][contributors-contrib]][contributors-url]
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 📝 许可证
|
||||
|
||||
版权所有 © 2024 [PPanel][profile-link]。<br />
|
||||
本项目使用 [GNU](./LICENSE) 许可证。
|
||||
|
||||
<!-- LINK GROUP -->
|
||||
|
||||
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
|
||||
[codespaces-link]: https://codespaces.new/perfect-panel/ppanel-web
|
||||
[codespaces-shield]: https://github.com/codespaces/badge.svg
|
||||
[contributors-contrib]: https://contrib.rocks/image?repo=perfect-panel/ppanel-web
|
||||
[contributors-url]: https://github.com/perfect-panel/ppanel-web/graphs/contributors
|
||||
[github-action-release-link]: https://github.com/perfect-panel/ppanel-web/actions/workflows/release.yml
|
||||
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/perfect-panel/ppanel-web/release.yml?label=release&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
|
||||
[github-action-test-link]: https://github.com/perfect-panel/ppanel-web/actions/workflows/test.yml
|
||||
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/perfect-panel/ppanel-web/test.yml?label=test&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
|
||||
[github-contributors-link]: https://github.com/perfect-panel/ppanel-web/graphs/contributors
|
||||
[github-contributors-shield]: https://img.shields.io/github/contributors/perfect-panel/ppanel-web?color=c4f042&labelColor=black&style=flat-square
|
||||
[github-forks-link]: https://github.com/perfect-panel/ppanel-web/network/members
|
||||
[github-forks-shield]: https://img.shields.io/github/forks/perfect-panel/ppanel-web?color=8ae8ff&labelColor=black&style=flat-square
|
||||
[github-issues-link]: https://github.com/perfect-panel/ppanel-web/issues
|
||||
[github-issues-shield]: https://img.shields.io/github/issues/perfect-panel/ppanel-web?color=ff80eb&labelColor=black&style=flat-square
|
||||
[github-license-link]: https://github.com/perfect-panel/ppanel-web/blob/master/LICENSE
|
||||
[github-license-shield]: https://img.shields.io/github/license/perfect-panel/ppanel-web?color=white&labelColor=black&style=flat-square
|
||||
[github-release-link]: https://github.com/perfect-panel/ppanel-web/releases
|
||||
[github-release-shield]: https://img.shields.io/github/v/release/perfect-panel/ppanel-web?style=flat-square&sort=semver&logo=github
|
||||
[github-releasedate-link]: https://github.com/perfect-panel/ppanel-web/releases
|
||||
[github-releasedate-shield]: https://img.shields.io/github/release-date/perfect-panel/ppanel-web?labelColor=black&style=flat-square
|
||||
[github-stars-link]: https://github.com/perfect-panel/ppanel-web/network/stargazers
|
||||
[github-stars-shield]: https://img.shields.io/github/stars/perfect-panel/ppanel-web?color=ffcb47&labelColor=black&style=flat-square
|
||||
[gitpod-link]: https://gitpod.io/#https://github.com/perfect-panel/ppanel-web
|
||||
[issues-link]: https://github.com/perfect-panel/ppanel-web/issues/new/choose
|
||||
[pr-welcome-link]: https://github.com/perfect-panel/ppanel-web/pulls
|
||||
[pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge
|
||||
[profile-link]: https://github.com/perfect-panel
|
||||
[split]: https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png
|
||||
[ppanel-user-web-github]: https://github.com/perfect-panel/ppanel-web/tree/main/apps/user
|
||||
[ppanel-user-web-cover]: https://urlscan.io/liveshot/?width=1920&height=1080&url=https://user.ppanel.dev
|
||||
[ppanel-user-web-preview]: https://user.ppanel.dev
|
||||
[ppanel-user-web-deploy]: https://vercel.com/new/clone?demo-description=PPanel%20is%20a%20pure%2C%20professional%2C%20and%20perfect%20open-source%20proxy%20panel%20tool%2C%20designed%20to%20be%20your%20ideal%20choice%20for%20learning%20and%20practical%20use&demo-image=https%3A%2F%2Furlscan.io%2Fliveshot%2F%3Fwidth%3D1920%26height%3D1080%26url%3Dhttps%3A%2F%2Fuser.ppanel.dev&demo-title=PPanel%20User%20Web&demo-url=https%3A%2F%2Fuser.ppanel.dev%2F&from=.&project-name=ppanel-user-web&repository-name=ppanel-web&repository-url=https%3A%2F%2Fgithub.com%2Fperfect-panel%2Fppanel-web&root-directory=apps%2Fuser&skippable-integrations=1
|
||||
[ppanel-admin-web-github]: https://github.com/perfect-panel/ppanel-web/tree/main/apps/admin
|
||||
[ppanel-admin-web-cover]: https://urlscan.io/liveshot/?width=1920&height=1080&url=https://admin.ppanel.dev
|
||||
[ppanel-admin-web-preview]: https://admin.ppanel.dev
|
||||
[ppanel-admin-web-deploy]: https://vercel.com/new/clone?demo-description=PPanel%20is%20a%20pure%2C%20professional%2C%20and%20perfect%20open-source%20proxy%20panel%20tool%2C%20designed%20to%20be%20your%20ideal%20choice%20for%20learning%20and%20practical%20use&demo-image=https%3A%2F%2Furlscan.io%2Fliveshot%2F%3Fwidth%3D1920%26height%3D1080%26url%3Dhttps%3A%2F%2Fadmin.ppanel.dev&demo-title=PPanel%20Admin%20Web&demo-url=https%3A%2F%2Fadmin.ppanel.dev%2F&from=.&project-name=ppanel-admin-web&repository-name=ppanel-web&repository-url=https%3A%2F%2Fgithub.com%2Fperfect-panel%2Fppanel-web&root-directory=apps%2Fadmin&skippable-integrations=1
|
||||
@ -1,141 +0,0 @@
|
||||
<a name="readme-top"></a>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img width="160" src="https://raw.githubusercontent.com/perfect-panel/ppanel-assets/refs/heads/main/logo.svg">
|
||||
|
||||
<h1>PPanel 用户端</h1>
|
||||
|
||||
这是由 PPanel 提供支持的 PPanel 用户端
|
||||
|
||||
[英文](./README.md)
|
||||
·
|
||||
中文
|
||||
·
|
||||
[更新日志](../../CHANGELOG.md)
|
||||
·
|
||||
[报告问题][issues-link]
|
||||
·
|
||||
[请求功能][issues-link]
|
||||
|
||||
<!-- SHIELD GROUP -->
|
||||
|
||||
[![][github-release-shield]][github-release-link]
|
||||
[![][github-releasedate-shield]][github-releasedate-link]
|
||||
[![][github-action-test-shield]][github-action-test-link]
|
||||
[![][github-action-release-shield]][github-action-release-link]<br/>
|
||||
[![][github-contributors-shield]][github-contributors-link]
|
||||
[![][github-forks-shield]][github-forks-link]
|
||||
[![][github-stars-shield]][github-stars-link]
|
||||
[![][github-issues-shield]][github-issues-link]
|
||||
[![][github-license-shield]][github-license-link]
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<details>
|
||||
<summary><kbd>目录</kbd></summary>
|
||||
|
||||
#### 目录
|
||||
|
||||
- [⌨️ 本地开发](#️-本地开发)
|
||||
- [🚀 在 Vercel 上部署](#-在-vercel-上部署)
|
||||
- [🤝 贡献](#-贡献)
|
||||
- [📝 许可证](#-许可证)
|
||||
|
||||
####
|
||||
|
||||
</details>
|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
您可以使用 Github Codespaces 进行在线开发:
|
||||
|
||||
[![][codespaces-shield]][codespaces-link]
|
||||
|
||||
您可以使用 Gitpod 进行在线开发:
|
||||
|
||||
[][gitpod-link]
|
||||
|
||||
或者克隆项目进行本地开发:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/perfect-panel/ppanel-web.git
|
||||
cd ppanel-web
|
||||
|
||||
# 安装依赖
|
||||
bun install
|
||||
|
||||
# 运行开发服务器
|
||||
cd apps/user
|
||||
bun dev
|
||||
```
|
||||
|
||||
在浏览器中打开 <http://localhost:3000> 查看结果。
|
||||
|
||||
## 🚀 在 Vercel 上部署
|
||||
|
||||
[](https://vercel.com/new/clone?demo-description=PPanel%20is%20a%20pure%2C%20professional%2C%20and%20perfect%20open-source%20proxy%20panel%20tool%2C%20designed%20to%20be%20your%20ideal%20choice%20for%20learning%20and%20practical%20use&demo-image=https%3A%2F%2Furlscan.io%2Fliveshot%2F%3Fwidth%3D1920%26height%3D1080%26url%3Dhttps%3A%2F%2Fuser.ppanel.dev&demo-title=PPanel%20User%20Web&demo-url=https%3A%2F%2Fuser.ppanel.dev%2F&from=.&project-name=ppanel-user-web&repository-name=ppanel-web&repository-url=https%3A%2F%2Fgithub.com%2Fperfect-panel%2Fppanel-web&root-directory=apps%2Fuser&skippable-integrations=1)
|
||||
|
||||
部署 Next.js 应用的最简单方式是使用
|
||||
[ Vercel 平台](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme)
|
||||
由 Next.js 的创建者提供支持。
|
||||
|
||||
查看我们的
|
||||
[Next.js 部署文档](https://nextjs.org/docs/deployment)
|
||||
获取更多详情。
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
欢迎各种类型的贡献,
|
||||
如果您有兴趣贡献代码,请随时查看我们的 GitHub
|
||||
[问题][github-issues-link] 来展示您的能力。
|
||||
|
||||
[![][pr-welcome-shield]][pr-welcome-link]
|
||||
|
||||
[![][contributors-contrib]][contributors-url]
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 📝 许可证
|
||||
|
||||
版权所有 © 2024 [PPanel][profile-link]。<br />
|
||||
本项目使用 [GNU](./LICENSE) 许可证。
|
||||
|
||||
<!-- LINK GROUP -->
|
||||
|
||||
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
|
||||
[codespaces-link]: https://codespaces.new/perfect-panel/ppanel-web
|
||||
[codespaces-shield]: https://github.com/codespaces/badge.svg
|
||||
[contributors-contrib]: https://contrib.rocks/image?repo=perfect-panel/ppanel-web
|
||||
[contributors-url]: https://github.com/perfect-panel/ppanel-web/graphs/contributors
|
||||
[github-action-release-link]: https://github.com/perfect-panel/ppanel-web/actions/workflows/release.yml
|
||||
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/perfect-panel/ppanel-web/release.yml?label=release&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
|
||||
[github-action-test-link]: https://github.com/perfect-panel/ppanel-web/actions/workflows/test.yml
|
||||
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/perfect-panel/ppanel-web/test.yml?label=test&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
|
||||
[github-contributors-link]: https://github.com/perfect-panel/ppanel-web/graphs/contributors
|
||||
[github-contributors-shield]: https://img.shields.io/github/contributors/perfect-panel/ppanel-web?color=c4f042&labelColor=black&style=flat-square
|
||||
[github-forks-link]: https://github.com/perfect-panel/ppanel-web/network/members
|
||||
[github-forks-shield]: https://img.shields.io/github/forks/perfect-panel/ppanel-web?color=8ae8ff&labelColor=black&style=flat-square
|
||||
[github-issues-link]: https://github.com/perfect-panel/ppanel-web/issues
|
||||
[github-issues-shield]: https://img.shields.io/github/issues/perfect-panel/ppanel-web?color=ff80eb&labelColor=black&style=flat-square
|
||||
[github-license-link]: https://github.com/perfect-panel/ppanel-web/blob/master/LICENSE
|
||||
[github-license-shield]: https://img.shields.io/github/license/perfect-panel/ppanel-web?color=white&labelColor=black&style=flat-square
|
||||
[github-release-link]: https://github.com/perfect-panel/ppanel-web/releases
|
||||
[github-release-shield]: https://img.shields.io/github/v/release/perfect-panel/ppanel-web?style=flat-square&sort=semver&logo=github
|
||||
[github-releasedate-link]: https://github.com/perfect-panel/ppanel-web/releases
|
||||
[github-releasedate-shield]: https://img.shields.io/github/release-date/perfect-panel/ppanel-web?labelColor=black&style=flat-square
|
||||
[github-stars-link]: https://github.com/perfect-panel/ppanel-web/network/stargazers
|
||||
[github-stars-shield]: https://img.shields.io/github/stars/perfect-panel/ppanel-web?color=ffcb47&labelColor=black&style=flat-square
|
||||
[gitpod-link]: https://gitpod.io/#https://github.com/perfect-panel/ppanel-web
|
||||
[issues-link]: https://github.com/perfect-panel/ppanel-web/issues/new/choose
|
||||
[pr-welcome-link]: https://github.com/perfect-panel/ppanel-web/pulls
|
||||
[pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge
|
||||
[profile-link]: https://github.com/perfect-panel
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 9.4 KiB |
@ -1 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" fill="none"><path stroke="url(#a)" stroke-linecap="round" stroke-width="25" d="M162.779 118.828v105.346"/><path fill="url(#b)" fill-rule="evenodd" d="M175.279 38.443v97.01l39.384-16.222c6.384-2.629 13.69.414 16.319 6.797 2.629 6.383-.414 13.689-6.797 16.319l-29.869 12.303 39.758 21.079c6.099 3.234 8.422 10.8 5.188 16.899-3.234 6.099-10.8 8.422-16.899 5.188l-58.083-30.794-24.537 10.107c-.308.127-.617.24-.928.341L32.554 221.278l-17.265 7.118V86.468l-.007-.017 142.683-59.543 17.314-7.226v18.761Zm-39.745 113.338-95.245 39.267v-87.943l109.99-45.9v74.098l-35.34-18.737c-6.1-3.234-13.666-.911-16.9 5.188-3.233 6.1-.91 13.666 5.189 16.899l32.306 17.128Z" clip-rule="evenodd"/><defs><linearGradient id="a" x1="163.279" x2="163.279" y1="118.828" y2="224.174" gradientUnits="userSpaceOnUse"><stop stop-color="#2E58FF"/><stop offset="1" stop-color="#26D0FF"/></linearGradient><linearGradient id="b" x1="128.003" x2="105.241" y1="19.688" y2="214.91" gradientUnits="userSpaceOnUse"><stop stop-color="#02F"/><stop offset=".48" stop-color="#5EE7FF"/><stop offset=".975" stop-color="#FCD8FF"/></linearGradient></defs></svg>
|
||||
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1583_1546)">
|
||||
<path d="M97.2435 256H83.0516V250.119C77.5634 254.04 71.2606 256 64.1289 256C54.982 256 47.1786 252.766 40.7043 246.285C34.2443 239.818 31 231.991 31 222.834C31 213.677 34.23 205.864 40.7043 199.383C47.1786 192.901 54.982 189.668 64.1289 189.668C73.2758 189.668 81.0793 192.901 87.5536 199.383C94.0135 205.85 97.2578 213.677 97.2578 222.834V256H97.2435ZM77.5063 236.24C81.1936 232.549 83.0373 228.071 83.0373 222.834C83.0373 217.597 81.1936 213.119 77.5063 209.427C73.8189 205.736 69.3455 203.89 64.1146 203.89C58.8837 203.89 54.4103 205.736 50.723 209.427C47.0357 213.119 45.192 217.597 45.192 222.834C45.192 228.071 47.0357 232.549 50.723 236.24C54.4103 239.932 58.8837 241.778 64.1146 241.778C69.3455 241.778 73.8189 239.932 77.5063 236.24Z" fill="#0F2C53"/>
|
||||
<path d="M116.166 175.46V189.668H101.974V175.46H116.166ZM116.166 194.418V256H101.974V194.418H116.166Z" fill="#0F2C53"/>
|
||||
<path d="M120.897 222.834C120.897 213.677 124.127 205.864 130.601 199.383C137.075 192.901 144.879 189.668 154.026 189.668V203.876C148.795 203.876 144.321 205.721 140.634 209.413C136.947 213.104 135.103 217.583 135.103 222.82V255.986H120.911V222.82L120.897 222.834Z" fill="#0F2C53"/>
|
||||
<path d="M215.296 199.383C221.756 205.85 225 213.677 225 222.834C225 231.991 221.77 239.803 215.296 246.285C208.821 252.766 201.018 256 191.871 256C182.724 256 174.921 252.766 168.446 246.285C161.986 239.818 158.742 231.991 158.742 222.834C158.742 213.677 161.972 205.864 168.446 199.383C174.921 192.901 182.724 189.668 191.871 189.668C201.018 189.668 208.821 192.901 215.296 199.383ZM191.871 203.89C186.64 203.89 182.167 205.736 178.479 209.427C174.792 213.119 172.948 217.597 172.948 222.834C172.948 228.071 174.792 232.549 178.479 236.24C182.167 239.932 186.64 241.778 191.871 241.778C197.102 241.778 201.575 239.932 205.263 236.24C208.95 232.549 210.794 228.071 210.794 222.834C210.794 217.597 208.95 213.119 205.263 209.427C201.575 205.736 197.102 203.89 191.871 203.89Z" fill="#0F2C53"/>
|
||||
<path d="M141.42 86.5209C137.29 86.5209 133.874 87.9374 130.958 90.8419C128.043 93.7608 126.642 97.1804 126.642 101.315C126.642 105.45 128.057 108.87 130.958 111.789C133.86 114.708 137.29 116.11 141.42 116.11C145.551 116.11 148.966 114.693 151.882 111.789C154.783 108.884 156.198 105.45 156.198 101.315C156.198 97.1804 154.783 93.7608 151.882 90.8419C148.981 87.9374 145.551 86.5209 141.42 86.5209Z" fill="#0F2C53"/>
|
||||
<path d="M187.869 24.6671L117.152 1.57387C100.531 -3.84889 82.6657 5.23674 77.249 21.8627L54.1817 92.6447C48.765 109.285 57.8404 127.17 74.4478 132.593L175.235 165.516L208.121 64.6152C213.538 47.9749 204.462 30.0899 187.855 24.6671H187.869ZM171.648 131.577H156.184V127.814C151.782 130.318 146.823 131.577 141.406 131.577C133.088 131.577 125.899 128.601 120.025 122.706C114.151 116.825 111.164 109.628 111.164 101.301C111.164 92.9738 114.137 85.7769 120.025 79.8962C125.899 74.0156 133.088 71.0252 141.406 71.0252C149.724 71.0252 156.913 74.0013 162.787 79.8962C168.661 85.7769 171.648 92.9881 171.648 101.301V131.577Z" fill="#0F2C53"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1583_1546">
|
||||
<rect width="194" height="256" fill="white" transform="translate(31)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "PPanel",
|
||||
"short_name": "PPanel",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/pwa-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/pwa-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/pwa-maskable-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/pwa-maskable-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#FFFFFF",
|
||||
"theme_color": "#FFFFFF"
|
||||
}
|
||||