重命名
This commit is contained in:
11
src/App.tsx
11
src/App.tsx
@@ -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>
|
||||
|
||||
@@ -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
126
src/pages/Cate/index.tsx
Normal 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;
|
||||
@@ -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 (
|
||||
|
||||
2
src/types/Article.d.ts
vendored
2
src/types/Article.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface Article {
|
||||
export interface Article {
|
||||
id?: number,
|
||||
title: string,
|
||||
description: string,
|
||||
|
||||
4
src/types/Comment.d.ts
vendored
4
src/types/Comment.d.ts
vendored
@@ -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
2
src/types/File.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface File {
|
||||
export interface File {
|
||||
children: Child[];
|
||||
list: string[];
|
||||
name: string;
|
||||
|
||||
2
src/types/Link.d.ts
vendored
2
src/types/Link.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface Link {
|
||||
export interface Link {
|
||||
id?: number;
|
||||
title: string;
|
||||
description: string;
|
||||
|
||||
2
src/types/Swiper.d.ts
vendored
2
src/types/Swiper.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface Swiper {
|
||||
export interface Swiper {
|
||||
id?: number,
|
||||
title: string,
|
||||
description: string,
|
||||
|
||||
14
src/types/System.d.ts
vendored
14
src/types/System.d.ts
vendored
@@ -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
2
src/types/Tag.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface Tag {
|
||||
export interface Tag {
|
||||
id?: number,
|
||||
name: string
|
||||
}
|
||||
|
||||
2
src/types/Cate..d.ts → src/types/cate.d.ts
vendored
2
src/types/Cate..d.ts → src/types/cate.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
interface Cate {
|
||||
export interface Cate {
|
||||
id?: number,
|
||||
name: string,
|
||||
mark: string,
|
||||
0
src/types/chat.ts → src/types/chat.d.ts
vendored
0
src/types/chat.ts → src/types/chat.d.ts
vendored
10
src/types/user.d.ts
vendored
10
src/types/user.d.ts
vendored
@@ -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
9
src/utils/authHelper.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useUserStore } from "@/stores";
|
||||
|
||||
export const getToken = () => {
|
||||
return useUserStore.getState().token;
|
||||
};
|
||||
|
||||
export const quitLogin = () => {
|
||||
return useUserStore.getState().quitLogin;
|
||||
};
|
||||
@@ -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()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user