大改动
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Table, Button, Form, Input, Popconfirm, message, Card } from 'antd';
|
||||
import { getTagListAPI, addTagDataAPI, editTagDataAPI, delTagDataAPI } from '@/api/Tag';
|
||||
import { getTagListAPI, addTagDataAPI, editTagDataAPI, delTagDataAPI, getTagDataAPI } from '@/api/Tag';
|
||||
import { Tag } from '@/types/app/tag';
|
||||
import Title from '@/components/Title';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
|
||||
const TagPage = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [btnLoading, setBtnLoading] = useState(false)
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [tag, setTag] = useState<Tag>({} as Tag);
|
||||
const [list, setList] = useState<Tag[]>([]);
|
||||
@@ -28,49 +31,76 @@ const TagPage = () => {
|
||||
];
|
||||
|
||||
const getTagList = async () => {
|
||||
setLoading(true);
|
||||
const { data } = await getTagListAPI();
|
||||
setList(data as Tag[]);
|
||||
try {
|
||||
const { data } = await getTagListAPI();
|
||||
setList(data as Tag[]);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
getTagList();
|
||||
}, []);
|
||||
|
||||
const [form] = Form.useForm();
|
||||
const editTagData = (record: Tag) => {
|
||||
setTag(record);
|
||||
form.setFieldsValue(record);
|
||||
const editTagData = async (record: Tag) => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const { data } = await getTagDataAPI(record.id)
|
||||
setTag(data);
|
||||
form.setFieldsValue(data);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const delTagData = async (id: number) => {
|
||||
setLoading(true);
|
||||
await delTagDataAPI(id);
|
||||
message.success('🎉 删除标签成功');
|
||||
getTagList();
|
||||
|
||||
try {
|
||||
await delTagDataAPI(id);
|
||||
await getTagList();
|
||||
message.success('🎉 删除标签成功');
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
setLoading(true);
|
||||
form.validateFields().then(async (values: Tag) => {
|
||||
if (tag.id) {
|
||||
await editTagDataAPI({ ...tag, ...values });
|
||||
message.success('🎉 编辑标签成功');
|
||||
} else {
|
||||
await addTagDataAPI(values);
|
||||
message.success('🎉 新增标签成功');
|
||||
}
|
||||
setBtnLoading(true);
|
||||
|
||||
getTagList();
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ name: '' })
|
||||
setTag({} as Tag);
|
||||
});
|
||||
try {
|
||||
form.validateFields().then(async (values: Tag) => {
|
||||
if (tag.id) {
|
||||
await editTagDataAPI({ ...tag, ...values });
|
||||
message.success('🎉 编辑标签成功');
|
||||
} else {
|
||||
await addTagDataAPI(values);
|
||||
message.success('🎉 新增标签成功');
|
||||
}
|
||||
|
||||
await getTagList();
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ name: '' })
|
||||
setTag({} as Tag);
|
||||
});
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
setBtnLoading(false);
|
||||
}
|
||||
|
||||
setBtnLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Title value="标签管理" />
|
||||
|
||||
<div className='flex md:justify-between flex-col md:flex-row mx-auto mt-2'>
|
||||
@@ -81,14 +111,13 @@ const TagPage = () => {
|
||||
initialValues={tag}
|
||||
onFinish={onSubmit}
|
||||
size='large'
|
||||
|
||||
>
|
||||
<Form.Item label="标签名称" name="name" rules={[{ required: true, message: '标签名称不能为空' }]}>
|
||||
<Input placeholder="请输入标签名称" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={loading} className="w-full">{tag.id ? '编辑标签' : '新增标签'}</Button>
|
||||
<Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{tag.id ? '编辑标签' : '新增标签'}</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
@@ -107,7 +136,7 @@ const TagPage = () => {
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ import dayjs from 'dayjs';
|
||||
const UserPage = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [btnLoading, setBtnLoading] = useState(false)
|
||||
const [editLoading, setEditLoading] = useState(false)
|
||||
|
||||
const [form] = Form.useForm();
|
||||
const store = useUserStore()
|
||||
|
||||
const [userList, setUserList] = useState<User[]>([]);
|
||||
@@ -107,76 +109,105 @@ const UserPage = () => {
|
||||
},
|
||||
];
|
||||
|
||||
const [userForm] = Form.useForm();
|
||||
|
||||
const getUserList = async () => {
|
||||
setLoading(true);
|
||||
const { data } = await getUserListAPI();
|
||||
setUserList(data as User[]);
|
||||
try {
|
||||
const { data } = await getUserListAPI();
|
||||
setUserList(data as User[]);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const getRoleList = async () => {
|
||||
const { data } = await getRoleListAPI();
|
||||
setRoleList(data as Role[]);
|
||||
console.log(data);
|
||||
|
||||
setRoleList(data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
getUserList();
|
||||
getRoleList()
|
||||
}, []);
|
||||
|
||||
const delUserData = async (id: number) => {
|
||||
setLoading(true);
|
||||
await delUserDataAPI(id);
|
||||
await getUserList();
|
||||
notification.success({ message: '🎉 删除用户成功' });
|
||||
setLoading(false);
|
||||
|
||||
try {
|
||||
await delUserDataAPI(id);
|
||||
await getUserList();
|
||||
notification.success({ message: '🎉 删除用户成功' });
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const editUserData = async (id: number) => {
|
||||
const { data } = await getUserDataAPI(id)
|
||||
setUser({ ...data, role: data.role.id });
|
||||
setEditLoading(true);
|
||||
|
||||
userForm.setFieldsValue({ ...data, roleId: data.role.id });
|
||||
setDrawerVisible(true);
|
||||
try {
|
||||
setDrawerVisible(true);
|
||||
const { data } = await getUserDataAPI(id)
|
||||
setUser(data);
|
||||
form.setFieldsValue(data);
|
||||
} catch (error) {
|
||||
setEditLoading(false);
|
||||
}
|
||||
|
||||
setEditLoading(false);
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
setUser({} as User)
|
||||
userForm.resetFields()
|
||||
form.resetFields()
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
setBtnLoading(true)
|
||||
|
||||
userForm.validateFields().then(async (values: User) => {
|
||||
if (user.id) {
|
||||
await editUserDataAPI({ ...user, ...values });
|
||||
notification.success({ message: '🎉 编辑用户成功' });
|
||||
} else {
|
||||
await addUserDataAPI({ ...values, password: "123456", createTime: new Date().getTime().toString() });
|
||||
notification.success({ message: '🎉 创建用户成功' });
|
||||
}
|
||||
setDrawerVisible(false);
|
||||
getUserList();
|
||||
})
|
||||
try {
|
||||
form.validateFields().then(async (values: User) => {
|
||||
if (user.id) {
|
||||
await editUserDataAPI({ ...user, ...values });
|
||||
notification.success({ message: '🎉 编辑用户成功' });
|
||||
} else {
|
||||
await addUserDataAPI({ ...values, password: "123456", createTime: new Date().getTime().toString() });
|
||||
notification.success({ message: '🎉 创建用户成功' });
|
||||
}
|
||||
|
||||
await getUserList();
|
||||
setDrawerVisible(false);
|
||||
reset()
|
||||
})
|
||||
} catch (error) {
|
||||
setBtnLoading(false)
|
||||
}
|
||||
|
||||
setBtnLoading(false)
|
||||
};
|
||||
|
||||
const [filterForm] = Form.useForm();
|
||||
|
||||
const onFilterSubmit = async (values: FilterForm) => {
|
||||
const query: FilterUser = {
|
||||
key: values.name,
|
||||
roleId: values.role,
|
||||
startDate: values.createTime && values.createTime[0].valueOf() + '',
|
||||
endDate: values.createTime && values.createTime[1].valueOf() + ''
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const query: FilterUser = {
|
||||
key: values.name,
|
||||
roleId: values.role,
|
||||
startDate: values.createTime && values.createTime[0].valueOf() + '',
|
||||
endDate: values.createTime && values.createTime[1].valueOf() + ''
|
||||
}
|
||||
|
||||
const { data } = await getUserListAPI({ query });
|
||||
setUserList(data as User[]);
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const { data } = await getUserListAPI({ query });
|
||||
setUserList(data as User[]);
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -186,7 +217,7 @@ const UserPage = () => {
|
||||
</Title>
|
||||
|
||||
<Card className='my-2 overflow-scroll'>
|
||||
<Form form={filterForm} layout="inline" onFinish={onFilterSubmit} autoComplete="off" className='flex-nowrap'>
|
||||
<Form layout="inline" onFinish={onFilterSubmit} autoComplete="off" className='flex-nowrap'>
|
||||
<Form.Item label="名称" name="name" className='min-w-[200px]'>
|
||||
<Input placeholder='请输入名称' />
|
||||
</Form.Item>
|
||||
@@ -227,9 +258,10 @@ const UserPage = () => {
|
||||
setDrawerVisible(false)
|
||||
}}
|
||||
open={drawerVisible}
|
||||
loading={editLoading}
|
||||
>
|
||||
<Form
|
||||
form={userForm}
|
||||
form={form}
|
||||
layout="vertical"
|
||||
size='large'
|
||||
onFinish={onSubmit}
|
||||
@@ -278,7 +310,7 @@ const UserPage = () => {
|
||||
label="角色"
|
||||
rules={[{ required: true, message: '请选择角色' }]}
|
||||
>
|
||||
<Select options={roleList.map(item => ({ label: item.name, value: item.id }))} placeholder="选择用户角色" />
|
||||
<Select options={roleList.map(item => ({ label: item.name, value: +item.id }))} placeholder="选择用户角色" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
|
||||
@@ -9,23 +9,35 @@ import dayjs from 'dayjs';
|
||||
|
||||
const WallPage = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [wall, setWall] = useState<Wall>();
|
||||
|
||||
const [wall, setWall] = useState<Wall>({} as Wall);
|
||||
const [list, setList] = useState<Wall[]>([]);
|
||||
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
const getWallList = async () => {
|
||||
const { data } = await getWallListAPI();
|
||||
try {
|
||||
const { data } = await getWallListAPI();
|
||||
setList(data)
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
setList(data)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const delWallData = async (id: number) => {
|
||||
setLoading(true)
|
||||
await delWallDataAPI(id);
|
||||
getWallList();
|
||||
message.success('🎉 删除留言成功');
|
||||
|
||||
try {
|
||||
await delWallDataAPI(id);
|
||||
await getWallList();
|
||||
message.success('🎉 删除留言成功');
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
};
|
||||
|
||||
// 获取留言的分类列表
|
||||
@@ -105,16 +117,24 @@ const WallPage = () => {
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const onSubmit = async (values: FilterForm) => {
|
||||
const query: FilterWall = {
|
||||
key: values.content,
|
||||
cateId: values.cateId,
|
||||
startDate: values.createTime && values.createTime[0].valueOf() + '',
|
||||
endDate: values.createTime && values.createTime[1].valueOf() + ''
|
||||
const onFilterSubmit = async (values: FilterForm) => {
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const query: FilterWall = {
|
||||
key: values.content,
|
||||
cateId: values.cateId,
|
||||
startDate: values.createTime && values.createTime[0].valueOf() + '',
|
||||
endDate: values.createTime && values.createTime[1].valueOf() + ''
|
||||
}
|
||||
|
||||
const { data } = await getWallListAPI({ query });
|
||||
setList(data)
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const { data } = await getWallListAPI({ query });
|
||||
setList(data)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -122,7 +142,7 @@ const WallPage = () => {
|
||||
<Title value='留言管理' />
|
||||
|
||||
<Card className='my-2 overflow-scroll'>
|
||||
<Form layout="inline" onFinish={onSubmit} autoComplete="off" className='flex-nowrap'>
|
||||
<Form layout="inline" onFinish={onFilterSubmit} autoComplete="off" className='flex-nowrap'>
|
||||
<Form.Item label="内容" name="content" className='min-w-[200px]'>
|
||||
<Input placeholder='请输入内容关键词' />
|
||||
</Form.Item>
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Tabs, Input, Button, Form, Spin, Empty, Card, Popconfirm, Select, message } from 'antd';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { getLinkListAPI, addLinkDataAPI, editLinkDataAPI, delLinkDataAPI, getWebTypeListAPI } from '@/api/Web';
|
||||
import { getLinkListAPI, addLinkDataAPI, editLinkDataAPI, delLinkDataAPI, getWebTypeListAPI, getLinkDataAPI } from '@/api/Web';
|
||||
import { WebType, Web } from '@/types/app/web';
|
||||
import Title from '@/components/Title';
|
||||
import { RuleObject } from 'antd/es/form';
|
||||
import './index.scss';
|
||||
|
||||
const LinkPage = () => {
|
||||
export default () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [btnLoading, setBtnLoading] = useState(false)
|
||||
const [editLoading, setEditLoading] = useState(false)
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [tab, setTab] = useState<string>('list');
|
||||
const [list, setList] = useState<Web[]>([]);
|
||||
@@ -23,13 +26,18 @@ const LinkPage = () => {
|
||||
|
||||
// 获取网站列表
|
||||
const getLinkList = async () => {
|
||||
const { data } = await getLinkListAPI();
|
||||
data.sort((a, b) => a.order - b.order)
|
||||
data.sort((a, b) => a.type.order - b.type.order)
|
||||
try {
|
||||
const { data } = await getLinkListAPI();
|
||||
data.sort((a, b) => a.order - b.order)
|
||||
data.sort((a, b) => a.type.order - b.type.order)
|
||||
|
||||
setList(data as Web[]);
|
||||
setListTemp(data as Web[]);
|
||||
setLoading(false);
|
||||
setList(data);
|
||||
setListTemp(data);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
};
|
||||
|
||||
// 获取网站类型列表
|
||||
@@ -50,18 +58,31 @@ const LinkPage = () => {
|
||||
|
||||
const deleteLinkData = async (id: number) => {
|
||||
setLoading(true);
|
||||
await delLinkDataAPI(id);
|
||||
message.success('🎉 删除网站成功');
|
||||
getLinkList();
|
||||
|
||||
try {
|
||||
await delLinkDataAPI(id);
|
||||
await getLinkList();
|
||||
message.success('🎉 删除网站成功');
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
};
|
||||
|
||||
const [form] = Form.useForm();
|
||||
const editLinkData = async (record: Web) => {
|
||||
setEditLoading(true)
|
||||
|
||||
const editLinkData = (item: Web) => {
|
||||
setTab('operate');
|
||||
setIsMethod("edit");
|
||||
setLink(item);
|
||||
form.setFieldsValue(item); // 回显数据
|
||||
try {
|
||||
setTab('operate');
|
||||
setIsMethod("edit");
|
||||
|
||||
const { data } = await getLinkDataAPI(record.id)
|
||||
setLink(data);
|
||||
form.setFieldsValue(data);
|
||||
} catch (error) {
|
||||
setEditLoading(false)
|
||||
}
|
||||
|
||||
setEditLoading(false)
|
||||
};
|
||||
|
||||
// 做一些初始化的事情
|
||||
@@ -79,19 +100,23 @@ const LinkPage = () => {
|
||||
const submit = async () => {
|
||||
setBtnLoading(true)
|
||||
|
||||
form.validateFields().then(async (values: Web) => {
|
||||
if (isMethod === "edit") {
|
||||
await editLinkDataAPI({ ...link, ...values });
|
||||
message.success('🎉 编辑网站成功');
|
||||
} else {
|
||||
await addLinkDataAPI({ ...values, createTime: new Date().getTime().toString() });
|
||||
message.success('🎉 新增网站成功');
|
||||
}
|
||||
try {
|
||||
form.validateFields().then(async (values: Web) => {
|
||||
if (isMethod === "edit") {
|
||||
await editLinkDataAPI({ ...link, ...values });
|
||||
message.success('🎉 编辑网站成功');
|
||||
} else {
|
||||
await addLinkDataAPI({ ...values, createTime: new Date().getTime().toString() });
|
||||
message.success('🎉 新增网站成功');
|
||||
}
|
||||
|
||||
getLinkList();
|
||||
setTab('list');
|
||||
reset()
|
||||
});
|
||||
await getLinkList();
|
||||
reset()
|
||||
setTab('list');
|
||||
});
|
||||
} catch (error) {
|
||||
setBtnLoading(false)
|
||||
}
|
||||
|
||||
setBtnLoading(false)
|
||||
};
|
||||
@@ -164,47 +189,49 @@ const LinkPage = () => {
|
||||
<>
|
||||
<h2 className="text-xl pb-4 text-center">{isMethod === "edit" ? '编辑网站' : '新增网站'}</h2>
|
||||
|
||||
<div className='w-full md:w-[500px] mx-auto'>
|
||||
<Form form={form} layout="vertical" size='large' initialValues={link} onFinish={submit}>
|
||||
<Form.Item label="网站标题" name="title" rules={[{ required: true, message: '网站标题不能为空' }]}>
|
||||
<Input placeholder="Thrive" />
|
||||
</Form.Item>
|
||||
<Spin spinning={editLoading}>
|
||||
<div className='w-full md:w-[500px] mx-auto'>
|
||||
<Form form={form} layout="vertical" size='large' initialValues={link} onFinish={submit}>
|
||||
<Form.Item label="网站标题" name="title" rules={[{ required: true, message: '网站标题不能为空' }]}>
|
||||
<Input placeholder="Thrive" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="网站描述" name="description" rules={[{ required: true, message: '网站描述不能为空' }]}>
|
||||
<Input placeholder="记录前端、Python、Java点点滴滴" />
|
||||
</Form.Item>
|
||||
<Form.Item label="网站描述" name="description" rules={[{ required: true, message: '网站描述不能为空' }]}>
|
||||
<Input placeholder="记录前端、Python、Java点点滴滴" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="站长邮箱" name="email">
|
||||
<Input placeholder="3311118881@qq.com" />
|
||||
</Form.Item>
|
||||
<Form.Item label="站长邮箱" name="email">
|
||||
<Input placeholder="3311118881@qq.com" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="网站图标" name="image" rules={[{ required: true, message: '网站图标不能为空' }]}>
|
||||
<Input placeholder="https://liuyuyang.net/logo.png" />
|
||||
</Form.Item>
|
||||
<Form.Item label="网站图标" name="image" rules={[{ required: true, message: '网站图标不能为空' }]}>
|
||||
<Input placeholder="https://liuyuyang.net/logo.png" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="网站链接" name="url" rules={[{ required: true, message: '网站链接不能为空' }, { validator: validateURL }]}>
|
||||
<Input placeholder="https://liuyuyang.net/" />
|
||||
</Form.Item>
|
||||
<Form.Item label="网站链接" name="url" rules={[{ required: true, message: '网站链接不能为空' }, { validator: validateURL }]}>
|
||||
<Input placeholder="https://liuyuyang.net/" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="订阅地址" name="rss" rules={[{ validator: validateURL }]}>
|
||||
<Input placeholder="https://liuyuyang.net/api/rss" />
|
||||
</Form.Item>
|
||||
<Form.Item label="订阅地址" name="rss" rules={[{ validator: validateURL }]}>
|
||||
<Input placeholder="https://liuyuyang.net/api/rss" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="typeId" label="网站类型" rules={[{ required: true, message: '网站类型不能为空' }]}>
|
||||
<Select placeholder="请选择网站类型" allowClear>
|
||||
{typeList.map(item => <Option key={item.id} value={item.id}>{item.name}</Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="typeId" label="网站类型" rules={[{ required: true, message: '网站类型不能为空' }]}>
|
||||
<Select placeholder="请选择网站类型" allowClear>
|
||||
{typeList.map(item => <Option key={item.id} value={item.id}>{item.name}</Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="顺序" name="order">
|
||||
<Input placeholder="请输入网站顺序(值越小越靠前)" />
|
||||
</Form.Item>
|
||||
<Form.Item label="顺序" name="order">
|
||||
<Input placeholder="请输入网站顺序(值越小越靠前)" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={btnLoading} className='w-full'>{isMethod === "edit" ? '编辑网站' : '新增网站'}</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={btnLoading} className='w-full'>{isMethod === "edit" ? '编辑网站' : '新增网站'}</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Spin>
|
||||
</>
|
||||
),
|
||||
},
|
||||
@@ -219,6 +246,4 @@ const LinkPage = () => {
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinkPage;
|
||||
};
|
||||
210
src/pages/Work/components/List/index.tsx
Normal file
210
src/pages/Work/components/List/index.tsx
Normal file
@@ -0,0 +1,210 @@
|
||||
import { useState } from "react";
|
||||
import { Button, Dropdown, message, Modal } from "antd";
|
||||
import { delLinkDataAPI, auditWebDataAPI } from '@/api/Web';
|
||||
import { auditCommentDataAPI, delCommentDataAPI, addCommentDataAPI } from "@/api/Comment";
|
||||
import { auditWallDataAPI, delWallDataAPI } from "@/api/Wall";
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import RandomAvatar from "@/components/RandomAvatar";
|
||||
|
||||
import { useUserStore, useWebStore } from '@/stores';
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { sendDismissEmailAPI } from "@/api/Email";
|
||||
|
||||
type Menu = "comment" | "link" | "wall";
|
||||
|
||||
interface ListItemProps {
|
||||
item: any;
|
||||
type: Menu;
|
||||
fetchData: (type: Menu) => void;
|
||||
}
|
||||
|
||||
export default ({ item, type, fetchData }: ListItemProps) => {
|
||||
const web = useWebStore(state => state.web)
|
||||
const user = useUserStore(state => state.user)
|
||||
|
||||
const [btnType, setBtnType] = useState<"reply" | "dismiss" | string>("")
|
||||
|
||||
// 通过
|
||||
const handleApproval = async () => {
|
||||
if (type === "link") {
|
||||
await auditWebDataAPI(item.id);
|
||||
} else if (type === "comment") {
|
||||
await auditCommentDataAPI(item.id);
|
||||
} else if (type === "wall") {
|
||||
await auditWallDataAPI(item.id);
|
||||
}
|
||||
|
||||
btnType != "reply" && message.success('🎉 审核成功');
|
||||
fetchData(type);
|
||||
};
|
||||
|
||||
// 回复
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [replyInfo, setReplyInfo] = useState("")
|
||||
const handleReply = async () => {
|
||||
// 审核通过评论
|
||||
await handleApproval()
|
||||
|
||||
// 发送回复内容
|
||||
await addCommentDataAPI({
|
||||
avatar: user.avatar,
|
||||
url: web.url,
|
||||
content: replyInfo,
|
||||
commentId: item?.id!,
|
||||
auditStatus: 1,
|
||||
email: user.email ? user.email : null,
|
||||
name: user.name,
|
||||
articleId: item?.articleId!,
|
||||
createTime: new Date().getTime().toString(),
|
||||
})
|
||||
|
||||
message.success('🎉 回复成功');
|
||||
setIsModalOpen(false)
|
||||
fetchData(type);
|
||||
setReplyInfo("")
|
||||
setBtnType("")
|
||||
}
|
||||
|
||||
// 驳回
|
||||
const [dismissInfo, setDismissInfo] = useState("")
|
||||
const handleDismiss = async () => {
|
||||
if (type === "link") {
|
||||
await delLinkDataAPI(item.id);
|
||||
} else if (type === "comment") {
|
||||
await delCommentDataAPI(item.id);
|
||||
} else if (type === "wall") {
|
||||
await delWallDataAPI(item.id);
|
||||
}
|
||||
|
||||
// 有内容就发送驳回通知邮件,反之直接删除
|
||||
if (dismissInfo.trim().length) await sendDismissEmail()
|
||||
|
||||
message.success('🎉 驳回成功');
|
||||
setIsModalOpen(false)
|
||||
fetchData(type);
|
||||
setDismissInfo("")
|
||||
setBtnType("")
|
||||
};
|
||||
|
||||
// 发送驳回通知邮件
|
||||
const sendDismissEmail = async () => {
|
||||
// 类型名称
|
||||
let email_info = {
|
||||
name: "",
|
||||
type: "",
|
||||
url: ""
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "link":
|
||||
email_info = {
|
||||
name: item.title,
|
||||
type: "友链",
|
||||
url: `${web.url}/friend`,
|
||||
}
|
||||
break;
|
||||
case "comment":
|
||||
email_info = {
|
||||
name: item.name,
|
||||
type: "评论",
|
||||
url: `${web.url}/article/${item.articleId}`,
|
||||
}
|
||||
break;
|
||||
case "wall":
|
||||
email_info = {
|
||||
name: item.name,
|
||||
type: "留言",
|
||||
url: `${web.url}/wall/all`,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 有邮箱才会邮件通知
|
||||
item.email != null && await sendDismissEmailAPI({
|
||||
to: item.email,
|
||||
content: dismissInfo,
|
||||
recipient: email_info.name,
|
||||
subject: `${email_info.type}驳回通知`,
|
||||
time: dayjs(Date.now()).format('YYYY年MM月DD日 HH:mm'),
|
||||
type: email_info.type,
|
||||
url: email_info.url
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div key={item.id}>
|
||||
<div className="text-center text-xs text-[#e0e0e0] mb-4">
|
||||
{dayjs(+item.createTime!).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between md:p-7 rounded-md transition-colors">
|
||||
<div className="flex mr-10">
|
||||
{type !== "wall" ? (
|
||||
<img src={item.avatar || item.image} alt="" className="w-13 h-13 border border-[#eee] rounded-full" />
|
||||
) : <RandomAvatar className="w-13 h-13 border border-[#eee] rounded-full" />}
|
||||
|
||||
<div className="flex flex-col justify-center ml-4 px-4 py-2 min-w-[210px] text-xs md:text-sm bg-[#F9F9FD] dark:bg-[#4e5969] rounded-md">
|
||||
{type === "link" ? (
|
||||
<>
|
||||
<div>名称:{item.title}</div>
|
||||
<div>介绍:{item.description}</div>
|
||||
<div>类型:{item.type.name}</div>
|
||||
<div>网站:{item?.url ? <a href={item?.url} target='_blank' className="hover:text-primary font-bold">{item?.url}</a> : '无网站'}</div>
|
||||
</>
|
||||
) : type === "comment" ? (
|
||||
<>
|
||||
<div>名称:{item.name}</div>
|
||||
<div>内容:{item.content}</div>
|
||||
<div>网站:{item?.url ? <a href={item?.url} target='_blank' className="hover:text-primary font-bold">{item?.url}</a> : '无网站'}</div>
|
||||
<div>所属文章:<a href={`${web.url}/article/${item.articleId}`} target='_blank' className="hover:text-primary">{item.articleTitle || '暂无'}</a></div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div>名称:{item.name}</div>
|
||||
<div>内容:{item.content}</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div>邮箱:{item.email || '暂无'}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-end">
|
||||
<Dropdown menu={{
|
||||
items: type === "comment"
|
||||
? [
|
||||
{ key: 'ok', label: "通过", onClick: handleApproval },
|
||||
{ key: 'reply', label: "回复", onClick: () => [setIsModalOpen(true), setBtnType("reply")] },
|
||||
{ key: 'dismiss', label: "驳回", onClick: () => [setIsModalOpen(true), , setBtnType("dismiss")] }
|
||||
]
|
||||
: [
|
||||
{ key: 'ok', label: "通过", onClick: handleApproval },
|
||||
{ key: 'dismiss', label: "驳回", onClick: () => [setIsModalOpen(true), , setBtnType("dismiss")] }
|
||||
]
|
||||
}}>
|
||||
<div className="flex justify-evenly items-center bg-[#F9F9FD] dark:bg-[#4e5969] w-11 h-5 rounded-md cursor-pointer">
|
||||
<span className="inline-block w-2 h-2 bg-[#b5c2d3] rounded-full"></span>
|
||||
<span className="inline-block w-2 h-2 bg-[#b5c2d3] rounded-full"></span>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal title={btnType === "reply" ? "回复内容" : "驳回原因"} open={isModalOpen} footer={null} onCancel={() => setIsModalOpen(false)} onClose={() => setIsModalOpen(false)}>
|
||||
<TextArea
|
||||
value={btnType === "reply" ? replyInfo : dismissInfo}
|
||||
onChange={(e) => (btnType === "reply" ? setReplyInfo(e.target.value) : setDismissInfo(e.target.value))}
|
||||
placeholder={btnType === "reply" ? "请输入回复内容" : "请输入驳回原因"}
|
||||
autoSize={{ minRows: 3, maxRows: 5 }}
|
||||
/>
|
||||
|
||||
<div className="flex space-x-4">
|
||||
<Button className="w-full mt-2" onClick={() => setIsModalOpen(false)}>取消</Button>
|
||||
<Button type="primary" className="w-full mt-2" onClick={btnType === "reply" ? handleReply : handleDismiss}>确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button, Card, Dropdown, message, Modal } from "antd";
|
||||
import { getLinkListAPI, delLinkDataAPI, auditWebDataAPI } from '@/api/Web';
|
||||
import { getCommentListAPI, auditCommentDataAPI, delCommentDataAPI, addCommentDataAPI } from "@/api/Comment";
|
||||
import { getWallListAPI, auditWallDataAPI, delWallDataAPI } from "@/api/Wall";
|
||||
import { Card, Spin } from "antd";
|
||||
import { getLinkListAPI } from '@/api/Web';
|
||||
import { getCommentListAPI } from "@/api/Comment";
|
||||
import { getWallListAPI } from "@/api/Wall";
|
||||
|
||||
import Title from "@/components/Title";
|
||||
|
||||
@@ -10,213 +10,14 @@ import comment from './image/comment.svg';
|
||||
import info from './image/message.svg';
|
||||
import link from './image/link.svg';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import RandomAvatar from "@/components/RandomAvatar";
|
||||
import Empty from "@/components/Empty";
|
||||
|
||||
import { useUserStore, useWebStore } from '@/stores';
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { sendDismissEmailAPI } from "@/api/Email";
|
||||
import List from "./components/List";
|
||||
|
||||
type Menu = "comment" | "link" | "wall";
|
||||
|
||||
interface ListItemProps {
|
||||
item: any;
|
||||
type: Menu;
|
||||
fetchData: (type: Menu) => void;
|
||||
}
|
||||
export default () => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const ListItem = ({ item, type, fetchData }: ListItemProps) => {
|
||||
const web = useWebStore(state => state.web)
|
||||
const user = useUserStore(state => state.user)
|
||||
|
||||
const [btnType, setBtnType] = useState<"reply" | "dismiss" | string>("")
|
||||
|
||||
// 通过
|
||||
const handleApproval = async () => {
|
||||
if (type === "link") {
|
||||
await auditWebDataAPI(item.id);
|
||||
} else if (type === "comment") {
|
||||
await auditCommentDataAPI(item.id);
|
||||
} else if (type === "wall") {
|
||||
await auditWallDataAPI(item.id);
|
||||
}
|
||||
|
||||
btnType != "reply" && message.success('🎉 审核成功');
|
||||
fetchData(type);
|
||||
};
|
||||
|
||||
// 回复
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [replyInfo, setReplyInfo] = useState("")
|
||||
const handleReply = async () => {
|
||||
// 审核通过评论
|
||||
await handleApproval()
|
||||
|
||||
// 发送回复内容
|
||||
await addCommentDataAPI({
|
||||
avatar: user.avatar,
|
||||
url: web.url,
|
||||
content: replyInfo,
|
||||
commentId: item?.id!,
|
||||
auditStatus: 1,
|
||||
email: user.email ? user.email : null,
|
||||
name: user.name,
|
||||
articleId: item?.articleId!,
|
||||
createTime: new Date().getTime().toString(),
|
||||
})
|
||||
|
||||
message.success('🎉 回复成功');
|
||||
setIsModalOpen(false)
|
||||
fetchData(type);
|
||||
setReplyInfo("")
|
||||
setBtnType("")
|
||||
}
|
||||
|
||||
// 驳回
|
||||
const [dismissInfo, setDismissInfo] = useState("")
|
||||
const handleDismiss = async () => {
|
||||
if (type === "link") {
|
||||
await delLinkDataAPI(item.id);
|
||||
} else if (type === "comment") {
|
||||
await delCommentDataAPI(item.id);
|
||||
} else if (type === "wall") {
|
||||
await delWallDataAPI(item.id);
|
||||
}
|
||||
|
||||
// 有内容就发送驳回通知邮件,反之直接删除
|
||||
if (dismissInfo.trim().length) await sendDismissEmail()
|
||||
|
||||
message.success('🎉 驳回成功');
|
||||
setIsModalOpen(false)
|
||||
fetchData(type);
|
||||
setDismissInfo("")
|
||||
setBtnType("")
|
||||
};
|
||||
|
||||
// 发送驳回通知邮件
|
||||
const sendDismissEmail = async () => {
|
||||
// 类型名称
|
||||
let email_info = {
|
||||
name: "",
|
||||
type: "",
|
||||
url: ""
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "link":
|
||||
email_info = {
|
||||
name: item.title,
|
||||
type: "友链",
|
||||
url: `${web.url}/friend`,
|
||||
}
|
||||
break;
|
||||
case "comment":
|
||||
email_info = {
|
||||
name: item.name,
|
||||
type: "评论",
|
||||
url: `${web.url}/article/${item.articleId}`,
|
||||
}
|
||||
break;
|
||||
case "wall":
|
||||
email_info = {
|
||||
name: item.name,
|
||||
type: "留言",
|
||||
url: `${web.url}/wall/all`,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 有邮箱才会邮件通知
|
||||
item.email != null && await sendDismissEmailAPI({
|
||||
to: item.email,
|
||||
content: dismissInfo,
|
||||
recipient: email_info.name,
|
||||
subject: `${email_info.type}驳回通知`,
|
||||
time: dayjs(Date.now()).format('YYYY年MM月DD日 HH:mm'),
|
||||
type: email_info.type,
|
||||
url: email_info.url
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div key={item.id}>
|
||||
<div className="text-center text-xs text-[#e0e0e0] mb-4">
|
||||
{dayjs(+item.createTime!).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between md:p-7 rounded-md transition-colors">
|
||||
<div className="flex mr-10">
|
||||
{type !== "wall" ? (
|
||||
<img src={item.avatar || item.image} alt="" className="w-13 h-13 border border-[#eee] rounded-full" />
|
||||
) : <RandomAvatar className="w-13 h-13 border border-[#eee] rounded-full" />}
|
||||
|
||||
<div className="flex flex-col justify-center ml-4 px-4 py-2 min-w-[210px] text-xs md:text-sm bg-[#F9F9FD] dark:bg-[#4e5969] rounded-md">
|
||||
{type === "link" ? (
|
||||
<>
|
||||
<div>名称:{item.title}</div>
|
||||
<div>介绍:{item.description}</div>
|
||||
<div>类型:{item.type.name}</div>
|
||||
<div>网站:{item?.url ? <a href={item?.url} target='_blank' className="hover:text-primary font-bold">{item?.url}</a> : '无网站'}</div>
|
||||
</>
|
||||
) : type === "comment" ? (
|
||||
<>
|
||||
<div>名称:{item.name}</div>
|
||||
<div>内容:{item.content}</div>
|
||||
<div>网站:{item?.url ? <a href={item?.url} target='_blank' className="hover:text-primary font-bold">{item?.url}</a> : '无网站'}</div>
|
||||
<div>所属文章:<a href={`${web.url}/article/${item.articleId}`} target='_blank' className="hover:text-primary">{item.articleTitle || '暂无'}</a></div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div>名称:{item.name}</div>
|
||||
<div>内容:{item.content}</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div>邮箱:{item.email || '暂无'}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-end">
|
||||
<Dropdown menu={{
|
||||
items: type === "comment"
|
||||
? [
|
||||
{ key: 'ok', label: "通过", onClick: handleApproval },
|
||||
{ key: 'reply', label: "回复", onClick: () => [setIsModalOpen(true), setBtnType("reply")] },
|
||||
{ key: 'dismiss', label: "驳回", onClick: () => [setIsModalOpen(true), , setBtnType("dismiss")] }
|
||||
]
|
||||
: [
|
||||
{ key: 'ok', label: "通过", onClick: handleApproval },
|
||||
{ key: 'dismiss', label: "驳回", onClick: () => [setIsModalOpen(true), , setBtnType("dismiss")] }
|
||||
]
|
||||
}}>
|
||||
<div className="flex justify-evenly items-center bg-[#F9F9FD] dark:bg-[#4e5969] w-11 h-5 rounded-md cursor-pointer">
|
||||
<span className="inline-block w-2 h-2 bg-[#b5c2d3] rounded-full"></span>
|
||||
<span className="inline-block w-2 h-2 bg-[#b5c2d3] rounded-full"></span>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal title={btnType === "reply" ? "回复内容" : "驳回原因"} open={isModalOpen} footer={null} onCancel={() => setIsModalOpen(false)} onClose={() => setIsModalOpen(false)}>
|
||||
<TextArea
|
||||
value={btnType === "reply" ? replyInfo : dismissInfo}
|
||||
onChange={(e) => (btnType === "reply" ? setReplyInfo(e.target.value) : setDismissInfo(e.target.value))}
|
||||
placeholder={btnType === "reply" ? "请输入回复内容" : "请输入驳回原因"}
|
||||
autoSize={{ minRows: 3, maxRows: 5 }}
|
||||
/>
|
||||
|
||||
<div className="flex space-x-4">
|
||||
<Button className="w-full mt-2" onClick={() => setIsModalOpen(false)}>取消</Button>
|
||||
<Button type="primary" className="w-full mt-2" onClick={btnType === "reply" ? handleReply : handleDismiss}>确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const WorkPage = () => {
|
||||
const activeSty = "bg-[#f9f9ff] dark:bg-[#3c5370] text-primary";
|
||||
const [active, setActive] = useState<Menu>("comment");
|
||||
const [commentList, setCommentList] = useState<any[]>([]);
|
||||
@@ -225,19 +26,26 @@ const WorkPage = () => {
|
||||
|
||||
// 重新获取最新数据
|
||||
const fetchData = async (type: Menu) => {
|
||||
if (type === "comment") {
|
||||
const { data } = await getCommentListAPI({ query: { status: 0 }, pattern: "list" });
|
||||
setCommentList(data);
|
||||
} else if (type === "link") {
|
||||
const { data } = await getLinkListAPI({ query: { status: 0 } });
|
||||
setLinkList(data);
|
||||
} else if (type === "wall") {
|
||||
const { data } = await getWallListAPI({ query: { status: 0 } });
|
||||
setWallList(data);
|
||||
try {
|
||||
if (type === "comment") {
|
||||
const { data } = await getCommentListAPI({ query: { status: 0 }, pattern: "list" });
|
||||
setCommentList(data);
|
||||
} else if (type === "link") {
|
||||
const { data } = await getLinkListAPI({ query: { status: 0 } });
|
||||
setLinkList(data);
|
||||
} else if (type === "wall") {
|
||||
const { data } = await getWallListAPI({ query: { status: 0 } });
|
||||
setWallList(data);
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
fetchData(active);
|
||||
}, [active]);
|
||||
|
||||
@@ -246,39 +54,40 @@ const WorkPage = () => {
|
||||
return <Empty />;
|
||||
}
|
||||
return list.map(item => (
|
||||
<ListItem key={item.id} item={item} type={type} fetchData={(type) => fetchData(type)} />
|
||||
<List key={item.id} item={item} type={type} fetchData={(type) => fetchData(type)} />
|
||||
));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title value="工作台" />
|
||||
<Card className="mt-2 min-h-[calc(100vh-180px)]">
|
||||
<div className="flex flex-col md:flex-row w-full">
|
||||
<div className="w-full min-w-[200px] md:w-2/12 md:min-h-96 mb-5 md:mb-0 pr-4 md:border-b-transparent md:border-r border-[#eee] dark:border-strokedark">
|
||||
<ul className="space-y-1">
|
||||
{(["comment", "link", "wall"] as Menu[]).map((menu) => (
|
||||
<li
|
||||
key={menu}
|
||||
className={`flex items-center w-full py-3 px-4 hover:bg-[#f9f9ff] dark:hover:bg-[#3c5370] hover:text-primary ${active === menu ? activeSty : ''} rounded-md text-base cursor-pointer transition-colors`}
|
||||
onClick={() => setActive(menu)}
|
||||
>
|
||||
<img src={menu === "comment" ? comment : menu === "link" ? link : info} alt="" className="w-8 mr-4" />
|
||||
<span>{menu === "comment" ? "评论" : menu === "link" ? "友联" : "留言"}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-10/12 md:pl-6 py-4 space-y-10">
|
||||
{active === "link" && renderList(linkList, "link")}
|
||||
{active === "comment" && renderList(commentList, "comment")}
|
||||
{active === "wall" && renderList(wallList, "wall")}
|
||||
<Spin spinning={loading}>
|
||||
<Card className="mt-2 min-h-[calc(100vh-180px)]">
|
||||
<div className="flex flex-col md:flex-row w-full">
|
||||
<div className="w-full min-w-[200px] md:w-2/12 md:min-h-96 mb-5 md:mb-0 pr-4 md:border-b-transparent md:border-r border-[#eee] dark:border-strokedark">
|
||||
<ul className="space-y-1">
|
||||
{(["comment", "link", "wall"] as Menu[]).map((menu) => (
|
||||
<li
|
||||
key={menu}
|
||||
className={`flex items-center w-full py-3 px-4 hover:bg-[#f9f9ff] dark:hover:bg-[#3c5370] hover:text-primary ${active === menu ? activeSty : ''} rounded-md text-base cursor-pointer transition-colors`}
|
||||
onClick={() => setActive(menu)}
|
||||
>
|
||||
<img src={menu === "comment" ? comment : menu === "link" ? link : info} alt="" className="w-8 mr-4" />
|
||||
<span>{menu === "comment" ? "评论" : menu === "link" ? "友联" : "留言"}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-10/12 md:pl-6 py-4 space-y-10">
|
||||
{active === "link" && renderList(linkList, "link")}
|
||||
{active === "comment" && renderList(commentList, "comment")}
|
||||
{active === "wall" && renderList(wallList, "wall")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Card>
|
||||
</Spin>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default WorkPage;
|
||||
}
|
||||
Reference in New Issue
Block a user