Compare commits
10 Commits
21805d5d4b
...
024df07314
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
024df07314 | ||
|
|
49600e8da0 | ||
|
|
cd371a49df | ||
|
|
b6b1732fcd | ||
|
|
b12519b330 | ||
|
|
7c72dcd434 | ||
|
|
07af30b649 | ||
|
|
61c6a934ca | ||
|
|
b99fb241fe | ||
|
|
2057e1ea0f |
4
.env
4
.env
@@ -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
|
||||||
|
|||||||
@@ -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
6616
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 ===== --> */}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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('🎉 删除分类成功');
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -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)]">
|
||||||
|
|||||||
@@ -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[];
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
export interface MonthlySums {
|
|
||||||
[key: string]: {
|
|
||||||
pv: number;
|
|
||||||
ip: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChartOneState {
|
|
||||||
series: {
|
|
||||||
name: string;
|
|
||||||
data: number[];
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
@@ -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(() => {
|
||||||
|
|||||||
10
src/pages/Dashboard/components/Stats/type.d.ts
vendored
10
src/pages/Dashboard/components/Stats/type.d.ts
vendored
@@ -1,10 +0,0 @@
|
|||||||
export interface Result {
|
|
||||||
timeSpan: string[];
|
|
||||||
fields: string[];
|
|
||||||
items: [
|
|
||||||
string[][],
|
|
||||||
number[][],
|
|
||||||
any[],
|
|
||||||
any[]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -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;
|
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
1
src/pages/Web/assets/svg/group.svg
Normal file
1
src/pages/Web/assets/svg/group.svg
Normal 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 |
@@ -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;
|
||||||
|
|||||||
@@ -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">前往该网站 →</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">前往该网站 →</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>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|
||||||
|
|||||||
@@ -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
2
src/types/env.d.ts
vendored
@@ -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;
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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/',
|
||||||
|
|||||||
Reference in New Issue
Block a user