Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xiaomai-cloud-class-web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xiaomai-cloud-class
xiaomai-cloud-class-web
Commits
b64f7607
Commit
b64f7607
authored
Nov 26, 2020
by
zhangleyuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:新增登录的页面
parent
9f064025
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1796 additions
and
10 deletions
+1796
-10
src/common/less/index.less
+3
-0
src/components/CheckBeforeSendCode.jsx
+81
-0
src/components/CheckBeforeSendCode.less
+50
-0
src/core/function.js
+1159
-0
src/core/variables.less
+2
-2
src/modules/root/Login.jsx
+90
-3
src/modules/root/Login.less
+411
-5
No files found.
src/common/less/index.less
View file @
b64f7607
...
@@ -2,6 +2,9 @@
...
@@ -2,6 +2,9 @@
@import './antd-override.less';
@import './antd-override.less';
@import './variable.less';
@import './variable.less';
#root{
height:100%;
}
.page-body {
.page-body {
background: #fff;
background: #fff;
padding: 16px;
padding: 16px;
...
...
src/components/CheckBeforeSendCode.jsx
0 → 100644
View file @
b64f7607
import
React
from
'react'
import
PropTypes
from
'prop-types'
;
import
'./CheckBeforeSendCode.less'
;
class
CheckBeforeSendCode
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
loading
:
true
,
id
:
window
.
random_string
(),
}
}
componentDidMount
()
{
this
.
initCheckVerifyCode
();
}
initCheckVerifyCode
()
{
this
.
setState
({
loading
:
false
})
const
nc_token
=
[
"FFFF0N000000000084CA"
,
(
new
Date
()).
getTime
(),
Math
.
random
()].
join
(
':'
);
const
NC_Opt
=
{
//声明滑动验证需要渲染的目标元素ID。
renderTo
:
`#
${
this
.
state
.
id
}
`
,
//应用类型标识。它和使用场景标识(scene字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在人机验证控制台的配置管理页签找到对应的appkey字段值,请务必正确填写。
appkey
:
"FFFF0N000000000084CA"
,
//使用场景标识。它和应用类型标识(appkey字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在人机验证控制台的配置管理页签找到对应的scene值,请务必正确填写。
scene
:
"nc_login"
,
//滑动验证码的主键,请勿将该字段定义为固定值。确保每个用户每次打开页面时,其token值都是不同的。系统默认的格式为:”您的appkey”+”时间戳”+”随机数”。
token
:
nc_token
,
//滑动条的宽度。
customWidth
:
300
,
//业务键字段,可为空。为便于线上问题的排查,建议您按照线上问题定位文档中推荐的方法配置该字段值。
trans
:{
"key1"
:
"code0"
},
//通过Dom的ID属性自动填写trans业务键,可为空。建议您按照线上问题定位文档中推荐的方法配置该字段值。
elementID
:
[
"usernameID"
],
//是否自定义配置底层采集组件。如无特殊场景,请使用默认值(0),即不自定义配置底层采集组件。
is_Opt
:
0
,
//语言。PC端Web页面场景默认支持18国语言,详细配置方法请参见自定义文案与多语言文档。
language
:
"cn"
,
//是否启用。一般情况,保持默认值(true)即可。
isEnabled
:
true
,
//内部网络请求的超时时间。一般情况建议保持默认值(3000ms)。
timeout
:
3000
,
//允许服务器超时重复次数,默认5次。超过重复次数后将触发报错。
times
:
5
,
//用于自定义滑动验证各项请求的接口地址。一般情况,请勿配置该参数。
apimap
:
{
// 'analyze': '//a.com/nocaptcha/analyze.jsonp',
// 'get_captcha': '//b.com/get_captcha/ver3',
// 'get_captcha': '//pin3.aliyun.com/get_captcha/ver3'
// 'get_img': '//c.com/get_img',
// 'checkcode': '//d.com/captcha/checkcode.jsonp',
// 'umid_Url': '//e.com/security/umscript/3.2.1/um.js',
// 'uab_Url': '//aeu.alicdn.com/js/uac/909.js',
// 'umid_serUrl': 'https://g.com/service/um.json'
},
//前端滑动验证通过时会触发该回调参数。您可以在该回调参数中将请求标识(token)、会话ID(sessionid)、签名串(sig)字段记录下来,随业务请求一同发送至您的服务端调用验签。
callback
:
(
data
)
=>
{
this
.
props
.
callback
(
data
,
nc
);
}
}
const
nc
=
new
noCaptcha
(
NC_Opt
)
//用于自定义文案。详细配置方法请参见自定义文案与多语言文档。
nc
.
upLang
(
'cn'
,
{
_startTEXT
:
"请按住滑块,拖动到最右边"
,
_yesTEXT
:
"验证通过"
,
_error300
:
"点击<a href=
\"
javascript:__nc.reset()
\"
>刷新</a>再来一次"
,
_errorNetwork
:
"网络不给力,请<a href=
\"
javascript:__nc.reset()
\"
>点击刷新</a>"
})
}
render
()
{
return
<
div
id=
{
this
.
state
.
id
}
className=
"nc-container check-before-send"
></
div
>
}
}
CheckBeforeSendCode
.
propTypes
=
{
callback
:
PropTypes
.
func
,
}
export
default
CheckBeforeSendCode
;
\ No newline at end of file
src/components/CheckBeforeSendCode.less
0 → 100644
View file @
b64f7607
.check-before-send {
#nc_1_wrapper, .nc-container.tb-login #nc_1_wrapper {
width: 288px !important;
}
.nc_scale {
background: #FAFAFA;
border-radius: 4px;
height: 40px;
box-sizing: border-box;
.scale_text2 {
color: #666;
}
.nc_iconfont {
color: #FF8534;
font-weight: bold;
border-color: #e8e8e8;
height: 40px;
line-height: 40px;
width: 52px;
box-sizing: border-box;
}
}
.nc_scale span.nc-lang-cnt {
height: 40px;
line-height: 40px;
box-sizing: border-box;
}
.nc_scale .nc_ok, .nc_scale .nc_bg {
background: #FFE7D6;
border-radius: 4px 0 0 4px;
}
.nc_scale .btn_ok {
color: #FF8534;
height: 40px;
line-height: 40px;
box-sizing: border-box;
}
.errloading {
color: #fff;
white-space: nowrap;
overflow: hidden;
.nc-lang-cnt {
color: #666;
a {
color: #FC9C6B;
}
}
}
}
\ No newline at end of file
src/core/function.js
0 → 100644
View file @
b64f7607
/**
* 处理一个学员,报名同一个包月课多次 的时间计算
* @param courseList
* @returns {*}
*/
import
domtoimage
from
'dom-to-image'
import
{
Popover
}
from
'antd'
import
React
from
'react'
// 时间控件优化方法
window
.
setCorrectDate
=
date
=>
{
let
_date
=
date
;
if
((
date
-
(
+
new
Date
())
<
30
*
60
*
1000
))
{
const
currentMinute
=
new
Date
().
getMinutes
();
if
(
currentMinute
>
30
)
{
_date
=
moment
().
add
(
60
-
currentMinute
,
'minute'
);
}
else
{
_date
=
moment
().
add
(
30
-
currentMinute
,
'minute'
);
}
}
return
_date
;
}
// 优化四舍五入方法
if
(
!
Number
.
prototype
.
toFixedCorrect
)
{
Number
.
prototype
.
toFixedCorrect
=
function
(
n
)
{
return
Math
.
round
((
this
*
Math
.
pow
(
10
,
n
)).
toFixed
(
10
)
*
1
)
/
Math
.
pow
(
10
,
n
);
}
}
window
.
processMonthCourseDate
=
courseList
=>
{
if
(
Array
.
isArray
(
courseList
)
&&
courseList
.
length
>
0
)
{
// 因为所购买的时间不可能有重叠,先排序
courseList
=
courseList
.
sort
(
function
(
now
,
next
)
{
return
parseInt
(
now
.
startDate
)
-
parseInt
(
next
.
startDate
)
})
// 总天数,与已完成天数
let
sumDays
=
0
,
finishDays
=
0
,
givingDays
=
0
courseList
.
forEach
(
function
(
item
)
{
if
(
item
.
endDate
!=
item
.
purchaseEndDate
)
{
givingDays
+=
moment
(
parseInt
(
item
.
endDate
)).
diff
(
parseInt
(
item
.
purchaseEndDate
),
'days'
)
}
const
temp
=
moment
(
parseInt
(
item
.
endDate
)).
diff
(
parseInt
(
item
.
startDate
),
'days'
)
+
1
sumDays
+=
temp
if
(
item
.
endDate
<
Date
.
now
())
{
finishDays
+=
temp
}
else
if
(
item
.
startDate
<
Date
.
now
()
&&
Date
.
now
()
<
item
.
endDate
)
{
finishDays
+=
moment
().
diff
(
parseInt
(
item
.
startDate
),
'days'
)
+
1
}
})
let
date
=
{}
for
(
let
i
=
0
,
len
=
courseList
.
length
;
i
<
len
;
i
++
)
{
const
course
=
courseList
[
i
],
nextCourse
=
courseList
[
i
+
1
]
const
startDate
=
(
course
.
startDate
=
moment
(
parseInt
(
course
.
startDate
))
.
startOf
(
'day'
)
.
valueOf
())
const
purchaseEndDate
=
(
course
.
purchaseEndDate
=
moment
(
parseInt
(
course
.
purchaseEndDate
)
)
.
endOf
(
'day'
)
.
valueOf
())
const
endDate
=
(
course
.
endDate
=
course
.
endDate
?
moment
(
parseInt
(
course
.
endDate
))
.
endOf
(
'day'
)
.
valueOf
()
:
undefined
)
if
(
i
==
0
&&
Date
.
now
()
<
startDate
)
{
date
=
{
startDate
:
startDate
,
endDate
:
endDate
,
purchaseEndDate
:
purchaseEndDate
,
text
:
'课程未开始'
}
break
}
if
((
i
==
len
-
1
&&
endDate
<
Date
.
now
())
||
!
endDate
)
{
date
=
{
text
:
'课程到期'
,
startDate
:
startDate
,
endDate
:
endDate
,
purchaseEndDate
:
purchaseEndDate
}
break
}
if
(
startDate
<
Date
.
now
()
&&
Date
.
now
()
<
endDate
)
{
date
=
{
startDate
:
startDate
,
endDate
:
endDate
,
purchaseEndDate
:
purchaseEndDate
,
text
:
'课程进行中'
}
break
}
else
if
(
endDate
<
Date
.
now
()
&&
Date
.
now
()
<
parseInt
(
nextCourse
.
startDate
)
)
{
date
=
{
startDate
:
parseInt
(
nextCourse
.
startDate
),
endDate
:
parseInt
(
nextCourse
.
endDate
),
purchaseEndDate
:
parseInt
(
nextCourse
.
purchaseEndDate
),
text
:
'课程未开始'
}
break
}
}
// 总天数
date
.
sumDays
=
sumDays
// 已过去天数
date
.
finishDays
=
finishDays
// 剩余总天数
date
.
subDays
=
sumDays
-
finishDays
// 赠送天数
date
.
givingDays
=
givingDays
// 购买天数
date
.
purchaseDays
=
sumDays
-
givingDays
return
date
}
return
false
}
/**
* 生成树
* @param parentCode
* @param datas
* @param level
* @returns {Array}
*/
window
.
createTree
=
(
parentCode
,
datas
,
level
=
0
)
=>
{
const
child
=
[]
const
childCodes
=
[]
// 找子节点
for
(
let
i
in
datas
)
{
const
item
=
datas
[
i
]
if
(
item
.
parent
==
parentCode
)
{
item
.
level
=
level
child
.
push
(
item
)
childCodes
.
push
(
item
.
code
)
}
}
const
len
=
child
.
length
if
(
len
>
0
)
{
if
(
parentCode
!=
0
)
{
datas
[
parentCode
].
child
=
child
datas
[
parentCode
].
childCodes
=
childCodes
}
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
createTree
(
child
[
i
].
code
,
datas
,
level
+
1
)
}
}
return
child
}
window
.
sortPermission
=
data
=>
{
data
.
sort
((
a
,
b
)
=>
{
return
a
.
sequence
-
b
.
sequence
})
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
if
(
data
[
i
].
child
)
{
window
.
sortPermission
(
data
[
i
].
child
)
}
}
return
data
}
/**
* 生成指定长度的随机字符串
* @param len
* @returns {string}
*/
window
.
random_string
=
len
=>
{
len
=
len
||
32
const
chars
=
'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
const
maxPos
=
chars
.
length
let
pwd
=
''
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
pwd
+=
chars
.
charAt
(
Math
.
floor
(
Math
.
random
()
*
maxPos
))
}
return
pwd
}
/**
* 金额转大写
* @param num
* @returns {string|*}
*/
window
.
numberToChines
=
num
=>
{
if
(
num
!=
0
&&
!
num
)
return
''
let
strOutput
=
''
let
strUnit
=
'仟佰拾亿仟佰拾万仟佰拾元角分'
num
+=
'00'
const
intPos
=
num
.
indexOf
(
'.'
)
if
(
intPos
>=
0
)
num
=
num
.
substring
(
0
,
intPos
)
+
num
.
substr
(
intPos
+
1
,
2
)
strUnit
=
strUnit
.
substr
(
strUnit
.
length
-
num
.
length
)
for
(
let
i
=
0
;
i
<
num
.
length
;
i
++
)
strOutput
+=
'零壹贰叁肆伍陆柒捌玖'
.
substr
(
num
.
substr
(
i
,
1
),
1
)
+
strUnit
.
substr
(
i
,
1
)
return
strOutput
.
replace
(
/零角零分$/
,
'整'
)
.
replace
(
/零
[
仟佰拾
]
/g
,
'零'
)
.
replace
(
/零
{2,}
/g
,
'零'
)
.
replace
(
/零
([
亿|万
])
/g
,
'$1'
)
.
replace
(
/零+元/
,
'元'
)
.
replace
(
/亿零
{0,3}
万/
,
'亿'
)
.
replace
(
/^元/
,
'零元'
)
}
/**
* 人名币格式
* @param price 人名币
*
*/
window
.
getMoneyFormat
=
price
=>
{
if
(
!
_
.
isNumber
(
Number
(
price
)))
{
return
'0.00'
}
const
n
=
parseFloat
(
Math
.
round
(
price
)
/
CONFIG
.
moneyUnit
).
toFixed
(
2
)
const
re
=
/
(\d{1,3})(?=(\d{3})
+
(?:\.))
/g
return
n
.
replace
(
re
,
'$1,'
)
}
window
.
getNumberFormat
=
price
=>
{
const
n
=
price
+
''
let
arr
=
n
.
split
(
'.'
)
if
(
arr
[
1
])
{
arr
[
1
]
=
arr
[
1
].
substring
(
0
,
2
)
}
arr
.
splice
(
2
)
return
arr
.
join
(
'.'
)
}
/**
* 人名币转化为分
* @param price 人名币
*
*/
window
.
getMoneyByMoneyUnit
=
price
=>
{
return
Math
.
round
(
price
*
CONFIG
.
moneyUnit
)
}
/**
* 时间格式
* @param format 时间格式
* @param timestamp 时间戳
*/
window
.
formatTime
=
(
format
,
timestamp
)
=>
{
if
(
!
timestamp
)
{
return
}
const
date
=
new
Date
(
parseInt
(
timestamp
))
let
y
=
date
.
getFullYear
(),
m
=
date
.
getMonth
()
+
1
,
d
=
date
.
getDate
(),
h
=
date
.
getHours
()
-
8
,
i
=
date
.
getMinutes
(),
s
=
date
.
getSeconds
(),
w
=
date
.
getDay
()
return
format
.
replace
(
'YYYY'
,
y
)
.
replace
(
'MM'
,
m
)
.
replace
(
'DD'
,
d
)
.
replace
(
'H'
,
h
)
.
replace
(
'i'
,
i
)
.
replace
(
's'
,
s
)
}
window
.
formatDate
=
(
format
,
timestamp
)
=>
{
if
(
!
timestamp
)
return
''
if
(
timestamp
==
0
)
return
''
const
date
=
new
Date
(
parseInt
(
timestamp
))
let
y
=
date
.
getFullYear
(),
m
=
date
.
getMonth
()
+
1
,
d
=
date
.
getDate
(),
h
=
date
.
getHours
(),
i
=
date
.
getMinutes
(),
s
=
date
.
getSeconds
(),
w
=
date
.
getDay
(),
week
=
[
'周日'
,
'周一'
,
'周二'
,
'周三'
,
'周四'
,
'周五'
,
'周六'
]
m
=
m
<
10
?
'0'
+
m
:
m
d
=
d
<
10
?
'0'
+
d
:
d
h
=
h
<
10
?
'0'
+
h
:
h
i
=
i
<
10
?
'0'
+
i
:
i
s
=
s
<
10
?
'0'
+
s
:
s
return
format
.
replace
(
'YYYY'
,
y
)
.
replace
(
'MM'
,
m
)
.
replace
(
'DD'
,
d
)
.
replace
(
'H'
,
h
)
.
replace
(
'i'
,
i
)
.
replace
(
's'
,
s
)
.
replace
(
'WW'
,
week
[
w
])
}
/**
* 查询字符串参数
* @returns {Object}
* @constructor
*/
window
.
getRequest
=
()
=>
{
const
url
=
location
.
search
//获取url中"?"符后的字串
const
theRequest
=
{}
if
(
url
.
indexOf
(
'?'
)
!=
-
1
)
{
const
str
=
url
.
substr
(
1
)
const
strs
=
str
.
split
(
'&'
)
for
(
var
i
=
0
;
i
<
strs
.
length
;
i
++
)
{
theRequest
[
strs
[
i
].
split
(
'='
)[
0
]]
=
unescape
(
strs
[
i
].
split
(
'='
)[
1
])
}
}
return
theRequest
}
window
.
getParameterByName
=
function
(
name
)
{
name
=
name
.
replace
(
/
[\\
[
]
/
,
'
\\
['
).
replace
(
/
[\]]
/
,
'
\\
]'
)
const
regex
=
new
RegExp
(
'[
\\
?&]'
+
name
+
'=([^&#]*)'
)
const
results
=
regex
.
exec
(
location
.
href
)
return
results
===
null
?
''
:
decodeURIComponent
(
results
[
1
].
replace
(
/
\+
/g
,
' '
))
}
window
.
getUrlParam
=
function
()
{
const
urlArr
=
location
.
href
.
split
(
'/'
);
const
str
=
urlArr
[
urlArr
.
length
-
1
];
const
param
=
parseInt
(
str
);
return
isNaN
(
param
)
?
''
:
str
;
}
window
.
getStringParamete
=
function
(
string
,
name
)
{
const
theRequest
=
{}
if
(
string
.
indexOf
(
'?'
)
!=
-
1
)
{
const
str
=
string
.
substr
(
1
)
const
strs
=
str
.
split
(
'&'
)
for
(
var
i
=
0
;
i
<
strs
.
length
;
i
++
)
{
theRequest
[
strs
[
i
].
split
(
'='
)[
0
]]
=
decodeURIComponent
(
strs
[
i
].
split
(
'='
)[
1
])
}
}
return
theRequest
[
name
]
}
/**
* dataURL 转 Blob
* @param dataurl
* @returns {Blob}
*/
window
.
dataURLtoBlob
=
dataurl
=>
{
const
arr
=
dataurl
.
split
(
','
),
mime
=
arr
[
0
].
match
(
/:
(
.*
?)
;/
)[
1
],
bstr
=
atob
(
arr
[
1
]),
u8arr
=
new
Uint8Array
(
n
)
let
n
=
bstr
.
length
while
(
n
--
)
{
u8arr
[
n
]
=
bstr
.
charCodeAt
(
n
)
}
return
new
Blob
([
u8arr
],
{
type
:
mime
})
}
window
.
timeFormat
=
(
time
,
defaultValue
)
=>
{
const
stringTime
=
time
?
(
time
/
CONFIG
.
timeUnit
).
toFixed
(
2
)
:
defaultValue
==
undefined
?
0
:
defaultValue
return
Number
(
stringTime
)
}
window
.
stringCompare
=
(
s1
,
s2
)
=>
{
if
(
!
(
s1
&&
s2
))
{
return
true
}
const
s1Arr
=
s1
.
split
(
'.'
)
const
s2Arr
=
s2
.
split
(
'.'
)
var
s1Num
=
0
var
s2Num
=
0
var
flag
=
true
s1Arr
.
map
((
item
,
index
)
=>
{
s1Num
+=
item
*
Math
.
pow
(
10
,
6
-
2
*
index
)
})
s2Arr
.
map
((
item
,
index
)
=>
{
s2Num
+=
item
*
Math
.
pow
(
10
,
6
-
2
*
index
)
})
return
!
(
s1Num
<
s2Num
)
}
window
.
timeFormatSixty
=
(
time
,
defaultValue
)
=>
{
const
stringTime
=
time
?
(
time
/
60
).
toFixed
(
2
)
:
defaultValue
==
undefined
?
0
:
defaultValue
return
Number
(
stringTime
)
}
window
.
type
=
obj
=>
{
var
toString
=
Object
.
prototype
.
toString
var
map
=
{
'[object Boolean]'
:
'boolean'
,
'[object Number]'
:
'number'
,
'[object String]'
:
'string'
,
'[object Function]'
:
'function'
,
'[object Array]'
:
'array'
,
'[object Date]'
:
'date'
,
'[object RegExp]'
:
'regExp'
,
'[object Undefined]'
:
'undefined'
,
'[object Null]'
:
'null'
,
'[object Object]'
:
'object'
}
return
map
[
toString
.
call
(
obj
)]
}
window
.
deepClone
=
data
=>
{
var
self
=
this
var
t
=
type
(
data
),
o
,
i
,
ni
if
(
t
===
'array'
)
{
o
=
[]
}
else
if
(
t
===
'object'
)
{
o
=
{}
}
else
{
return
data
}
if
(
t
===
'array'
)
{
for
(
i
=
0
,
ni
=
data
.
length
;
i
<
ni
;
i
++
)
{
o
.
push
(
deepClone
(
data
[
i
]))
}
return
o
}
else
if
(
t
===
'object'
)
{
for
(
i
in
data
)
{
o
[
i
]
=
deepClone
(
data
[
i
])
}
return
o
}
}
window
.
moneyFormat
=
(
money
,
defaultValue
)
=>
{
const
stringMoney
=
money
?
(
Math
.
round
(
money
)
/
CONFIG
.
moneyUnit
).
toFixed
(
2
)
:
defaultValue
==
undefined
?
0
:
defaultValue
return
Number
(
stringMoney
)
}
//格式化金额为千位加逗号
window
.
moneyFormatThousands
=
(
number
,
places
,
symbol
,
thousand
,
decimal
)
=>
{
number
=
number
||
0
places
=
!
isNaN
((
places
=
Math
.
abs
(
places
)))
?
places
:
2
symbol
=
symbol
!==
undefined
?
symbol
:
''
thousand
=
thousand
||
','
decimal
=
decimal
||
'.'
let
negative
=
number
<
0
?
'-'
:
''
,
i
=
parseInt
((
number
=
Math
.
abs
(
+
number
||
0
).
toFixed
(
places
)),
10
)
+
''
,
j
=
i
.
length
>
3
?
(
i
.
length
)
%
3
:
0
return
(
symbol
+
negative
+
(
j
?
i
.
substr
(
0
,
j
)
+
thousand
:
''
)
+
i
.
substr
(
j
).
replace
(
/
(\d{3})(?=\d)
/g
,
'$1'
+
thousand
)
+
(
places
?
decimal
+
Math
.
abs
(
number
-
i
)
.
toFixed
(
places
)
.
slice
(
2
)
:
''
)
)
}
/**
* js数字精度转换
*/
window
.
formatFloat
=
(
f
,
digit
=
2
)
=>
{
const
m
=
Math
.
pow
(
10
,
digit
)
return
Math
.
round
(
f
*
m
,
10
)
/
m
}
/**
* 分钟数转成小时表示
* @param number
* @returns {string}
*/
window
.
intToHours
=
number
=>
{
//如果的整数
let
hours
let
minutes
if
(
number
%
1
==
0
)
{
hours
=
Math
.
floor
(
number
/
60
)
minutes
=
number
%
60
}
hours
=
hours
<
10
?
'0'
.
concat
(
hours
)
:
hours
minutes
=
minutes
<
10
?
'0'
.
concat
(
minutes
)
:
minutes
return
hours
+
':'
+
minutes
}
window
.
getMonthLastDate
=
timestamp
=>
{
const
date
=
new
Date
(
parseInt
(
timestamp
))
const
y
=
date
.
getFullYear
()
const
m
=
date
.
getMonth
()
+
2
let
time
=
y
+
'-'
+
m
+
'-01'
time
=
new
Date
(
time
).
getTime
()
-
1000
return
time
}
/*
获取日期相差多少天
* */
window
.
getSubDays
=
(
endDate
,
startDate
)
=>
{
return
Math
.
ceil
(
moment
(
parseInt
(
endDate
)).
diff
(
moment
(
parseInt
(
startDate
)))
/
86400000
)
}
window
.
getPlusMonths
=
(
startDate
,
plusMonths
)
=>
{
let
dtTmp
=
new
Date
(
parseInt
(
startDate
))
plusMonths
=
parseInt
(
plusMonths
)
return
(
new
Date
(
dtTmp
.
getFullYear
(),
dtTmp
.
getMonth
()
+
plusMonths
,
dtTmp
.
getDate
(),
dtTmp
.
getHours
(),
dtTmp
.
getMinutes
(),
dtTmp
.
getSeconds
()
).
getTime
()
-
1000
)
}
window
.
getReduceMonths
=
(
endDate
,
reduceMonths
)
=>
{
let
dtTmp
=
new
Date
(
parseInt
(
endDate
));
reduceMonths
=
parseInt
(
reduceMonths
);
return
(
new
Date
(
dtTmp
.
getFullYear
(),
dtTmp
.
getMonth
()
-
reduceMonths
,
dtTmp
.
getDate
(),
dtTmp
.
getHours
(),
dtTmp
.
getMinutes
(),
dtTmp
.
getSeconds
()
).
getTime
()
+
1000
);
}
window
.
getMinusMonths
=
(
endDate
,
minusMonths
)
=>
{
let
dtTmp
=
new
Date
(
parseInt
(
endDate
))
minusMonths
=
parseInt
(
minusMonths
)
return
new
Date
(
dtTmp
.
getFullYear
(),
(
dtTmp
.
getMonth
())
-
minusMonths
,
dtTmp
.
getDate
(),
dtTmp
.
getHours
(),
dtTmp
.
getMinutes
(),
dtTmp
.
getSeconds
()).
getTime
()
}
window
.
getPlusDays
=
(
startDate
,
plusDays
)
=>
{
let
dtTmp
=
new
Date
(
parseInt
(
startDate
))
plusDays
=
parseInt
(
plusDays
)
return
new
Date
(
Date
.
parse
(
dtTmp
)
+
86400000
*
plusDays
).
getTime
()
}
window
.
getMinusDays
=
(
endDate
,
minusDays
)
=>
{
let
dtTmp
=
new
Date
(
parseInt
(
endDate
))
minusDays
=
parseInt
(
minusDays
)
return
new
Date
(
Date
.
parse
(
dtTmp
)
-
(
86400000
*
minusDays
)).
getTime
()
}
//判断课时是否为整数
window
.
deleteZero
=
classHour
=>
{
return
new
Number
(
classHour
).
valueOf
()
}
//判断是否为两位小数
window
.
isNumber
=
str
=>
{
var
regex
=
/^
\d
+
\.?\d{0,2}
$/
return
regex
.
test
(
str
)
}
// 判断是否是数组且长度不为0
window
.
isLongArr
=
arr
=>
{
return
Array
.
isArray
(
arr
)
&&
arr
.
length
>
0
}
//判断是否为整数
window
.
isInteger
=
obj
=>
{
return
obj
%
1
===
0
}
// 判断是否为 >=0 的数字
window
.
isPositiveNum
=
num
=>
{
return
isNumber
(
num
)
&&
Number
(
num
)
>=
0
}
/**
* 通过课程类型 type 和 课时 得到正确的课时
*/
window
.
getCorrectClassHour
=
(
type
,
classHour
)
=>
{
if
(
type
==
3
)
{
return
classHour
}
else
if
(
type
==
1
||
type
==
2
)
{
return
timeFormat
(
classHour
)
}
}
/**
* 返回下一个需要刷新的页面索引
* @param number total 总数据量
* @param number current 当前页面
* @param number size 页面展示个数
* @param number deleteNumber 删除数量
* @return number 需要刷新的页面
*/
window
.
nextReloadPageNumber
=
(
total
,
current
,
size
,
deleteNumber
)
=>
{
const
currentTotal
=
total
-
deleteNumber
const
pageNumber
=
Math
.
max
(
parseInt
(
currentTotal
-
1
/
size
),
0
)
return
Math
.
min
(
pageNumber
,
current
)
}
// 获取剩余天数,设置课程有效期之后启用
window
.
getLeftExpiredDay
=
(
expiredDate
,
minWarningDays
,
onlyShowTimeover
)
=>
{
const
expiredDay
=
Math
.
floor
(
(
Number
(
expiredDate
)
-
Date
.
now
())
/
(
24
*
60
*
60000
)
)
let
tempStr
=
'(剩余'
+
expiredDay
+
'天)'
if
(
expiredDay
<=
0
)
{
tempStr
=
'(已到期)'
}
// 最小预警天数
if
(
minWarningDays
)
{
if
(
expiredDay
>
minWarningDays
)
{
tempStr
=
''
}
}
if
(
onlyShowTimeover
)
{
if
(
expiredDay
>
0
)
{
tempStr
=
''
}
}
return
tempStr
}
// 处理月份
window
.
handleMonth
=
(
num
)
=>
{
var
result
=
''
if
(
num
<
12
)
{
result
=
`
${
num
}
个月`
}
else
{
var
year
=
Math
.
floor
(
num
/
12
)
var
month
=
num
%
12
if
(
!
month
)
{
result
=
`
${
year
}
年`
}
else
{
result
=
`
${
year
}
年
${
month
}
月`
}
}
return
result
}
// 检测是否为正确的手机号码
window
.
isValidPhone
=
phone
=>
{
// const tempPhone = Number(phone)
return
/^
[
0-9
]{11}
$/
.
test
(
phone
)
}
window
.
timeFilter
=
time
=>
{
const
timeUnit
=
60
let
hour
=
Math
.
floor
(
time
/
timeUnit
)
let
minute
=
time
%
timeUnit
if
(
hour
.
toString
().
length
==
1
)
{
hour
=
'0'
+
hour
}
if
(
minute
.
toString
().
length
==
1
)
{
minute
=
'0'
+
minute
}
return
hour
+
':'
+
minute
}
window
.
getMinutesTime
=
date
=>
{
const
hour
=
parseInt
(
date
/
60
)
let
mint
=
date
-
hour
*
60
mint
>
10
?
(
mint
=
mint
)
:
(
mint
=
'0'
+
mint
)
return
hour
+
':'
+
mint
}
// 冲突函数
window
.
clashFunction
=
data
=>
{
const
returnData
=
{
teachers
:
{},
students
:
{},
classRooms
:
{},
classes
:
{}
}
Array
.
isArray
(
data
)
&&
data
.
map
(
item
=>
{
Array
.
isArray
(
item
.
instScheduleClassConflictVOList
)
&&
item
.
instScheduleClassConflictVOList
.
map
(
value
=>
{
value
.
type
=
item
.
conflictType
if
(
item
.
conflictType
==
1
)
{
//老师
if
(
!
returnData
.
teachers
[
item
.
conflictName
])
{
returnData
.
teachers
[
item
.
conflictName
]
=
[]
}
value
.
teacherName
=
item
.
conflictName
returnData
.
teachers
[
item
.
conflictName
].
push
(
value
)
}
else
if
(
item
.
conflictType
==
2
)
{
//学生
if
(
!
returnData
.
students
[
item
.
conflictName
])
{
returnData
.
students
[
item
.
conflictName
]
=
[]
}
value
.
studentName
=
item
.
conflictName
returnData
.
students
[
item
.
conflictName
].
push
(
value
)
}
else
if
(
item
.
conflictType
==
3
)
{
//本班冲突
if
(
!
returnData
.
classRooms
[
item
.
conflictName
])
{
returnData
.
classRooms
[
item
.
conflictName
]
=
[]
}
value
.
classRoomName
=
item
.
conflictName
returnData
.
classRooms
[
item
.
conflictName
].
push
(
value
)
}
else
if
(
item
.
conflictType
==
4
)
{
//班级冲突
if
(
!
returnData
.
classes
[
item
.
conflictName
])
{
returnData
.
classes
[
item
.
conflictName
]
=
[]
}
value
.
classesName
=
item
.
conflictName
returnData
.
classes
[
item
.
conflictName
].
push
(
value
)
}
})
})
returnData
.
students
=
_
.
values
(
returnData
.
students
)
returnData
.
teachers
=
_
.
values
(
returnData
.
teachers
)
returnData
.
classRooms
=
_
.
values
(
returnData
.
classRooms
)
returnData
.
classes
=
_
.
values
(
returnData
.
classes
)
return
returnData
}
function
checkClash
(
url
,
query
)
{
let
result
=
JSON
.
parse
(
axios
.
post
(
url
,
query
,
{
sync
:
true
}))
let
hasClash
=
0
if
(
result
.
data
&&
result
.
data
.
constructor
.
name
==
'Object'
)
{
result
.
data
=
[
result
.
data
][
0
]
}
let
returnData
=
window
.
clashFunction
(
result
.
data
)
if
(
returnData
.
classRooms
.
length
>
0
||
returnData
.
students
.
length
>
0
||
returnData
.
teachers
.
length
>
0
)
{
hasClash
=
returnData
}
if
(
typeof
result
==
'string'
)
{
result
=
JSON
.
parse
(
result
)
}
result
.
hasClash
=
hasClash
result
.
data
=
returnData
return
result
}
window
.
checkClash
=
checkClash
window
.
caluDateTimeStamp
=
(
date
,
minute
)
=>
{
let
dateTimeStamp
=
date
.
startOf
(
'day'
).
valueOf
()
if
(
minute
)
{
let
minuteTimeStamp
=
parseInt
(
minute
)
*
60
*
1000
return
dateTimeStamp
+
minuteTimeStamp
}
return
dateTimeStamp
}
window
.
hashFilter
=
hash
=>
{
if
(
!
hash
)
{
return
'/'
}
hash
.
replace
(
/#/
,
''
)
let
list
=
hash
.
split
(
'/'
)
list
=
_
.
filter
(
list
,
item
=>
{
return
item
&&
!
/^
[
0-9
]
*$/
.
test
(
item
)
})
return
list
.
join
(
'/'
)
}
window
.
getObjectURL
=
file
=>
{
var
url
=
null
if
(
window
.
createObjcectURL
!=
undefined
)
{
url
=
window
.
createOjcectURL
(
file
)
}
else
if
(
window
.
URL
!=
undefined
)
{
url
=
window
.
URL
.
createObjectURL
(
file
)
}
else
if
(
window
.
webkitURL
!=
undefined
)
{
url
=
window
.
webkitURL
.
createObjectURL
(
file
)
}
return
url
}
window
.
setNumberInput
=
(
str
,
ret
=
1
)
=>
{
if
(
!
str
&&
!
isNumber
(
str
))
{
return
''
}
return
str
/
ret
}
window
.
getNumberInput
=
(
str
,
ret
=
1
)
=>
{
str
=
str
+
''
if
(
!
str
&&
!
isNumber
(
str
))
{
return
''
}
return
str
*
ret
}
window
.
removeNull
=
function
(
param
)
{
if
(
!
param
)
{
return
}
for
(
let
attr
in
param
)
{
if
(
_
.
isNull
(
param
[
attr
])
||
_
.
isUndefined
(
param
[
attr
]))
{
delete
param
[
attr
]
continue
}
if
(
typeof
param
[
attr
]
==
'number'
&&
(
param
[
attr
]
+
''
).
indexOf
(
'.9999'
)
!=
-
1
)
{
param
[
attr
]
=
Math
.
round
(
param
[
attr
])
}
if
(
typeof
param
[
attr
]
==
'object'
)
{
removeNull
(
param
[
attr
])
}
}
}
window
.
convertBase64ToBlob
=
function
(
base64
)
{
var
base64Arr
=
base64
.
split
(
','
)
var
imgtype
=
''
var
base64String
=
''
if
(
base64Arr
.
length
>
1
)
{
//如果是图片base64,去掉头信息
base64String
=
base64Arr
[
1
]
imgtype
=
base64Arr
[
0
].
substring
(
base64Arr
[
0
].
indexOf
(
':'
)
+
1
,
base64Arr
[
0
].
indexOf
(
';'
)
)
}
// 将base64解码
var
bytes
=
atob
(
base64String
)
//var bytes = base64;
var
bytesCode
=
new
ArrayBuffer
(
bytes
.
length
)
// 转换为类型化数组
var
byteArray
=
new
Uint8Array
(
bytesCode
)
// 将base64转换为ascii码
for
(
var
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
byteArray
[
i
]
=
bytes
.
charCodeAt
(
i
)
}
// 生成Blob对象(文件对象)
return
new
Blob
([
bytesCode
],
{
type
:
imgtype
})
}
window
.
formatMsgCreateTime
=
function
(
createTime
)
{
const
newTime
=
moment
().
year
()
>
moment
(
parseInt
(
createTime
)).
year
()
?
formatDate
(
'YYYY-MM-DD H:i'
,
parseInt
(
createTime
))
:
moment
().
dayOfYear
()
-
1
>
moment
(
parseInt
(
createTime
)).
dayOfYear
()
?
formatDate
(
'MM-DD H:i'
,
parseInt
(
createTime
))
:
moment
().
dayOfYear
()
-
1
==
moment
(
parseInt
(
createTime
)).
dayOfYear
()
?
'昨天 '
+
formatDate
(
'H:i'
,
parseInt
(
createTime
))
:
Math
.
floor
((
moment
().
valueOf
()
-
parseInt
(
createTime
))
/
1000
/
60
)
>
60
?
'今天'
+
formatDate
(
'H:i'
,
parseInt
(
createTime
))
:
Math
.
floor
((
moment
().
valueOf
()
-
parseInt
(
createTime
))
/
1000
/
60
)
>
1
?
Math
.
floor
((
moment
().
valueOf
()
-
parseInt
(
createTime
))
/
1000
/
60
)
+
'分钟前'
:
'刚刚'
return
newTime
}
window
.
getBase64Img
=
(
url
,
size
=
500
)
=>
{
let
img
=
document
.
getElementById
(
'xm_img_div'
)
if
(
img
)
{
img
.
remove
()
}
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
url
)
{
resolve
(
''
)
}
url
=
url
.
replace
(
/http:/
,
"https:"
)
+
`?x-oss-process=image/resize,h_
${
size
}
,w_
${
size
}
`
;
img
=
document
.
createElement
(
"div"
);
img
.
style
.
position
=
"fixed"
;
img
.
style
.
left
=
"-10000px"
;
img
.
id
=
"xm_img_div"
;
img
.
innerHTML
=
`<img id='xm_img_url' src=
${
url
}
/>`
;
document
.
body
.
appendChild
(
img
);
setTimeout
(()
=>
{
let
node
=
document
.
getElementById
(
'xm_img_url'
)
domtoimage
.
toPng
(
node
).
then
(
imgData
=>
{
resolve
(
imgData
)
})
},
2000
)
})
}
window
.
getDateStr
=
timeStamp
=>
{
const
date
=
new
Date
(
timeStamp
)
const
year
=
date
.
getFullYear
()
let
month
=
date
.
getMonth
()
+
1
let
day
=
date
.
getDate
()
if
(
month
<
10
)
{
month
=
`0
${
month
}
`
}
if
(
day
<
10
)
{
day
=
`0
${
day
}
`
}
return
`
${
year
}${
month
}${
day
}
`
}
window
.
copyText
=
textContent
=>
{
const
inputDom
=
document
.
createElement
(
'textarea'
)
inputDom
.
value
=
textContent
document
.
body
.
appendChild
(
inputDom
)
inputDom
.
select
()
document
.
execCommand
(
'copy'
)
document
.
body
.
removeChild
(
inputDom
)
}
window
.
downloadFile
=
(
dataURL
,
fileName
)
=>
{
const
eleDom
=
document
.
createElement
(
'a'
)
const
blob
=
window
.
convertBase64ToBlob
(
dataURL
)
const
href
=
window
.
getObjectURL
(
blob
)
$
(
eleDom
)
.
attr
({
href
,
download
:
fileName
})
.
get
(
0
)
.
click
()
}
window
.
getCouponRule
=
record
=>
{
const
{
type
,
couponType
,
consumeAmount
,
discount
,
classHour
,
giftName
}
=
record
let
rule
=
''
switch
(
type
||
couponType
)
{
case
1
:
if
(
consumeAmount
)
{
rule
=
`满
${
consumeAmount
/
100
}
可用`
}
break
case
2
:
rule
=
`
${
discount
/
10
}
折`
break
case
3
:
rule
=
`
${
classHour
/
100
}
课时`
break
case
4
:
rule
=
giftName
break
default
:
break
}
return
rule
}
window
.
getCouponRuleNew
=
record
=>
{
const
{
type
,
couponType
,
consumeAmount
,
decimalDiscountAmount
,
discount
,
classHour
,
giftName
}
=
record
let
rule
=
''
switch
(
couponType
)
{
case
'CASH'
:
rule
=
`抵扣
${
decimalDiscountAmount
}
元`
break
case
'DISCOUNT'
:
rule
=
`
${
discount
/
10
}
折`
break
case
'CLASS_HOUR'
:
rule
=
`
${
classHour
/
100
}
课时`
break
case
'GIFT'
:
rule
=
giftName
break
default
:
break
}
return
rule
}
window
.
replaceString
=
str
=>
{
return
str
.
replace
(
/
\n
/g
,
'<br/>'
)
}
/**
处理换行字符
*/
window
.
replaceStringReverse
=
str
=>
{
return
str
.
replace
(
/<br
\/
>/g
,
'
\
n'
)
}
// 判断是否是腾讯视频
window
.
isTencentVideo
=
url
=>
{
const
TENCENT_FLAG
=
'v.qq.com'
return
url
.
indexOf
(
TENCENT_FLAG
)
>=
0
}
// 判断是否是优酷视频
window
.
isYoukuVideo
=
url
=>
{
const
YOUKU_FLAG
=
'v.youku.com'
return
url
.
indexOf
(
YOUKU_FLAG
)
>=
0
}
// 手机号中间4位星号处理
window
.
starPhone
=
(
phone
)
=>
{
let
newPhone
=
''
if
(
phone
)
{
newPhone
=
phone
.
substr
(
0
,
3
)
+
'****'
+
phone
.
substr
(
7
)
}
return
newPhone
}
// 人民币格式 单位元
window
.
getMoneyFormatYuan
=
(
price
)
=>
{
if
(
!
_
.
isNumber
(
Number
(
price
)))
{
return
'0.00'
}
const
n
=
parseFloat
(
price
).
toFixed
(
2
)
const
re
=
/
(\d{1,3})(?=(\d{3})
+
(?:\.))
/g
return
n
.
replace
(
re
,
'$1,'
)
}
// 处理定价标准 仅订单详情,打印收据预览可用
window
.
formatPriceStandard
=
(
info
)
=>
{
let
{
quantityUnit
,
specName
,
commoditySpecs
,
purchaseItemType
,
unitPriceAfterDiscount
,
specCurrentPrice
}
=
info
let
newCommoditySpecs
=
JSON
.
parse
(
commoditySpecs
||
'[]'
)
||
{}
let
{
containQuantity
,
unitPrice
,
measurementUnits
}
=
newCommoditySpecs
let
content
=
''
if
(
purchaseItemType
!=
'COURSE'
)
{
content
=
`
${
specCurrentPrice
}
元/
${
ENUM
.
itemUnit
[
quantityUnit
]}
`
}
else
{
let
text
=
containQuantity
!=
1
?
containQuantity
:
'/'
content
=
`
${
specName
}
(
${
specCurrentPrice
}
元
${
text
}${
measurementUnits
}
)`
}
return
content
}
window
.
getCouponRuleNew
=
(
record
)
=>
{
const
{
type
,
couponType
,
consumeAmount
,
decimalDiscountAmount
,
discount
,
classHour
,
giftName
}
=
record
let
rule
=
''
switch
(
couponType
)
{
case
'CASH'
:
rule
=
`抵扣
${
decimalDiscountAmount
}
元`
break
case
'DISCOUNT'
:
rule
=
`
${
discount
/
10
}
折`
break
case
'CLASS_HOUR'
:
rule
=
`
${
classHour
/
100
}
课时`
break
case
'GIFT'
:
rule
=
giftName
break
default
:
break
}
return
rule
}
window
.
renderCourseName
=
(
list
)
=>
{
if
(
list
&&
list
.
length
)
{
const
associatedCourseList
=
JSON
.
parse
(
JSON
.
stringify
(
list
))
const
length
=
associatedCourseList
.
length
const
majorCourseIndex
=
associatedCourseList
.
findIndex
((
item
)
=>
item
.
major
===
'YES'
)
const
majorCourse
=
associatedCourseList
.
splice
(
majorCourseIndex
,
1
)[
0
]
const
content
=
(
<
div
className
=
"course-content"
>
<
p
><
i
className
=
"icon iconfont icon-zhu"
><
/i>{majorCourse.name}</
p
>
{
associatedCourseList
.
map
((
item
,
index
)
=>
{
return
<
p
><
i
className
=
"icon iconfont icon-ci"
><
/i>{item.name}</
p
>
})
}
<
/div
>
)
return
length
>
1
?
<
span
>
{
majorCourse
.
name
}
<
Popover
placement
=
"bottomLeft"
content
=
{
content
}
arrowPointAtCenter
>
等
<
span
style
=
{{
color
:
'#FF7519'
,
cursor
:
'pointer'
}}
>
{
length
}
<
/span>
门
<
/Popover
>
<
/span>
:
<
span
>
{
majorCourse
.
name
}
<
/span
>
}
return
''
}
window
.
convertBase64UrlToBlob
=
(
urlData
)
=>
{
const
bytes
=
window
.
atob
(
urlData
.
split
(
","
)[
1
]);
const
ab
=
new
ArrayBuffer
(
bytes
.
length
);
const
ia
=
new
Uint8Array
(
ab
);
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
ia
[
i
]
=
bytes
.
charCodeAt
(
i
);
}
return
new
Blob
([
ab
],
{
type
:
"image/png"
});
}
// 小麦秀 new 标签显示
window
.
XMShowClassName
=
(
date
,
itemName
)
=>
{
// 超过时间不显示
if
(
new
Date
().
getTime
()
>
date
)
{
return
''
;
}
// 用户点击相应区域后不显示
if
(
localStorage
.
getItem
(
itemName
)
===
'true'
)
{
return
''
;
}
return
'new-icon'
}
\ No newline at end of file
src/core/variables.less
View file @
b64f7607
@sunLight: #FED951;
@sunLight: #FED951;
@sun: #F
c9C6B
;
@sun: #F
FB714
;
@sunDark: #DD8029;
@sunDark: #DD8029;
...
@@ -18,7 +18,7 @@
...
@@ -18,7 +18,7 @@
@sucess: @sun;
@sucess: @sun;
@warning: #F
B696A
;
@warning: #F
F4F4F
;
@border: #e8e8e8;
@border: #e8e8e8;
...
...
src/modules/root/Login.jsx
View file @
b64f7607
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
{
import
{
withRouter
withRouter
}
from
'react-router-dom'
;
}
from
'react-router-dom'
;
import
'./Login.less'
;
import
'./Login.less'
;
import
{
Input
,
Popover
}
from
'antd'
;
import
CheckBeforeSendCode
from
'../../components/CheckBeforeSendCode'
;
function
Login
(
props
)
{
function
Login
(
props
)
{
const
[
openCheck1
,
setOpenCheck1
]
=
useState
(
false
);
const
[
checkObject1
,
setCheckObject1
]
=
useState
({});
const
[
checking1
,
setChecking1
]
=
useState
(
false
);
useEffect
(()
=>
{
useEffect
(()
=>
{
},
[])
},
[])
async
function
checkAccount
(
code
,
callback
=
()
=>
{
})
{
}
function
checkSend
(
code
)
{
}
return
(
return
(
<
div
className=
"login-page"
>
<
div
className=
"login-page"
>
<
div
className=
"login-main"
>
<
div
className=
"login-main"
>
<
div
className=
"left-banner"
>
<
div
className=
"left-banner"
>
<
img
src=
'https://image.xiaomaiketang.com/xm/DXDsNKB3Fn.png'
alt=
""
style=
{
{
width
:
448
,
marginTop
:
60
}
}
/>
<
div
><
img
src=
{
require
(
"../../common/images/logo.png"
)
}
alt=
""
style=
{
{
width
:
60
,
height
:
61
}
}
/></
div
>
<
div
class=
"name"
>
小麦云课堂
</
div
>
<
div
class=
"desc"
>
一键开启直播授课 让知识更有价值
</
div
>
</
div
>
</
div
>
<
div
className=
"login-box"
>
<
div
className=
"login-box"
>
登录
<
div
className=
"login"
>
<
div
className=
"r"
>
<
div
className=
"title"
>
手机号登录
</
div
>
<
form
action=
""
className=
"login-form"
>
<
div
className=
"form"
>
<
div
className=
"username"
style=
{
{
marginBottom
:
16
}
}
>
<
Input
type=
"phone"
autoComplete=
"off"
name=
"account"
maxLength=
{
11
}
placeholder=
"手机号"
/>
</
div
>
<
div
className=
"phoneverify"
>
<
Input
type=
"text"
id=
"phoneverify"
name=
"phoneverify"
placeholder=
"验证码"
autoComplete=
"off"
/>
<
Popover
visible=
{
false
}
trigger=
"click"
title=
""
content=
{
<
div
>
<
span
style=
{
{
fontSize
:
'12px'
,
color
:
'#999'
,
marginBottom
:
8
,
display
:
'block'
}
}
>
请完成安全验证
</
span
>
<
CheckBeforeSendCode
callback=
{
(
data
,
nc
)
=>
{
setCheckObject1
(
nc
);
checkAccount
(
1
,
(
userType
)
=>
{
handleSendSMSCode
(
data
,
userType
);
setTimeout
(()
=>
{
setOpenCheck1
(
false
);
},
500
)
})
}
}
/>
</
div
>
}
onVisibleChange=
{
(
value
)
=>
{
if
(
!
value
)
{
setOpenCheck1
(
false
);
}
}
}
placement=
"bottomRight"
>
<
div
className=
"btn"
id=
"sendVerifyCode"
onClick=
{
()
=>
{
if
(
checking1
)
return
;
checkSend
(
1
)
}
}
>
获取验证码
</
div
>
</
Popover
>
</
div
>
<
div
className=
"error-message"
>
验证码有误
</
div
>
<
div
className=
"submit"
>
<
div
className=
"btn"
>
<
button
id=
'loginIn'
type=
"submit"
>
登录
</
button
>
</
div
>
</
div
>
<
div
className=
"network-message"
>
<
span
className=
"icon iconfont"
>

</
span
>
网络不给力,请
<
span
className=
"refresh"
>
点击刷新
</
span
>
</
div
>
</
div
>
</
form
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/modules/root/Login.less
View file @
b64f7607
@import url('../../core/variables.less');
@import url('../../core/variables.less');
.login-page {
.login-page {
position: static; // background: url('../../images/main_banner.png');
position: static;
// background-size: 100%;
font-family: "微软雅黑";
font-family: "微软雅黑";
padding: 0;
padding: 0;
height: 100%;
min-width: 1200px;
min-width: 1200px;
background: #21242E;
height:100%;
.login-main {
.login-main {
min-width: 1200px;
min-width: 1200px;
}
}
.left-banner {
.left-banner {
position: fixed;
min-width:315px;
text-align:center;
top: 50%;
left: 30%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform:translate(-50%, -50%);
.name{
font-size: 30px;
font-weight: 500;
color: #FFFFFF;
line-height: 42px;
margin-top:11px;
}
.desc{
font-size: 14px;
font-weight: 400;
color: #FFFFFF;
line-height: 20px;
margin-top:10px;
}
}
}
.login-box {
.login-box {
min-width: 360px;
height: 340px;
position: fixed;
top: 50%;
left: 70%;
-webkit-transform:translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform:translate(-50%, -50%);
transform: translate(-50%, -50%);
.go-to-site {
position: absolute;
bottom: -80px;
width: 200px;
margin: 0 auto;
left: 50%;
margin-left: -50px;
a {
color: #FFF;
text-decoration: none;
}
span.icon {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
font-size: 12px;
display: inline-block;
margin-right: 10px;
}
}
.login {
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
height: 100%;
overflow: hidden;
background-color: #ffffff;
border-radius: 4px; //box-shadow: 0 0 17px @sun;
.l {
width: 280px;
height: 100%;
background: @primary;
background: -webkit-gradient(linear, left top, left bottom, from(#ffaa1a), to(#ff8634)) !important;
display: flex;
display: -webkit-flex;
-webkit-flex-direction: column;
flex-direction: column;
align-items: center;
color: #ffffff;
font-size: 12px;
justify-content: center;
-webkit-justify-content: center;
.logo {
height: 125px;
img {
height: 100%;
}
}
.name {
font-size: 16px;
margin-bottom: 20px;
}
.desc {
opacity: .7;
margin-bottom: 20px;
}
.items {
ul {
padding: 0;
li {
.icon {
-webkit-transform: scale(.8);
-moz-transform: scale(.8);
-ms-transform: scale(.8);
-o-transform: scale(.8);
transform: scale(.8);
display: inline-block;
margin-right: 10px;
}
line-height: 30px;
list-style-type: none;
}
}
}
}
.r {
flex: 1;
-webkit-flex: 1;
height: 100%;
padding: 30px;
box-sizing: border-box;
position: relative;
&.show-qrcode {
.qrcode {
display: block;
}
.top-right-tip {
.computer {
display: inline-block;
}
.icon-container {
display: none;
}
}
}
.qrcode {
display: none;
text-align: center;
position: absolute;
background: #FFF;
z-index: 1;
left: 20px;
top: 28px;
padding-top: 20px;
img {
display: inline-block;
width: 180px;
}
}
.top-right-tip {
cursor: pointer;
position: absolute;
top: 4px;
right: 4px;
.computer {
display: none;
}
.icon-container {
position: relative;
height: 32px;
width: 32px;
display: inline-block;
.tips {
width: 69px;
position: absolute;
top: 0;
right: 36px;
img {
width: 100%;
}
}
.shade {
position: absolute;
width: 100%;
height: 150%;
top: 0;
margin-left: -100%;
background: #FFF;
transform-origin: right top;
transform: rotate(-45deg);
}
}
span.icon {
font-size: 32px;
}
}
.title {
font-size: 18px;
font-weight: 500;
color: #333333;
line-height: 25px;
text-align:center;
font-weight:bold;
margin-bottom:43px;
&::after {
}
.text1 {
color: black;
}
.icon {
font-size: 11px;
}
#login-method {
width: 100%;
text-align: center;
span {
color: #999;
font-weight: 400;
&:hover {
color: #333;
}
}
span.active {
font-weight: 500;
color: #333;
&::after {
content: '';
display: block;
width: 24px;
height: 4px;
border-radius: 3px;
background: #FF8534;
margin: 10px auto 0;
}
}
#password-login {
margin-right: 32px;
}
}
}
#password-icon {
color: #BFBFBF;
margin-right: 10px;
cursor: pointer;
&:hover {
color: #FC9C6B;
}
-webkit-user-select: none;
-moz-user-select:none;
-o-user-select:none;
-ms-user-select:none;
}
input {
display: block;
width: 100%;
height: 40px;
line-height: 40px;
border: 1px solid #e8e8e8; // border-bottom: 1px solid @xm-color-border;
padding-right: 30px;
padding-left: 10px;
margin-bottom: 16px;
background-color: transparent;
background-image: none;
border-radius: 4px;
box-sizing: border-box;
-webkit-transition: all .3s linear;
-moz-transition: all .3s linear;
-ms-transition: all .3s linear;
-o-transition: all .3s linear;
transition: all .3s linear;
&:focus,
&:active,
&:hover {
outline: none; // border: none!important;
// border-bottom: 1px solid @sun!important;
box-shadow: none;
border-color: @primary;
}
}
::-webkit-input-placeholder {
/* WebKit, Blink, Edge */
color: #ccc;
}
:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #ccc;
}
::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #ccc;
}
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #ccc
}
input:-webkit-autofill,
textarea:-webkit-autofill,
select:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px white inset;
}
.username,
.password,
.phoneverify {
height: 40px;
position: relative;
color: #666666;
.icon {
position: absolute;
right: 5px;
top: 5px;
font-size: 20px;
}
#sendVerifyCode {
cursor: pointer;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
position: absolute;
right: 10px;
top: -53px; // border: 1px solid @sun;
color: #333;
height: 25px;
width: 90px;
border-radius: 3px;
margin-top: 60px;
font-size: 14px; // font-weight: 300;
&:hover {
color: #FF8534;
}
&::before {
content: '';
display: block;
height: 20px;
width: 1px;
background-color: #e8e8e8;
margin-right: 10px;
}
}
}
.error-message{
font-size: 14px;
font-weight: 400;
color: @warning;
line-height: 20px;
margin-top:9px;
}
.network-message{
text-align:center;
font-size:14px;
color:#000;
margin-top:11px;
.icon{
font-size:14px;
color:@primary;
margin-right:8px;
}
.refresh{
font-size:14px;
color:#5289FA;
cursor: pointer;
}
}
#sendVoiceVerifyCode {
cursor: pointer;
}
.phoneverify-voice {
// padding-left: 5px;
margin-top: 10px;
&::after {}
}
.submit {
margin-top:11px;
button {
// font-weight: 300;
}
}
.apply {
cursor: pointer;
text-align: right;
margin-top: 10px;
color: #999;
float: right; // font-weight: 300;
span.icon {
font-size: 12px;
margin-left: 7px;
}
&:hover {
color: #FC9C6B;
}
}
.btn {
button {
display: block;
width: 100%;
background: @primary;
color: #fff;
font-size: 14px;
font-weight: 400;
line-height: 40px;
border-radius: 4px;
-webkit-transition: all .3s;
-moz-transition: all .3s;
-ms-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
cursor: pointer;
border: none;
&:hover {
opacity: 0.7;
background: linear-gradient(90deg, #FFB714 0%, #FFAD34 100%);
}
}
}
}
}
}
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment