Compare commits

...

10 Commits

Author SHA1 Message Date
宇阳
024df07314 暗黑主题适配70% 2025-01-20 16:51:08 +08:00
宇阳
49600e8da0 优化暗黑适配30% 2025-01-19 21:17:03 +08:00
宇阳
cd371a49df 更新版本 2025-01-19 20:56:00 +08:00
宇阳
b6b1732fcd 解决已知问题 2025-01-19 20:48:15 +08:00
宇阳
b12519b330 优化网站管理页面 2025-01-19 20:25:40 +08:00
宇阳
7c72dcd434 更新网站页面布局 2025-01-19 20:09:04 +08:00
宇阳
07af30b649 解决已知问题 2025-01-17 23:01:42 +08:00
宇阳
61c6a934ca 小调整 2025-01-12 20:54:26 +08:00
宇阳
b99fb241fe 大改动 2025-01-12 20:49:35 +08:00
宇阳
2057e1ea0f 大改动 2025-01-12 20:31:08 +08:00
42 changed files with 7116 additions and 412 deletions

4
.env
View File

@@ -1,5 +1,5 @@
# 项目版本号 # 项目版本号
VITE_VERSION=2.2.1 VITE_VERSION=2.3.3
# 项目后端API地址 # 项目后端API地址
VITE_PROJECT_API=https://你的后端域名/api VITE_PROJECT_API=https://你的后端域名/api
@@ -11,7 +11,7 @@ VITE_BAIDU_TONGJI_ACCESS_TOKEN=
# 星火AI相关配置可选 # 星火AI相关配置可选
# 配置教程https://docs.liuyuyang.net/docs/项目部署/API/星火大模型.html # 配置教程https://docs.liuyuyang.net/docs/项目部署/API/星火大模型.html
VITE_AI_APIPassword= VITE_AI_APIPASSWORD=
VITE_AI_MODEL=lite VITE_AI_MODEL=lite
# 高德地图Web API # 高德地图Web API

View File

@@ -80,7 +80,7 @@ VITE_BAIDU_TONGJI_ACCESS_TOKEN=
VITE_BAIDU_TONGJI_REFRESH_TOKEN= VITE_BAIDU_TONGJI_REFRESH_TOKEN=
# 星火AI相关配置 # 星火AI相关配置
VITE_AI_APIPassword= VITE_AI_APIPASSWORD=
VITE_AI_MODEL= VITE_AI_MODEL=
``` ```

6616
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ const DefaultLayout: React.FC<{ children: ReactNode }> = ({ children }) => {
const [sidebarOpen, setSidebarOpen] = useState(false); const [sidebarOpen, setSidebarOpen] = useState(false);
return ( return (
<div className="dark:bg-boxdark-2 dark:text-bodydark"> <div className="dark:bg-[#1A222C] dark:text-bodydark">
{/* <!-- ===== Page Wrapper Start ===== --> */} {/* <!-- ===== Page Wrapper Start ===== --> */}
<div className="flex h-screen overflow-hidden"> <div className="flex h-screen overflow-hidden">
{/* <!-- ===== Sidebar Start ===== --> */} {/* <!-- ===== Sidebar Start ===== --> */}

View File

@@ -27,11 +27,12 @@ export default () => {
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const getArticleList = async () => { const getArticleList = async () => {
setLoading(true);
try { try {
setLoading(true);
const { data } = await getArticleListAPI(); const { data } = await getArticleListAPI();
setArticleList(data); setArticleList(data);
setLoading(false); setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
@@ -39,9 +40,9 @@ export default () => {
}; };
const delArticleData = async (id: number) => { const delArticleData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
// 普通删除:可从回收站恢复 // 普通删除:可从回收站恢复
await delArticleDataAPI(id, true); await delArticleDataAPI(id, true);
await getArticleList(); await getArticleList();
@@ -151,9 +152,9 @@ export default () => {
]; ];
const onFilterSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
setLoading(true)
try { try {
setLoading(true)
const query: FilterArticle = { const query: FilterArticle = {
key: values.title, key: values.title,
cateIds: values.cateIds, cateIds: values.cateIds,
@@ -166,6 +167,7 @@ export default () => {
const { data } = await getArticleListAPI({ query }); const { data } = await getArticleListAPI({ query });
setArticleList(data); setArticleList(data);
setLoading(false) setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)

View File

@@ -25,6 +25,7 @@ const CatePage = () => {
const { data } = await getCateListAPI(); const { data } = await getCateListAPI();
data.sort((a, b) => a.order - b.order) data.sort((a, b) => a.order - b.order)
setList(data); setList(data);
setLoading(false) setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
@@ -46,14 +47,16 @@ const CatePage = () => {
const editCateData = async (id: number) => { const editCateData = async (id: number) => {
try { try {
setEditLoading(true)
setIsMethod("edit"); setIsMethod("edit");
setIsModelOpen(true); setIsModelOpen(true);
setEditLoading(true)
const { data } = await getCateDataAPI(id); const { data } = await getCateDataAPI(id);
setIsCateShow(data.type === "cate" ? false : true); setIsCateShow(data.type === "cate" ? false : true);
setCate(data); setCate(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false) setEditLoading(false)
} catch (error) { } catch (error) {
setEditLoading(false) setEditLoading(false)
@@ -61,9 +64,9 @@ const CatePage = () => {
}; };
const delCateData = async (id: number) => { const delCateData = async (id: number) => {
setLoading(true)
try { try {
setLoading(true)
await delCateDataAPI(id); await delCateDataAPI(id);
await getCateList(); await getCateList();
message.success('🎉 删除分类成功'); message.success('🎉 删除分类成功');

View File

@@ -30,21 +30,20 @@ export default () => {
const getCommentList = async () => { const getCommentList = async () => {
try { try {
setLoading(true)
const { data } = await getCommentListAPI(); const { data } = await getCommentListAPI();
setList(data) setList(data)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
useEffect(() => { useEffect(() => {
setLoading(true)
getCommentList(); getCommentList();
}, []); }, []);
const columns: ColumnsType = [ const columns: ColumnsType<Comment> = [
{ {
title: 'ID', title: 'ID',
dataIndex: 'id', dataIndex: 'id',
@@ -61,7 +60,7 @@ export default () => {
dataIndex: 'content', dataIndex: 'content',
key: 'content', key: 'content',
width: 400, width: 400,
render: (text: string, record) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => { render: (text: string, record: Comment) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => {
setComment(record) setComment(record)
setIsCommentModalOpen(true) setIsCommentModalOpen(true)
}}>{text}</span> }}>{text}</span>
@@ -150,9 +149,9 @@ export default () => {
const [replyInfo, setReplyInfo] = useState("") const [replyInfo, setReplyInfo] = useState("")
const [isReplyModalOpen, setIsReplyModalOpen] = useState(false); const [isReplyModalOpen, setIsReplyModalOpen] = useState(false);
const handleReply = async () => { const handleReply = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
await addCommentDataAPI({ await addCommentDataAPI({
avatar: user.avatar, avatar: user.avatar,
url: web.url, url: web.url,
@@ -169,6 +168,8 @@ export default () => {
message.success('🎉 回复评论成功'); message.success('🎉 回复评论成功');
setIsReplyModalOpen(false) setIsReplyModalOpen(false)
setReplyInfo("") setReplyInfo("")
setBtnLoading(true)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { Button, Card, Drawer, Dropdown, MenuProps, message } from 'antd'; import { Button, Card, Drawer, Dropdown, MenuProps, message, Spin } from 'antd';
import Title from '@/components/Title'; import Title from '@/components/Title';
import Editor from './components/Editor'; import Editor from './components/Editor';
@@ -32,19 +32,20 @@ export default () => {
// 获取文章数据 // 获取文章数据
const getArticleData = async () => { const getArticleData = async () => {
try { try {
setLoading(true)
const { data } = await getArticleDataAPI(id) const { data } = await getArticleDataAPI(id)
setData(data) setData(data)
setContent(data.content) setContent(data.content)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// 回显数据 // 回显数据
useEffect(() => { useEffect(() => {
setLoading(true)
setPublishOpen(false) setPublishOpen(false)
// 有Id就回显指定的数据 // 有Id就回显指定的数据
@@ -93,14 +94,14 @@ export default () => {
// 解析接口数据 // 解析接口数据
const parsingData = async (command: string) => { const parsingData = async (command: string) => {
setLoading(true)
try { try {
setLoading(true)
const res = await fetch(`/ai/v1/chat/completions`, { const res = await fetch(`/ai/v1/chat/completions`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${import.meta.env.VITE_AI_APIPassword}` "Authorization": `Bearer ${import.meta.env.VITE_AI_APIPASSWORD}`
}, },
body: JSON.stringify({ body: JSON.stringify({
model: import.meta.env.VITE_AI_MODEL, model: import.meta.env.VITE_AI_MODEL,
@@ -142,12 +143,12 @@ export default () => {
// 保留最后一行未处理的数据 // 保留最后一行未处理的数据
receivedText = lines[lines.length - 1]; receivedText = lines[lines.length - 1];
setLoading(false)
} }
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// AI功能 // AI功能
@@ -193,19 +194,21 @@ export default () => {
</div> </div>
</Title> </Title>
<Card loading={loading} className={`${titleSty} overflow-hidden rounded-xl min-h-[calc(100vh-180px)]`}> <Spin spinning={loading}>
<Editor value={content} onChange={(value) => setContent(value)} /> <Card className={`${titleSty} overflow-hidden rounded-xl min-h-[calc(100vh-180px)]`}>
<Editor value={content} onChange={(value) => setContent(value)} />
<Drawer <Drawer
title={(id && !isDraftParams) ? "编辑文章" : "发布文章"} title={(id && !isDraftParams) ? "编辑文章" : "发布文章"}
placement="right" placement="right"
size='large' size='large'
onClose={() => setPublishOpen(false)} onClose={() => setPublishOpen(false)}
open={publishOpen} open={publishOpen}
> >
<PublishForm data={data} closeModel={() => setPublishOpen(false)} /> <PublishForm data={data} closeModel={() => setPublishOpen(false)} />
</Drawer> </Drawer>
</Card > </Card >
</Spin>
</div> </div>
); );
}; };

View File

@@ -32,9 +32,9 @@ export default () => {
} }
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true)
try { try {
setLoading(true)
const data = { const data = {
content, content,
images: JSON.stringify(imageList), images: JSON.stringify(imageList),
@@ -52,29 +52,29 @@ export default () => {
await addRecordDataAPI(data) await addRecordDataAPI(data)
} }
setLoading(false)
navigate("/record") navigate("/record")
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
const getRecordData = async () => { const getRecordData = async () => {
try { try {
setLoading(true)
const { data } = await getRecordDataAPI(id) const { data } = await getRecordDataAPI(id)
setContent(data.content) setContent(data.content)
setImageList(JSON.parse(data.images as string)) setImageList(JSON.parse(data.images as string))
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// 回显数据 // 回显数据
useEffect(() => { useEffect(() => {
setLoading(true)
// 有Id就回显指定的数据 // 有Id就回显指定的数据
if (id) getRecordData() if (id) getRecordData()
}, [id]) }, [id])
@@ -145,7 +145,7 @@ export default () => {
placeholder="记录此刻!" placeholder="记录此刻!"
value={content} value={content}
onChange={(e) => setContent(e.target.value)} onChange={(e) => setContent(e.target.value)}
className="w-full p-4 border-2 border-[#eee] dark:border-strokedark text-base rounded-md" className="w-full p-4 border-2 border-[#eee] dark:bg-boxdark-2 dark:border-transparent text-base rounded-md"
/> />
<div className="absolute bottom-4 left-4 flex items-end space-x-3 max-w-[calc(100%-80px)]"> <div className="absolute bottom-4 left-4 flex items-end space-x-3 max-w-[calc(100%-80px)]">

View File

@@ -1,24 +0,0 @@
export interface Result {
timeSpan: string[];
fields: string[];
items: [
string[][],
number[][],
any[],
any[]
];
}
export interface MonthlySums {
[key: string]: {
pv: number;
ip: number;
};
}
export interface ChartOneState {
series: {
name: string;
data: number[];
}[];
}

View File

@@ -67,7 +67,7 @@ export default () => {
const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID; const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID;
const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN; const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN;
const response = await fetch(`/api/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${siteId}&start_date=${date}&end_date=${date}&metrics=new_visitor_count%2Cnew_visitor_ratio&method=trend%2Ftime%2Fa&gran=day&area=`); const response = await fetch(`/baidu/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${siteId}&start_date=${date}&end_date=${date}&metrics=new_visitor_count%2Cnew_visitor_ratio&method=trend%2Ftime%2Fa&gran=day&area=`);
const data = await response.json(); const data = await response.json();
const { result } = data; const { result } = data;
@@ -88,8 +88,8 @@ export default () => {
}, []) }, [])
return ( return (
<Spin spinning={loading}> <div className="sm:px-7.5 col-span-12 rounded-lg border border-stroke bg-white px-5 pb-5 pt-7.5 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4">
<div className="sm:px-7.5 col-span-12 rounded-lg border border-stroke bg-white px-5 pb-5 pt-7.5 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4"> <Spin spinning={loading}>
<div className="mb-3 justify-between gap-4 sm:flex"> <div className="mb-3 justify-between gap-4 sm:flex">
<div> <div>
<h5 className="text-xl font-semibold text-black dark:text-white"> <h5 className="text-xl font-semibold text-black dark:text-white">
@@ -100,11 +100,7 @@ export default () => {
<div className="mb-2"> <div className="mb-2">
<div id="chartThree" className="mx-auto flex justify-center"> <div id="chartThree" className="mx-auto flex justify-center">
<ReactApexChart <ReactApexChart options={options} series={state.series} type="donut" />
options={options}
series={state.series}
type="donut"
/>
</div> </div>
</div> </div>
@@ -129,7 +125,7 @@ export default () => {
</div> </div>
</div> </div>
</div> </div>
</div> </Spin>
</Spin> </div>
); );
}; };

View File

@@ -2,9 +2,32 @@ import { useEffect, useState, useCallback, useMemo } from 'react';
import { Spin } from 'antd'; import { Spin } from 'antd';
import { ApexOptions } from 'apexcharts'; import { ApexOptions } from 'apexcharts';
import ReactApexChart from 'react-apexcharts'; import ReactApexChart from 'react-apexcharts';
import { MonthlySums, ChartOneState } from './type';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Result } from '../../type';
interface Result {
timeSpan: string[];
fields: string[];
items: [
string[][],
number[][],
any[],
any[]
];
}
interface MonthlySums {
[key: string]: {
pv: number;
ip: number;
};
}
interface ChartOneState {
series: {
name: string;
data: number[];
}[];
}
export default () => { export default () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
@@ -124,26 +147,26 @@ export default () => {
// 获取统计数据 // 获取统计数据
const getDataList = useCallback(async () => { const getDataList = useCallback(async () => {
setLoading(true)
try { try {
setLoading(true)
const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID; const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID;
const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN; const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN;
const response = await fetch(`/api/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${siteId}&start_date=${startDate}&end_date=${endDate}&metrics=pv_count%2Cip_count&method=overview%2FgetTimeTrendRpt`); const response = await fetch(`/baidu/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${siteId}&start_date=${startDate}&end_date=${endDate}&metrics=pv_count%2Cip_count&method=overview%2FgetTimeTrendRpt`);
const data = await response.json(); const data = await response.json();
const { result } = data; const { result } = data;
setResult(result); setResult(result);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false);
}, [startDate, endDate]); }, [startDate, endDate]);
useEffect(() => { useEffect(() => {
getDataList(); getDataList();
}, [getDataList]); }, []);
// 切换不同范围的数据 // 切换不同范围的数据
const scopeData = useMemo(() => { const scopeData = useMemo(() => {
@@ -199,6 +222,10 @@ export default () => {
case "year": case "year":
const yearlySums: { [year: string]: { pv: number, ip: number } } = {}; const yearlySums: { [year: string]: { pv: number, ip: number } } = {};
console.log(result.items);
console.log(result.items[0]);
result.items[0].forEach((dateArray: string[], index: number) => { result.items[0].forEach((dateArray: string[], index: number) => {
const date: string = dateArray[0]; const date: string = dateArray[0];
const [year, month, day] = date.split('/'); const [year, month, day] = date.split('/');
@@ -239,6 +266,7 @@ export default () => {
// 当数据发生变化时,更新图表选项和状态 // 当数据发生变化时,更新图表选项和状态
useEffect(() => { useEffect(() => {
setLoading(true) setLoading(true)
setOptions((data) => ({ setOptions((data) => ({
...data, ...data,
xaxis: { ...options.xaxis, categories: scopeData.categories || [] } xaxis: { ...options.xaxis, categories: scopeData.categories || [] }
@@ -304,7 +332,7 @@ export default () => {
</div> </div>
<div className="flex w-full max-w-45 justify-end"> <div className="flex w-full max-w-45 justify-end">
<div className="inline-flex items-center rounded-md bg-whiter p-1.5 dark:bg-meta-4"> <div className="inline-flex items-center rounded-md bg-whiter p-1.5 dark:bg-meta-4 space-x-1">
<button className={`rounded py-1 px-3 text-xs font-medium text-black hover:bg-white hover:shadow-card dark:bg-meta-4 dark:text-white dark:hover:bg-boxdark ${scope === "day" ? "bg-white dark:!bg-[#4e5969] shadow-card" : ""}`} onClick={() => handleScopeChange("day")}> <button className={`rounded py-1 px-3 text-xs font-medium text-black hover:bg-white hover:shadow-card dark:bg-meta-4 dark:text-white dark:hover:bg-boxdark ${scope === "day" ? "bg-white dark:!bg-[#4e5969] shadow-card" : ""}`} onClick={() => handleScopeChange("day")}>
</button> </button>

View File

@@ -1,13 +0,0 @@
export interface MonthlySums {
[key: string]: {
pv: number;
ip: number;
};
}
export interface ChartOneState {
series: {
name: string;
data: number[];
}[];
}

View File

@@ -31,9 +31,9 @@ export default () => {
// 获取统计数据 // 获取统计数据
const getDataList = async () => { const getDataList = async () => {
setLoading(true)
try { try {
setLoading(true)
const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID; const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID;
const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN; const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN;
@@ -78,11 +78,10 @@ export default () => {
setStats({ pv, ip, bounce: (bounce / count) || 0, avgTime: formatTime(avgTime / count) || "00:00:00" }) setStats({ pv, ip, bounce: (bounce / count) || 0, avgTime: formatTime(avgTime / count) || "00:00:00" })
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
}; };
useEffect(() => { useEffect(() => {

View File

@@ -1,10 +0,0 @@
export interface Result {
timeSpan: string[];
fields: string[];
items: [
string[][],
number[][],
any[],
any[]
];
}

View File

@@ -25,24 +25,25 @@ export default () => {
const getArticleList = async () => { const getArticleList = async () => {
try { try {
setLoading(true);
const { data } = await getArticleListAPI({ query: { isDel: 1 } }); const { data } = await getArticleListAPI({ query: { isDel: 1 } });
setArticleList(data as Article[]); setArticleList(data);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getArticleList() getArticleList()
}, []); }, []);
const delArticleData = async (id: number) => { const delArticleData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
// 严格删除:彻底从数据库删除,无法恢复 // 严格删除:彻底从数据库删除,无法恢复
await delArticleDataAPI(id); await delArticleDataAPI(id);
await getArticleList(); await getArticleList();
@@ -55,12 +56,14 @@ export default () => {
}; };
const reductionArticleData = async (id: number) => { const reductionArticleData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await reductionArticleDataAPI(id) await reductionArticleDataAPI(id)
navigate("/article")
notification.success({ message: '🎉 还原文章成功' }) notification.success({ message: '🎉 还原文章成功' })
navigate("/article")
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }

View File

@@ -23,23 +23,25 @@ export default () => {
const getArticleList = async () => { const getArticleList = async () => {
try { try {
setLoading(true)
const { data } = await getArticleListAPI({ query: { isDraft: 1 } }); const { data } = await getArticleListAPI({ query: { isDraft: 1 } });
setArticleList(data as Article[]); setArticleList(data as Article[]);
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false)
}; };
useEffect(() => { useEffect(() => {
setLoading(true)
getArticleList() getArticleList()
}, []); }, []);
const delArticleData = async (id: number) => { const delArticleData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delArticleDataAPI(id); await delArticleDataAPI(id);
await getArticleList(); await getArticleList();
form.resetFields() form.resetFields()

View File

@@ -36,56 +36,56 @@ export default () => {
// 获取目录列表 // 获取目录列表
const getDirList = async () => { const getDirList = async () => {
setLoading(true)
try { try {
setLoading(true)
const { data } = await getDirListAPI() const { data } = await getDirListAPI()
setDirList(data) setDirList(data)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// 获取指定目录的文件列表 // 获取指定目录的文件列表
const getFileList = async (dir: string) => { const getFileList = async (dir: string) => {
setLoading(true)
try { try {
setLoading(true)
const { data } = await getFileListAPI(dir) const { data } = await getFileListAPI(dir)
if (!fileList.length && !data.length) message.error("该目录中没有文件") if (!fileList.length && !data.length) message.error("该目录中没有文件")
setFileList(data) setFileList(data)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// 删除图片 // 删除图片
const onDeleteImage = async (data: File) => { const onDeleteImage = async (data: File) => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
await delFileDataAPI(data.url) await delFileDataAPI(data.url)
await getFileList(dirName) await getFileList(dirName)
message.success("🎉 删除图片成功") message.success("🎉 删除图片成功")
setFile({} as File) setFile({} as File)
setOpenFileInfoDrawer(false) setOpenFileInfoDrawer(false)
setOpenFilePreviewDrawer(false) setOpenFilePreviewDrawer(false)
setBtnLoading(false)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }
setBtnLoading(false)
} }
// 下载图片 // 下载图片
const onDownloadImage = (data: File) => { const onDownloadImage = (data: File) => {
setDownloadLoading(true)
try { try {
setDownloadLoading(true)
fetch(data.url) fetch(data.url)
.then((response) => response.blob()) .then((response) => response.blob())
.then((blob) => { .then((blob) => {
@@ -98,11 +98,11 @@ export default () => {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
link.remove(); link.remove();
}); });
setDownloadLoading(false)
} catch (error) { } catch (error) {
setDownloadLoading(false) setDownloadLoading(false)
} }
setDownloadLoading(false)
}; };
// 打开目录 // 打开目录
@@ -199,22 +199,22 @@ export default () => {
<div className='flex flex-col'> <div className='flex flex-col'>
<div className='flex'> <div className='flex'>
<span className='min-w-20 font-bold'></span> <span className='min-w-20 font-bold'></span>
<span className='text-[#333]'>{file.name}</span> <span className='text-[#333] dark:text-white'>{file.name}</span>
</div> </div>
<div className='flex'> <div className='flex'>
<span className='min-w-20 font-bold'></span> <span className='min-w-20 font-bold'></span>
<span className='text-[#333]'>{file.type}</span> <span className='text-[#333] dark:text-white'>{file.type}</span>
</div> </div>
<div className='flex'> <div className='flex'>
<span className='min-w-20 font-bold'></span> <span className='min-w-20 font-bold'></span>
<span className='text-[#333]'>{(file.size / 1048576).toFixed(2)}MB</span> <span className='text-[#333] dark:text-white'>{(file.size / 1048576).toFixed(2)}MB</span>
</div> </div>
<div className='flex'> <div className='flex'>
<span className='min-w-20 font-bold'></span> <span className='min-w-20 font-bold'></span>
<span className='text-[#333] hover:text-primary cursor-pointer transition' onClick={async () => { <span className='text-[#333] dark:text-white hover:text-primary cursor-pointer transition' onClick={async () => {
await navigator.clipboard.writeText(file.url) await navigator.clipboard.writeText(file.url)
message.success("🎉 复制成功") message.success("🎉 复制成功")
}}>{file.url}</span> }}>{file.url}</span>

View File

@@ -129,9 +129,9 @@ export default () => {
}; };
const editFootprintData = async (id: number) => { const editFootprintData = async (id: number) => {
setEditLoading(true);
try { try {
setEditLoading(true);
setIsMethod("edit"); setIsMethod("edit");
setIsModelOpen(true); setIsModelOpen(true);
@@ -142,17 +142,17 @@ export default () => {
setFootprint(data); setFootprint(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false);
} catch (error) { } catch (error) {
setEditLoading(false); setEditLoading(false);
} }
setEditLoading(false);
}; };
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
form.validateFields().then(async (values: Footprint) => { form.validateFields().then(async (values: Footprint) => {
values.createTime = values.createTime.valueOf() values.createTime = values.createTime.valueOf()
values.images = values.images ? (values.images as string).split("\n") : [] values.images = values.images ? (values.images as string).split("\n") : []
@@ -166,6 +166,7 @@ export default () => {
} }
await getFootprintList(); await getFootprintList();
setBtnLoading(false)
reset() reset()
}); });
} catch (error) { } catch (error) {
@@ -176,9 +177,9 @@ export default () => {
const closeModel = () => reset(); const closeModel = () => reset();
const onFilterSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
setLoading(true)
try { try {
setLoading(true)
const query: FilterData = { const query: FilterData = {
key: values.address, key: values.address,
startDate: values.createTime && values.createTime[0].valueOf() + '', startDate: values.createTime && values.createTime[0].valueOf() + '',
@@ -187,18 +188,18 @@ export default () => {
const { data } = await getFootprintListAPI({ query }); const { data } = await getFootprintListAPI({ query });
setFootprintList(data); setFootprintList(data);
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
// 通过详细地址获取纬度 // 通过详细地址获取纬度
const getGeocode = async () => { const getGeocode = async () => {
setEditLoading(true)
try { try {
setEditLoading(true)
const address = form.getFieldValue("address") const address = form.getFieldValue("address")
const { data } = await axios.get('https://restapi.amap.com/v3/geocode/geo', { const { data } = await axios.get('https://restapi.amap.com/v3/geocode/geo', {
@@ -215,17 +216,15 @@ export default () => {
// 立即触发校验 // 立即触发校验
form.validateFields(['position']); form.validateFields(['position']);
setEditLoading(false)
return data.geocodes[0].location; return data.geocodes[0].location;
} else { } else {
message.warning('未找到该地址的经纬度'); message.warning('未找到该地址的经纬度');
} }
setEditLoading(false)
} catch (error) { } catch (error) {
setEditLoading(false) setEditLoading(false)
} }
setEditLoading(false)
}; };
return ( return (

View File

@@ -24,6 +24,8 @@ export default () => {
// 从github获取最近10次迭代记录 // 从github获取最近10次迭代记录
const getCommitData = async (project: string) => { const getCommitData = async (project: string) => {
try { try {
setLoading(true)
const res = await fetch(`https://api.github.com/repos/LiuYuYang01/${project}/commits?per_page=10`) const res = await fetch(`https://api.github.com/repos/LiuYuYang01/${project}/commits?per_page=10`)
const data = await res.json() const data = await res.json()
const result = data?.map((item: Commit) => ( const result = data?.map((item: Commit) => (
@@ -47,11 +49,11 @@ export default () => {
setServer_IterativeRecording(result) setServer_IterativeRecording(result)
break; break;
} }
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
useEffect(() => { useEffect(() => {

View File

@@ -7,19 +7,21 @@ import { loginDataAPI } from '@/api/User';
import { useUserStore } from '@/stores'; import { useUserStore } from '@/stores';
export default () => { export default () => {
const navigate = useNavigate();
const location = useLocation();
const store = useUserStore();
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [form] = useForm(); const [form] = useForm();
const [isPassVisible, setIsPassVisible] = useState(false); const [isPassVisible, setIsPassVisible] = useState(false);
const store = useUserStore();
const navigate = useNavigate();
const location = useLocation();
const returnUrl = new URLSearchParams(location.search).get('returnUrl') || '/'; const returnUrl = new URLSearchParams(location.search).get('returnUrl') || '/';
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true)
try { try {
setLoading(true)
const values = await form.validateFields(); const values = await form.validateFields();
const { data } = await loginDataAPI(values); const { data } = await loginDataAPI(values);
@@ -33,12 +35,11 @@ export default () => {
description: `Hello ${data.user.name} 欢迎回来`, description: `Hello ${data.user.name} 欢迎回来`,
}); });
setLoading(false)
navigate(returnUrl); navigate(returnUrl);
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
}; };
return ( return (

View File

@@ -86,25 +86,26 @@ export default () => {
const getOssList = async () => { const getOssList = async () => {
try { try {
setLoading(true);
const { data } = await getOssListAPI(); const { data } = await getOssListAPI();
setOssList(data); setOssList(data);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getOssList(); getOssList();
getOssPlatformList() getOssPlatformList()
}, []); }, []);
const enableOssData = async (id: number) => { const enableOssData = async (id: number) => {
setLoading(true)
try { try {
setLoading(true)
await enableOssDataAPI(id); await enableOssDataAPI(id);
await getOssList(); await getOssList();
message.success('启用成功'); message.success('启用成功');
@@ -114,9 +115,9 @@ export default () => {
}; };
const disableOssData = async (id: number) => { const disableOssData = async (id: number) => {
setLoading(true)
try { try {
setLoading(true)
await disableOssDataAPI(id); await disableOssDataAPI(id);
await getOssList(); await getOssList();
message.success('禁用成功'); message.success('禁用成功');
@@ -126,25 +127,25 @@ export default () => {
}; };
const editOssData = async (record: Oss) => { const editOssData = async (record: Oss) => {
setEditLoading(true)
try { try {
setEditLoading(true)
setIsModalOpen(true); setIsModalOpen(true);
const { data } = await getOssDataAPI(record.id) const { data } = await getOssDataAPI(record.id)
setOss(data); setOss(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false)
} catch (error) { } catch (error) {
setEditLoading(false) setEditLoading(false)
} }
setEditLoading(false)
}; };
const delOssData = async (id: number) => { const delOssData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delOssDataAPI(id); await delOssDataAPI(id);
await getOssList(); await getOssList();
message.success('🎉 删除存储配置成功'); message.success('🎉 删除存储配置成功');
@@ -166,9 +167,9 @@ export default () => {
}; };
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true);
try { try {
setBtnLoading(true);
const values = await form.validateFields(); const values = await form.validateFields();
if (oss.id) { if (oss.id) {
@@ -179,15 +180,14 @@ export default () => {
message.success('🎉 新增存储配置成功'); message.success('🎉 新增存储配置成功');
} }
await getOssList();
setIsModalOpen(false); setIsModalOpen(false);
getOssList();
form.resetFields(); form.resetFields();
setBtnLoading(false); setBtnLoading(false);
} catch (error) { } catch (error) {
setBtnLoading(false); setBtnLoading(false);
} }
setBtnLoading(false)
}; };
return ( return (

View File

@@ -23,28 +23,31 @@ export default () => {
const getRecordList = async () => { const getRecordList = async () => {
try { try {
setLoading(true);
const { data } = await getRecordListAPI(); const { data } = await getRecordListAPI();
setRecordList(data as Record[]); setRecordList(data as Record[]);
setLoading(false);
} catch (error) { } 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);
try { try {
setLoading(true);
await delRecordDataAPI(id); await delRecordDataAPI(id);
await getRecordList(); await getRecordList();
form.resetFields() form.resetFields()
notification.success({ message: '🎉 删除说说成功' }) notification.success({ message: '🎉 删除说说成功' })
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
@@ -116,9 +119,9 @@ export default () => {
]; ];
const onFilterSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
setLoading(true);
try { try {
setLoading(true);
const query = { const query = {
key: values.content, key: values.content,
startDate: values.createTime && values.createTime[0].valueOf() + '', startDate: values.createTime && values.createTime[0].valueOf() + '',
@@ -126,12 +129,12 @@ export default () => {
} }
const { data } = await getRecordListAPI({ query }); const { data } = await getRecordListAPI({ query });
setRecordList(data as Record[]); setRecordList(data);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
} }
return ( return (

View File

@@ -52,54 +52,56 @@ export default () => {
// 获取角色列表 // 获取角色列表
const getRoleList = async () => { const getRoleList = async () => {
try { try {
setLoading(true);
const { data } = await getRoleListAPI(); const { data } = await getRoleListAPI();
setRoleList(data as Role[]); setRoleList(data as Role[]);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRoleList() getRoleList()
getRouteList() getRouteList()
}, []); }, []);
// 获取指定角色的路由列表 // 获取指定角色的路由列表
const bindingRoute = async (record: Role) => { const bindingRoute = async (record: Role) => {
setEditLoading(true)
try { try {
setEditLoading(true)
setIsModalOpen(true) setIsModalOpen(true)
const { data } = await getRoleRouteListAPI(record.id); const { data } = await getRoleRouteListAPI(record.id);
setTargetKeys(data.map(item => item.id) as number[]) setTargetKeys(data.map(item => item.id) as number[])
setEditLoading(false)
} catch (error) { } catch (error) {
setEditLoading(false) setEditLoading(false)
} }
setEditLoading(false)
} }
const editRoleData = async (record: Role) => { const editRoleData = async (record: Role) => {
setEditLoading(true);
try { try {
setEditLoading(true);
const { data } = await getRoleDataAPI(record.id); const { data } = await getRoleDataAPI(record.id);
setRole(data); setRole(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false);
} catch (error) { } catch (error) {
setEditLoading(false); setEditLoading(false);
} }
setEditLoading(false);
}; };
const delRoleData = async (id: number) => { const delRoleData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delRoleDataAPI(id); await delRoleDataAPI(id);
await getRoleList(); await getRoleList();
message.success('🎉 删除角色成功'); message.success('🎉 删除角色成功');
@@ -109,9 +111,9 @@ export default () => {
}; };
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
form.validateFields().then(async (values: Role) => { form.validateFields().then(async (values: Role) => {
if (role.id) { if (role.id) {
await editRoleDataAPI({ ...role, ...values }); await editRoleDataAPI({ ...role, ...values });
@@ -126,11 +128,11 @@ export default () => {
form.setFieldsValue({ name: '', description: '' }) form.setFieldsValue({ name: '', description: '' })
setRole({} as Role); setRole({} as Role);
}); });
setBtnLoading(false)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }
setBtnLoading(false)
}; };
// 设置目标路由 // 设置目标路由
@@ -138,10 +140,11 @@ export default () => {
// 绑定路由 // 绑定路由
const onBindingRouteSubmit = async () => { const onBindingRouteSubmit = async () => {
setBindingLoading(true);
try { try {
setBindingLoading(true);
await bindingRouteAPI(role.id, targetKeys) await bindingRouteAPI(role.id, targetKeys)
setBindingLoading(false);
message.success('🎉 绑定成功'); message.success('🎉 绑定成功');
// 刷新页面 // 刷新页面
window.location.reload() window.location.reload()

View File

@@ -33,51 +33,54 @@ export default () => {
const getRouteList = async () => { const getRouteList = async () => {
try { try {
setLoading(true);
const { data } = await getRouteListAPI(); const { data } = await getRouteListAPI();
setList(data); setList(data);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRouteList(); getRouteList();
}, []); }, []);
const editRouteData = async (record: Route) => { const editRouteData = async (record: Route) => {
setLoading(true)
try { try {
setLoading(true)
const { data } = await getRouteDataAPI(record.id); const { data } = await getRouteDataAPI(record.id);
setRoute(data); setRoute(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
}; };
const delRouteData = async (id: number) => { const delRouteData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delRouteDataAPI(id); await delRouteDataAPI(id);
await getRouteList(); await getRouteList();
message.success('🎉 删除路由成功'); message.success('🎉 删除路由成功');
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
}; };
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true);
setBtnLoading(true)
try { try {
setLoading(true);
setBtnLoading(true)
form.validateFields().then(async (values: Route) => { form.validateFields().then(async (values: Route) => {
if (route.id) { if (route.id) {
await editRouteDataAPI({ ...route, ...values }); await editRouteDataAPI({ ...route, ...values });
@@ -92,13 +95,13 @@ export default () => {
form.setFieldsValue({ path: '', description: '' }) form.setFieldsValue({ path: '', description: '' })
setRoute({} as Route); setRoute({} as Route);
}); });
setLoading(false)
setBtnLoading(true)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
setBtnLoading(true) setBtnLoading(true)
} }
setLoading(false)
setBtnLoading(true)
}; };
return ( return (

View File

@@ -20,17 +20,18 @@ export default () => {
const getRssList = async () => { const getRssList = async () => {
try { try {
setLoading(true);
const { data } = await getRssListAPI(); const { data } = await getRssListAPI();
setList(data); setList(data);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getRssList(); getRssList();
}, []); }, []);

View File

@@ -19,25 +19,26 @@ export default () => {
const getUserData = async () => { const getUserData = async () => {
try { try {
setLoading(true);
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);
setLoading(false);
} catch (error) { } 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)
try { try {
setLoading(true)
await editUserDataAPI({ await editUserDataAPI({
id: store.user.id, ...values, id: store.user.id, ...values,
role: undefined role: undefined

View File

@@ -35,9 +35,9 @@ export default () => {
}; };
const handleSubmit = async (values: EditUser) => { const handleSubmit = async (values: EditUser) => {
setLoading(true)
try { try {
setLoading(true)
await editAdminPassAPI(values); await editAdminPassAPI(values);
confirm({ confirm({
@@ -47,11 +47,11 @@ export default () => {
onOk: store.quitLogin, onOk: store.quitLogin,
cancelButtonProps: { style: { display: 'none' } } cancelButtonProps: { style: { display: 'none' } }
}); });
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
}; };
return ( return (

View File

@@ -1,49 +1,48 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Spin, Form, notification, Input, Button } from 'antd'; import { Form, notification, Input, Button } from 'antd';
import { LoadingOutlined } from '@ant-design/icons';
import { Theme } from '@/types/app/project'; import { Theme } from '@/types/app/project';
import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project'; import { editConfigDataAPI, getConfigDataAPI } from '@/api/Project';
const RecordTheme = () => { export default () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
const getLayoutData = async () => { const getLayoutData = async () => {
try { try {
const { data } = await getConfigDataAPI<Theme>("layout"); setLoading(true);
const { data } = await getConfigDataAPI<Theme>("layout");
form.setFieldsValue({ form.setFieldsValue({
record_name: data.record_name, record_name: data.record_name,
record_info: data.record_info record_info: data.record_info
}); });
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); 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);
try { try {
setLoading(true);
await editConfigDataAPI("layout", values); await editConfigDataAPI("layout", values);
notification.success({ notification.success({
message: '成功', message: '成功',
description: '🎉 修改主题成功', description: '🎉 修改主题成功',
}); });
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
return ( return (
@@ -70,5 +69,3 @@ const RecordTheme = () => {
</div> </div>
); );
}; };
export default RecordTheme;

View File

@@ -1,11 +1,11 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { notification, Divider, Input, Alert, Button, Spin, Form } from 'antd'; import { notification, Divider, Input, Alert, Button, Form } from 'antd';
import { PictureOutlined, LoadingOutlined, CloudUploadOutlined } from '@ant-design/icons'; import { PictureOutlined, 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';
import FileUpload from '@/components/FileUpload'; import FileUpload from '@/components/FileUpload';
const SynthesisTheme = () => { export default () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
@@ -22,6 +22,8 @@ const SynthesisTheme = () => {
const getLayoutData = async () => { const getLayoutData = async () => {
try { try {
setLoading(true);
const { data } = await getConfigDataAPI<Theme>("layout"); const { data } = await getConfigDataAPI<Theme>("layout");
setTheme(data); setTheme(data);
@@ -34,22 +36,21 @@ const SynthesisTheme = () => {
covers: data.covers ? JSON.parse(data.covers).join("\n") : '', covers: data.covers ? JSON.parse(data.covers).join("\n") : '',
reco_article: data.reco_article ? JSON.parse(data.reco_article).join("\n") : '', reco_article: data.reco_article ? JSON.parse(data.reco_article).join("\n") : '',
}); });
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getLayoutData(); getLayoutData();
}, []); }, []);
const editThemeData = async (values: any) => { const editThemeData = async (values: any) => {
setLoading(true);
try { try {
setLoading(true);
const updatedLayout = { const updatedLayout = {
...theme, ...theme,
...values, ...values,
@@ -64,11 +65,11 @@ const SynthesisTheme = () => {
message: '成功', message: '成功',
description: '🎉 修改主题成功', description: '🎉 修改主题成功',
}); });
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
const getFile = (name: string) => { const getFile = (name: string) => {
@@ -199,5 +200,3 @@ const SynthesisTheme = () => {
</div> </div>
); );
}; };
export default SynthesisTheme;

View File

@@ -43,53 +43,54 @@ export default () => {
const getSwiperList = async () => { const getSwiperList = async () => {
try { try {
setLoading(true);
const { data } = await getSwiperListAPI(); const { data } = await getSwiperListAPI();
setList(data as Swiper[]); setList(data as Swiper[]);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getSwiperList(); getSwiperList();
}, []); }, []);
const editSwiperData = async (record: Swiper) => { const editSwiperData = async (record: Swiper) => {
setEditLoading(true);
setTab('operate');
try { try {
setEditLoading(true);
setTab('operate');
const { data } = await getSwiperDataAPI(record.id) const { data } = await getSwiperDataAPI(record.id)
setSwiper(data); setSwiper(data);
form.setFieldsValue(record); form.setFieldsValue(record);
setEditLoading(false);
} catch (error) { } catch (error) {
setEditLoading(false); setEditLoading(false);
} }
setEditLoading(false);
}; };
const delSwiperData = async (id: number) => { const delSwiperData = async (id: number) => {
setBtnLoading(true);
try { try {
setBtnLoading(true);
await delSwiperDataAPI(id); await delSwiperDataAPI(id);
await getSwiperList(); await getSwiperList();
message.success('🎉 删除轮播图成功'); message.success('🎉 删除轮播图成功');
setBtnLoading(false);
} catch (error) { } catch (error) {
setBtnLoading(false); setBtnLoading(false);
} }
setBtnLoading(false);
}; };
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
form.validateFields().then(async (values: Swiper) => { form.validateFields().then(async (values: Swiper) => {
if (swiper.id) { if (swiper.id) {
await editSwiperDataAPI({ ...swiper, ...values }); await editSwiperDataAPI({ ...swiper, ...values });
@@ -104,6 +105,8 @@ export default () => {
form.resetFields(); form.resetFields();
setSwiper({} as Swiper); setSwiper({} as Swiper);
}) })
setBtnLoading(false)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }

View File

@@ -1,5 +1,5 @@
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, Spin } from 'antd';
import { getTagListAPI, addTagDataAPI, editTagDataAPI, delTagDataAPI, getTagDataAPI } from '@/api/Tag'; import { getTagListAPI, addTagDataAPI, editTagDataAPI, delTagDataAPI, getTagDataAPI } from '@/api/Tag';
import { Tag } from '@/types/app/tag'; import { Tag } from '@/types/app/tag';
import Title from '@/components/Title'; import Title from '@/components/Title';
@@ -8,6 +8,7 @@ import { ColumnsType } from 'antd/es/table';
export default () => { export default () => {
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 [form] = Form.useForm();
@@ -32,38 +33,39 @@ export default () => {
const getTagList = async () => { const getTagList = async () => {
try { try {
setLoading(true);
const { data } = await getTagListAPI(); const { data } = await getTagListAPI();
setList(data as Tag[]); setList(data as Tag[]);
setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getTagList(); getTagList();
}, []); }, []);
const editTagData = async (record: Tag) => { const editTagData = async (record: Tag) => {
setLoading(true);
try { try {
setEditLoading(true);
const { data } = await getTagDataAPI(record.id) const { data } = await getTagDataAPI(record.id)
setTag(data); setTag(data);
form.setFieldsValue(data); form.setFieldsValue(data);
} catch (error) {
setLoading(false);
}
setLoading(false); setEditLoading(false);
} catch (error) {
setEditLoading(false);
}
}; };
const delTagData = async (id: number) => { const delTagData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delTagDataAPI(id); await delTagDataAPI(id);
await getTagList(); await getTagList();
message.success('🎉 删除标签成功'); message.success('🎉 删除标签成功');
@@ -73,10 +75,10 @@ export default () => {
}; };
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true);
setBtnLoading(true);
try { try {
setLoading(true);
setBtnLoading(true);
form.validateFields().then(async (values: Tag) => { form.validateFields().then(async (values: Tag) => {
if (tag.id) { if (tag.id) {
await editTagDataAPI({ ...tag, ...values }); await editTagDataAPI({ ...tag, ...values });
@@ -91,36 +93,42 @@ export default () => {
form.setFieldsValue({ name: '' }) form.setFieldsValue({ name: '' })
setTag({} as Tag); setTag({} as Tag);
}); });
setLoading(false);
setBtnLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
setBtnLoading(false); setBtnLoading(false);
} }
setBtnLoading(false);
}; };
return ( return (
<div> <div>
<Title value="标签管理" /> <Title value="标签管理" />
<div className='flex md:justify-between flex-col md:flex-row mx-auto mt-2'> <div className='flex md:justify-between flex-col md:flex-row mx-auto mt-2 h-[calc(100vh-180px)]'>
<Card className="w-full md:w-[40%] h-[calc(100vh-180px)]"> <div className='w-full md:w-[40%]'>
<Form <Spin spinning={editLoading}>
form={form} {/* <Card className="w-full md:w-[40%] h-46"> */}
layout="vertical" <Card className="w-full h-46">
initialValues={tag} <Form
onFinish={onSubmit} form={form}
size='large' layout="vertical"
> initialValues={tag}
<Form.Item label="标签名称" name="name" rules={[{ required: true, message: '标签名称不能为空' }]}> onFinish={onSubmit}
<Input placeholder="请输入标签名称" /> size='large'
</Form.Item> >
<Form.Item label="标签名称" name="name" rules={[{ required: true, message: '标签名称不能为空' }]}>
<Input placeholder="请输入标签名称" />
</Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{tag.id ? '编辑标签' : '新增标签'}</Button> <Button type="primary" htmlType="submit" loading={btnLoading} className="w-full">{tag.id ? '编辑标签' : '新增标签'}</Button>
</Form.Item> </Form.Item>
</Form> </Form>
</Card> </Card>
</Spin>
</div>
<Card className="w-full md:w-[59%] [&>.ant-card-body]:!p-0 mt-2 md:mt-0"> <Card className="w-full md:w-[59%] [&>.ant-card-body]:!p-0 mt-2 md:mt-0">
<Table <Table

View File

@@ -111,33 +111,31 @@ export default () => {
const getUserList = async () => { const getUserList = async () => {
try { try {
setLoading(true);
const { data } = await getUserListAPI(); const { data } = await getUserListAPI();
setUserList(data as User[]); setUserList(data as User[]);
setLoading(false); setLoading(false);
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false);
}; };
const getRoleList = async () => { const getRoleList = async () => {
const { data } = await getRoleListAPI(); const { data } = await getRoleListAPI();
console.log(data);
setRoleList(data); setRoleList(data);
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getUserList(); getUserList();
getRoleList() getRoleList()
}, []); }, []);
const delUserData = async (id: number) => { const delUserData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delUserDataAPI(id); await delUserDataAPI(id);
await getUserList(); await getUserList();
notification.success({ message: '🎉 删除用户成功' }); notification.success({ message: '🎉 删除用户成功' });
@@ -147,18 +145,18 @@ export default () => {
}; };
const editUserData = async (id: number) => { const editUserData = async (id: number) => {
setEditLoading(true);
try { try {
setEditLoading(true);
setDrawerVisible(true); setDrawerVisible(true);
const { data } = await getUserDataAPI(id) const { data } = await getUserDataAPI(id)
setUser(data); setUser(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false);
} catch (error) { } catch (error) {
setEditLoading(false); setEditLoading(false);
} }
setEditLoading(false);
}; };
const reset = () => { const reset = () => {
@@ -167,9 +165,9 @@ export default () => {
} }
const onSubmit = async () => { const onSubmit = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
form.validateFields().then(async (values: User) => { form.validateFields().then(async (values: User) => {
if (user.id) { if (user.id) {
await editUserDataAPI({ ...user, ...values }); await editUserDataAPI({ ...user, ...values });
@@ -183,17 +181,17 @@ export default () => {
setDrawerVisible(false); setDrawerVisible(false);
reset() reset()
}) })
setBtnLoading(false)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }
setBtnLoading(false)
}; };
const onFilterSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
setLoading(true)
try { try {
setLoading(true)
const query: FilterUser = { const query: FilterUser = {
key: values.name, key: values.name,
roleId: values.role, roleId: values.role,
@@ -202,12 +200,12 @@ export default () => {
} }
const { data } = await getUserListAPI({ query }); const { data } = await getUserListAPI({ query });
setUserList(data as User[]); setUserList(data);
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
return ( return (

View File

@@ -17,13 +17,15 @@ export default () => {
const getWallList = async () => { const getWallList = async () => {
try { try {
setLoading(true)
const { data } = await getWallListAPI(); const { data } = await getWallListAPI();
setList(data) setList(data)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
const delWallData = async (id: number) => { const delWallData = async (id: number) => {
@@ -48,12 +50,11 @@ export default () => {
} }
useEffect(() => { useEffect(() => {
setLoading(true)
getWallList(); getWallList();
getCateList() getCateList()
}, []); }, []);
const columns: ColumnsType = [ const columns: ColumnsType<Wall> = [
{ {
title: 'ID', title: 'ID',
dataIndex: 'id', dataIndex: 'id',
@@ -64,7 +65,7 @@ export default () => {
title: '分类', title: '分类',
dataIndex: 'cate', dataIndex: 'cate',
key: 'cate', key: 'cate',
render: ({ name }, { color }) => <Tag bordered={false} color={color} className='!text-[#565656]'>{name}</Tag>, render: ({ name }, { color }) => <Tag bordered={false} color={color} className='!text-[#565656] dark:!text-white'>{name}</Tag>,
}, },
{ {
title: '名称', title: '名称',
@@ -76,7 +77,7 @@ export default () => {
dataIndex: 'content', dataIndex: 'content',
key: 'content', key: 'content',
width: 400, width: 400,
render: (text: string, record) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => { render: (text: string, record: Wall) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => {
setWall(record) setWall(record)
setIsModalOpen(true) setIsModalOpen(true)
}}>{text}</span> }}>{text}</span>
@@ -118,9 +119,9 @@ export default () => {
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const onFilterSubmit = async (values: FilterForm) => { const onFilterSubmit = async (values: FilterForm) => {
setLoading(true)
try { try {
setLoading(true)
const query: FilterWall = { const query: FilterWall = {
key: values.content, key: values.content,
cateId: values.cateId, cateId: values.cateId,
@@ -130,11 +131,11 @@ export default () => {
const { data } = await getWallListAPI({ query }); const { data } = await getWallListAPI({ query });
setList(data) setList(data)
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
} }
return ( return (

View File

@@ -0,0 +1 @@
<svg t="1737289214739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1760" width="200" height="200"><path d="M878.08 807.936l-192-92.16 8.192-190.464 194.56 82.432z" fill="#FF8F00" p-id="1761"></path><path d="M707.072 841.216l-186.88-96.256 165.888-29.184 192 92.16z" fill="#C16500" p-id="1762"></path><path d="M632.832 935.936l-183.296-101.888L459.264 481.28l188.416 82.944z" fill="#C16500" p-id="1763"></path><path d="M647.68 564.224L459.264 481.28l303.104-41.984 197.632 76.8z" fill="#FF8F00" p-id="1764"></path><path d="M647.68 564.224l312.832-48.128-19.968 357.376-306.688 62.464 13.824-371.712z m230.4 243.712l10.752-200.192-173.056 28.672-8.704 204.8 171.008-33.28" fill="#FFC107" p-id="1765"></path><path d="M650.752 479.232L461.824 400.896l10.24-371.2L665.6 87.04z" fill="#1E88E5" p-id="1766"></path><path d="M665.6 87.04L472.064 29.696 781.824 5.12l204.288 53.248z" fill="#90CAF9" p-id="1767"></path><path d="M986.112 58.368l-21.504 376.32-313.856 44.544L665.6 87.04z" fill="#2196F3" p-id="1768"></path><path d="M220.16 1020.416l-168.96-112.64 1.536-370.176 173.056 91.648z" fill="#64B5F6" p-id="1769"></path><path d="M225.792 629.248L52.736 537.6l335.872-46.592 185.344 84.48z" fill="#1976D2" p-id="1770"></path><path d="M573.952 575.488l-12.8 375.296L220.16 1020.416l5.632-391.168z" fill="#2196F3" p-id="1771"></path><path d="M504.832 413.184L319.488 336.896l4.096-210.432 187.904 64.512z" fill="#FF8F00" p-id="1772"></path><path d="M309.248 438.784L131.072 358.912l188.416-22.016 185.344 76.288z" fill="#C16500" p-id="1773"></path><path d="M226.816 539.648L53.248 453.12l1.536-390.144 178.176 62.976z" fill="#FFD366" p-id="1774"></path><path d="M232.96 125.952L54.784 62.976 399.36 35.328l191.488 58.368z" fill="#FFE5AB" p-id="1775"></path><path d="M232.96 125.952l357.888-31.744-13.824 395.776-350.208 49.664 6.144-413.696z m271.872 287.232l6.656-222.208-197.632 19.968-4.096 227.84 195.072-25.6" fill="#FFC107" p-id="1776"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -5,7 +5,6 @@
gap: 20px; gap: 20px;
justify-items: center; justify-items: center;
min-height: 100px; min-height: 100px;
margin-top: 40px;
.item { .item {
overflow: hidden; overflow: hidden;

View File

@@ -5,6 +5,7 @@ import { getLinkListAPI, addLinkDataAPI, editLinkDataAPI, delLinkDataAPI, getWeb
import { WebType, Web } from '@/types/app/web'; import { WebType, Web } from '@/types/app/web';
import Title from '@/components/Title'; import Title from '@/components/Title';
import { RuleObject } from 'antd/es/form'; import { RuleObject } from 'antd/es/form';
import group from "./assets/svg/group.svg"
import './index.scss'; import './index.scss';
export default () => { export default () => {
@@ -15,7 +16,7 @@ export default () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [tab, setTab] = useState<string>('list'); const [tab, setTab] = useState<string>('list');
const [list, setList] = useState<Web[]>([]); const [list, setList] = useState<{ [key: string]: Web[] }>({});
const [listTemp, setListTemp] = useState<Web[]>([]); const [listTemp, setListTemp] = useState<Web[]>([]);
const [typeList, setTypeList] = useState<WebType[]>([]); const [typeList, setTypeList] = useState<WebType[]>([]);
const [search, setSearch] = useState<string>(''); const [search, setSearch] = useState<string>('');
@@ -27,17 +28,27 @@ export default () => {
// 获取网站列表 // 获取网站列表
const getLinkList = async () => { const getLinkList = async () => {
try { try {
setLoading(true);
const { data } = await getLinkListAPI(); const { data } = await getLinkListAPI();
data.sort((a, b) => a.order - b.order) data.sort((a, b) => a.order - b.order)
data.sort((a, b) => a.type.order - b.type.order) data.sort((a, b) => a.type.order - b.type.order)
setList(data); const grouped = data.reduce((acc, item) => {
const groupName = item.type.name;
if (!acc[groupName]) {
acc[groupName] = [];
}
acc[groupName].push(item);
return acc;
}, {} as { [key: string]: Web[] });
setList(grouped);
setListTemp(data); setListTemp(data);
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false); setLoading(false);
} }
setLoading(false)
}; };
// 获取网站类型列表 // 获取网站类型列表
@@ -47,19 +58,33 @@ export default () => {
}; };
useEffect(() => { useEffect(() => {
setLoading(true);
getLinkList(); getLinkList();
getWebTypeList(); getWebTypeList();
}, []); }, []);
useEffect(() => { useEffect(() => {
setListTemp(list.filter(item => item.title.includes(search) || item.description.includes(search))); // 过滤出符合搜索条件的网站
}, [search, list]); const filteredList = listTemp.filter(item =>
item.title.includes(search) || item.description.includes(search)
);
// 按类型分组
const grouped = filteredList.reduce((acc, item) => {
const groupName = item.type.name;
if (!acc[groupName]) {
acc[groupName] = [];
}
acc[groupName].push(item);
return acc;
}, {} as { [key: string]: Web[] });
setList(grouped);
}, [search, listTemp]);
const deleteLinkData = async (id: number) => { const deleteLinkData = async (id: number) => {
setLoading(true);
try { try {
setLoading(true);
await delLinkDataAPI(id); await delLinkDataAPI(id);
await getLinkList(); await getLinkList();
message.success('🎉 删除网站成功'); message.success('🎉 删除网站成功');
@@ -69,20 +94,19 @@ export default () => {
}; };
const editLinkData = async (record: Web) => { const editLinkData = async (record: Web) => {
setEditLoading(true)
try { try {
setEditLoading(true)
setTab('operate'); setTab('operate');
setIsMethod("edit"); setIsMethod("edit");
const { data } = await getLinkDataAPI(record.id) const { data } = await getLinkDataAPI(record.id)
setLink(data); setLink(data);
form.setFieldsValue(data); form.setFieldsValue(data);
setEditLoading(false)
} catch (error) { } catch (error) {
setEditLoading(false) setEditLoading(false)
} }
setEditLoading(false)
}; };
// 做一些初始化的事情 // 做一些初始化的事情
@@ -98,9 +122,9 @@ export default () => {
}; };
const submit = async () => { const submit = async () => {
setBtnLoading(true)
try { try {
setBtnLoading(true)
form.validateFields().then(async (values: Web) => { form.validateFields().then(async (values: Web) => {
if (isMethod === "edit") { if (isMethod === "edit") {
await editLinkDataAPI({ ...link, ...values }); await editLinkDataAPI({ ...link, ...values });
@@ -114,11 +138,11 @@ export default () => {
reset() reset()
setTab('list'); setTab('list');
}); });
setBtnLoading(false)
} catch (error) { } catch (error) {
setBtnLoading(false) setBtnLoading(false)
} }
setBtnLoading(false)
}; };
const { Option } = Select; const { Option } = Select;
@@ -137,56 +161,70 @@ export default () => {
label: '网站列表', label: '网站列表',
key: 'list', key: 'list',
children: ( children: (
<> <div>
<div className="w-[300px] mx-auto"> <div className="flex justify-end w-full mb-8">
<Input <Input
size="large" size="large"
placeholder="请输入网站名称或描述信息进行查询" placeholder="请输入网站名称或描述信息进行查询"
prefix={<SearchOutlined />} prefix={<SearchOutlined />}
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className='w-[400px]'
/> />
</div> </div>
<Spin spinning={loading}> <Spin spinning={loading}>
{listTemp.length > 0 ? ( <div className='space-y-8'>
<div className="list"> {
{ Object.keys(list).map((key) => (
listTemp.map(item => ( <div>
<div key={item.id} className="item"> <Card className="[&>.ant-card-body]:flex [&>.ant-card-body]:py-2 [&>.ant-card-body]:px-4 my-2 ml-1.5 text-base bg-[#f5f6ff] dark:bg-boxdark transition-colors">
<div className="avatar"> <img src={group} alt="分组图标" className='w-6 h-6 mr-2' />
<img src={item.image} alt="" className="avatar-img" /> <span>{key}</span>
</div> </Card>
<div className="name">{item.title}</div> {
<div className="description">{item.description}</div> Object.values(list[key]).length ? (
<div className="type">{item.type.name}</div> <div className="list">
{
Object.values(list[key]).map(item => (
<div key={item.id} className="item">
<div className="avatar">
<img src={item.image} alt="" className="avatar-img" />
</div>
<div className="operate"> <div className="name">{item.title}</div>
<div onClick={() => editLinkData(item)} className="edit"></div> <div className="description">{item.description}</div>
<div className="type">{item.type.name}</div>
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => deleteLinkData(item.id!)}> <div className="operate">
<div className="delete"></div> <div onClick={() => editLinkData(item)} className="edit"></div>
</Popconfirm>
</div>
<div onClick={() => toHref(item.url)} className="headFor"> &rarr;</div> <Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => deleteLinkData(item.id!)}>
</div> <div className="delete"></div>
)) </Popconfirm>
} </div>
</div>
) : ( <div onClick={() => toHref(item.url)} className="headFor"> &rarr;</div>
<Empty description="暂无数据" className='my-7' /> </div>
)} ))
}
</div>
) : <Empty description="暂无数据" className='my-7' />
}
</div>
))
}
</div>
</Spin> </Spin>
</> </div>
), ),
}, },
{ {
label: isMethod === "edit" ? '编辑网站' : '新增网站', label: isMethod === "edit" ? '编辑网站' : '新增网站',
key: 'operate', key: 'operate',
children: ( children: (
<> <div>
<h2 className="text-xl pb-4 text-center">{isMethod === "edit" ? '编辑网站' : '新增网站'}</h2> <h2 className="text-xl pb-4 text-center">{isMethod === "edit" ? '编辑网站' : '新增网站'}</h2>
<Spin spinning={editLoading}> <Spin spinning={editLoading}>
@@ -232,7 +270,7 @@ export default () => {
</Form> </Form>
</div> </div>
</Spin> </Spin>
</> </div>
), ),
}, },
]; ];

View File

@@ -27,6 +27,8 @@ export default () => {
// 重新获取最新数据 // 重新获取最新数据
const fetchData = async (type: Menu) => { const fetchData = async (type: Menu) => {
try { try {
setLoading(true)
if (type === "comment") { if (type === "comment") {
const { data } = await getCommentListAPI({ query: { status: 0 }, pattern: "list" }); const { data } = await getCommentListAPI({ query: { status: 0 }, pattern: "list" });
setCommentList(data); setCommentList(data);
@@ -37,15 +39,14 @@ export default () => {
const { data } = await getWallListAPI({ query: { status: 0 } }); const { data } = await getWallListAPI({ query: { status: 0 } });
setWallList(data); setWallList(data);
} }
setLoading(false)
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
} }
setLoading(false)
}; };
useEffect(() => { useEffect(() => {
setLoading(true)
fetchData(active); fetchData(active);
}, [active]); }, [active]);

View File

@@ -8,3 +8,43 @@
} }
} }
} }
// ------------------> Antd组件库暗色适配 开始 <------------------
.ant-card {
@apply overflow-hidden;
}
.ant-card-body,
.ant-pagination-item,
.ant-drawer-header,
.ant-drawer-body,
.ant-table-cell::before {
@apply dark:bg-boxdark;
}
.ant-pagination-item:hover,
.ant-table-cell,
.ant-table-row:hover .ant-table-cell,
.ant-card {
@apply dark:!bg-boxdark dark:!border-strokedark;
}
.ant-input,
.ant-input-affix-wrapper,
.ant-picker-outlined,
.ant-picker-panel-layout,
.ant-picker-range-arrow::before,
.ant-select,
.ant-select-selector,
.ant-modal-content {
@apply dark:!bg-boxdark-2 dark:!border-strokedark;
}
.ant-modal-header{
@apply dark:bg-transparent;
}
.ant-transfer-list{
@apply dark:border-strokedark;
}
// ------------------> Antd组件库暗色适配 结束 <------------------

2
src/types/env.d.ts vendored
View File

@@ -6,7 +6,7 @@ interface ImportMetaEnv {
readonly VITE_BAIDU_TONGJI_SITE_ID: string; readonly VITE_BAIDU_TONGJI_SITE_ID: string;
readonly VITE_BAIDU_TONGJI_ACCESS_TOKEN: string; readonly VITE_BAIDU_TONGJI_ACCESS_TOKEN: string;
readonly VITE_AI_APIPassword: string; readonly VITE_AI_APIPASSWORD: string;
readonly VITE_AI_MODEL: string; readonly VITE_AI_MODEL: string;
readonly VITE_GAODE_WEB_API: string; readonly VITE_GAODE_WEB_API: string;

View File

@@ -40,7 +40,7 @@ module.exports = {
whiten: '#F1F5F9', whiten: '#F1F5F9',
whiter: '#F5F7FD', whiter: '#F5F7FD',
boxdark: '#334459', boxdark: '#334459',
'boxdark-2': '#1A222C', 'boxdark-2': '#263444',
strokedark: '#475f7d', strokedark: '#475f7d',
'form-strokedark': '#3d4d60', 'form-strokedark': '#3d4d60',
'form-input': '#1d2a39', 'form-input': '#1d2a39',

View File

@@ -26,7 +26,7 @@ export default defineConfig({
'/baidu': { '/baidu': {
target: 'https://openapi.baidu.com/', target: 'https://openapi.baidu.com/',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/baidu/, ''),
}, },
'/qiniu': { '/qiniu': {
target: 'https://rsf.qiniuapi.com/', target: 'https://rsf.qiniuapi.com/',