Commit 840fffc3 by zhanghaozhe

微信登录无痕验证

parent c6d13618
import React, { Component } from 'react' import React, { Component } from 'react'
import Routes from './router' import Routes from './router'
import cookie from 'js-cookie' import cookie from 'js-cookie'
import { connect } from "react-redux" import { connect } from 'react-redux'
import { setCurrentUser, startFetchUser } from "@/store/userAction" import { setCurrentUser, startFetchUser } from '@/store/userAction'
import { initialState } from "@/store/userReducer" import {
import { withRouter, Link } from 'react-router-dom' updateCaptchaState,
closeCaptchaModal,
showCaptchaModal,
validationPassed,
} from '@/store/no-trace-validation/reducer'
import { initialState } from '@/store/userReducer'
import { withRouter } from 'react-router-dom'
import { compose } from 'redux' import { compose } from 'redux'
import { getParam, http, browser, loadScript, getTimestamp } from "@/utils" import { getParam, http, browser, loadScript, getTimestamp } from '@/utils'
import { Toast } from "antd-mobile" import { Toast } from 'antd-mobile'
import { addDays } from 'date-fns' import { addDays } from 'date-fns'
import stringify from 'json-stringify-safe' import stringify from 'json-stringify-safe'
//拦截ajax请求,返回mock数据 //拦截ajax请求,返回mock数据
/*import mock from '@/utils/mock' /*import mock from '@/utils/mock'
mock()*/ mock()*/
// 默认样式 // 默认样式
import './assets/css/index.scss' import './assets/css/index.scss'
// iconfont // iconfont
import './assets/font/iconfont.css' import './assets/font/iconfont.css'
class App extends Component { class App extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
...@@ -30,7 +34,7 @@ class App extends Component { ...@@ -30,7 +34,7 @@ class App extends Component {
isShowActivityEntry: 0, isShowActivityEntry: 0,
jumpUrl: '', jumpUrl: '',
entryImage: '', entryImage: '',
isNeedCaptcha: true, mkey: '',
} }
} }
...@@ -45,10 +49,14 @@ class App extends Component { ...@@ -45,10 +49,14 @@ class App extends Component {
firstLoad = true firstLoad = true
componentWillMount() { componentWillMount() {
let url = window.location.href; let url = window.location.href
if (url.indexOf('ccode') > -1) { if (url.indexOf('ccode') > -1) {
if (!getParam('ccode').includes('%')) { if (!getParam('ccode').includes('%')) {
cookie.set('ccode', getParam('ccode'), {expires: 1, domain: '.julyedu.com', path: '/'}) cookie.set('ccode', getParam('ccode'), {
expires: 1,
domain: '.julyedu.com',
path: '/',
})
} }
} }
} }
...@@ -61,23 +69,19 @@ class App extends Component { ...@@ -61,23 +69,19 @@ class App extends Component {
//平台信息 //平台信息
!getParam('version') && cookie.set('plat', '5', {domain: '.julyedu.com'}) !getParam('version') && cookie.set('plat', '5', {domain: '.julyedu.com'})
if (browser.isWeixin && browser.isIOS) { if (browser.isWeixin && browser.isIOS) {
sessionStorage.setItem('enter_url', window.location.href) sessionStorage.setItem('enter_url', window.location.href)
} }
this.utm() this.utm()
const {history} = this.props const {history} = this.props
this.getUser() this.getUser()
this.setNavigationRecord(this.props.location, this.props.history.action) this.setNavigationRecord(this.props.location, this.props.history.action)
this.setPreviousLocation() this.setPreviousLocation()
history.listen((location, action) => { history.listen((location, action) => {
this.firstLoad = false this.firstLoad = false
this.setNavigationRecord(location, action) this.setNavigationRecord(location, action)
...@@ -87,7 +91,10 @@ class App extends Component { ...@@ -87,7 +91,10 @@ class App extends Component {
this.getUser() this.getUser()
} }
if (location.pathname.startsWith('/passport')) { if (location.pathname.startsWith('/passport')) {
window.localStorage.setItem('binding_redirect', stringify(this.previousLocation)) window.localStorage.setItem(
'binding_redirect',
stringify(this.previousLocation),
)
} }
const {pathname, state} = location const {pathname, state} = location
if (pathname.startsWith('/passport')) { if (pathname.startsWith('/passport')) {
...@@ -107,27 +114,46 @@ class App extends Component { ...@@ -107,27 +114,46 @@ class App extends Component {
}) })
} }
componentDidUpdate(prevProps, prevState) {
this.setPreviousLocation()
if (!this.props.user.hasError && getParam('redirect')) {
window.location.href = getParam('redirect')
}
const {noTraceValidation: {isShowCaptcha}} = this.props
if (prevProps.noTraceValidation.isShowCaptcha !== isShowCaptcha && isShowCaptcha) {
typeof nvcReset === 'function' && nvcReset()
typeof getNC === 'function' && getNC().then(() => {
_nvc_nc.reset()
})
}
}
// 获取宝箱阶段 // 获取宝箱阶段
getStage = () => { getStage = () => {
let ccode = cookie.get('ccode') let ccode = cookie.get('ccode')
http.get(`${API.home}/sys/anniversary/floating?ccode=${ccode}`).then(res => { http
const {code, data, msg} = res.data .get(`${API.home}/sys/anniversary/floating?ccode=${ccode}`)
if (code === 200) { .then(res => {
this.setState({ const {code, data, msg} = res.data
isShowActivityEntry: data.is_show, if (code === 200) {
jumpUrl: data.jump_url, this.setState({
entryImage: data.image_path, isShowActivityEntry: data.is_show,
}) jumpUrl: data.jump_url,
} else { entryImage: data.image_path,
Toast.info(msg, 2) })
} } else {
}) Toast.info(msg, 2)
}
})
} }
umengStatistic = () => { umengStatistic = () => {
// 友盟统计 // 友盟统计
const script = document.createElement('script') const script = document.createElement('script')
script.src = 'https://s22.cnzz.com/z_stat.php?id=1265696973&web_id=1265696973' script.src =
'https://s22.cnzz.com/z_stat.php?id=1265696973&web_id=1265696973'
script.language = 'JavaScript' script.language = 'JavaScript'
document.body.appendChild(script) document.body.appendChild(script)
} }
...@@ -138,18 +164,26 @@ class App extends Component { ...@@ -138,18 +164,26 @@ class App extends Component {
setNavigationRecord = (location, action) => { setNavigationRecord = (location, action) => {
const {pathname, search, hash} = location const {pathname, search, hash} = location
let isLastRecord = location.pathname === (this.records.length && this.records[this.records.length - 1].pathname) let isLastRecord =
let needHistoryMutation = location.pathname !== this.previousLocation.pathname location.pathname ===
(this.records.length && this.records[this.records.length - 1].pathname)
let needHistoryMutation =
location.pathname !== this.previousLocation.pathname
switch (action) { switch (action) {
case 'POP': case 'POP':
if (needHistoryMutation) { if (needHistoryMutation) {
this.firstLoad ? this.records.push({pathname, search, hash}) : this.records.pop() this.firstLoad
? this.records.push({pathname, search, hash})
: this.records.pop()
} else { } else {
this.records.length ? (this.records[this.records.length - 1] = location) : this.records = [location] this.records.length
? (this.records[this.records.length - 1] = location)
: (this.records = [location])
} }
break break
case 'REPLACE': case 'REPLACE':
this.records.length > 1 && (this.records[this.records.length - 1] = {pathname, search, hash}) this.records.length > 1 &&
(this.records[this.records.length - 1] = {pathname, search, hash})
break break
default: default:
!isLastRecord && this.records.push({pathname, search, hash}) !isLastRecord && this.records.push({pathname, search, hash})
...@@ -157,26 +191,25 @@ class App extends Component { ...@@ -157,26 +191,25 @@ class App extends Component {
location.state && location.state.records location.state && location.state.records
? (location.state.records = this.records) ? (location.state.records = this.records)
: location.state ? location.state = { : location.state
? (location.state = {
...location.state, ...location.state,
records: this.records, records: this.records,
} : (location.state = {records: this.records}) })
: (location.state = {records: this.records})
} }
utm = () => { utm = () => {
// utm统计 m站全站统计广告投放、以及统计详情页浏览 // utm统计 m站全站统计广告投放、以及统计详情页浏览
let zhihu_cb = getParam('cb') let zhihu_cb = getParam('cb')
if (zhihu_cb) { if (zhihu_cb) {
let data = { let data = {
'zhihu_cb': zhihu_cb, zhihu_cb: zhihu_cb,
} }
http.post(`${API['home']}/sys/zhihu/firstRecord`, data) http.post(`${API['home']}/sys/zhihu/firstRecord`, data).then(res => {
.then(res => { })
})
} }
} }
...@@ -188,13 +221,18 @@ class App extends Component { ...@@ -188,13 +221,18 @@ class App extends Component {
let code = getParam('code') let code = getParam('code')
let oid = getParam('oid') let oid = getParam('oid')
if (code && !oid) { if (code && !oid) {
http.get(`${API['passport-api']}/m/wx_loginInfo/code/${code}?redirect=${encodeURIComponent(window.location.href)}`)
http.get(`${API["passport-api"]}/m/wx_loginInfo/code/${code}?redirect=${encodeURIComponent(window.location.href)}`)
.then(res => { .then(res => {
let data = res.data let data = res.data
if (data.errno == 200) { if (data.errno == 200) {
if (data.data.is_check) { if (data.data.is_check) {
this.setupNoTraceValidate(data.data.mkey) this.props.updateCaptchaState({
isNeedValidation: true
})
this.setState({
mkey: data.data.mkey,
});
this.setupNoTraceValidate()
} else { } else {
if (data.data['is_bind_mobile']) { if (data.data['is_bind_mobile']) {
window.location.assign(data.data.url) window.location.assign(data.data.url)
...@@ -207,8 +245,6 @@ class App extends Component { ...@@ -207,8 +245,6 @@ class App extends Component {
this.props.setCurrentUser(initialState) this.props.setCurrentUser(initialState)
} }
}) })
} else { } else {
if (this.props.location.pathname !== '/my') { if (this.props.location.pathname !== '/my') {
http.get(`${API.home}/m/user_info_sample/0`).then(res => { http.get(`${API.home}/m/user_info_sample/0`).then(res => {
...@@ -225,18 +261,17 @@ class App extends Component { ...@@ -225,18 +261,17 @@ class App extends Component {
cookie.set('uid', uid, {expires, domain: '.julyedu.com', path: '/'}) cookie.set('uid', uid, {expires, domain: '.julyedu.com', path: '/'})
cookie.set('token', token, {expires, domain: '.julyedu.com', path: '/'}) cookie.set('token', token, {expires, domain: '.julyedu.com', path: '/'})
/*const search = new URLSearchParams(window.location.search) const search = new URLSearchParams(window.location.search)
search.delete('code') search.delete('code')
search.delete('aa') search.delete('aa')
if (search.has('state') && search.get('state') === 'STATE') { if (search.has('state') && search.get('state') === 'STATE') {
search.delete('state') search.delete('state')
} }
const loc = window.location const loc = window.location
loc.replace(loc.origin + loc.pathname + '?' + search.toString() + loc.hash)*/ loc.replace(loc.origin + loc.pathname + '?' + search.toString() + loc.hash)
} }
setupNoTraceValidate = mkey => { setupNoTraceValidate = () => {
let src = '//g.alicdn.com/sd/nvc/1.1.112/guide.js?t=' + getTimestamp(60 * 1000) let src = '//g.alicdn.com/sd/nvc/1.1.112/guide.js?t=' + getTimestamp(60 * 1000)
const appkey = 'FFFF0N000000000090FC' const appkey = 'FFFF0N000000000090FC'
const scene = 'nvc_register_h5' const scene = 'nvc_register_h5'
...@@ -262,42 +297,44 @@ class App extends Component { ...@@ -262,42 +297,44 @@ class App extends Component {
let timer = setInterval(() => { let timer = setInterval(() => {
if (window.getNVCVal) { if (window.getNVCVal) {
let NVC = window.getNVCVal() let NVC = window.getNVCVal()
this.requestRegister({mkey, NVC}) this.requestRegister(NVC)
clearInterval(timer) clearInterval(timer)
} }
}, 1000) }, 1000)
}) })
} }
requestRegister = data => { requestRegister = (NVC) => {
http.post(`${API["passport-api"]}/m/wxRegister`, data) http.post(`${API['passport-api']}/m/wxRegister`, {
.then(res => { mkey: this.state.mkey,
const {errno, msg, data} = res.data NVC,
if (errno === 200) { }).then(res => {
this.handleLoginResponse(data) const {errno, msg, data} = res.data
} else if (errno === 5002) { if (errno === 200) {
nvcReset && nvcReset()
getNC().then(() => {
})
} else {
Toast.info(msg)
}
})
}
componentDidUpdate() {
this.setPreviousLocation() this.props.validationPassed()
this.handleLoginResponse(data)
if (!this.props.user.hasError && getParam('redirect')) { } else if (errno === 5002) {
window.location.href = getParam('redirect') this.props.updateCaptchaState({
} isShowCaptcha: true
})
typeof nvcReset === 'function' && nvcReset()
typeof getNC === 'function' && getNC().then(() => {
_nvc_nc.reset()
})
} else {
Toast.info(msg)
}
})
} }
setPreviousLocation = () => { setPreviousLocation = () => {
const {location} = this.props const {location} = this.props
let isInBlacklist = this.pathnameBlacklist.some(item => location.pathname.startsWith(item)) let isInBlacklist = this.pathnameBlacklist.some(item =>
location.pathname.startsWith(item),
)
!isInBlacklist && (this.previousLocation = location) !isInBlacklist && (this.previousLocation = location)
} }
...@@ -307,7 +344,8 @@ class App extends Component { ...@@ -307,7 +344,8 @@ class App extends Component {
//移除红包统计cookie //移除红包统计cookie
this.removeShareCodeCookie() this.removeShareCodeCookie()
const { const {
msg, data: { msg,
data: {
avatar_file: avatar, avatar_file: avatar,
user_name: username, user_name: username,
is_vip: isVIP, is_vip: isVIP,
...@@ -378,7 +416,11 @@ class App extends Component { ...@@ -378,7 +416,11 @@ class App extends Component {
if (lastCloseTime) { if (lastCloseTime) {
const pastDate = new Date(parseInt(lastCloseTime)) const pastDate = new Date(parseInt(lastCloseTime))
const now = new Date() const now = new Date()
if (now.getFullYear() > pastDate.getFullYear() || now.getMonth() > pastDate.getMonth() || now.getDate() > pastDate.getDate()) { if (
now.getFullYear() > pastDate.getFullYear() ||
now.getMonth() > pastDate.getMonth() ||
now.getDate() > pastDate.getDate()
) {
this.getStage() this.getStage()
} }
} else { } else {
...@@ -387,29 +429,50 @@ class App extends Component { ...@@ -387,29 +429,50 @@ class App extends Component {
} }
render() { render() {
const {isShowActivityEntry, entryImage, jumpUrl, isNeedCaptcha} = this.state const {
return <> isShowActivityEntry,
<Routes/> entryImage,
{ jumpUrl,
!!isShowActivityEntry && } = this.state
<div className="year19-index"> const {
<i className={'iconfont iconiconfront-2'} onClick={this.closeGlobalEntry}></i> noTraceValidation: {isShowCaptcha, isNeedValidation},
<a href={jumpUrl}> } = this.props
<img src={entryImage} alt=""/> return (
</a> <>
</div> <Routes/>
} {!!isShowActivityEntry && (
{ <div className="year19-index">
isNeedCaptcha && <div id={'global-captcha'}></div> <i
} className={'iconfont iconiconfront-2'}
</> onClick={this.closeGlobalEntry}
></i>
<a href={jumpUrl}>
<img src={entryImage} alt=""/>
</a>
</div>
)}
{isNeedValidation && isShowCaptcha && (
<div className="modal-cover">
<div className="modal">
<div>亲,系统正忙,滑动一下马上回来</div>
<div id={'global-captcha'}></div>
<i className="iconfont iconiconfront-2 close" onClick={this.props.closeCaptchaModal}></i>
</div>
</div>
)}
</>
)
} }
} }
export default compose( export default compose(
connect( connect(({user, noTraceValidation}) => ({user, noTraceValidation}), {
state => ({user: state.user}), setCurrentUser,
{setCurrentUser, startFetchUser}, startFetchUser,
), updateCaptchaState,
closeCaptchaModal,
showCaptchaModal,
validationPassed,
}),
withRouter, withRouter,
)(App) )(App)
...@@ -10,25 +10,70 @@ $link-visited: #333; // 设置链接访问后的颜色 ...@@ -10,25 +10,70 @@ $link-visited: #333; // 设置链接访问后的颜色
$main-color: #09f; // 主体颜色 $main-color: #09f; // 主体颜色
// 字体 // 字体
$font-family-zh: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; $font-family-zh: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
$font-family-en: Arial, sans-serif !default; $font-family-en: Arial, sans-serif !default;
// 盒子模型 // 盒子模型
$box-model: border-box !default; $box-model: border-box !default;
// z-index
$z-50: 50;
$z-100: 100;
$z-150: 150;
$z-200: 200;
$z-250: 250;
$z-max: 999999; //为了应付某些插件z-index 值过高的问题
// 全局设置 // 全局设置
// -------------------------------------------------- // --------------------------------------------------
// //
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { html,
body,
div,
span,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
address,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
samp,
small,
strong,
sub,
sup,
var,
b,
i,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td {
border: 0 none; border: 0 none;
font-size: inherit; font-size: inherit;
color: inherit; color: inherit;
...@@ -40,15 +85,23 @@ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pr ...@@ -40,15 +85,23 @@ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pr
max-height: 100000px; max-height: 100000px;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: normal; font-weight: normal;
} }
em, strong { em,
strong {
font-style: normal; font-style: normal;
} }
ul, ol, li { ul,
ol,
li {
list-style: none; list-style: none;
} }
...@@ -78,252 +131,12 @@ body { ...@@ -78,252 +131,12 @@ body {
padding-bottom: constant(safe-area-inset-bottom); padding-bottom: constant(safe-area-inset-bottom);
} }
// Links
a {
text-decoration: none;
outline: none;
&:hover,
&:link,
&:focus {
text-decoration: none;
}
&:visited {
}
}
// 暂时放置样式,后期需处理
.homeImg {
display: block;
width: 100%;
}
// 字体颜色
.main-color {
color: $main-color;
}
.color333 {
color: #333
}
.color666 {
color: #666
}
.color999 {
color: #999
}
// 背景颜色
.bg-white {
background-color: #fff
}
// 间隔
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt50 {
padding-top: 50px;
}
.pt60 {
padding-top: 60px;
}
.plr20 {
padding-left: 0.2rem;
padding-right: 0.2rem;
}
// 请保证你的设计稿为750px宽,如果有其余字体大小,请在私有样式中设置
.font-20 {
font-size: 0.2rem;
}
.font-24 {
font-size: 0.24rem;
}
.font-26 {
font-size: 0.26rem;
}
.font-28 {
font-size: 0.28rem;
}
.font-30 {
font-size: 0.3rem;
}
.font-32 {
font-size: 0.32rem;
}
.font-34 {
font-size: 0.34rem;
}
.font-36 {
font-size: 0.36rem;
}
.font-38 {
font-size: 0.38rem;
}
.font-40 {
font-size: 0.4rem;
}
// 设置block
.block {
display: block;
}
.show {
display: inherit;
}
.hide {
display: none;
}
// 最外层页面设置
.box {
max-width: 10rem;
margin-left: auto;
margin-right: auto;
}
// 半透明弹层
.alert-bg {
position: fixed;
z-index: $z-50;
width: 100%;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
display: none; //注意:默认隐藏!!
}
.alpha-bg {
position: fixed;
z-index: 100;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
}
// 布局相关
// 水平
.hor {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
// 水平居中
.hor-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
// 垂直居中
.ver-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
// 子元素内联垂直居中
.center-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 子元素块联水平垂直居中
.center-center-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 两边对齐
.space-between {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
// last-no-border
.last-no-border:last-child {
border: none;
background: none;
}
// 图片设置
img {
max-width: 100%;
}
.img-responsive {
display: block;
width: 100%;
}
// 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题 // 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题
.home-swipe { .home-swipe {
height: 40.625vw; height: 40.625vw;
max-height: 406.25px; max-height: 406.25px;
} }
// 文本控制类
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
// 字符溢出隐藏 // 字符溢出隐藏
.text-overflow-1 { .text-overflow-1 {
overflow: hidden; overflow: hidden;
...@@ -361,75 +174,6 @@ img { ...@@ -361,75 +174,6 @@ img {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
// 浮动控制
.cf {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.fl {
float: left;
}
.fr {
float: right;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.z-150 {
z-index: 150;
}
.z-200 {
z-index: 200;
}
.z-250 {
z-index: 250;
}
.z-max {
z-index: 999999;
}
.overflow-h {
overflow: hidden;
}
// 元素绝对定位的垂直水平居中
.absolute-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// radio 样式重写 // radio 样式重写
input[type="radio"] { input[type="radio"] {
position: relative; position: relative;
...@@ -445,7 +189,7 @@ input[type="radio"] { ...@@ -445,7 +189,7 @@ input[type="radio"] {
input[type="radio"]:before { input[type="radio"]:before {
position: absolute; position: absolute;
content: ''; content: "";
display: block; display: block;
width: 0.36rem; width: 0.36rem;
height: 0.36rem; height: 0.36rem;
...@@ -461,7 +205,7 @@ input[type="radio"]:before { ...@@ -461,7 +205,7 @@ input[type="radio"]:before {
input[type="radio"]:checked:after { input[type="radio"]:checked:after {
position: absolute; position: absolute;
z-index: 50; z-index: 50;
content: ''; content: "";
display: block; display: block;
width: 0.36rem; width: 0.36rem;
height: 0.36rem; height: 0.36rem;
...@@ -476,7 +220,7 @@ input[type="radio"]:checked:after { ...@@ -476,7 +220,7 @@ input[type="radio"]:checked:after {
input[type="radio"]:checked:before { input[type="radio"]:checked:before {
position: absolute; position: absolute;
z-index: 100; z-index: 100;
content: ''; content: "";
display: block; display: block;
width: 0.18rem; width: 0.18rem;
height: 0.18rem; height: 0.18rem;
...@@ -501,14 +245,14 @@ input[type="radio"]:checked:before { ...@@ -501,14 +245,14 @@ input[type="radio"]:checked:before {
font-weight: 600; font-weight: 600;
} }
.am-modal-button-group-h { .am-modal-button-group-h {
.am-modal-button { .am-modal-button {
font-size: 15px; font-size: 15px;
} }
} }
.am-modal-alert-content, .am-modal-propmt-content { .am-modal-alert-content,
.am-modal-propmt-content {
color: #333; color: #333;
font-size: 15px; font-size: 15px;
} }
...@@ -538,7 +282,69 @@ input[type="radio"]:checked:before { ...@@ -538,7 +282,69 @@ input[type="radio"]:checked:before {
} }
} }
#global-captcha{ .modal-cover {
height: 44px; position: fixed;
margin-bottom: 50px; top: 0;
} left: 0;
\ No newline at end of file right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 9999;
.modal {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -65%);
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
width: 300px;
height: 130px;
text-align: center;
padding: 20px 20px;
background: #fff;
border-radius: 5px;
font-size: 16px;
color: #525c65;
& > div {
margin-bottom: 10px;
}
._nc {
height: 48px;
}
.stage {
height: 48px;
.slider {
height: 48px;
box-shadow: 0 0 3px #9a9a9a;
.label, .track, .button {
height: 48px;
}
}
}
}
.close {
position: absolute;
bottom: -80px;
left: 50%;
margin-left: -18px;
font-size: 36px;
color: #fff;
}
#global-captcha {
width: 100%;
height: 48px;
margin-bottom: 50px;
}
}
...@@ -9,6 +9,7 @@ import { CopyToClipboard } from "react-copy-to-clipboard"; ...@@ -9,6 +9,7 @@ import { CopyToClipboard } from "react-copy-to-clipboard";
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import storage from 'store2' import storage from 'store2'
import { CaptchaAli } from "@common/index" import { CaptchaAli } from "@common/index"
import { showCaptchaModal } from "@/store/no-trace-validation/reducer";
class Invitation extends Component { class Invitation extends Component {
...@@ -94,7 +95,12 @@ class Invitation extends Component { ...@@ -94,7 +95,12 @@ class Invitation extends Component {
} }
joinTeam = data => { joinTeam = data => {
const {user, history} = this.props const {user, history, noTraceValidation, showCaptchaModal} = this.props
if (noTraceValidation.isNeedValidation && !noTraceValidation.isShowCaptcha) {
showCaptchaModal()
return
}
if (user.hasError) { if (user.hasError) {
if (browser.isWeixin) { if (browser.isWeixin) {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect" window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
...@@ -103,33 +109,42 @@ class Invitation extends Component { ...@@ -103,33 +109,42 @@ class Invitation extends Component {
} }
return return
} }
if (this.state.teamInfo.is_check && !this.state.isShowCaptcha) { if (this.state.teamInfo.is_check && !this.state.isShowCaptcha) {
this.setState({ this.setState({
isShowCaptcha: true, isShowCaptcha: true,
}); });
return return
} }
let _data = {team_code: getParam('team_code')} let _data = {team_code: getParam('team_code')}
if (data.token && data.sig) { if (data.token && data.sig) {
_data = {..._data, ...data} _data = {..._data, ...data}
} }
http.post(`${API.home}/activity/anniversary/joinTeam`, _data) http.post(`${API.home}/activity/anniversary/joinTeam`, _data)
.then(res => { .then(res => {
const {code, msg} = res.data const {code, msg} = res.data
if (code === 200) { if (code === 200) {
Toast.info('加入成功', 2, null, false) Toast.info('加入成功', 2, null, false)
this.setState((state, props) => { this.setState((state, props) => {
return { return {
teamInfo: {...state.teamInfo, ...{status: 2, is_check: false}}, teamInfo: {...state.teamInfo, ...{status: 2, is_check: false}},
isShowCaptcha: false, isShowCaptcha: false,
} }
}); })
} else if (code === 5002) { } else if (code === 5002) {
this.state.instance && this.state.instance.reset() this.state.instance && this.state.instance.reset()
} else if (code === 25015) { } else if (code === 25015) {
this.setState({ this.setState({
isActivityEnd: true, isActivityEnd: true,
}); })
} else { } else {
Toast.info(msg) Toast.info(msg)
} }
...@@ -265,7 +280,9 @@ function BottomButton({status, isActivityEnd, isAnswered, joinTeam, drawQuestion ...@@ -265,7 +280,9 @@ function BottomButton({status, isActivityEnd, isAnswered, joinTeam, drawQuestion
export default compose( export default compose(
connect( connect(
({user}) => ({user}), ({user, noTraceValidation}) => ({user, noTraceValidation}),
null, {
showCaptchaModal,
},
), ),
)(Invitation); )(Invitation);
\ No newline at end of file
import { combineReducers } from 'redux'; import { combineReducers } from "redux"
import myCourses from '@/components/study/myCourses/reducers' import myCourses from "@/components/study/myCourses/reducers"
import courseInfo from '@/components/detail/reducers' import courseInfo from "@/components/detail/reducers"
import user from './userReducer' import user from "./userReducer"
import country from '@/components/country/countryRedux' import country from "@/components/country/countryRedux"
import intelligentRecommend from "@components/intelligent-recommend/store" import intelligentRecommend from "@components/intelligent-recommend/store"
import anniversary2020Question from '@components/activity/2020-717/question/store/reducer' //2020周年庆活动答题页 import anniversary2020Question from "@components/activity/2020-717/question/store/reducer" //2020周年庆活动答题页
import noTraceValidation from "./no-trace-validation/reducer"
const reducer = combineReducers({ const reducer = combineReducers({
myCourses, myCourses,
...@@ -14,6 +14,7 @@ const reducer = combineReducers({ ...@@ -14,6 +14,7 @@ const reducer = combineReducers({
country, country,
intelligentRecommend, intelligentRecommend,
anniversary2020Question, anniversary2020Question,
}); noTraceValidation,
})
export default reducer; export default reducer
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment