调整部分代码

This commit is contained in:
宇阳
2024-12-17 12:08:17 +08:00
parent 5fdfad0dde
commit c83b4736df
3 changed files with 130 additions and 137 deletions

View File

@@ -176,7 +176,7 @@ const FootprintPage = () => {
const { data } = await axios.get('https://restapi.amap.com/v3/geocode/geo', { const { data } = await axios.get('https://restapi.amap.com/v3/geocode/geo', {
params: { params: {
address, address,
key: import.meta.env.VITE_GAODE_WEB_API // 替换为你的高德地图 API 密钥 key: import.meta.env.VITE_GAODE_WEB_API
} }
}); });

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { notification, Divider, Input, Alert, Button, Spin } from 'antd'; import { notification, Divider, Input, Alert, Button, Spin, Segmented, Form } from 'antd';
import { PictureOutlined, LoadingOutlined, CloudUploadOutlined } from '@ant-design/icons'; import { PictureOutlined, LoadingOutlined, CloudUploadOutlined } from '@ant-design/icons';
import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project'; import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project';
import { Theme } from '@/types/app/project'; import { Theme } from '@/types/app/project';
@@ -7,18 +7,16 @@ import FileUpload from '@/components/FileUpload';
const ThemePage = () => { const ThemePage = () => {
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 [swiperText, setSwiperText] = useState<string>('');
const [social, setSocial] = useState<string>('');
const [cover, setCover] = useState<string>('');
const [recoArticle, setRecoArticle] = useState<string>('');
const [theme, setTheme] = useState<Theme>({} as Theme); const [theme, setTheme] = useState<Theme>({} as Theme);
const [current, setCurrent] = useState<string>("综合配置");
const [form] = Form.useForm();
const onSidebar = (value: string) => { const onSidebar = (value: string) => {
const rightSidebar = JSON.parse(theme.right_sidebar || '[]'); const rightSidebar = JSON.parse(theme.right_sidebar || '[]');
const index = rightSidebar.indexOf(value); const index = rightSidebar.indexOf(value);
index > -1 ? rightSidebar.splice(index, 1) : rightSidebar.push(value) index > -1 ? rightSidebar.splice(index, 1) : rightSidebar.push(value);
setTheme({ ...theme, right_sidebar: JSON.stringify(rightSidebar) }); setTheme({ ...theme, right_sidebar: JSON.stringify(rightSidebar) });
}; };
@@ -26,13 +24,17 @@ const ThemePage = () => {
setLoading(true); setLoading(true);
const { data } = await getConfigDataAPI<Theme>("layout"); const { data } = await getConfigDataAPI<Theme>("layout");
setTheme(data); setTheme(data);
setSwiperText(data.swiper_text ? JSON.parse(data.swiper_text).join('\n') : '');
form.setFieldsValue({
setSocial(data.social); light_logo: data.light_logo,
setCover(data.covers ? JSON.parse(data.covers).join("\n") : ''); dark_logo: data.dark_logo,
setRecoArticle(data.reco_article ? JSON.parse(data.reco_article).join("\n") : ''); swiper_image: data.swiper_image,
swiper_text: data.swiper_text ? JSON.parse(data.swiper_text).join('\n') : '',
social: data.social,
covers: data.covers ? JSON.parse(data.covers).join("\n") : '',
reco_article: data.reco_article ? JSON.parse(data.reco_article).join("\n") : '',
});
setLoading(false); setLoading(false);
}; };
@@ -41,18 +43,19 @@ const ThemePage = () => {
getLayoutData(); getLayoutData();
}, []); }, []);
const editLayoutData = async () => { const editLayoutData = async (values: any) => {
setLoading(true); setLoading(true);
const updatedLayout = { const updatedLayout = {
...theme, ...theme,
swiper_text: JSON.stringify(swiperText.split('\n')), ...values,
social, swiper_text: JSON.stringify(values.swiper_text.split('\n')),
covers: JSON.stringify(cover.split('\n')), covers: JSON.stringify(values.covers.split('\n')),
reco_article: JSON.stringify(recoArticle.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: '🎉 修改主题成功',
@@ -61,143 +64,133 @@ const ThemePage = () => {
setLoading(false); setLoading(false);
}; };
// 动态渲染图片
const getFile = (name: string) => { const getFile = (name: string) => {
return new URL(`./image/${name}.png`, import.meta.url).href return new URL(`./image/${name}.png`, import.meta.url).href;
} };
// 文件上传
const UploadBtn = () => ( const UploadBtn = () => (
<CloudUploadOutlined className='text-xl cursor-pointer' onClick={() => setIsModalOpen(true)} /> <CloudUploadOutlined className='text-xl cursor-pointer' onClick={() => setIsModalOpen(true)} />
) );
return ( return (
<> <>
<Spin spinning={loading} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}> <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>
<Segmented<string>
size="large"
options={['综合配置', '说说配置']}
onChange={setCurrent}
className='md:ml-10 mb-4'
/>
<div className='w-full lg:w-[500px] md:ml-10'> <div className='w-full lg:w-[500px] md:ml-10'>
<Divider orientation="left"> Logo</Divider> {current === "综合配置" && (
<div className="mb-8"> <Form form={form} onFinish={editLayoutData} layout="vertical">
<Input <Divider orientation="left"> Logo</Divider>
value={theme.light_logo} <Form.Item name="light_logo" label="亮色主题 Logo">
onChange={(e) => setTheme({ ...theme, light_logo: e.target.value })} <Input
prefix={<PictureOutlined />} prefix={<PictureOutlined />}
addonAfter={<UploadBtn />} addonAfter={<UploadBtn />}
size='large' size='large'
placeholder="请输入亮色Logo地址" placeholder="请输入亮色Logo地址"
className='customizeAntdInputAddonAfter' />
/> </Form.Item>
<img src={theme.light_logo} alt="" className="w-1/3 mt-4 rounded" /> <img src={form.getFieldValue('light_logo')} alt="" className="w-1/3 mt-4 rounded" />
</div>
<Divider orientation="left"> Logo</Divider> <Divider orientation="left"> Logo</Divider>
<div className="mb-8"> <Form.Item name="dark_logo" label="暗色主题 Logo">
<Input <Input
value={theme.dark_logo} prefix={<PictureOutlined />}
onChange={(e) => setTheme({ ...theme, dark_logo: e.target.value })} addonAfter={<UploadBtn />}
prefix={<PictureOutlined />} size='large'
addonAfter={<UploadBtn />} placeholder="请输入暗色Logo地址"
size='large' />
placeholder="请输入暗色Logo地址" </Form.Item>
className='customizeAntdInputAddonAfter' <img src={form.getFieldValue('dark_logo')} alt="" className="w-1/3 mt-4 rounded" />
/>
<img src={theme.dark_logo} alt="" className="w-1/3 mt-4 rounded" />
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className="mb-8"> <Form.Item name="swiper_image" label="首页背景图">
<Input <Input
value={theme.swiper_image} prefix={<PictureOutlined />}
onChange={(e) => setTheme({ ...theme, swiper_image: e.target.value })} addonAfter={<UploadBtn />}
prefix={<PictureOutlined />} size='large'
addonAfter={<UploadBtn />} placeholder="请输入背景图地址"
size='large' />
placeholder="请输入背景图地址" </Form.Item>
className='customizeAntdInputAddonAfter' <img src={form.getFieldValue('swiper_image')} alt="" className="w-1/3 mt-4 rounded" />
/>
<img src={theme.swiper_image} alt="" className="w-1/3 mt-4 rounded" />
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className="mb-8"> <Form.Item name="swiper_text" label="打字机文本">
<Input.TextArea <Input.TextArea
value={swiperText} autoSize={{ minRows: 2, maxRows: 4 }}
onChange={(e) => setSwiperText(e.target.value)} size='large'
autoSize={{ minRows: 2, maxRows: 4 }} placeholder="请输入打字机文本"
size='large' />
placeholder="请输入打字机文本" </Form.Item>
/> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className="mb-8"> <Form.Item name="social" label="社交网站">
<Input.TextArea <Input.TextArea
value={social} autoSize={{ minRows: 2, maxRows: 4 }}
onChange={(e) => setSocial(e.target.value)} size='large'
autoSize={{ minRows: 2, maxRows: 4 }} placeholder="请输入社交网站"
size='large' />
placeholder="请输入社交网站" </Form.Item>
/> <Alert message="请务必确保每一项格式正确,否则会导致网站无法访问" type="info" className="mt-2" />
<Alert message="请务必确保每一项格式正确,否则会导致网站无法访问" type="info" className="mt-2" />
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className="mb-8"> <Form.Item name="covers" label="文章随机封面">
<Input.TextArea <Input.TextArea
value={cover} autoSize={{ minRows: 2, maxRows: 4 }}
onChange={(e) => setCover(e.target.value)} size='large'
autoSize={{ minRows: 2, maxRows: 4 }} placeholder="请输入文章随机封面"
size='large' />
placeholder="请输入文章随机封面" </Form.Item>
/> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
</div>
<Divider orientation="left"></Divider> <Divider orientation="left"></Divider>
<div className="mb-8"> <Form.Item name="reco_article" label="作者推荐文章">
<Input.TextArea <Input.TextArea
value={recoArticle} autoSize={{ minRows: 2, maxRows: 4 }}
onChange={(e) => setRecoArticle(e.target.value)} size='large'
autoSize={{ minRows: 2, maxRows: 4 }} placeholder="请输入作者推荐文章ID"
size='large' />
placeholder="请输入作者推荐文章ID" </Form.Item>
/> <Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
<Alert message="以换行分隔,每行表示一段文本" type="info" className="mt-2" />
</div>
<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" loading={loading} onClick={editLayoutData}></Button> <Button type="primary" size="large" className="w-full mt-4" htmlType="submit" loading={loading}>
</Button>
</Form>
)}
</div> </div>
</Spin> </Spin>

View File

@@ -39,7 +39,7 @@ const SetupPage = () => {
title: "主题设置", title: "主题设置",
description: "配置网站主题风格", description: "配置网站主题风格",
icon: <BiLayout className={iconSty} />, icon: <BiLayout className={iconSty} />,
key: "layout" key: "theme"
}, },
{ {
title: "个人设置", title: "个人设置",
@@ -80,7 +80,7 @@ const SetupPage = () => {
<div className='w-full md:w-[80%] px-0 md:px-8'> <div className='w-full md:w-[80%] px-0 md:px-8'>
{active === "system" && <System />} {active === "system" && <System />}
{active === "web" && <Web />} {active === "web" && <Web />}
{active === "layout" && <Theme />} {active === "theme" && <Theme />}
{active === "my" && <My />} {active === "my" && <My />}
{/* {active === "other" && <Other />} */} {/* {active === "other" && <Other />} */}
</div> </div>