大改动

This commit is contained in:
宇阳
2025-01-11 22:53:12 +08:00
parent c0946a7f40
commit 2a1391da72
13 changed files with 443 additions and 344 deletions

View File

@@ -12,7 +12,7 @@ import axios from 'axios';
const FootprintPage = () => { const FootprintPage = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [btnLoading, setBtnLoading] = useState(false) const [btnLoading, setBtnLoading] = useState(false)
const [modalLoading, setModalLoading] = useState(false) const [editLoading, setEditLoading] = useState(false)
const [footprintList, setFootprintList] = useState<Footprint[]>([]); const [footprintList, setFootprintList] = useState<Footprint[]>([]);
const [isModelOpen, setIsModelOpen] = useState(false); const [isModelOpen, setIsModelOpen] = useState(false);
@@ -129,7 +129,7 @@ const FootprintPage = () => {
}; };
const editFootprintData = async (id: number) => { const editFootprintData = async (id: number) => {
setModalLoading(true); setEditLoading(true);
try { try {
setIsMethod("edit"); setIsMethod("edit");
@@ -143,10 +143,10 @@ const FootprintPage = () => {
setFootprint(data); setFootprint(data);
form.setFieldsValue(data); form.setFieldsValue(data);
} catch (error) { } catch (error) {
setModalLoading(false); setEditLoading(false);
} }
setModalLoading(false); setEditLoading(false);
}; };
const onSubmit = async () => { const onSubmit = async () => {
@@ -196,7 +196,7 @@ const FootprintPage = () => {
// 通过详细地址获取纬度 // 通过详细地址获取纬度
const getGeocode = async () => { const getGeocode = async () => {
setModalLoading(true) setEditLoading(true)
try { try {
const address = form.getFieldValue("address") const address = form.getFieldValue("address")
@@ -215,14 +215,14 @@ const FootprintPage = () => {
// 立即触发校验 // 立即触发校验
form.validateFields(['position']); form.validateFields(['position']);
setModalLoading(false) setEditLoading(false)
return data.geocodes[0].location; return data.geocodes[0].location;
} else { } else {
message.warning('未找到该地址的经纬度'); message.warning('未找到该地址的经纬度');
} }
} catch (error) { } catch (error) {
setModalLoading(false) setEditLoading(false)
} }
@@ -266,7 +266,7 @@ const FootprintPage = () => {
/> />
</Card> </Card>
<Modal loading={modalLoading} title={isMethod === "edit" ? "编辑足迹" : "新增足迹"} open={isModelOpen} onCancel={closeModel} destroyOnClose footer={null}> <Modal loading={editLoading} title={isMethod === "edit" ? "编辑足迹" : "新增足迹"} open={isModelOpen} onCancel={closeModel} destroyOnClose footer={null}>
<Form form={form} layout="vertical" initialValues={footprint} size='large' preserve={false} className='mt-6'> <Form form={form} layout="vertical" initialValues={footprint} size='large' preserve={false} className='mt-6'>
<Form.Item label="标题" name="title" rules={[{ required: true, message: '标题不能为空' }]}> <Form.Item label="标题" name="title" rules={[{ required: true, message: '标题不能为空' }]}>
<Input placeholder="请输入标题" /> <Input placeholder="请输入标题" />

View File

@@ -9,7 +9,7 @@ import { titleSty } from '@/styles/sty';
const StoragePage = () => { const StoragePage = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [btnLoading, setBtnLoading] = useState(false); const [btnLoading, setBtnLoading] = useState(false);
const [modalLoading, setModalLoading] = useState(false) const [editLoading, setEditLoading] = useState(false)
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [oss, setOss] = useState<Oss>({} as Oss); const [oss, setOss] = useState<Oss>({} as Oss);
@@ -122,7 +122,7 @@ const StoragePage = () => {
}; };
const editOssData = async (record: Oss) => { const editOssData = async (record: Oss) => {
setModalLoading(true) setEditLoading(true)
try { try {
setIsModalOpen(true); setIsModalOpen(true);
@@ -131,10 +131,10 @@ const StoragePage = () => {
setOss(data); setOss(data);
form.setFieldsValue(data); form.setFieldsValue(data);
} catch (error) { } catch (error) {
setModalLoading(false) setEditLoading(false)
} }
setModalLoading(false) setEditLoading(false)
}; };
const delOssData = async (id: number) => { const delOssData = async (id: number) => {
@@ -207,7 +207,7 @@ const StoragePage = () => {
</Card> </Card>
<Modal <Modal
loading={modalLoading} loading={editLoading}
title={oss.id ? "编辑存储配置" : "新增存储配置"} title={oss.id ? "编辑存储配置" : "新增存储配置"}
open={isModalOpen} open={isModalOpen}
onCancel={handleCancel} onCancel={handleCancel}

View File

@@ -15,34 +15,39 @@ export interface FilterForm {
} }
const RecordPage = () => { const RecordPage = () => {
const [current, setCurrent] = useState<number>(1);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [recordList, setRecordList] = useState<Record[]>([]);
const [recordList, setRecordList] = useState<Record[]>([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const getRecordList = async () => { const getRecordList = async () => {
setLoading(true); try {
const { data } = await getRecordListAPI(); const { data } = await getRecordListAPI();
setRecordList(data as Record[]); setRecordList(data as Record[]);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRecordList() getRecordList()
}, []); }, []);
const delRecordData = async (id: number) => { const delRecordData = async (id: number) => {
setLoading(true); setLoading(true);
await delRecordDataAPI(id); try {
await getRecordList(); await delRecordDataAPI(id);
form.resetFields() await getRecordList();
setCurrent(1) form.resetFields()
notification.success({ message: '🎉 删除说说成功' }) notification.success({ message: '🎉 删除说说成功' })
} catch (error) {
setLoading(false); setLoading(false);
}
}; };
const columns = [ const columns = [
@@ -110,15 +115,23 @@ const RecordPage = () => {
}, },
]; ];
const onSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
const query = { setLoading(true);
key: values.content,
startDate: values.createTime && values.createTime[0].valueOf() + '', try {
endDate: values.createTime && values.createTime[1].valueOf() + '' const query = {
key: values.content,
startDate: values.createTime && values.createTime[0].valueOf() + '',
endDate: values.createTime && values.createTime[1].valueOf() + ''
}
const { data } = await getRecordListAPI({ query });
setRecordList(data as Record[]);
} catch (error) {
setLoading(false);
} }
const { data } = await getRecordListAPI({ query }); setLoading(false);
setRecordList(data as Record[]);
} }
return ( return (
@@ -126,7 +139,7 @@ const RecordPage = () => {
<Title value="说说管理" /> <Title value="说说管理" />
<Card className='my-2 overflow-scroll'> <Card className='my-2 overflow-scroll'>
<Form form={form} layout="inline" onFinish={onSubmit} autoComplete="off" className='flex-nowrap'> <Form form={form} layout="inline" onFinish={onFilterSubmit} autoComplete="off" className='flex-nowrap'>
<Form.Item label="内容" name="content" className='min-w-[200px]'> <Form.Item label="内容" name="content" className='min-w-[200px]'>
<Input placeholder='请输入关键词' /> <Input placeholder='请输入关键词' />
</Form.Item> </Form.Item>
@@ -150,11 +163,7 @@ const RecordPage = () => {
scroll={{ x: 'max-content' }} scroll={{ x: 'max-content' }}
pagination={{ pagination={{
position: ['bottomCenter'], position: ['bottomCenter'],
current,
defaultPageSize: 8, defaultPageSize: 8,
onChange(current) {
setCurrent(current)
}
}} }}
/> />
</Card> </Card>

View File

@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Table, Button, Form, Input, Popconfirm, message, Card, Modal, Transfer, Spin } from 'antd'; import { Table, Button, Form, Input, Popconfirm, message, Card, Modal, Transfer, Spin } from 'antd';
import { getRouteListAPI } from '@/api/Route'; import { getRouteListAPI } from '@/api/Route';
import { getRoleListAPI, addRoleDataAPI, editRoleDataAPI, delRoleDataAPI, getRouteListAPI as getRoleRouteListAPI, bindingRouteAPI } from '@/api/Role'; import { getRoleListAPI, addRoleDataAPI, editRoleDataAPI, delRoleDataAPI, getRouteListAPI as getRoleRouteListAPI, bindingRouteAPI, getRoleDataAPI } from '@/api/Role';
import { Role } from '@/types/app/role'; import { Role } from '@/types/app/role';
import Title from '@/components/Title'; import Title from '@/components/Title';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
@@ -9,8 +9,11 @@ import "./index.scss"
const RolePage = () => { const RolePage = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [btnLoading, setBtnLoading] = useState(false)
const [editLoading, setEditLoading] = useState<boolean>(false);
const [bindingLoading, setBindingLoading] = useState<boolean>(false); const [bindingLoading, setBindingLoading] = useState<boolean>(false);
const [addLoading, setAddLoading] = useState(false)
const [form] = Form.useForm();
const [id, setId] = useState(0) const [id, setId] = useState(0)
const [role, setRole] = useState<Role>({} as Role); const [role, setRole] = useState<Role>({} as Role);
@@ -44,7 +47,6 @@ const RolePage = () => {
// 获取指定角色的路由列表 // 获取指定角色的路由列表
const getRoleRouteList = async (id: number) => { const getRoleRouteList = async (id: number) => {
const { data } = await getRoleRouteListAPI(id); const { data } = await getRoleRouteListAPI(id);
setTargetKeys(data.map(item => item.id) as number[]) setTargetKeys(data.map(item => item.id) as number[])
}; };
@@ -56,75 +58,95 @@ const RolePage = () => {
// 获取角色列表 // 获取角色列表
const getRoleList = async () => { const getRoleList = async () => {
setLoading(true); try {
const { data } = await getRoleListAPI(); const { data } = await getRoleListAPI();
setRoleList(data as Role[]); setRoleList(data as Role[]);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRoleList() getRoleList()
getRouteList() getRouteList()
}, []); }, []);
// 绑定路由
const [form] = Form.useForm();
const bindingRoute = (record: Role) => { const bindingRoute = (record: Role) => {
setIsModalOpen(true) setIsModalOpen(true)
getRoleRouteList(record.id) getRoleRouteList(record.id)
setId(record.id) setId(record.id)
} }
const editRoleData = (record: Role) => { const editRoleData = async (record: Role) => {
setRole(record); setEditLoading(true);
form.setFieldsValue(record);
try {
const { data } = await getRoleDataAPI(record.id);
setRole(data);
form.setFieldsValue(data);
} catch (error) {
setEditLoading(false);
}
setEditLoading(false);
}; };
const delRoleData = async (id: number) => { const delRoleData = async (id: number) => {
setLoading(true); setLoading(true);
await delRoleDataAPI(id);
message.success('🎉 删除角色成功'); try {
getRoleList(); await delRoleDataAPI(id);
await getRoleList();
message.success('🎉 删除角色成功');
} catch (error) {
setLoading(false);
}
}; };
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true); setBtnLoading(true)
setAddLoading(true)
form.validateFields().then(async (values: Role) => { try {
if (role.id) { form.validateFields().then(async (values: Role) => {
await editRoleDataAPI({ ...role, ...values }); if (role.id) {
message.success('🎉 编辑角色成功'); await editRoleDataAPI({ ...role, ...values });
} else { message.success('🎉 编辑角色成功');
await addRoleDataAPI(values); } else {
message.success('🎉 新增角色成功'); await addRoleDataAPI(values);
} message.success('🎉 新增角色成功');
}
getRoleList(); await getRoleList();
form.resetFields(); form.resetFields();
form.setFieldsValue({ name: '', description: '' }) form.setFieldsValue({ name: '', description: '' })
setRole({} as Role); setRole({} as Role);
}); });
} catch (error) {
setBtnLoading(false)
}
setAddLoading(false) setBtnLoading(false)
}; };
const onChange: any = (list: number[]) => { // 设置目标路由
setTargetKeys(list); const onChange: any = (list: number[]) => setTargetKeys(list);
};
// 绑定路由 // 绑定路由
const onBindingRouteSubmit = async () => { const onBindingRouteSubmit = async () => {
setBindingLoading(true); setBindingLoading(true);
await bindingRouteAPI(id, targetKeys)
setBindingLoading(false)
message.success('🎉 绑定成功'); try {
setIsModalOpen(false) await bindingRouteAPI(id, targetKeys)
message.success('🎉 绑定成功');
// 刷新页面 // 刷新页面
window.location.reload() window.location.reload()
} catch (error) {
setBindingLoading(false);
}
} }
// 让n改变 触发Transfer重新渲染 // 让n改变 触发Transfer重新渲染
@@ -157,7 +179,7 @@ const RolePage = () => {
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" loading={addLoading} className="w-full">{role.id ? '编辑角色' : '新增角色'}</Button> <Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{role.id ? '编辑角色' : '新增角色'}</Button>
</Form.Item> </Form.Item>
</Form> </Form>
</Card> </Card>
@@ -177,7 +199,7 @@ const RolePage = () => {
</Card> </Card>
</div> </div>
<Modal title="角色权限" open={isModalOpen} onCancel={() => [setIsModalOpen(false), setN(n + 1)]} footer={null} className='RolePageModal'> <Modal loading={editLoading} title="角色权限" open={isModalOpen} onCancel={() => [setIsModalOpen(false), setN(n + 1)]} footer={null} className='RolePageModal'>
<div className='flex justify-center py-6'> <div className='flex justify-center py-6'>
<Spin spinning={bindingLoading}> <Spin spinning={bindingLoading}>
<Transfer <Transfer

View File

@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Table, Button, Form, Input, Popconfirm, message, Card } from 'antd'; import { Table, Button, Form, Input, Popconfirm, message, Card } from 'antd';
import { getRouteListAPI, addRouteDataAPI, editRouteDataAPI, delRouteDataAPI } from '@/api/Route'; import { getRouteListAPI, addRouteDataAPI, editRouteDataAPI, delRouteDataAPI, getRouteDataAPI } from '@/api/Route';
import { Route } from '@/types/app/route'; import { Route } from '@/types/app/route';
import Title from '@/components/Title'; import Title from '@/components/Title';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
@@ -9,6 +9,8 @@ const RoutePage = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [btnLoading, setBtnLoading] = useState(false) const [btnLoading, setBtnLoading] = useState(false)
const [form] = Form.useForm();
const [route, setRoute] = useState<Route>({} as Route); const [route, setRoute] = useState<Route>({} as Route);
const [list, setList] = useState<Route[]>([]); const [list, setList] = useState<Route[]>([]);
@@ -30,50 +32,73 @@ const RoutePage = () => {
]; ];
const getRouteList = async () => { const getRouteList = async () => {
setLoading(true); try {
const { data } = await getRouteListAPI(); const { data } = await getRouteListAPI();
setList(data as Route[]); setList(data);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRouteList(); getRouteList();
}, []); }, []);
const [form] = Form.useForm(); const editRouteData = async (record: Route) => {
const editRouteData = (record: Route) => { setLoading(true)
setRoute(record);
form.setFieldsValue(record); try {
const { data } = await getRouteDataAPI(record.id);
setRoute(data);
form.setFieldsValue(data);
} catch (error) {
setLoading(false)
}
setLoading(false)
}; };
const delRouteData = async (id: number) => { const delRouteData = async (id: number) => {
setLoading(true); setLoading(true);
await delRouteDataAPI(id);
message.success('🎉 删除路由成功'); try {
getRouteList(); await delRouteDataAPI(id);
await getRouteList();
message.success('🎉 删除路由成功');
} catch (error) {
setLoading(false)
}
}; };
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true); setLoading(true);
setBtnLoading(true) setBtnLoading(true)
form.validateFields().then(async (values: Route) => { try {
form.validateFields().then(async (values: Route) => {
if (route.id) {
await editRouteDataAPI({ ...route, ...values });
message.success('🎉 编辑路由成功');
} else {
await addRouteDataAPI(values);
message.success('🎉 新增路由成功');
}
if (route.id) { await getRouteList();
await editRouteDataAPI({ ...route, ...values }); form.resetFields();
message.success('🎉 编辑路由成功'); form.setFieldsValue({ path: '', description: '' })
} else { setRoute({} as Route);
await addRouteDataAPI(values); });
message.success('🎉 新增路由成功'); } catch (error) {
} setLoading(false)
setBtnLoading(true)
}
getRouteList(); setLoading(false)
form.resetFields(); setBtnLoading(true)
form.setFieldsValue({ path: '', description: '' })
setRoute({} as Route);
});
setBtnLoading(false)
}; };
return ( return (

View File

@@ -13,18 +13,24 @@ const IconText = ({ icon, text }: { icon: React.FC; text: string }) => (
</Space> </Space>
); );
const RssPage = () => { export default () => {
const [list, setList] = useState<Rss[]>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [list, setList] = useState<Rss[]>([]);
const getRssList = async () => { const getRssList = async () => {
setLoading(true); try {
const { data } = await getRssListAPI(); const { data } = await getRssListAPI();
setList(data as Rss[]); setList(data);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRssList(); getRssList();
}, []); }, []);
@@ -32,8 +38,8 @@ const RssPage = () => {
<> <>
<Title value='订阅中心' /> <Title value='订阅中心' />
<Card className='mt-2 min-h-[calc(100vh-180px)]'> <Spin spinning={loading}>
<Spin spinning={loading}> <Card className='mt-2 min-h-[calc(100vh-180px)]'>
<List <List
dataSource={list} dataSource={list}
size="large" size="large"
@@ -62,10 +68,8 @@ const RssPage = () => {
</List.Item> </List.Item>
)} )}
/> />
</Spin> </Card>
</Card> </Spin>
</> </>
); );
}; };
export default RssPage;

View File

@@ -12,36 +12,43 @@ interface UserForm {
} }
const UserPage = () => { const UserPage = () => {
const [form] = Form.useForm<UserForm>();
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [form] = Form.useForm<UserForm>();
const store = useUserStore(); const store = useUserStore();
const getUserData = async () => { const getUserData = async () => {
setLoading(true); try {
const { data } = await getUserDataAPI(store.user?.id);
const { data } = await getUserDataAPI(store.user?.id); store.setUser(data);
store.setUser(data); form.setFieldsValue(data);
form.setFieldsValue(data); } catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getUserData(); getUserData();
}, []); }, []);
const onSubmit = async (values: UserForm) => { const onSubmit = async (values: UserForm) => {
setLoading(true) setLoading(true)
await editUserDataAPI({ try {
id: store.user.id, ...values, await editUserDataAPI({
role: undefined id: store.user.id, ...values,
}); role: undefined
message.success("🎉 修改用户信息成功"); });
store.setUser(values as User);
getUserData();
setLoading(false) await getUserData();
message.success("🎉 修改用户信息成功");
store.setUser(values as User);
} catch (error) {
setLoading(false)
}
}; };
return ( return (
@@ -88,7 +95,7 @@ const UserPage = () => {
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" className="w-full" loading={loading}></Button> <Button type="primary" htmlType="submit" className="w-full" loading={loading}></Button>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>

View File

@@ -35,29 +35,23 @@ const SystemPage = () => {
}; };
const handleSubmit = async (values: EditUser) => { const handleSubmit = async (values: EditUser) => {
try { setLoading(true)
setLoading(true)
try {
await editAdminPassAPI(values); await editAdminPassAPI(values);
confirm({ confirm({
title: '提示', title: '提示',
content: '🔒️ 修改成功,请重新登录', content: '🔒️ 修改成功,请重新登录',
okText: '确定', okText: '确定',
onOk: () => { onOk: store.quitLogin,
store.quitLogin();
},
cancelButtonProps: { style: { display: 'none' } } cancelButtonProps: { style: { display: 'none' } }
}); });
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
notification.error({
message: '错误',
description: '修改密码失败,请重试:' + error
});
} }
setLoading(false)
}; };
return ( return (
@@ -97,9 +91,7 @@ const SystemPage = () => {
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" loading={loading} className="w-full"> <Button type="primary" htmlType="submit" loading={loading} className="w-full"></Button>
</Button>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>

View File

@@ -6,66 +6,68 @@ import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project';
const RecordTheme = () => { const RecordTheme = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
// const [theme, setTheme] = useState<Theme>({} as Theme);
const [form] = Form.useForm(); const [form] = Form.useForm();
const getLayoutData = async () => { const getLayoutData = async () => {
setLoading(true); try {
const { data } = await getConfigDataAPI<Theme>("layout");
const { data } = await getConfigDataAPI<Theme>("layout"); form.setFieldsValue({
record_name: data.record_name,
// setTheme(data); record_info: data.record_info
});
form.setFieldsValue({ } catch (error) {
record_name: data.record_name, setLoading(false);
record_info: data.record_info }
});
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getLayoutData(); getLayoutData();
}, []); }, []);
const editThemeData = async (values: { record_name: string, record_info: string }) => { const editThemeData = async (values: { record_name: string, record_info: string }) => {
setLoading(true); setLoading(true);
await editConfigDataAPI("layout", values); try {
await editConfigDataAPI("layout", values);
notification.success({ notification.success({
message: '成功', message: '成功',
description: '🎉 修改主题成功', description: '🎉 修改主题成功',
}); });
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
return ( return (
<> <div>
<Spin spinning={loading} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}> <h2 className="text-xl pb-4 pl-10"></h2>
<h2 className="text-xl pb-4 pl-10"></h2>
<div className='w-full lg:w-[500px] md:ml-10'> <div className='w-full lg:w-[500px] md:ml-10'>
<Form form={form} onFinish={editThemeData} layout="vertical"> <Form form={form} onFinish={editThemeData} layout="vertical">
<Form.Item name="record_name" label="个人名称"> <Form.Item name="record_name" label="个人名称">
<Input size='large' placeholder="请输入个人名称" /> <Input size='large' placeholder="请输入个人名称" />
</Form.Item> </Form.Item>
<Form.Item name="record_info" label="个人介绍"> <Form.Item name="record_info" label="个人介绍">
<Input.TextArea <Input.TextArea
size='large' size='large'
autoSize={{ minRows: 2, maxRows: 4 }} autoSize={{ minRows: 2, maxRows: 4 }}
placeholder="请输入个人介绍" placeholder="请输入个人介绍"
/> />
</Form.Item> </Form.Item>
<Button type="primary" size="large" className="w-full mt-4" htmlType="submit" loading={loading}></Button> <Button type="primary" size="large" className="w-full mt-4" htmlType="submit" loading={loading}></Button>
</Form> </Form>
</div> </div>
</Spin> </div>
</>
); );
}; };

View File

@@ -7,6 +7,7 @@ import FileUpload from '@/components/FileUpload';
const SynthesisTheme = () => { const SynthesisTheme = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [theme, setTheme] = useState<Theme>({} as Theme); const [theme, setTheme] = useState<Theme>({} as Theme);
@@ -20,45 +21,52 @@ const SynthesisTheme = () => {
}; };
const getLayoutData = async () => { const getLayoutData = async () => {
setLoading(true); try {
const { data } = await getConfigDataAPI<Theme>("layout");
setTheme(data);
const { data } = await getConfigDataAPI<Theme>("layout"); form.setFieldsValue({
setTheme(data); light_logo: data.light_logo,
dark_logo: data.dark_logo,
form.setFieldsValue({ swiper_image: data.swiper_image,
light_logo: data.light_logo, swiper_text: data.swiper_text ? JSON.parse(data.swiper_text).join('\n') : '',
dark_logo: data.dark_logo, social: data.social,
swiper_image: data.swiper_image, covers: data.covers ? JSON.parse(data.covers).join("\n") : '',
swiper_text: data.swiper_text ? JSON.parse(data.swiper_text).join('\n') : '', reco_article: data.reco_article ? JSON.parse(data.reco_article).join("\n") : '',
social: data.social, });
covers: data.covers ? JSON.parse(data.covers).join("\n") : '', } catch (error) {
reco_article: data.reco_article ? JSON.parse(data.reco_article).join("\n") : '', setLoading(false);
}); }
setLoading(false); setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getLayoutData(); getLayoutData();
}, []); }, []);
const editThemeData = async (values: any) => { const editThemeData = async (values: any) => {
setLoading(true); setLoading(true);
const updatedLayout = { try {
...theme, const updatedLayout = {
...values, ...theme,
swiper_text: JSON.stringify(values.swiper_text.split('\n')), ...values,
covers: JSON.stringify(values.covers.split('\n')), swiper_text: JSON.stringify(values.swiper_text.split('\n')),
reco_article: JSON.stringify(values.reco_article.split('\n')), covers: JSON.stringify(values.covers.split('\n')),
}; reco_article: JSON.stringify(values.reco_article.split('\n')),
};
await editConfigDataAPI("layout", updatedLayout); await editConfigDataAPI("layout", updatedLayout);
notification.success({ notification.success({
message: '成功', message: '成功',
description: '🎉 修改主题成功', description: '🎉 修改主题成功',
}); });
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
@@ -72,117 +80,115 @@ const SynthesisTheme = () => {
); );
return ( return (
<> <div>
<Spin spinning={loading} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}> <h2 className="text-xl pb-4 pl-10"></h2>
<h2 className="text-xl pb-4 pl-10"></h2>
<div className='w-full lg:w-[500px] md:ml-10'> <div className='w-full lg:w-[500px] md:ml-10'>
<Form form={form} onFinish={editThemeData} layout="vertical"> <Form form={form} onFinish={editThemeData} layout="vertical">
<Divider orientation="left"> Logo</Divider> <Divider orientation="left"> Logo</Divider>
<Form.Item name="light_logo" label="亮色主题 Logo"> <Form.Item name="light_logo" label="亮色主题 Logo">
<Input <Input
prefix={<PictureOutlined />} prefix={<PictureOutlined />}
addonAfter={<UploadBtn />} addonAfter={<UploadBtn />}
size='large' size='large'
placeholder="请输入亮色Logo地址" placeholder="请输入亮色Logo地址"
/> />
</Form.Item> </Form.Item>
<img src={form.getFieldValue('light_logo')} alt="" className="w-1/3 mt-4 rounded" /> <img src={form.getFieldValue('light_logo')} alt="" className="w-1/3 mt-4 rounded" />
<Divider orientation="left"> Logo</Divider> <Divider orientation="left"> Logo</Divider>
<Form.Item name="dark_logo" label="暗色主题 Logo"> <Form.Item name="dark_logo" label="暗色主题 Logo">
<Input <Input
prefix={<PictureOutlined />} prefix={<PictureOutlined />}
addonAfter={<UploadBtn />} addonAfter={<UploadBtn />}
size='large' size='large'
placeholder="请输入暗色Logo地址" placeholder="请输入暗色Logo地址"
/> />
</Form.Item> </Form.Item>
<img src={form.getFieldValue('dark_logo')} alt="" className="w-1/3 mt-4 rounded" /> <img src={form.getFieldValue('dark_logo')} alt="" className="w-1/3 mt-4 rounded" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<Form.Item name="swiper_image" label="首页背景图"> <Form.Item name="swiper_image" label="首页背景图">
<Input <Input
prefix={<PictureOutlined />} prefix={<PictureOutlined />}
addonAfter={<UploadBtn />} addonAfter={<UploadBtn />}
size='large' size='large'
placeholder="请输入背景图地址" placeholder="请输入背景图地址"
/> />
</Form.Item> </Form.Item>
<img src={form.getFieldValue('swiper_image')} alt="" className="w-1/3 mt-4 rounded" /> <img src={form.getFieldValue('swiper_image')} alt="" className="w-1/3 mt-4 rounded" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<Form.Item name="swiper_text" label="打字机文本"> <Form.Item name="swiper_text" label="打字机文本">
<Input.TextArea <Input.TextArea
autoSize={{ minRows: 2, maxRows: 4 }} autoSize={{ minRows: 2, maxRows: 4 }}
size='large' size='large'
placeholder="请输入打字机文本" placeholder="请输入打字机文本"
/> />
</Form.Item> </Form.Item>
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" /> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<Form.Item name="social" label="社交网站"> <Form.Item name="social" label="社交网站">
<Input.TextArea <Input.TextArea
autoSize={{ minRows: 2, maxRows: 4 }} autoSize={{ minRows: 2, maxRows: 4 }}
size='large' size='large'
placeholder="请输入社交网站" placeholder="请输入社交网站"
/> />
</Form.Item> </Form.Item>
<Alert message="请务必确保每一项格式正确,否则会导致网站无法访问" type="info" className="mt-2" /> <Alert message="请务必确保每一项格式正确,否则会导致网站无法访问" type="info" className="mt-2" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<Form.Item name="covers" label="文章随机封面"> <Form.Item name="covers" label="文章随机封面">
<Input.TextArea <Input.TextArea
autoSize={{ minRows: 2, maxRows: 4 }} autoSize={{ minRows: 2, maxRows: 4 }}
size='large' size='large'
placeholder="请输入文章随机封面" placeholder="请输入文章随机封面"
/> />
</Form.Item> </Form.Item>
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" /> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<Form.Item name="reco_article" label="作者推荐文章"> <Form.Item name="reco_article" label="作者推荐文章">
<Input.TextArea <Input.TextArea
autoSize={{ minRows: 2, maxRows: 4 }} autoSize={{ minRows: 2, maxRows: 4 }}
size='large' size='large'
placeholder="请输入作者推荐文章ID" placeholder="请输入作者推荐文章ID"
/> />
</Form.Item> </Form.Item>
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" /> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className='overflow-auto w-full'> <div className='overflow-auto w-full'>
<div className="sidebar w-[750px] flex mb-4"> <div className="sidebar w-[750px] flex mb-4">
{['author', 'randomArticle', 'newComments', 'hotArticle'].map((item) => ( {['author', 'randomArticle', 'newComments', 'hotArticle'].map((item) => (
<div key={item} className={`item flex flex-col items-center p-4 m-4 border-2 rounded cursor-pointer ${theme.right_sidebar && JSON.parse(theme.right_sidebar).includes(item) ? 'border-primary' : 'border-[#eee]'}`} onClick={() => onSidebar(item)}> <div key={item} className={`item flex flex-col items-center p-4 m-4 border-2 rounded cursor-pointer ${theme.right_sidebar && JSON.parse(theme.right_sidebar).includes(item) ? 'border-primary' : 'border-[#eee]'}`} onClick={() => onSidebar(item)}>
<p className={`text-center ${theme.right_sidebar && JSON.parse(theme.right_sidebar).includes(item) ? 'text-primary' : ''}`}> <p className={`text-center ${theme.right_sidebar && JSON.parse(theme.right_sidebar).includes(item) ? 'text-primary' : ''}`}>
{item === 'author' ? '作者信息模块' : item === 'hotArticle' ? '作者推荐模块' : item === 'randomArticle' ? '随机推荐模块' : '最新评论模块'} {item === 'author' ? '作者信息模块' : item === 'hotArticle' ? '作者推荐模块' : item === 'randomArticle' ? '随机推荐模块' : '最新评论模块'}
</p> </p>
<img src={`${getFile(item)}`} alt="" className="mt-4 rounded" /> <img src={`${getFile(item)}`} alt="" className="mt-4 rounded" />
</div> </div>
))} ))}
</div>
</div> </div>
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className='overflow-auto w-full'> <div className='overflow-auto w-full'>
<div className="article flex w-[650px]"> <div className="article flex w-[650px]">
{['classics', 'card', 'waterfall'].map((item) => ( {['classics', 'card', 'waterfall'].map((item) => (
<div key={item} onClick={() => setTheme({ ...theme, is_article_layout: item })} className={`item flex flex-col items-center p-4 m-4 border-2 rounded cursor-pointer ${theme.is_article_layout === item ? 'border-primary' : 'border-[#eee]'}`}> <div key={item} onClick={() => setTheme({ ...theme, is_article_layout: item })} className={`item flex flex-col items-center p-4 m-4 border-2 rounded cursor-pointer ${theme.is_article_layout === item ? 'border-primary' : 'border-[#eee]'}`}>
<p className={`text-center ${theme.is_article_layout === item ? 'text-primary' : ''}`}> <p className={`text-center ${theme.is_article_layout === item ? 'text-primary' : ''}`}>
{item === 'classics' ? '经典布局' : item === 'card' ? '卡片布局' : '瀑布流布局'} {item === 'classics' ? '经典布局' : item === 'card' ? '卡片布局' : '瀑布流布局'}
</p> </p>
<img src={`${getFile(item)}`} alt="" className="w-[200px] mt-4 rounded" /> <img src={`${getFile(item)}`} alt="" className="w-[200px] mt-4 rounded" />
</div> </div>
))} ))}
</div>
</div> </div>
</div>
<Button type="primary" size="large" className="w-full mt-4" htmlType="submit" loading={loading}></Button> <Button type="primary" size="large" className="w-full mt-4" htmlType="submit" loading={loading}></Button>
</Form> </Form>
</div> </div>
</Spin>
<FileUpload <FileUpload
dir="swiper" dir="swiper"
@@ -190,7 +196,7 @@ const SynthesisTheme = () => {
onSuccess={(url: string[]) => setTheme({ ...theme, swiper_image: url.join("\n") })} onSuccess={(url: string[]) => setTheme({ ...theme, swiper_image: url.join("\n") })}
onCancel={() => setIsModalOpen(false)} onCancel={() => setIsModalOpen(false)}
/> />
</> </div>
); );
}; };

View File

@@ -5,19 +5,25 @@ import { Web } from '@/types/app/project'
import { useWebStore } from '@/stores'; import { useWebStore } from '@/stores';
const WebPage = () => { const WebPage = () => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const web = useWebStore(state => state.web) const web = useWebStore(state => state.web)
const setWeb = useWebStore(state => state.setWeb) const setWeb = useWebStore(state => state.setWeb)
const onSubmit = async (values: Web) => { const onSubmit = async (values: Web) => {
setLoading(true); setLoading(true);
await editConfigDataAPI("web", values);
message.success("🎉 编辑网站成功");
setWeb(values) try {
form.setFieldsValue(values); await editConfigDataAPI("web", values);
message.success("🎉 编辑网站成功");
setWeb(values)
form.setFieldsValue(values);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
@@ -90,7 +96,7 @@ const WebPage = () => {
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" loading={loading} block></Button> <Button type="primary" htmlType="submit" loading={loading} block></Button>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>

View File

@@ -22,6 +22,7 @@ const SetupPage = () => {
const [active, setActive] = useState("system"); const [active, setActive] = useState("system");
const iconSty = "w-5 h-8 mr-1" const iconSty = "w-5 h-8 mr-1"
const list: Setup[] = [ const list: Setup[] = [
{ {
title: "系统设置", title: "系统设置",

View File

@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Table, Button, Image, Form, Input, Tabs, Card, Popconfirm, message } from 'antd'; import { Table, Button, Image, Form, Input, Tabs, Card, Popconfirm, message, Spin } from 'antd';
import { getSwiperListAPI, addSwiperDataAPI, editSwiperDataAPI, delSwiperDataAPI } from '@/api/Swiper'; import { getSwiperListAPI, addSwiperDataAPI, editSwiperDataAPI, delSwiperDataAPI, getSwiperDataAPI } from '@/api/Swiper';
import { Swiper } from '@/types/app/swiper'; import { Swiper } from '@/types/app/swiper';
import Title from '@/components/Title'; import Title from '@/components/Title';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
@@ -10,6 +10,9 @@ import FileUpload from '@/components/FileUpload';
const SwiperPage = () => { const SwiperPage = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [btnLoading, setBtnLoading] = useState(false) const [btnLoading, setBtnLoading] = useState(false)
const [editLoading, setEditLoading] = useState(false)
const [form] = Form.useForm();
const [swiper, setSwiper] = useState<Swiper>({} as Swiper); const [swiper, setSwiper] = useState<Swiper>({} as Swiper);
const [list, setList] = useState<Swiper[]>([]); const [list, setList] = useState<Swiper[]>([]);
@@ -39,8 +42,13 @@ const SwiperPage = () => {
]; ];
const getSwiperList = async () => { const getSwiperList = async () => {
const { data } = await getSwiperListAPI(); try {
setList(data as Swiper[]); const { data } = await getSwiperListAPI();
setList(data as Swiper[]);
} catch (error) {
setLoading(false);
}
setLoading(false); setLoading(false);
}; };
@@ -49,39 +57,56 @@ const SwiperPage = () => {
getSwiperList(); getSwiperList();
}, []); }, []);
const [form] = Form.useForm(); const editSwiperData = async (record: Swiper) => {
const editSwiperData = (record: Swiper) => { setEditLoading(true);
setSwiper(record);
form.setFieldsValue(record);
setTab('operate'); setTab('operate');
try {
const { data } = await getSwiperDataAPI(record.id)
setSwiper(data);
form.setFieldsValue(record);
} catch (error) {
setEditLoading(false);
}
setEditLoading(false);
}; };
const delSwiperData = async (id: number) => { const delSwiperData = async (id: number) => {
setLoading(true); setBtnLoading(true);
await delSwiperDataAPI(id);
message.success('🎉 删除轮播图成功'); try {
getSwiperList(); await delSwiperDataAPI(id);
await getSwiperList();
message.success('🎉 删除轮播图成功');
} catch (error) {
setBtnLoading(false);
}
setBtnLoading(false);
}; };
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true) setBtnLoading(true)
form.validateFields().then(async (values: Swiper) => { try {
if (swiper.id) { form.validateFields().then(async (values: Swiper) => {
await editSwiperDataAPI({ ...swiper, ...values }); if (swiper.id) {
message.success('🎉 编辑轮播图成功'); await editSwiperDataAPI({ ...swiper, ...values });
} else { message.success('🎉 编辑轮播图成功');
await addSwiperDataAPI({ ...swiper, ...values }); } else {
message.success('🎉 新增轮播图成功'); await addSwiperDataAPI({ ...swiper, ...values });
} message.success('🎉 新增轮播图成功');
}
getSwiperList(); await getSwiperList();
setTab('list'); setTab('list');
form.resetFields(); form.resetFields();
setSwiper({} as Swiper); setSwiper({} as Swiper);
}) })
} catch (error) {
setBtnLoading(false) setBtnLoading(false)
}
}; };
const handleTabChange = (key: string) => { const handleTabChange = (key: string) => {
@@ -118,7 +143,7 @@ const SwiperPage = () => {
label: swiper.id ? '编辑轮播图' : '新增轮播图', label: swiper.id ? '编辑轮播图' : '新增轮播图',
key: 'operate', key: 'operate',
children: ( children: (
<> <Spin spinning={editLoading}>
<h2 className="text-xl pb-4 text-center">{swiper.id ? '编辑轮播图' : '新增轮播图'}</h2> <h2 className="text-xl pb-4 text-center">{swiper.id ? '编辑轮播图' : '新增轮播图'}</h2>
<Form <Form
@@ -149,7 +174,7 @@ const SwiperPage = () => {
<Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{swiper.id ? '编辑轮播图' : '新增轮播图'}</Button> <Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{swiper.id ? '编辑轮播图' : '新增轮播图'}</Button>
</Form.Item> </Form.Item>
</Form> </Form>
</> </Spin>
) )
} }
]; ];