重命名
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 PageTitle from './components/PageTitle';
|
||||||
import ECommerce from './pages/Dashboard/ECommerce';
|
import ECommerce from './pages/Dashboard/ECommerce';
|
||||||
import Create from './pages/Create';
|
import Create from './pages/Create';
|
||||||
|
import Cate from './pages/Cate';
|
||||||
import DefaultLayout from './layout/DefaultLayout';
|
import DefaultLayout from './layout/DefaultLayout';
|
||||||
import { ConfigProvider } from 'antd';
|
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>
|
</Routes>
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
|
|||||||
@@ -122,6 +122,18 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</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
|
<SidebarLinkGroup
|
||||||
activeCondition={
|
activeCondition={
|
||||||
pathname === '/forms' || pathname.includes('forms')
|
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 PublishForm from './components/PublishForm';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate'
|
||||||
|
|
||||||
const Create = () => {
|
const Create = () => {
|
||||||
const [content, setContent] = useState('');
|
const [content, setContent] = useState('');
|
||||||
const [publishOpen, setPublishOpen] = useState(false)
|
const [publishOpen, setPublishOpen] = useState(false)
|
||||||
@@ -17,6 +19,9 @@ const Create = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(content);
|
console.log(content);
|
||||||
|
getCateListAPI().then(async res => {
|
||||||
|
console.log(await res);
|
||||||
|
})
|
||||||
}, [content])
|
}, [content])
|
||||||
|
|
||||||
return (
|
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,
|
id?: number,
|
||||||
title: string,
|
title: string,
|
||||||
description: 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,
|
aid: number,
|
||||||
avatar: string,
|
avatar: string,
|
||||||
content: string,
|
content: string,
|
||||||
@@ -11,7 +11,7 @@ interface Comment {
|
|||||||
audit: number
|
audit: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Info {
|
export interface Info {
|
||||||
tab: string,
|
tab: string,
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
list: Comment[],
|
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[];
|
children: Child[];
|
||||||
list: string[];
|
list: string[];
|
||||||
name: 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;
|
id?: number;
|
||||||
title: string;
|
title: string;
|
||||||
description: 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,
|
id?: number,
|
||||||
title: string,
|
title: string,
|
||||||
description: 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;
|
diskFree: number;
|
||||||
diskPercent: number;
|
diskPercent: number;
|
||||||
diskTotal: number;
|
diskTotal: number;
|
||||||
@@ -7,7 +7,7 @@ interface Disk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 内存
|
// 内存
|
||||||
interface Memory {
|
export interface Memory {
|
||||||
memoryAvailable: number;
|
memoryAvailable: number;
|
||||||
memoryPercent: number;
|
memoryPercent: number;
|
||||||
memoryTotal: number;
|
memoryTotal: number;
|
||||||
@@ -15,7 +15,7 @@ interface Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 系统信息
|
// 系统信息
|
||||||
interface System {
|
export interface System {
|
||||||
boot_time: string;
|
boot_time: string;
|
||||||
cpu: number;
|
cpu: number;
|
||||||
disk: Disk;
|
disk: Disk;
|
||||||
@@ -26,7 +26,7 @@ interface System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 网站信息
|
// 网站信息
|
||||||
interface Web {
|
export interface Web {
|
||||||
url: string,
|
url: string,
|
||||||
title: string,
|
title: string,
|
||||||
subhead: string,
|
subhead: string,
|
||||||
@@ -41,11 +41,11 @@ interface Web {
|
|||||||
covers: string[]
|
covers: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArticleLayout = "classics" | "card" | "waterfall" | ""
|
export type ArticleLayout = "classics" | "card" | "waterfall" | ""
|
||||||
type RightSidebar = "author" | "hotArticle" | "randomArticle" | "newComments"
|
export type RightSidebar = "author" | "hotArticle" | "randomArticle" | "newComments"
|
||||||
|
|
||||||
// 布局配置
|
// 布局配置
|
||||||
interface Layout {
|
export interface Layout {
|
||||||
isArticleLayout: ArticleLayout,
|
isArticleLayout: ArticleLayout,
|
||||||
rightSidebar: RightSidebar[],
|
rightSidebar: RightSidebar[],
|
||||||
swiperImage: string,
|
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,
|
id?: number,
|
||||||
name: string
|
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,
|
id?: number,
|
||||||
name: string,
|
name: string,
|
||||||
mark: 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,
|
username: string,
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserInfo {
|
export interface UserInfo {
|
||||||
id?: number,
|
id?: number,
|
||||||
name: string,
|
name: string,
|
||||||
email: string,
|
email: string,
|
||||||
@@ -12,14 +12,14 @@ interface UserInfo {
|
|||||||
role?: string
|
role?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type User = Login & UserInfo
|
export type User = Login & UserInfo
|
||||||
|
|
||||||
interface account {
|
export interface account {
|
||||||
token: string,
|
token: string,
|
||||||
user: User
|
user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
interface editUser {
|
export interface editUser {
|
||||||
username: string,
|
username: string,
|
||||||
oldPassword: string,
|
oldPassword: string,
|
||||||
newPassword: 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 axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from "axios";
|
||||||
import { useUserStore } from "@/stores";
|
|
||||||
import { Modal, notification } from "antd";
|
import { Modal, notification } from "antd";
|
||||||
|
import { useUserStore } from "@/stores";
|
||||||
|
|
||||||
// 配置项目API域名
|
// 配置项目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 实例
|
// 创建 axios 实例
|
||||||
export const instance = axios.create({
|
export const instance = axios.create({
|
||||||
@@ -13,10 +14,12 @@ export const instance = axios.create({
|
|||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const store = useUserStore.getState()
|
||||||
|
|
||||||
// 请求拦截
|
// 请求拦截
|
||||||
instance.interceptors.request.use(
|
instance.interceptors.request.use(
|
||||||
(config: InternalAxiosRequestConfig) => {
|
(config: InternalAxiosRequestConfig) => {
|
||||||
const token = useUserStore((state) => state.token)
|
const token = store.token
|
||||||
|
|
||||||
// 如果有token就把赋值给请求头
|
// 如果有token就把赋值给请求头
|
||||||
if (token) config.headers["Authorization"] = `Bearer ${token}`;
|
if (token) config.headers["Authorization"] = `Bearer ${token}`;
|
||||||
@@ -38,14 +41,12 @@ instance.interceptors.response.use(
|
|||||||
(res: AxiosResponse) => {
|
(res: AxiosResponse) => {
|
||||||
// 如果code为401就证明认证失败
|
// 如果code为401就证明认证失败
|
||||||
if (res.data.code === 401) {
|
if (res.data.code === 401) {
|
||||||
const quitLogin = useUserStore((state) => state.quitLogin)
|
|
||||||
|
|
||||||
return Modal.error({
|
return Modal.error({
|
||||||
title: '暂无权限',
|
title: '暂无权限',
|
||||||
content: '🔒️ 登录已过期,是否重新登录?',
|
content: '🔒️ 登录已过期,是否重新登录?',
|
||||||
okText: "去登录",
|
okText: "去登录",
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
quitLogin();
|
store.quitLogin()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user