Skip to content

Commit f0f3336

Browse files
author
AutoCodingBot
committed
add:profile edit
1 parent 5b6d4a9 commit f0f3336

File tree

10 files changed

+405
-345
lines changed

10 files changed

+405
-345
lines changed

TodoList.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,36 @@ router 独立 `checked` ,升级成v6 `checked`
1313

1414
switch组件,切换用户和群聊,都会向后端请求 本地缓存?但本地缓存又如何判断是否最新?
1515

16+
拆分上传头像组件 `checked`
1617

17-
添加好友(群),无法立即加载,必须 真·刷新
18+
添加好友(群),无法立即加载,必须 真·刷新 `checked`
1819

1920

21+
前端间隔性检查jwt过期时间,示例代码
22+
23+
function decodeJWT(token) {
24+
const base64Url = token.split('.')[1];
25+
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
26+
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
27+
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
28+
}).join(''));
29+
30+
return JSON.parse(jsonPayload);
31+
}
32+
33+
// 使用函数
34+
const decodedToken = decodeJWT(yourJWTToken);
35+
console.log(decodedToken.exp); // 这里假设你的JWT中有`exp` claim
36+
2037
分页加载历史聊天记录,参考:https://ant-design.antgroup.com/components/list-cn#listitemmeta
2138

2239
聊天窗口,参考:https://daisyui.com/components/chat/
2340

2441
未读消息,必须点击其他人才能提示;并仅能提示一次
2542

26-
自己能添加自己,自己给自己发消息,会重复消息;解决思路,将自己改成"文件传输助手",消息记录存单独表,关闭socket推送机制
43+
自己能添加自己
44+
自己给自己发消息,会重复消息;
45+
基本
46+
尝试将自己改成"文件传输助手",消息记录存单独表,关闭socket推送机制
47+
高级
48+
接通通义千问API

src/Test.jsx

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +0,0 @@
1-
import React, { useEffect, useState } from 'react';
2-
import { Avatar, Divider, List, Skeleton } from 'antd';
3-
import InfiniteScroll from 'react-infinite-scroll-component';
4-
const Test = () => {
5-
const [loading, setLoading] = useState(false);
6-
const [data, setData] = useState([]);
7-
const loadMoreData = () => {
8-
if (loading) {
9-
return;
10-
}
11-
setLoading(true);
12-
fetch('https://randomuser.me/api/?results=10&inc=name,gender,email,nat,picture&noinfo')
13-
.then((res) => res.json())
14-
.then((body) => {
15-
setData([...data, ...body.results]);
16-
setLoading(false);
17-
})
18-
.catch(() => {
19-
setLoading(false);
20-
});
21-
};
22-
useEffect(() => {
23-
loadMoreData();
24-
}, []);
25-
return (
26-
<div
27-
id="scrollableDiv"
28-
style={{
29-
height: 400,
30-
overflow: 'auto',
31-
padding: '0 16px',
32-
border: '1px solid rgba(140, 140, 140, 0.35)',
33-
}}
34-
>
35-
<InfiniteScroll
36-
dataLength={data.length}
37-
next={loadMoreData}
38-
hasMore={data.length < 50}
39-
loader={
40-
<Skeleton
41-
avatar
42-
paragraph={{
43-
rows: 1,
44-
}}
45-
active
46-
/>
47-
}
48-
endMessage={<Divider plain>It is all, nothing more 🤐</Divider>}
49-
scrollableTarget="scrollableDiv"
50-
>
51-
<List
52-
dataSource={data}
53-
renderItem={(item) => (
54-
<List.Item key={item.email}>
55-
<List.Item.Meta
56-
avatar={<Avatar src={item.picture.large} />}
57-
title={<a href="https://ant.design">{item.name.last}</a>}
58-
description={item.email}
59-
/>
60-
<div>Content</div>
61-
</List.Item>
62-
)}
63-
/>
64-
</InfiniteScroll>
65-
</div>
66-
);
67-
};
68-
export default Test;

src/chat/Login.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import {
88
} from 'antd';
99
import { axiosPostBody } from './util/Request';
1010
import * as Params from './common/param/Params';
11-
import { redirect ,useNavigate } from 'react-router-dom';
11+
import { useNavigate } from 'react-router-dom';
1212

1313
const Login = () => {
1414
const [registerDrawerVisible, setRegisterDrawerVisible] = useState(false);
1515
const navigate = useNavigate();
1616

1717
useEffect(()=>{
1818
const _uuid = localStorage.getItem('uuid');
19-
if(_uuid){
19+
const _accessToken= localStorage.getItem('ACCESS_TOKEN');
20+
if(_uuid && _accessToken){
2021
navigate(`/panel/${_uuid}`);
2122
}
2223
},[navigate])

src/chat/Panel.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Right from './panel/right/index'
2222
import protobuf from './proto/proto'
2323
import { connect } from 'react-redux'
2424
import { actions } from './redux/module/panel'
25+
import { useNavigate } from 'react-router-dom';
2526

2627
var socket = null;
2728
var peer = null;
@@ -90,6 +91,7 @@ class Panel extends React.Component {
9091
this.connection()
9192
}
9293

94+
9395
/**
9496
* websocket连接
9597
*/
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
2+
import { Upload } from 'antd';
3+
import * as Params from '../param/Params';
4+
import { useSelector } from 'react-redux';
5+
import { useState } from 'react';
6+
import { message } from 'antd';
7+
8+
const UploadAvatar = (props)=>{
9+
const fileUploadHeader = {
10+
"Authorization": "Bearer "+ localStorage.getItem("ACCESS_TOKEN"),
11+
}
12+
const user = useSelector(state => state.userInfoReducer.user);
13+
const [loading, setLoading] = useState(false);
14+
const [imageUrl, setImageUrl] = useState(user.avatar);
15+
16+
const handleChange = (info) => {
17+
if (info.file.status === 'uploading') {
18+
setLoading(true);
19+
return;
20+
}
21+
if (info.file.status === 'done') {
22+
const response = info.file.response;
23+
if (response.code !== 0) {
24+
message.error(response.msg);
25+
} else {
26+
getBase64(info.file.originFileObj, (imageUrl) => {
27+
setImageUrl(imageUrl);
28+
setLoading(false);
29+
});
30+
31+
props.handleImgChange(response.data)
32+
}
33+
}
34+
};
35+
36+
const getBase64=(img, callback) =>{
37+
const reader = new FileReader();
38+
reader.addEventListener('load', () => callback(reader.result));
39+
reader.readAsDataURL(img);
40+
}
41+
const beforeUpload = (file) =>{
42+
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
43+
if (!isJpgOrPng) {
44+
message.error('JPG/PNG only!');
45+
}
46+
const isLt2M = file.size / 1024 / 1024 < 2;
47+
if (!isLt2M) {
48+
message.error('Image must smaller than 2MB!');
49+
}
50+
return isJpgOrPng && isLt2M;
51+
}
52+
return(
53+
<Upload
54+
name="file"
55+
listType="picture-card"
56+
className="avatar-uploader"
57+
style={{position: 'relative'}}
58+
showUploadList={false}
59+
action={Params.FILE_URL}
60+
beforeUpload={beforeUpload}
61+
onChange={handleChange}
62+
headers={fileUploadHeader}
63+
// data={{ objectType: props.objectType}}
64+
>
65+
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '40%',position:'absolute' }} /> : loading ? <LoadingOutlined /> : <PlusOutlined />}
66+
<div style={{ marginTop: 8 }}>Upload</div>
67+
</Upload>
68+
)
69+
}
70+
export default UploadAvatar

src/chat/common/param/Params.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const REGISTER_URL = HOST + '/user/register'
1010
export const USER_URL = HOST + '/user/'
1111
export const USER_NAME_URL = HOST + '/user/name'
1212
export const USER_LIST_URL = HOST + '/user'
13+
// export const USER_PROFILE_URL = HOST + '/user'
1314

1415
export const USER_FRIEND_URL = HOST + '/friend'
1516

src/chat/panel/center/component/UserList.jsx

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,6 @@ const UserList = () => {
1212
const [chooseUser, setChooseUserState] = useState({});//当前用户card
1313
const dispatch = useDispatch();
1414
const userList = useSelector(state => state.panelReducer.userList);
15-
// console.log('当前所在组的用户信息',userList)
16-
// "data": [
17-
// {
18-
// "id": 0,
19-
// "uuid": "28353ed6-5966-4804-9c52-9b00abd4401e",
20-
// "username": "eric",
21-
// "password": "",
22-
// "nickname": "",
23-
// "avatar": "5f9f6ad8-bd9a-4a8d-a9a6-b5ae0e8c0949.jpg",
24-
// "email": "",
25-
// "createAt": "0001-01-01T00:00:00Z",
26-
// "updateAt": null,
27-
// "deleteAt": 0
28-
// },
29-
// {
30-
// "id": 0,
31-
// "uuid": "c0fd020f-fa4d-4379-8f8b-f84a07fadd6a",
32-
// "username": "sam",
33-
// "password": "",
34-
// "nickname": "",
35-
// "avatar": "",
36-
// "email": "",
37-
// "createAt": "0001-01-01T00:00:00Z",
38-
// "updateAt": null,
39-
// "deleteAt": 0
40-
// }
41-
// ]
4215

4316
const chooseUserHandler = (value) => {
4417
//value是在Switch中渲染并提交给redux管理的数据
@@ -130,7 +103,7 @@ const UserList = () => {
130103
<List.Item.Meta
131104
style={{ paddingLeft: 30 ,backgroundColor: chooseUser === item.username ? '#87CEFA' : 'transparent'}}
132105
onClick={() => chooseUserHandler(item)}
133-
avatar={<Badge dot={item.hasUnreadMessage}><Avatar src={item.avatar} /></Badge>}
106+
avatar= {<Badge dot={item.hasUnreadMessage}><Avatar src={item.avatar || `https://api.dicebear.com/9.x/pixel-art/svg?seed=${item.username}`} /></Badge>}
134107
title={item.username}
135108
description=""
136109
// description 用来加载最后一条消息

0 commit comments

Comments
 (0)