提交 15b7fe57 作者: 龚洪江

功能:首页二维码登录

上级 24466da6
......@@ -165,3 +165,7 @@ export type getUserAccountByPhoneNumType = InterFunction<
{ phoneNum: string },
{ id: number; nickName: string; userName: string; phoneNum: string; uid: string }[]
>;
//获取小程序二维码
export type appletQRCodeType = InterFunction<{ page: string; scene: string }, string>;
//登录信息-获取
export type getLoginInfoType = InterFunction<{ randomLoginCode: string }, any>;
import axios from '../request';
import {
appletQRCodeType,
BackEndLoginType,
batchRemoveBannerInfo,
exchangeBannerInfo,
getLoginInfoType,
getUserAccountByPhoneNumType,
insertBannerInfo,
insertModuleInfo,
......@@ -75,4 +77,11 @@ export class CommonAPI {
//手机号筛选小程序用户
static getUserAccountByPhoneNum: getUserAccountByPhoneNumType = (params) =>
axios.get('/userapp/user-account/getUserAccountByPhoneNum', { params });
//获取小程序二维码
static getAppletQRCode: appletQRCodeType = (params) => {
return axios.get('/userapp/wx/getAppletQRCode', { params });
};
//获取登录信息
static getLoginInfo: getLoginInfoType = (params) =>
axios.get('/userapp/temp-auth/getLoginInfo', { params });
}
......@@ -36,7 +36,7 @@ service.interceptors.response.use(
// 当接口返回正常时执行
if (status === 200) {
// 如果不报错就直接返回数据
if (data.code === '200') {
if (['200', '7002'].includes(data.code)) {
return Promise.resolve(data);
}
// 重新登录?
......
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><filter x="-5.7%" y="-8.7%" width="112.4%" height="117.4%" filterUnits="objectBoundingBox" id="a"><feOffset dx="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="7.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1"/></filter><path d="M2 0h327.586a1 1 0 01.707.293l49.414 49.414a1 1 0 01.293.707V268a2 2 0 01-2 2H2a2 2 0 01-2-2V2a2 2 0 012-2z" id="b"/></defs><g transform="translate(-330)" fill="none" fill-rule="evenodd"><rect fill="#FFF" width="380" height="270" rx="2"/><path d="M366.833 10.833v2.334h2.334v-2.334h-2.334zm-7 16.334h2.334V29.5h-2.334v-2.333zm9.334-9.334h2.333v2.334h-2.333v-2.334zm-9.334 4.667h2.334v2.333h-2.334V22.5zm4.667-4.667h2.333v2.334H364.5v-2.334zM351.667 8.5H361c.644 0 1.167.522 1.167 1.167V19c0 .644-.523 1.167-1.167 1.167h-9.333A1.167 1.167 0 01350.5 19V9.667c0-.645.522-1.167 1.167-1.167zm1.166 2.333v7h7v-7h-7zm2.334 2.334h2.333V15.5h-2.333v-2.333zm10.5-4.667h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167V9.667c0-.645.522-1.167 1.167-1.167zm0 14h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167v-4.666c0-.645.522-1.167 1.167-1.167zm1.166 2.333v2.334h2.334v-2.334h-2.334zM351.667 22.5h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167v-4.666c0-.645.522-1.167 1.167-1.167zm1.166 2.333v2.334h2.334v-2.334h-2.334z" opacity=".5" fill="#000" fill-opacity=".9"/><use fill="#000" filter="url(#a)" xlink:href="#b"/><use fill="#FFF" xlink:href="#b"/></g></svg>
\ No newline at end of file
......@@ -17,8 +17,20 @@ body {
box-shadow: 0px 20px 30px rgba(112, 158, 254, 0.45);
display: flex;
flex-wrap: wrap;
position: relative;
.login-flex {
flex: 1;
position: relative;
.qr-code-wrap{
position: absolute;
top:50%;
left: 50%;
transform: translate(-50%, -50%);
img{
width: 200px;
height: 200px;
}
}
}
.login-content {
text-align: center;
......@@ -37,6 +49,7 @@ body {
color: rgba(0, 0, 0, 0.5);
}
}
.login-form {
.login-image {
margin: 62px auto 46px;
......@@ -79,5 +92,16 @@ body {
box-shadow: 3px 3px 30px #dddddd;
}
}
.qrCode-icon{
position: absolute;
top: 0;
right: 0;
}
.account-login-operate{
position: absolute;
top: 10px;
right: 10px;
}
}
}
import { Button, Checkbox, Form, Input, message } from 'antd';
import { useEffect } from 'react';
import { Button, Checkbox, Form, Image, Input, message } from 'antd';
import { useEffect, useState } from 'react';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import Cookies from 'js-cookie';
......@@ -10,10 +10,10 @@ import { CommonAPI } from '~/api';
import { useDispatch } from 'react-redux';
import { SET_USERINFO } from '~/store/module/userInfo';
import { authRouterList } from '~/router';
import qrCodeIcon from '~/assets/image/qr-code-icon.svg';
// 请求的类型
type ReqType = InterReqType<BackEndLoginType>;
function LoginView() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/ban-ts-comment
// @ts-ignore
......@@ -22,6 +22,15 @@ function LoginView() {
const dispatch = useDispatch();
// 表单钩子
const [form] = Form.useForm<ReqType>();
//是否二维码登录
const [isLoginCode, setIsLoginCode] = useState<boolean>(false);
//获取小程序二维码唯一标识
const [randomLoginCode] = useState<string>(parseInt(String(Math.random() * 10001), 10) + '');
//小程序二维码地址
const [qrCodeUrl, setQrCodeUrl] = useState<string>('');
//定时器暂存
const [time, setTime] = useState<NodeJS.Timer>();
// 提交数据
const onFinish = async (values: ReqType) => {
const res = await CommonAPI.BackEndLogin({
......@@ -49,7 +58,38 @@ function LoginView() {
message.error('登录失败,请检查账号信息');
}
};
//显示二维码登录方式
const changeLoginUseEvent = () => {
//第一次二维码
if (!isLoginCode && !qrCodeUrl) {
CommonAPI.getAppletQRCode({
page: 'page-identity/identity-empower/index',
scene: `randomLoginCode=${randomLoginCode}&port=1`,
}).then(({ result }) => {
setQrCodeUrl(result ? `data:image/png;base64,${result}` : '');
setTime(
setInterval(() => {
getLoginInfo();
}, 1000),
);
});
} else if (!isLoginCode && qrCodeUrl) {
setTime(
setInterval(() => {
getLoginInfo();
}, 1000),
);
} else {
if (time) {
clearInterval(time);
}
}
setIsLoginCode(!isLoginCode);
};
const getLoginInfo = () => {
CommonAPI.getLoginInfo({ randomLoginCode }).then(({ result }) => {});
};
// componentDidMount
useEffect(() => {
// 是否保存密码
......@@ -67,60 +107,84 @@ function LoginView() {
<div className='login-view'>
<div className='login-flex login-content'>
<div className='login-title'>欢迎来到</div>
<div className='login-text'>科比特 · 云享飞管理平台</div>
<div className='login-text'>云享飞管理平台</div>
<div className='login-detail'>让天空为世界所用</div>
</div>
<div className='login-flex login-form'>
<div className='login-image' />
<div className='login-input'>
<Form
name='basic'
form={form}
wrapperCol={{ span: 16, offset: 4 }}
initialValues={{ remember: true }}
onFinish={onFinish}
autoComplete='off'
>
<Form.Item name='accountNo' rules={[{ required: true, message: '请输入用户名' }]}>
<Input size='large' prefix={<UserOutlined />} placeholder='请输入账号' allowClear />
</Form.Item>
{isLoginCode ? (
<div className='qr-code-wrap'>{<img src={qrCodeUrl} alt='' />}</div>
) : (
<>
<div className='login-image' />
<div className='login-input'>
<Form
name='basic'
form={form}
wrapperCol={{ span: 16, offset: 4 }}
initialValues={{ remember: true }}
onFinish={onFinish}
autoComplete='off'
>
<Form.Item name='accountNo' rules={[{ required: true, message: '请输入用户名' }]}>
<Input
size='large'
prefix={<UserOutlined />}
placeholder='请输入账号'
allowClear
/>
</Form.Item>
<Form.Item
name='passWord'
className='login-password'
rules={[{ required: true, message: '请输入密码' }]}
>
<Input.Password
size='large'
prefix={<LockOutlined />}
placeholder='请输入密码'
allowClear
/>
</Form.Item>
<Form.Item
name='passWord'
className='login-password'
rules={[{ required: true, message: '请输入密码' }]}
>
<Input.Password
size='large'
prefix={<LockOutlined />}
placeholder='请输入密码'
allowClear
/>
</Form.Item>
<Form.Item
name='remember'
className='login-remember'
valuePropName='checked'
wrapperCol={{ offset: 4, span: 8 }}
>
<Checkbox>记住密码</Checkbox>
</Form.Item>
<Form.Item
name='remember'
className='login-remember'
valuePropName='checked'
wrapperCol={{ offset: 4, span: 8 }}
>
<Checkbox>记住密码</Checkbox>
</Form.Item>
<Form.Item wrapperCol={{ offset: 7, span: 15 }}>
<Button
type='primary'
htmlType='submit'
shape='round'
size='large'
className='login-submit'
>
登录
</Button>
</Form.Item>
</Form>
</div>
<Form.Item wrapperCol={{ offset: 7, span: 15 }}>
<Button
type='primary'
htmlType='submit'
shape='round'
size='large'
className='login-submit'
>
登录
</Button>
</Form.Item>
</Form>
</div>
</>
)}
</div>
{isLoginCode ? (
<div className='account-login-operate'>
<Button type='link' onClick={changeLoginUseEvent}>
使用账号登录
</Button>
</div>
) : (
<div className='qrCode-icon'>
<img src={qrCodeIcon} alt='icon' onClick={changeLoginUseEvent} />
</div>
)}
</div>
</div>
);
......
......@@ -203,7 +203,7 @@ const GoodsAddOrEditOrDetail = () => {
const videoList = result.resourcesList
.filter((v) => v.type === 2)
.map((v) => ({ id: v.id, name: 'video', uid: v.id, url: v.url }));
setGoodsDetailsInfo(result);
setGoodsDetailsInfo(JSON.parse(JSON.stringify(result)));
setSkuTable(result.goodsSpecList);
setGoodsDetails(result.goodsDetails || '');
baseInfoRef.current.getForm().setFieldsValue({
......
......@@ -16,6 +16,7 @@ const AddPeopleModal: FC<ModalProps & selfProps> = ({ open, onCancel, onOk, comp
if (code === '200') {
message.success('绑定成功');
onOk();
form.resetFields();
}
});
});
......
import { useSearchParams } from 'react-router-dom';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { SystemManageAPI } from '~/api';
import { InterDataType, PaginationProps } from '~/api/interface';
......@@ -18,6 +18,8 @@ type companyMembersType = InterDataType<listCompanyMembersType>['list'];
const CompanyDetail = () => {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const { userInfo } = useSelector((state: any) => state.UserInfo);
const tableColumns: ColumnsType<companyMembersType[0]> = [
......@@ -151,6 +153,10 @@ const CompanyDetail = () => {
},
});
};
//返回
const backRoute = () => {
navigate(-1);
};
useEffect(() => {
setCompanyId(Number(searchParams.get('id')));
......@@ -198,7 +204,9 @@ const CompanyDetail = () => {
/>
</div>
<div className='company-detail-operate'>
<Button type='primary'>返回</Button>
<Button type='primary' onClick={backRoute}>
返回
</Button>
</div>
{/*添加成员*/}
<AddPeopleModal
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论