重命名

This commit is contained in:
宇阳
2024-08-04 15:58:33 +08:00
parent 3a605d64ca
commit c86385affc
19 changed files with 190 additions and 26 deletions

View File

@@ -5,6 +5,7 @@ import Loader from './common/Loader';
import PageTitle from './components/PageTitle';
import ECommerce from './pages/Dashboard/ECommerce';
import Create from './pages/Create';
import Cate from './pages/Cate';
import DefaultLayout from './layout/DefaultLayout';
import { ConfigProvider } from 'antd';
@@ -53,6 +54,16 @@ function App() {
</>
}
/>
<Route
path="/cate"
element={
<>
<PageTitle title="Calendar | TailAdmin - Tailwind CSS Admin Dashboard Template" />
<Cate />
</>
}
/>
</Routes>
</DefaultLayout>
</ConfigProvider>

View File

@@ -122,6 +122,18 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
</NavLink>
</li>
<li>
<NavLink
to="/cate"
className={`group relative flex items-center gap-2.5 rounded-sm py-2 px-4 font-medium text-bodydark1 duration-300 ease-in-out hover:bg-graydark dark:hover:bg-meta-4 ${pathname.includes('cate') &&
'bg-graydark dark:bg-meta-4'
}`}
>
<BiSpa className='text-[22px]' />
</NavLink>
</li>
<SidebarLinkGroup
activeCondition={
pathname === '/forms' || pathname.includes('forms')

126
src/pages/Cate/index.tsx Normal file
View File

@@ -0,0 +1,126 @@
import React, { useState, useEffect, useRef } from 'react';
import { Form, Input, Button, Tree, Modal, notification, Spin, Dropdown, Menu, Card } from 'antd';
import { DownOutlined } from '@ant-design/icons';
import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate';
import Breadcrumb from '@/components/Breadcrumbs';
import { Cate } from '@/types/cate'
const CateManager: React.FC = () => {
const [loading, setLoading] = useState(false);
const [model, setModel] = useState(false);
const [cate, setCate] = useState<Cate>({ name: '', mark: '', url: '', icon: '', level: 0 });
const [list, setList] = useState<Cate[]>([]);
const formRef = useRef<any>(null);
useEffect(() => {
getCateList();
}, []);
const getCateList = async () => {
setLoading(true);
const { data } = await getCateListAPI();
setList(data as Cate[]);
setLoading(false);
};
const addCateData = (id: number) => {
setModel(true);
setCate({ ...cate, level: id });
};
const editCateData = async (id: number) => {
setLoading(true);
setModel(true);
const { data } = await getCateDataAPI(id);
setCate(data);
setLoading(false);
};
const submit = async () => {
formRef.current
.validateFields()
.then(async (values: any) => {
if (cate.id) {
await editCateDataAPI({ ...cate, ...values });
notification.success({ message: '🎉 修改分类成功' });
} else {
await addCateDataAPI({ ...cate, ...values });
notification.success({ message: '🎉 新增分类成功' });
}
formRef.current.resetFields();
setCate({ name: '', mark: '', url: '', icon: '', level: 0 });
setModel(false);
getCateList();
})
.catch((errorInfo: any) => {
console.error('Validate Failed:', errorInfo);
});
};
const delCateData = (id: number) => {
// whetherToDelete(async () => {
// await delCateDataAPI(id);
// notification.success({ message: '🎉 删除分类成功' });
// getCateList();
// }, '分类');
};
const close = () => {
setModel(false);
formRef.current.resetFields();
};
const renderTreeNodes = (data: Cate[]) =>
data.map(item => (
<Tree.TreeNode title={item.name} key={item.id} dataRef={item}>
{item.children ? renderTreeNodes(item.children) : null}
</Tree.TreeNode>
));
const menu = (data: Cate) => (
<Menu>
<Menu.Item onClick={() => addCateData(data.id!)}></Menu.Item>
<Menu.Item onClick={() => editCateData(data.id!)}></Menu.Item>
<Menu.Item onClick={() => delCateData(data.id!)}></Menu.Item>
</Menu>
);
return (
<Card title={<Breadcrumb pageName="分类" />} className='border-stroke dark:border-strokedark [&>.ant-card-head]:border-stroke [&>.ant-card-head]:dark:border-strokedark dark:bg-boxdark [&>.ant-card-body]:pt-2'>
<div className='mt-2 mb-4 text-right'>
<Button type="primary" onClick={() => setModel(true)}></Button>
</div>
<Spin spinning={loading}>
<Tree defaultExpandAll>{renderTreeNodes(list)}</Tree>
</Spin>
<Modal title="新增分类导航" open={model} onCancel={close} footer={null}>
<Form ref={formRef} layout="vertical" initialValues={cate} size='large' className='mt-6'>
<Form.Item label="名称" name="name" rules={[{ required: true, message: '分类名称不能为空' }, { min: 1, max: 10, message: '分类名称限制为 1 ~ 10 个字符' }]}>
<Input placeholder="大前端" />
</Form.Item>
<Form.Item label="标识" name="mark" rules={[{ required: true, message: '分类标识不能为空' }, { min: 1, max: 10, message: '分类标识限制为 1 ~ 10 个字符' }]}>
<Input placeholder="dqd" />
</Form.Item>
<Form.Item label="图标" name="icon">
<Input placeholder="🎉" />
</Form.Item>
<Form.Item label="链接(选填)" name="url">
<Input placeholder="https://liuyuyang.net/" />
</Form.Item>
<Form.Item className='!mb-0 flex justify-end'>
<Button onClick={close}></Button>
<Button type="primary" onClick={submit} className='ml-2'></Button>
</Form.Item>
</Form>
</Modal>
</Card >
);
};
export default CateManager;

View File

@@ -6,6 +6,8 @@ import VditorEditor from './components/VditorMD';
import PublishForm from './components/PublishForm';
import { useEffect, useState } from 'react';
import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate'
const Create = () => {
const [content, setContent] = useState('');
const [publishOpen, setPublishOpen] = useState(false)
@@ -17,6 +19,9 @@ const Create = () => {
useEffect(() => {
console.log(content);
getCateListAPI().then(async res => {
console.log(await res);
})
}, [content])
return (

View File

@@ -1,4 +1,4 @@
interface Article {
export interface Article {
id?: number,
title: string,
description: string,

View File

@@ -1,4 +1,4 @@
interface Comment {
export interface Comment {
aid: number,
avatar: string,
content: string,
@@ -11,7 +11,7 @@ interface Comment {
audit: number
}
interface Info {
export interface Info {
tab: string,
loading: boolean,
list: Comment[],

2
src/types/File.d.ts vendored
View File

@@ -1,4 +1,4 @@
interface File {
export interface File {
children: Child[];
list: string[];
name: string;

2
src/types/Link.d.ts vendored
View File

@@ -1,4 +1,4 @@
interface Link {
export interface Link {
id?: number;
title: string;
description: string;

View File

@@ -1,4 +1,4 @@
interface Swiper {
export interface Swiper {
id?: number,
title: string,
description: string,

14
src/types/System.d.ts vendored
View File

@@ -1,5 +1,5 @@
// 磁盘
interface Disk {
export interface Disk {
diskFree: number;
diskPercent: number;
diskTotal: number;
@@ -7,7 +7,7 @@ interface Disk {
}
// 内存
interface Memory {
export interface Memory {
memoryAvailable: number;
memoryPercent: number;
memoryTotal: number;
@@ -15,7 +15,7 @@ interface Memory {
}
// 系统信息
interface System {
export interface System {
boot_time: string;
cpu: number;
disk: Disk;
@@ -26,7 +26,7 @@ interface System {
}
// 网站信息
interface Web {
export interface Web {
url: string,
title: string,
subhead: string,
@@ -41,11 +41,11 @@ interface Web {
covers: string[]
}
type ArticleLayout = "classics" | "card" | "waterfall" | ""
type RightSidebar = "author" | "hotArticle" | "randomArticle" | "newComments"
export type ArticleLayout = "classics" | "card" | "waterfall" | ""
export type RightSidebar = "author" | "hotArticle" | "randomArticle" | "newComments"
// 布局配置
interface Layout {
export interface Layout {
isArticleLayout: ArticleLayout,
rightSidebar: RightSidebar[],
swiperImage: string,

2
src/types/Tag.d.ts vendored
View File

@@ -1,4 +1,4 @@
interface Tag {
export interface Tag {
id?: number,
name: string
}

View File

@@ -1,4 +1,4 @@
interface Cate {
export interface Cate {
id?: number,
name: string,
mark: string,

10
src/types/user.d.ts vendored
View File

@@ -1,9 +1,9 @@
interface Login {
export interface Login {
username: string,
password: string
}
interface UserInfo {
export interface UserInfo {
id?: number,
name: string,
email: string,
@@ -12,14 +12,14 @@ interface UserInfo {
role?: string
}
type User = Login & UserInfo
export type User = Login & UserInfo
interface account {
export interface account {
token: string,
user: User
}
interface editUser {
export interface editUser {
username: string,
oldPassword: string,
newPassword: string

9
src/utils/authHelper.ts Normal file
View File

@@ -0,0 +1,9 @@
import { useUserStore } from "@/stores";
export const getToken = () => {
return useUserStore.getState().token;
};
export const quitLogin = () => {
return useUserStore.getState().quitLogin;
};

View File

@@ -1,9 +1,10 @@
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from "axios";
import { useUserStore } from "@/stores";
import { Modal, notification } from "antd";
import { useUserStore } from "@/stores";
// 配置项目API域名
export const baseURL = "http://localhost:5000/api";
export const baseURL = "http://localhost:9999/api";
// export const baseURL = "http://82.157.186.125:5000/api";
// 创建 axios 实例
export const instance = axios.create({
@@ -13,10 +14,12 @@ export const instance = axios.create({
timeout: 5000,
});
const store = useUserStore.getState()
// 请求拦截
instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = useUserStore((state) => state.token)
const token = store.token
// 如果有token就把赋值给请求头
if (token) config.headers["Authorization"] = `Bearer ${token}`;
@@ -38,14 +41,12 @@ instance.interceptors.response.use(
(res: AxiosResponse) => {
// 如果code为401就证明认证失败
if (res.data.code === 401) {
const quitLogin = useUserStore((state) => state.quitLogin)
return Modal.error({
title: '暂无权限',
content: '🔒️ 登录已过期,是否重新登录?',
okText: "去登录",
onOk: () => {
quitLogin();
store.quitLogin()
}
});
}