feat: 访客登录提示与访客账号认领

pull/13/head
moonrailgun 4 years ago
parent 086458bb60
commit 446c70a42b

@ -110,6 +110,7 @@ export {
loginWithToken,
registerWithEmail,
createTemporaryUser,
claimTemporaryUser,
searchUserWithUniqueName,
checkTokenValid,
modifyUserField,
@ -136,7 +137,7 @@ export type { AppStore, AppState, AppDispatch } from './redux/store';
// utils
export { joinArray } from './utils/array-helper';
export { SYSTEM_USERID } from './utils/consts';
export { NAME_REGEXP, SYSTEM_USERID } from './utils/consts';
export {
shouldShowMessageTime,
getMessageTimeDiff,

@ -7,6 +7,7 @@ export interface UserBaseInfo {
nickname: string;
discriminator: string;
avatar: string | null;
temporary: boolean;
}
export interface UserLoginInfo extends UserBaseInfo {
@ -82,6 +83,23 @@ export async function createTemporaryUser(
return data;
}
/**
* 访
*/
export async function claimTemporaryUser(
userId: string,
email: string,
password: string
): Promise<UserLoginInfo> {
const { data } = await request.post('/api/user/claimTemporaryUser', {
userId,
email,
password,
});
return data;
}
/**
* 使
* @param uniqueName : #0000

@ -1,3 +1,11 @@
/**
*
* 16
*
*/
export const NAME_REGEXP =
/^([0-9a-zA-Z]{1,2}|[\u4e00-\u9eff]|[\u3040-\u309Fー]|[\u30A0-\u30FF]){1,8}$/;
/**
*
*/

@ -0,0 +1,45 @@
import { openModal } from '@/plugin/common';
import { Button } from 'antd';
import React, { useCallback } from 'react';
import { t, Trans, useUserInfo } from 'tailchat-shared';
import { closeModal } from './Modal';
import { ClaimTemporaryUser } from './modals/ClaimTemporaryUser';
/**
* 访
*/
export const GlobalTemporaryTip: React.FC = React.memo(() => {
const userInfo = useUserInfo();
const show = userInfo?.temporary === true;
const handleClaim = useCallback(() => {
if (!userInfo?._id) {
return;
}
const key = openModal(
<ClaimTemporaryUser
userId={userInfo._id}
onSuccess={() => closeModal(key)}
/>
);
}, [userInfo?._id]);
return show ? (
<div className="text-center bg-indigo-400 text-white">
<Trans>
使,{' '}
<Button
type="link"
className="text-indigo-700 font-bold"
size="small"
onClick={handleClaim}
>
</Button>
</Trans>
{t('')}
</div>
) : null;
});
GlobalTemporaryTip.displayName = 'GlobalTemporaryTip';

@ -0,0 +1,76 @@
import { setUserJWT } from '@/utils/jwt-helper';
import { setGlobalUserLoginInfo } from '@/utils/user-helper';
import React from 'react';
import { useDispatch } from 'react-redux';
import {
claimTemporaryUser,
createFastFormSchema,
FastFormFieldMeta,
fieldSchema,
t,
useAsyncRequest,
userActions,
} from 'tailchat-shared';
import { ModalWrapper } from '../Modal';
import { WebFastForm } from '../WebFastForm';
interface Values {
email: string;
password: string;
[key: string]: unknown;
}
const fields: FastFormFieldMeta[] = [
{ type: 'text', name: 'email', label: t('邮箱') },
{
type: 'password',
name: 'password',
label: t('密码'),
},
];
const schema = createFastFormSchema({
email: fieldSchema
.string()
.required(t('邮箱不能为空'))
.email(t('邮箱格式不正确')),
password: fieldSchema
.string()
.min(6, t('密码不能低于6位'))
.required(t('密码不能为空')),
});
interface ClaimTemporaryUserProps {
userId: string;
onSuccess: () => void;
}
export const ClaimTemporaryUser: React.FC<ClaimTemporaryUserProps> = React.memo(
(props) => {
const userId = props.userId;
const dispatch = useDispatch();
const [{}, handleClaim] = useAsyncRequest(
async (values: Values) => {
const data = await claimTemporaryUser(
userId,
values.email,
values.password
);
setGlobalUserLoginInfo(data);
await setUserJWT(data.token);
dispatch(userActions.setUserInfo(data));
typeof props.onSuccess === 'function' && props.onSuccess();
},
[, userId, props.onSuccess]
);
return (
<ModalWrapper title={t('认领账号')}>
<WebFastForm schema={schema} fields={fields} onSubmit={handleClaim} />
</ModalWrapper>
);
}
);
ClaimTemporaryUser.displayName = 'ClaimTemporaryUser';

@ -21,7 +21,7 @@ export const GuestView: React.FC = React.memo(() => {
const [nickname, setNickname] = useState('');
const [{ loading }, handleCreateTemporaryUser] = useAsyncRequest(async () => {
await string().required(t('昵称不能为空')).validate(nickname);
await string().required(t('昵称不能为空')).max(16).validate(nickname);
const data = await createTemporaryUser(nickname);

@ -1,3 +1,4 @@
import { GlobalTemporaryTip } from '@/components/GlobalTemporaryTip';
import { useRecordMeasure } from '@/utils/measure-helper';
import React from 'react';
import { MainContent } from './Content';
@ -10,13 +11,17 @@ const MainRoute: React.FC = React.memo(() => {
useShortcuts();
return (
<div className="flex h-full">
<MainProvider>
<Navbar />
<MainProvider>
<div className="flex flex-col h-full">
<GlobalTemporaryTip />
<MainContent />
</MainProvider>
</div>
<div className="flex flex-1">
<Navbar />
<MainContent />
</div>
</div>
</MainProvider>
);
});
MainRoute.displayName = 'MainRoute';

Loading…
Cancel
Save