优化:重构项目配置结构
This commit is contained in:
@@ -6,8 +6,9 @@ import { ConfigProvider } from 'antd';
|
|||||||
import RouteList from './components/RouteList';
|
import RouteList from './components/RouteList';
|
||||||
import "@/styles/customAntd.scss"
|
import "@/styles/customAntd.scss"
|
||||||
|
|
||||||
import { getWebDataAPI } from '@/api/Project';
|
import { getConfigDataAPI } from '@/api/Project';
|
||||||
import { useWebStore } from './stores';
|
import { useWebStore } from './stores';
|
||||||
|
import { Web } from './types/app/project';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
useAuthRedirect()
|
useAuthRedirect()
|
||||||
@@ -22,7 +23,7 @@ function App() {
|
|||||||
// 获取网站数据并把数据共享给全局方便使用
|
// 获取网站数据并把数据共享给全局方便使用
|
||||||
const setWeb = useWebStore(state => state.setWeb)
|
const setWeb = useWebStore(state => state.setWeb)
|
||||||
const getWebData = async () => {
|
const getWebData = async () => {
|
||||||
const { data } = await getWebDataAPI();
|
const { data } = await getConfigDataAPI<Web>("web");
|
||||||
setWeb(data)
|
setWeb(data)
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,23 +1,7 @@
|
|||||||
import Request from '@/utils/request'
|
import Request from '@/utils/request'
|
||||||
import { System, Web, Theme, Other } from '@/types/app/project'
|
|
||||||
|
|
||||||
// 获取系统配置信息
|
// 获取项目配置
|
||||||
export const getSystemDataAPI = () => Request<System>("GET", "/project/system")
|
export const getConfigDataAPI = <T>(type: string) => Request<T>("GET", `/config/list/${type}`)
|
||||||
|
|
||||||
// 获取网站配置信息
|
// 修改项目配置
|
||||||
export const getWebDataAPI = () => Request<Web>("GET", "/project/web")
|
export const editConfigDataAPI = (type: string, data: object) => Request<{ [string: string]: string }>("PATCH", `/config/${type}`, { data })
|
||||||
|
|
||||||
// 修改网站配置信息
|
|
||||||
export const editWebDataAPI = (data: Web) => Request<Web>("PATCH", "/project/web", { data })
|
|
||||||
|
|
||||||
// 获取主题配置信息
|
|
||||||
export const getThemeDataAPI = () => Request<Theme>("GET", "/project/theme")
|
|
||||||
|
|
||||||
// 修改主题配置信息
|
|
||||||
export const editThemeDataAPI = (data: Theme) => Request<Theme>("PATCH", "/project/theme", { data })
|
|
||||||
|
|
||||||
// 获取其他配置信息
|
|
||||||
export const getOtherDataAPI = () => Request<Other>("GET", "/project/other")
|
|
||||||
|
|
||||||
// 修改其他配置信息
|
|
||||||
export const editOtherDataAPI = (data: Other) => Request<Other>("PATCH", "/project/other", { data })
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
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 } from 'antd';
|
||||||
import { PictureOutlined, LoadingOutlined, CloudUploadOutlined } from '@ant-design/icons';
|
import { PictureOutlined, LoadingOutlined, CloudUploadOutlined } from '@ant-design/icons';
|
||||||
import { editThemeDataAPI, getThemeDataAPI } from '@/api/Project';
|
import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project';
|
||||||
import { Theme } from '@/types/app/project';
|
import { Theme } from '@/types/app/project';
|
||||||
import FileUpload from '@/components/FileUpload';
|
import FileUpload from '@/components/FileUpload';
|
||||||
|
|
||||||
@@ -16,23 +16,24 @@ const ThemePage = () => {
|
|||||||
const [theme, setTheme] = useState<Theme>({} as Theme);
|
const [theme, setTheme] = useState<Theme>({} as Theme);
|
||||||
|
|
||||||
const onSidebar = (value: string) => {
|
const onSidebar = (value: string) => {
|
||||||
const rightSidebar = JSON.parse(theme.rightSidebar || '[]');
|
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, rightSidebar: JSON.stringify(rightSidebar) });
|
setTheme({ ...theme, right_sidebar: JSON.stringify(rightSidebar) });
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLayoutData = async () => {
|
const getLayoutData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const { data } = await getThemeDataAPI();
|
const { data } = await getConfigDataAPI<Theme>("layout");
|
||||||
setTheme(data);
|
console.log(data.social);
|
||||||
|
|
||||||
setSwiperText(data.swiperText ? JSON.parse(data.swiperText).join('\n') : '');
|
setTheme(data);
|
||||||
setSocial(data.social ? JSON.parse(data.social).join("\n") : '');
|
setSwiperText(data.swiper_text ? JSON.parse(data.swiper_text).join('\n') : '');
|
||||||
|
setSocial(data.social ? JSON.parse(data.social)?.map((item: { name: string, url: string }) => JSON.stringify(item))?.join('\n') : '');
|
||||||
setCover(data.covers ? JSON.parse(data.covers).join("\n") : '');
|
setCover(data.covers ? JSON.parse(data.covers).join("\n") : '');
|
||||||
setRecoArticle(data.recoArticle ? JSON.parse(data.recoArticle).join("\n") : '');
|
setRecoArticle(data.reco_article ? JSON.parse(data.reco_article).join("\n") : '');
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,6 +44,10 @@ const ThemePage = () => {
|
|||||||
const editLayoutData = async () => {
|
const editLayoutData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
|
console.log(JSON.stringify(social.split('\n')),11111);
|
||||||
|
console.log(JSON.stringify(social.split('\n')),2222);
|
||||||
|
|
||||||
|
|
||||||
const updatedLayout = {
|
const updatedLayout = {
|
||||||
...theme,
|
...theme,
|
||||||
swiperText: JSON.stringify(swiperText.split('\n')),
|
swiperText: JSON.stringify(swiperText.split('\n')),
|
||||||
@@ -51,7 +56,7 @@ const ThemePage = () => {
|
|||||||
recoArticle: JSON.stringify(recoArticle.split('\n'))
|
recoArticle: JSON.stringify(recoArticle.split('\n'))
|
||||||
};
|
};
|
||||||
|
|
||||||
await editThemeDataAPI(updatedLayout);
|
await editConfigDataAPI("layout", updatedLayout);
|
||||||
notification.success({
|
notification.success({
|
||||||
message: '成功',
|
message: '成功',
|
||||||
description: '🎉 修改主题成功',
|
description: '🎉 修改主题成功',
|
||||||
@@ -79,43 +84,43 @@ const ThemePage = () => {
|
|||||||
<Divider orientation="left">亮色主题 Logo</Divider>
|
<Divider orientation="left">亮色主题 Logo</Divider>
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Input
|
<Input
|
||||||
value={theme.lightLogo}
|
value={theme.light_logo}
|
||||||
onChange={(e) => setTheme({ ...theme, lightLogo: e.target.value })}
|
onChange={(e) => setTheme({ ...theme, light_logo: e.target.value })}
|
||||||
prefix={<PictureOutlined />}
|
prefix={<PictureOutlined />}
|
||||||
addonAfter={<UploadBtn />}
|
addonAfter={<UploadBtn />}
|
||||||
size='large'
|
size='large'
|
||||||
placeholder="请输入亮色Logo地址"
|
placeholder="请输入亮色Logo地址"
|
||||||
className='customizeAntdInputAddonAfter'
|
className='customizeAntdInputAddonAfter'
|
||||||
/>
|
/>
|
||||||
<img src={theme.lightLogo} alt="" className="w-1/3 mt-4 rounded" />
|
<img src={theme.light_logo} alt="" className="w-1/3 mt-4 rounded" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider orientation="left">暗色主题 Logo</Divider>
|
<Divider orientation="left">暗色主题 Logo</Divider>
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Input
|
<Input
|
||||||
value={theme.darkLogo}
|
value={theme.dark_logo}
|
||||||
onChange={(e) => setTheme({ ...theme, darkLogo: e.target.value })}
|
onChange={(e) => setTheme({ ...theme, dark_logo: e.target.value })}
|
||||||
prefix={<PictureOutlined />}
|
prefix={<PictureOutlined />}
|
||||||
addonAfter={<UploadBtn />}
|
addonAfter={<UploadBtn />}
|
||||||
size='large'
|
size='large'
|
||||||
placeholder="请输入暗色Logo地址"
|
placeholder="请输入暗色Logo地址"
|
||||||
className='customizeAntdInputAddonAfter'
|
className='customizeAntdInputAddonAfter'
|
||||||
/>
|
/>
|
||||||
<img src={theme.darkLogo} alt="" className="w-1/3 mt-4 rounded" />
|
<img src={theme.dark_logo} alt="" className="w-1/3 mt-4 rounded" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider orientation="left">首页背景图</Divider>
|
<Divider orientation="left">首页背景图</Divider>
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Input
|
<Input
|
||||||
value={theme.swiperImage}
|
value={theme.swiper_image}
|
||||||
onChange={(e) => setTheme({ ...theme, swiperImage: e.target.value })}
|
onChange={(e) => setTheme({ ...theme, swiper_image: e.target.value })}
|
||||||
prefix={<PictureOutlined />}
|
prefix={<PictureOutlined />}
|
||||||
addonAfter={<UploadBtn />}
|
addonAfter={<UploadBtn />}
|
||||||
size='large'
|
size='large'
|
||||||
placeholder="请输入背景图地址"
|
placeholder="请输入背景图地址"
|
||||||
className='customizeAntdInputAddonAfter'
|
className='customizeAntdInputAddonAfter'
|
||||||
/>
|
/>
|
||||||
<img src={theme.swiperImage} alt="" className="w-1/3 mt-4 rounded" />
|
<img src={theme.swiper_image} alt="" className="w-1/3 mt-4 rounded" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider orientation="left">打字机文本</Divider>
|
<Divider orientation="left">打字机文本</Divider>
|
||||||
@@ -170,8 +175,8 @@ const ThemePage = () => {
|
|||||||
<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.rightSidebar && JSON.parse(theme.rightSidebar).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.rightSidebar && JSON.parse(theme.rightSidebar).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>
|
||||||
|
|
||||||
@@ -185,8 +190,8 @@ const ThemePage = () => {
|
|||||||
<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, isArticleLayout: item })} className={`item flex flex-col items-center p-4 m-4 border-2 rounded cursor-pointer ${theme.isArticleLayout === 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.isArticleLayout === item ? 'text-primary' : ''}`}>
|
<p className={`text-center ${theme.is_article_layout === item ? 'text-primary' : ''}`}>
|
||||||
{item === 'classics' ? '经典布局' : item === 'card' ? '卡片布局' : '瀑布流布局'}
|
{item === 'classics' ? '经典布局' : item === 'card' ? '卡片布局' : '瀑布流布局'}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -203,7 +208,7 @@ const ThemePage = () => {
|
|||||||
<FileUpload
|
<FileUpload
|
||||||
dir="swiper"
|
dir="swiper"
|
||||||
open={isModalOpen}
|
open={isModalOpen}
|
||||||
onSuccess={(url: string[]) => setTheme({ ...theme, swiperImage: url.join("\n") })}
|
onSuccess={(url: string[]) => setTheme({ ...theme, swiper_image: url.join("\n") })}
|
||||||
onCancel={() => setIsModalOpen(false)}
|
onCancel={() => setIsModalOpen(false)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Form, Input, Button, message } from 'antd';
|
import { Form, Input, Button, message } from 'antd';
|
||||||
import { editWebDataAPI } from '@/api/Project';
|
import { editConfigDataAPI } from '@/api/Project';
|
||||||
import { Web } from '@/types/app/project'
|
import { Web } from '@/types/app/project'
|
||||||
import { useWebStore } from '@/stores';
|
import { useWebStore } from '@/stores';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const WebPage = () => {
|
|||||||
|
|
||||||
const onSubmit = async (values: Web) => {
|
const onSubmit = async (values: Web) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await editWebDataAPI(values);
|
await editConfigDataAPI("web", values);
|
||||||
message.success("🎉 编辑网站成功");
|
message.success("🎉 编辑网站成功");
|
||||||
|
|
||||||
setWeb(values)
|
setWeb(values)
|
||||||
|
|||||||
@@ -9,5 +9,4 @@ interface WebStore {
|
|||||||
export default create<WebStore>((set) => ({
|
export default create<WebStore>((set) => ({
|
||||||
web: {} as Web,
|
web: {} as Web,
|
||||||
setWeb: (data: Web) => set(() => ({ web: data })),
|
setWeb: (data: Web) => set(() => ({ web: data })),
|
||||||
})
|
}));
|
||||||
);
|
|
||||||
14
src/types/app/project.d.ts
vendored
14
src/types/app/project.d.ts
vendored
@@ -33,13 +33,13 @@ export type RightSidebar = "author" | "hotArticle" | "randomArticle" | "newComme
|
|||||||
|
|
||||||
// 主题配置
|
// 主题配置
|
||||||
export interface Theme {
|
export interface Theme {
|
||||||
isArticleLayout: string,
|
is_article_layout: string,
|
||||||
rightSidebar: string,
|
right_sidebar: string,
|
||||||
lightLogo: string,
|
light_logo: string,
|
||||||
darkLogo: string,
|
dark_logo: string,
|
||||||
swiperImage: string,
|
swiper_image: string,
|
||||||
swiperText: string,
|
swiper_text: string,
|
||||||
recoArticle: string,
|
reco_article: string,
|
||||||
social: string,
|
social: string,
|
||||||
covers: string
|
covers: string
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user