diff --git a/client/shared/model/friend.ts b/client/shared/model/friend.ts index 45eb1945..2f7b3779 100644 --- a/client/shared/model/friend.ts +++ b/client/shared/model/friend.ts @@ -59,3 +59,16 @@ export async function removeFriend(friendUserId: string): Promise { friendUserId, }); } + +/** + * 设置好友昵称 + */ +export async function setFriendNickname( + targetId: string, + nickname: string +): Promise { + await request.post('/api/friend/setFriendNickname', { + targetId, + nickname, + }); +} diff --git a/client/shared/redux/slices/user.ts b/client/shared/redux/slices/user.ts index ab4731d1..65ba94e5 100644 --- a/client/shared/redux/slices/user.ts +++ b/client/shared/redux/slices/user.ts @@ -84,6 +84,16 @@ const userSlice = createSlice({ state.friendRequests.splice(index, 1); } }, + setFriendNickname( + state, + action: PayloadAction<{ friendId: string; nickname: string }> + ) { + const { friendId, nickname } = action.payload; + const target = state.friends.find((f) => f.id === friendId); + if (target) { + target.nickname = nickname; + } + }, }, }); diff --git a/client/web/src/components/SubmitButton.tsx b/client/web/src/components/SubmitButton.tsx new file mode 100644 index 00000000..4c9bd5e4 --- /dev/null +++ b/client/web/src/components/SubmitButton.tsx @@ -0,0 +1,28 @@ +import { Button, ButtonProps } from 'antd'; +import React, { useState } from 'react'; + +interface SubmitButtonProps extends ButtonProps { + onClick: (event: React.MouseEvent) => void | Promise; +} + +/** + * Submit Button, use for submit somthing to server + * auto add loading state in onClick + */ +export const SubmitButton: React.FC = React.memo((props) => { + const [loading, setLoading] = useState(false); + return ( + + + + {t('确认')} + + + + ); +}); +SetFriendNickname.displayName = 'SetFriendNickname'; diff --git a/client/web/src/routes/Main/Content/Personal/Friends/FriendList.tsx b/client/web/src/routes/Main/Content/Personal/Friends/FriendList.tsx index dd9c60a8..502f60a6 100644 --- a/client/web/src/routes/Main/Content/Personal/Friends/FriendList.tsx +++ b/client/web/src/routes/Main/Content/Personal/Friends/FriendList.tsx @@ -1,6 +1,7 @@ import React, { useCallback } from 'react'; import { createDMConverse, + isValidStr, removeFriend, showAlert, showErrorToasts, @@ -9,6 +10,7 @@ import { useAppDispatch, useAppSelector, useAsyncRequest, + useEvent, userActions, } from 'tailchat-shared'; import { UserListItem } from '@/components/UserListItem'; @@ -16,6 +18,8 @@ import { IconBtn } from '@/components/IconBtn'; import { Button, Dropdown, Menu, Tooltip } from 'antd'; import { useNavigate } from 'react-router'; import { Problem } from '@/components/Problem'; +import { closeModal, openModal } from '@/components/Modal'; +import { SetFriendNickname } from '@/components/modals/SetFriendNickname'; /** * 好友列表 @@ -35,7 +39,18 @@ export const FriendList: React.FC<{ [navigate] ); - const handleRemoveFriend = useCallback(async (targetId: string) => { + const handleSetFriendNickname = useEvent(async (userId: string) => { + const key = openModal( + { + closeModal(key); + }} + /> + ); + }); + + const handleRemoveFriend = useEvent(async (targetId: string) => { showAlert({ message: t( '是否要从自己的好友列表中删除对方? 注意:你不会从对方的好友列表消失' @@ -50,7 +65,7 @@ export const FriendList: React.FC<{ } }, }); - }, []); + }); if (friends.length === 0) { return ( @@ -88,6 +103,13 @@ export const FriendList: React.FC<{ handleSetFriendNickname(item.id), + label: isValidStr(item.nickname) + ? t('更改好友昵称') + : t('添加好友昵称'), + }, { key: 'delete', danger: true, diff --git a/server/services/core/user/friend.service.ts b/server/services/core/user/friend.service.ts index 17e51b4d..f599a0c0 100644 --- a/server/services/core/user/friend.service.ts +++ b/server/services/core/user/friend.service.ts @@ -4,6 +4,7 @@ import type { FriendModel, } from '../../../models/user/friend'; import { TcService, TcDbService, TcContext } from 'tailchat-server-sdk'; +import { isNil } from 'lodash'; interface FriendService extends TcService, @@ -33,6 +34,12 @@ class FriendService extends TcService { targetId: 'string', }, }); + this.registerAction('setFriendNickname', this.setFriendNickname, { + params: { + targetId: 'string', + nickname: 'string', + }, + }); } /** @@ -98,5 +105,32 @@ class FriendService extends TcService { return isFriend; } + + /** + * 设置好友昵称 + */ + async setFriendNickname( + ctx: TcContext<{ targetId: string; nickname: string }> + ) { + const { targetId, nickname } = ctx.params; + const userId = ctx.meta.userId; + const t = ctx.meta.t; + + const res = await this.adapter.model.findOneAndUpdate( + { + from: userId, + to: targetId, + }, + { + nickname: nickname, + } + ); + + if (isNil(res)) { + throw new Error(t('设置昵称失败, 没有找到好友关系信息')); + } + + return true; + } } export default FriendService;