fix: bug修复

This commit is contained in:
landaiqing
2024-07-24 00:59:28 +08:00
parent 8fa1c50fb3
commit 190fda426c
16 changed files with 1512 additions and 1301 deletions

View File

@@ -156,7 +156,10 @@ export const getUserInfoApi = (userId: string): any => {
export const updateUserInfo = (data: any): any => {
return web.request({
url: "/auth/auth/user/update",
method: "get",
method: "post",
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
data: data,
});
};
@@ -195,3 +198,29 @@ export const logout = (userId: any): any => {
},
});
};
/**
* 检查用户名是否已存在
* @param userName
*/
export const checkUserName = (userName: any): any => {
return web.request({
url: "/auth/auth/user/checkUserName",
method: "post",
params: {
userName: userName,
},
});
};
/**
* 获取最近分享
* @param userId
*/
export const getRecentShare = (userId: any): any => {
return web.request({
url: "/share/share/detail/getRecentShare",
method: "get",
params: {
userId: userId,
},
});
};

View File

@@ -29,10 +29,7 @@ const FileUpload = (props: any) => {
const uploadFile = async (options: any) => {
const { onSuccess, onError, file }: { onSuccess: any; onError: any; file: any } = options;
if (
store.getUploadFilePath() === null ||
(store.getUploadFileBucket() === null && store.getUploadFileStorage() === null)
) {
if (store.getUploadFileBucket() === null || store.getUploadFileStorage() === null) {
message.open({
content: "请选择存储桶和存储路径",
type: "error",

View File

@@ -339,7 +339,7 @@ const MainHome: React.FC = observer(() => {
color: "coral",
fontWeight: "bolder",
}}>
{storageCount}
{storageCount || 0}
</span>
}
/
@@ -400,7 +400,7 @@ const MainHome: React.FC = observer(() => {
color: "lightblue",
fontWeight: "bolder",
}}>
{bucketCount}
{bucketCount || 0}
</span>
}
/
@@ -467,7 +467,7 @@ const MainHome: React.FC = observer(() => {
color: "orange",
marginLeft: 5,
}}>
{uploadFile}
{uploadFile || 0}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
@@ -483,7 +483,7 @@ const MainHome: React.FC = observer(() => {
color: "green",
marginLeft: 5,
}}>
{downloadFile}
{downloadFile || 0}
</span>
</Flex>
</Flex>
@@ -531,7 +531,7 @@ const MainHome: React.FC = observer(() => {
color: "orange",
marginLeft: 5,
}}>
{uploadFlow}
{uploadFlow || 0}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
@@ -547,7 +547,7 @@ const MainHome: React.FC = observer(() => {
color: "green",
marginLeft: 5,
}}>
{downloadFlow}
{downloadFlow || 0}
</span>
</Flex>
</Flex>

View File

@@ -31,7 +31,7 @@ import { cyan, generate, green, presetPalettes, red } from "@ant-design/colors";
type Presets = Required<ColorPickerProps>["presets"][number];
const ShareAdd: React.FunctionComponent = observer(() => {
const ShareAdd: React.FunctionComponent = () => {
const navigate = useNavigate();
const divRef = useRef(null);
const [form] = Form.useForm();
@@ -373,5 +373,5 @@ const ShareAdd: React.FunctionComponent = observer(() => {
</div>
</>
);
});
};
export default observer(ShareAdd);

View File

@@ -8,6 +8,8 @@ import {
HeartOutlined,
InfoCircleOutlined,
LeftOutlined,
LikeOutlined,
StarOutlined,
TagsOutlined,
WarningOutlined,
} from "@ant-design/icons";
@@ -22,10 +24,10 @@ const { Paragraph } = Typography;
import like from "@/assets/icons/like.svg";
import favorite from "@/assets/icons/favorite.svg";
import useStore from "@/utils/store/useStore.tsx";
import { addLikeDetail, getShareDetail } from "@/api/share";
import { addLikeDetail, deletedLikeDetail, getShareDetail } from "@/api/share";
import StorageIcon from "@/constant/stroage-icon.ts";
import { observer } from "mobx-react";
import { addFavorites } from "@/api/user";
import { addFavorites, deleteFavorites } from "@/api/user";
const ShareDetail: React.FunctionComponent = () => {
const navigate = useNavigate();
const store = useStore("share");
@@ -44,18 +46,20 @@ const ShareDetail: React.FunctionComponent = () => {
}
async function addLike() {
const data: any = {
circleId: store.getCircleId(),
userId: userId,
detailId: params.id,
};
addLikeDetail(data).then();
}
// async function delLike() {
// const data: any = {
// userId: userId,
// detailId: params.id,
// };
// deletedLikeDetail(data).then();
// }
async function delLike() {
const data: any = {
circleId: store.getCircleId(),
userId: userId,
detailId: params.id,
};
deletedLikeDetail(data).then();
}
async function setFavorites() {
const data: any = {
userId: userId,
@@ -68,6 +72,7 @@ const ShareDetail: React.FunctionComponent = () => {
type: "success",
content: "收藏成功",
});
getDetail().then();
} else {
message.open({
type: "error",
@@ -76,6 +81,27 @@ const ShareDetail: React.FunctionComponent = () => {
}
});
}
async function cancelFavorites() {
const data: any = {
userId: userId,
detailId: params.id,
circleId: store.getCircleId(),
};
deleteFavorites(data).then((res: any) => {
if (res && res.success) {
message.open({
type: "success",
content: "取消成功",
});
getDetail().then();
} else {
message.open({
type: "error",
content: "取消失败",
});
}
});
}
useEffect(() => {
getDetail().then();
@@ -109,7 +135,7 @@ const ShareDetail: React.FunctionComponent = () => {
color: "gray",
overflow: "hidden",
}}>
{detail.nickname}
{detail.nickname || "unknown"}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
@@ -119,7 +145,7 @@ const ShareDetail: React.FunctionComponent = () => {
fontSize: 12,
color: "gray",
}}>
{detail.likesCount}
{detail.likesCount || 0}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
@@ -129,7 +155,7 @@ const ShareDetail: React.FunctionComponent = () => {
fontSize: 12,
color: "gray",
}}>
{detail.commentCount}
{detail.commentCount || 0}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
@@ -139,7 +165,7 @@ const ShareDetail: React.FunctionComponent = () => {
fontSize: 12,
color: "gray",
}}>
{detail.views}
{detail.views || 0}
</span>
</Flex>
</Flex>
@@ -218,7 +244,7 @@ const ShareDetail: React.FunctionComponent = () => {
color: "#1677FF",
fontSize: 16,
}}>
{url.typeName}
</span>
</div>
<ExportOutlined
@@ -277,7 +303,7 @@ const ShareDetail: React.FunctionComponent = () => {
Array.from(detail.tags).map((tag: any, index: number) => {
return (
<div key={index}>
<Tag bordered={false} color={getRandomColor()}>
<Tag bordered={false} color={"#" + detail.color}>
{tag.tagName}
</Tag>
</div>
@@ -290,21 +316,54 @@ const ShareDetail: React.FunctionComponent = () => {
align={"center"}
justify={"center"}
style={{ height: 50 }}>
{detail.isLike === true ? (
<>
<Tooltip title={"取消点赞"} placement={"bottom"}>
<Avatar
className={styles.like_icon}
src={like as any}
onClick={() => {
addLike().then();
delLike().then();
}}
size={"large"}></Avatar>
{/*isFavor*/}
</Tooltip>
</>
) : (
<>
<Tooltip title={"点赞"} placement={"bottom"}>
<LikeOutlined
className={styles.detail_link_btn}
onClick={() => {
addLike().then();
}}></LikeOutlined>
</Tooltip>
</>
)}
{detail.isFavor === true ? (
<>
<Tooltip title={"取消收藏"} placement={"bottom"}>
<Avatar
className={styles.favtorie_icon}
src={favorite as any}
onClick={() => {
setFavorites().then();
cancelFavorites().then();
}}
size={"large"}></Avatar>
</Tooltip>
</>
) : (
<>
<Tooltip title={"收藏"} placement={"bottom"}>
<StarOutlined
onClick={() => {
setFavorites().then();
}}
className={styles.detail_link_btn}
/>
</Tooltip>
</>
)}
</Flex>
</ProCard>
</div>

View File

@@ -44,33 +44,38 @@ const Comment = observer((props: any) => {
const userStore = useStore("user");
const userId: any = userStore.getUserId();
async function listComments() {
listComment(params.id, userId).then((res: any) => {
console.log(res);
if (res && res.success && res.data) {
setComment([]);
listComment(params.id, userId).then((res: any) => {
if (res && res.success && res.data) {
setComment(res.data);
setLoading(false);
}
});
}
async function addLike(commentId: any) {
setComment([]);
const data: any = {
detailId: params.id,
userId: userId,
commentId: commentId,
};
addLikeComment(data).then();
listComments().then();
}
async function delLike(commentId: any) {
setComment([]);
const data: any = {
detailId: params.id,
userId: userId,
commentId: commentId,
};
deletedLikeComment(data).then();
listComments().then();
}
async function getCommentHot() {
setComment([]);
listCommentHot(params.id, userId).then((res: any) => {
if (res && res.success && res.data) {
setComment([]);
setComment(res.data);
setLoading(false);
}
@@ -85,7 +90,7 @@ const Comment = observer((props: any) => {
}
async function addComments(data: any) {
addComment(data).then((res: any) => {
if (res && res.success && res.data) {
if (res && res.success) {
message.open({
content: "评论成功",
type: "success",
@@ -108,7 +113,7 @@ const Comment = observer((props: any) => {
}
async function addReplies(data: any) {
addReply(data).then((res: any) => {
if (res && res.success && res.data) {
if (res && res.success) {
message.open({
content: "回复成功",
type: "success",
@@ -132,7 +137,7 @@ const Comment = observer((props: any) => {
setIsReplyComment(isReplyComment === index ? null : index);
};
useEffect(() => {
listComments().then();
getCommentHot().then();
getAllCommentAndReply(params.id).then();
}, []);
return (
@@ -261,6 +266,10 @@ const Comment = observer((props: any) => {
extra={<></>}
style={{ width: "100%" }}>
<span>{item.content}</span>
<Flex
vertical={false}
align={"center"}
justify={"space-between"}>
<Flex
vertical={false}
align={"center"}
@@ -278,25 +287,23 @@ const Comment = observer((props: any) => {
<Flex
vertical={false}
align={"center"}>
{item.isLike === false ? (
<LikeOutlined
{item.isLike ===
true ? (
<LikeFilled
onClick={() => {
delLike(
item.id,
).then();
}}
className={
styles.like_icon
}
/>
) : (
<LikeFilled
className={
styles.like_icon
}
style={{
color: "red",
}}
/>
) : (
<LikeOutlined
className={
styles.like_icon
}
onClick={() => {
addLike(
item.id,
@@ -321,11 +328,13 @@ const Comment = observer((props: any) => {
if (item.id) {
replyComment(
item.id,
).then(() => {
).then(
() => {
handleExpandReplyCommentClick(
index,
);
});
},
);
}
}}
className={
@@ -359,6 +368,39 @@ const Comment = observer((props: any) => {
</Button>
</Flex>
</Flex>
<Flex
vertical={false}
align={"center"}>
<span
style={{
textWrap: "nowrap",
fontSize: 12,
color: "grey",
textAlign: "end",
}}>
{item.location ||
"unknown"}
</span>
<span
style={{
marginLeft: 10,
fontSize: 13,
color: "grey",
}}>
{item.browser ||
"unknown"}
</span>
<span
style={{
marginLeft: 10,
fontSize: 13,
color: "grey",
}}>
{item.browserVersion ||
"unknown"}
</span>
</Flex>
</Flex>
</ProCard>
{isReply === index && (
<Flex vertical={true}>
@@ -569,6 +611,16 @@ const Comment = observer((props: any) => {
replyItem.content
}
</span>
<Flex
vertical={
false
}
align={
"center"
}
justify={
"space-between"
}>
<Flex
vertical={
false
@@ -597,7 +649,7 @@ const Comment = observer((props: any) => {
false ? (
<LikeOutlined
onClick={() => {
delLike(
addLike(
replyItem.id,
).then();
}}
@@ -614,7 +666,7 @@ const Comment = observer((props: any) => {
color: "red",
}}
onClick={() => {
addLike(
delLike(
replyItem.id,
).then();
}}
@@ -655,6 +707,45 @@ const Comment = observer((props: any) => {
</Button>
</Flex>
</Flex>
<Flex
vertical={
false
}
align={
"center"
}>
<span
style={{
textWrap:
"nowrap",
fontSize: 12,
color: "grey",
textAlign:
"end",
}}>
{replyItem.location ||
"unknown"}
</span>
<span
style={{
marginLeft: 10,
fontSize: 13,
color: "grey",
}}>
{replyItem.browser ||
"unknown"}
</span>
<span
style={{
marginLeft: 10,
fontSize: 13,
color: "grey",
}}>
{replyItem.browserVersion ||
"unknown"}
</span>
</Flex>
</Flex>
</ProCard>
{isReplyReply ===
replyItem.id && (

View File

@@ -21,3 +21,10 @@
width: 50px;
height: auto;
}
.detail_link_btn{
font-size: 30px;
}
.detail_link_btn:hover{
font-size: 35px;
color: red;
}

View File

@@ -1,7 +1,7 @@
/** @format */
import { ProCard } from "@ant-design/pro-components";
import { Avatar, Button, Flex, Input, List, Skeleton, Tag } from "antd";
import { Avatar, Button, Empty, Flex, Input, List, Skeleton, Tag } from "antd";
import { useEffect, useState } from "react";
import styles from "./index.module.less";
@@ -25,24 +25,7 @@ export default observer(() => {
}
});
}
// async function cancelFavorites(id: any) {
// const data: any = {
// id: id,
// };
// deleteFavorites(data).then((res: any) => {
// if (res && res.success) {
// message.open({
// type: "success",
// content: "取消成功",
// });
// } else {
// message.open({
// type: "error",
// content: "取消失败",
// });
// }
// });
// }
useEffect(() => {
getMyShare().then();
}, []);
@@ -75,6 +58,10 @@ export default observer(() => {
</div>
</ProCard>
<ProCard bordered={false} boxShadow={false}>
{data.length === 0 ? (
<Empty description={"暂无数据"}></Empty>
) : (
<>
<Skeleton loading={loading} active={true} paragraph={{ rows: 14 }}>
<List
dataSource={data}
@@ -102,8 +89,12 @@ export default observer(() => {
key={index}>
<Tag
bordered={false}
color={"#" + tag.color}
style={{ marginLeft: 10 }}>
color={
"#" + tag.color
}
style={{
marginLeft: 10,
}}>
{tag.tagName}
</Tag>
</Flex>
@@ -124,7 +115,9 @@ export default observer(() => {
align={"center"}
justify={"space-between"}
style={{ width: "300px" }}>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<Avatar
src={item.avatar as any}
size={"small"}
@@ -138,7 +131,9 @@ export default observer(() => {
{item.nickname}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<HeartOutlined />
<span
style={{
@@ -148,7 +143,9 @@ export default observer(() => {
{item.likesCount}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<CommentOutlined />
<span
style={{
@@ -158,7 +155,9 @@ export default observer(() => {
{item.commentCount}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<EyeOutlined
style={{ color: "gray" }}
/>{" "}
@@ -179,6 +178,8 @@ export default observer(() => {
)}
/>
</Skeleton>
</>
)}
</ProCard>
</div>
</>

View File

@@ -1,7 +1,7 @@
/** @format */
import { ProCard } from "@ant-design/pro-components";
import { Avatar, Button, Flex, Input, List, Skeleton, Tag } from "antd";
import { Avatar, Button, Empty, Flex, Input, List, Skeleton, Tag } from "antd";
import { useEffect, useState } from "react";
import styles from "./index.module.less";
@@ -58,6 +58,10 @@ export default observer(() => {
</div>
</ProCard>
<ProCard bordered={false} boxShadow={false}>
{data.length === 0 ? (
<Empty description={"暂无数据"}></Empty>
) : (
<>
<Skeleton loading={loading} active={true} paragraph={{ rows: 14 }}>
<List
dataSource={data}
@@ -85,8 +89,12 @@ export default observer(() => {
key={index}>
<Tag
bordered={false}
color={"#" + tag.color}
style={{ marginLeft: 10 }}>
color={
"#" + tag.color
}
style={{
marginLeft: 10,
}}>
{tag.tagName}
</Tag>
</Flex>
@@ -107,7 +115,9 @@ export default observer(() => {
align={"center"}
justify={"space-between"}
style={{ width: "300px" }}>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<Avatar
src={item.avatar as any}
size={"small"}
@@ -121,7 +131,9 @@ export default observer(() => {
{item.nickname}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<HeartOutlined />
<span
style={{
@@ -131,7 +143,9 @@ export default observer(() => {
{item.likesCount}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<CommentOutlined />
<span
style={{
@@ -141,7 +155,9 @@ export default observer(() => {
{item.commentCount}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Flex
vertical={false}
align={"center"}>
<EyeOutlined
style={{ color: "gray" }}
/>{" "}
@@ -162,6 +178,8 @@ export default observer(() => {
)}
/>
</Skeleton>
</>
)}
</ProCard>
</div>
</>

View File

@@ -1,46 +1,37 @@
/** @format */
import { FunctionComponent, useEffect, useState } from "react";
import { Avatar, Card, Empty, Flex, List, Skeleton } from "antd";
import {
BankOutlined,
BulbOutlined,
EnvironmentOutlined,
} from "@ant-design/icons";
import { BankOutlined, BulbOutlined, EnvironmentOutlined } from "@ant-design/icons";
import styles from "./index.module.less";
import { ProCard } from "@ant-design/pro-components";
import Meta from "antd/es/card/Meta";
import { Link, useNavigate } from "react-router-dom";
import { getAllStorage } from "@/api/oss";
import StorageIcon from "@/constant/stroage-icon.ts";
import { getUserInfoApi } from "@/api/user";
import { getRecentShare, getUserInfoApi } from "@/api/user";
import useStore from "@/utils/store/useStore.tsx";
import { observer } from "mobx-react";
const UserInfo: FunctionComponent = observer(() => {
const navigate = useNavigate();
const [loading, setLoading] = useState(true);
const [loadingStorage, setLoadingStorage] = useState(true);
const [userStorage, setUserStorage] = useState([]);
const [recentShare, setRecentShare] = useState([]);
const [userInfo, setUserInfo] = useState<any>({} as any);
const store = useStore("user");
const userId: any = store.getUserId();
const data = [
{
title: "Ant Design Title 1",
},
{
title: "Ant Design Title 2",
},
{
title: "Ant Design Title 3",
},
{
title: "Ant Design Title 4",
},
];
async function getUserStorage() {
const res: any = await getAllStorage(userId);
if (res && res.success && res.data) {
setUserStorage(res.data);
setLoadingStorage(false);
}
}
async function getUserRecentShare() {
const res: any = await getRecentShare(userId);
if (res && res.success && res.data) {
setRecentShare(res.data);
setLoading(false);
}
}
@@ -53,6 +44,7 @@ const UserInfo: FunctionComponent = observer(() => {
useEffect(() => {
getUserInfo().then();
getUserStorage().then();
getUserRecentShare().then();
}, []);
return (
<>
@@ -79,81 +71,92 @@ const UserInfo: FunctionComponent = observer(() => {
<div className={styles.user_info_center_content}>
<ProCard
bordered
style={{ maxWidth: "64%" }}
style={{ maxWidth: "100%" }}
title="我的存储商"
boxShadow
extra={<Link to={"/main/setting"}></Link>}>
<Flex vertical={false} align={"center"} justify={"space-between"} wrap={true}>
<Skeleton loading={loading} active>
{userStorage && userStorage.length === 0 ? (
<Empty description={"暂无数据"}></Empty>
) : (
<>
<Skeleton loading={loadingStorage} active>
{userStorage.map((item: any, index: number) => {
return (
<>
<div key={index}>
<Card
key={index}
onClick={() => {
navigate(`/main/setting/${item.ossType}`);
}}
style={{ width: 350, marginTop: 16, marginLeft: 10 }}
style={{
width: 350,
marginTop: 16,
marginLeft: 10,
}}
hoverable={true}>
<Meta
avatar={<Avatar src={StorageIcon[item.ossType]} />}
avatar={
<Avatar
src={StorageIcon[item.ossType]}
/>
}
title={item.name}
description={
<>
<span> {item.configCount}</span>
<span>
{" "}
{item.configCount}
</span>
<span style={{ marginLeft: 10 }}>
{item.bucketCount}
</span>
</>
}></Meta>
</Card>
</>
</div>
);
})}
</Skeleton>
</>
)}
</Flex>
</ProCard>
<ProCard bordered style={{ maxWidth: "34%" }} title="我的存储桶" boxShadow>
<Skeleton loading={loading} active>
<Card style={{ width: 300, marginTop: 16 }} hoverable={true}>
<Meta
avatar={
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=1" />
}
title="Card title"
description="This is the description"
/>
</Card>
</Skeleton>
</ProCard>
{/*<ProCard bordered style={{ maxWidth: "34%" }} title="我的存储桶" boxShadow>*/}
{/* <Skeleton loading={loading} active>*/}
{/* <Card style={{ width: 300, marginTop: 16 }} hoverable={true}>*/}
{/* <Meta*/}
{/* avatar={*/}
{/* <Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=1" />*/}
{/* }*/}
{/* title="Card title"*/}
{/* description="This is the description"*/}
{/* />*/}
{/* </Card>*/}
{/* </Skeleton>*/}
{/*</ProCard>*/}
</div>
<div className={styles.user_info_bottom_content}>
<ProCard
bordered
style={{ maxWidth: "64%" }}
title="最近动态"
boxShadow
extra={<Link to={"#"}></Link>}>
<ProCard bordered style={{ maxWidth: "64%" }} title="最近动态" boxShadow>
{recentShare && recentShare.length === 0 ? (
<Empty description={"暂无数据"}></Empty>
) : (
<Skeleton loading={loading} active avatar>
<List
itemLayout="horizontal"
dataSource={data}
renderItem={(item, index) => (
dataSource={recentShare}
renderItem={(item: any) => (
<List.Item>
<List.Item.Meta
avatar={
<Avatar
src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`}
/>
}
title={<a href="https://ant.design">{item.title}</a>}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
avatar={<Avatar src={userInfo.avatar} />}
title={item.title}
description={item.date}
/>
</List.Item>
)}
/>
</Skeleton>
)}
</ProCard>
<ProCard bordered style={{ maxWidth: "34%" }} title="站内通知" boxShadow>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty>

View File

@@ -33,6 +33,7 @@ const UserSetting: FunctionComponent = observer(() => {
const userId: any = store.getUserId();
async function getUserInfo() {
getUserInfoApi(userId).then((res: any) => {
console.log(res);
if (res && res.success && res.data) {
setUserInfo(res.data);
setLoading(false);
@@ -40,8 +41,8 @@ const UserSetting: FunctionComponent = observer(() => {
});
}
type FieldType = {
nickname?: string;
location?: string;
nickName?: string;
// location?: string;
introduce?: string;
gender?: string;
company?: string;
@@ -64,7 +65,7 @@ const UserSetting: FunctionComponent = observer(() => {
}
const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
const data: any = {
userId: userId,
id: userId,
...values,
};
updateUserInfo(data).then((res: any) => {
@@ -92,24 +93,22 @@ const UserSetting: FunctionComponent = observer(() => {
getUserInfo().then();
}, []);
const prefixSelector = (
<Form.Item name="prefix" noStyle>
<Select style={{ width: 90 }}>
<Select.Option value="https://">https://</Select.Option>
<Select.Option value="http://">http://</Select.Option>
</Select>
</Form.Item>
);
const ProFormText = (props: any) => {
return (
<ProForm.Item {...props} style={{ height: "10px" }}>
<ProFormCascader
request={async () => city}
width="md"
name="location"
disabled={disable}></ProFormCascader>
</ProForm.Item>
);
};
// const ProFormText = (props: any) => {
// return (
// <ProForm.Item {...props} style={{ height: "10px" }}>
// <ProFormCascader
// request={async () => city}
// width="md"
// name="location"
// disabled={disable}></ProFormCascader>
// </ProForm.Item>
// );
// };
useEffect(() => {}, []);
const TabItems = [
{
@@ -142,7 +141,7 @@ const UserSetting: FunctionComponent = observer(() => {
{/*</Form.Item>*/}
<Form.Item<FieldType>
label="昵称"
name="nickname"
name="nickName"
rules={[
{
type: "string",
@@ -167,12 +166,12 @@ const UserSetting: FunctionComponent = observer(() => {
<Select.Option value="UNKNOWN"></Select.Option>
</Select>
</Form.Item>
<Form.Item<FieldType>
label="地区"
name="location"
rules={[{ required: true, message: "请输入地区!" }]}>
<ProFormText />
</Form.Item>
{/*<Form.Item<FieldType>*/}
{/* label="地区"*/}
{/* name="location"*/}
{/* rules={[{ required: true, message: "请输入地区!" }]}>*/}
{/* <ProFormText />*/}
{/*</Form.Item>*/}
<Form.Item<FieldType> label="公司" name="company">
<Input allowClear disabled={disable} />
</Form.Item>
@@ -240,7 +239,7 @@ const UserSetting: FunctionComponent = observer(() => {
type="text"
onClick={async () => {
const data: any = {
userId: userId,
id: userId,
password: password,
};
await updateUser(data);
@@ -264,7 +263,7 @@ const UserSetting: FunctionComponent = observer(() => {
type="text"
onClick={async () => {
const data: any = {
userId: userId,
id: userId,
phone: phone,
};
await updateUser(data);
@@ -288,7 +287,7 @@ const UserSetting: FunctionComponent = observer(() => {
type="text"
onClick={async () => {
const data: any = {
userId: userId,
id: userId,
email: email,
};
await updateUser(data);
@@ -323,14 +322,14 @@ const UserSetting: FunctionComponent = observer(() => {
<Flex vertical={true} justify={"flex-start"}>
<Flex vertical={false} align={"center"}>
<span style={{ color: "grey" }}></span>
<span style={{ width: 130 }}>{userInfo.userName}</span>
<span style={{ width: 200 }}>{userInfo.userName}</span>
</Flex>
<Flex
vertical={false}
align={"center"}
style={{ marginTop: 20 }}>
<span style={{ color: "grey" }}>ID</span>
<span style={{ width: 130 }}>{userInfo.id}</span>
<span style={{ width: 200 }}>{userInfo.id}</span>
</Flex>
</Flex>
<Flex vertical={true} style={{ marginLeft: 50 }}>

View File

@@ -4,7 +4,7 @@ import Request from "./request";
const web: Request = new Request({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 10000,
// timeout: 10000,
});
export default web;

View File

@@ -16,6 +16,8 @@ import { logout } from "@/api/user";
import { observer } from "mobx-react";
import useStore from "@/utils/store/useStore.tsx";
import { getUserMenuPermission } from "@/api/user";
import { clearStorage, getStorageFromKey, removeStorageFromKey } from "@/utils/localStorage/config.ts";
import localforage from "localforage";
const Layout = () => {
const location = useLocation();
@@ -75,7 +77,14 @@ const Layout = () => {
label: "退出登录",
onClick: () => {
logout(store.getUserId());
clearStorage();
store.setToken("");
store.setUserId("");
store.setAvatar("");
store.setNickName("");
setTimeout(() => {
navigate("/login");
}, 1000);
},
},
],

View File

@@ -115,7 +115,7 @@ export default observer(() => {
async function wechatLogin() {
createClientId().then((res: any) => {
generateQRCode(res.data).then((response: any) => {
if (response.success) {
if (res && response.success && res.data) {
setQRCode(response.data.qrCodeUrl);
setLoading(false);
timerManager.add(() => {
@@ -180,8 +180,6 @@ export default observer(() => {
className={styles.mp_code_img}
// src={generateMpRegCodeData.data?.qrCodeUrl}
src={QRCode}
fallback="data:image/png;base64,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"
/>
</Spin>
<Alert

View File

@@ -120,6 +120,7 @@ export default observer(() => {
store.setAvatar(res.data.user.avatar);
store.setNickName(res.data.user.nickName);
setStorage("token", res.data.token, 24 * 60 * 30);
setStorage("userId", res.data.user.id, 24 * 60 * 30);
if (store.getToken() !== null || store.getUserId() !== null) {
setTimeout(() => {
navigate("/main/home");
@@ -154,6 +155,7 @@ export default observer(() => {
store.setToken(res.data.token);
store.setUserId(res.data.user.id);
setStorage("token", res.data.token, 24 * 60 * 30);
setStorage("userId", res.data.user.id, 24 * 60 * 30);
if (store.getToken() !== null || store.getUserId() !== null) {
setTimeout(() => {
navigate("/main");
@@ -217,7 +219,7 @@ export default observer(() => {
async function wechatLogin() {
createClientId().then((res: any) => {
generateQRCode(res.data).then((response: any) => {
if (response.success) {
if (res && response.success && res.data) {
setQRCode(response.data.qrCodeUrl);
setLoading(false);
timerManager.add(() => {
@@ -289,7 +291,6 @@ export default observer(() => {
className={styles.mp_code_img}
// src={generateMpRegCodeData.data?.qrCodeUrl}
src={QRCode}
fallback="data:image/png;base64,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"
/>
</Spin>
<Alert

View File

@@ -125,7 +125,7 @@ export default observer(() => {
async function wechatLogin() {
createClientId().then((res: any) => {
generateQRCode(res.data).then((response: any) => {
if (response.success) {
if (res && response.success && res.data) {
setQRCode(response.data.qrCodeUrl);
setLoading(false);
timerManager.add(() => {
@@ -184,7 +184,6 @@ export default observer(() => {
className={styles.mp_code_img}
// src={generateMpRegCodeData.data?.qrCodeUrl}
src={QRCode}
fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
/>
</Spin>
<Alert