Authored by 陈轩

save

  1 +'use strict';
  2 +
  3 +exports.get = (req, res, next) => {
  4 + let data = {
  5 + src: 'http://portal.mogujie.com/api/validate/captcha/pc/33gp15as84ob',
  6 + code: '9999'
  7 + };
  8 +
  9 + res.session.captcha = {
  10 + code: '9999'
  11 + };
  12 +
  13 + res.json({
  14 + src: data.src
  15 + });
  16 +};
@@ -15,10 +15,13 @@ var multipartMiddleware = multipart(); @@ -15,10 +15,13 @@ var multipartMiddleware = multipart();
15 const uploadApi = require(cRoot + '/upload.js'); 15 const uploadApi = require(cRoot + '/upload.js');
16 16
17 const hotfix = require(`${cRoot}/hotfix`); 17 const hotfix = require(`${cRoot}/hotfix`);
  18 +const captcha = require(`${cRoot}/captcha`);
18 19
19 // routers 20 // routers
20 21
21 router.post('/api/upload/image', multipartMiddleware, uploadApi.uploadImg); 22 router.post('/api/upload/image', multipartMiddleware, uploadApi.uploadImg);
22 router.post('/hf/v1', hotfix.v1); 23 router.post('/hf/v1', hotfix.v1);
23 24
  25 +router.get('/api/captcha/get', captcha.get);
  26 +
24 module.exports = router; 27 module.exports = router;
@@ -97,6 +97,7 @@ const local = { @@ -97,6 +97,7 @@ const local = {
97 }); 97 });
98 98
99 res.render('login', { 99 res.render('login', {
  100 + width750: true,
100 loginIndex: true, // 模板中使用JS的标识 101 loginIndex: true, // 模板中使用JS的标识
101 102
102 // 返回的URL链接 103 // 返回的URL链接
@@ -3,11 +3,12 @@ @@ -3,11 +3,12 @@
3 const _ = require('lodash'); 3 const _ = require('lodash');
4 const helpers = global.yoho.helpers; 4 const helpers = global.yoho.helpers;
5 const cookie = global.yoho.cookie; 5 const cookie = global.yoho.cookie;
  6 +const EventEmitter = require('events');
6 const utils = require(global.utils); 7 const utils = require(global.utils);
7 const RegService = require('../models/reg-service'); 8 const RegService = require('../models/reg-service');
8 const PhoneService = require('../models/phone-service'); 9 const PhoneService = require('../models/phone-service');
9 const AuthHelper = require('../models/auth-helper'); 10 const AuthHelper = require('../models/auth-helper');
10 -const captchaService = require('../models/captcha-service'); 11 +const imgcheckAPI = require('../../serverAPI/imgcheck');
11 12
12 // constrant 13 // constrant
13 const CODE_REQUIRED = '请输入校验码'; 14 const CODE_REQUIRED = '请输入校验码';
@@ -42,19 +43,28 @@ const _step1 = (req, res, next) => { @@ -42,19 +43,28 @@ const _step1 = (req, res, next) => {
42 req.session.smsLogin.count = 5; 43 req.session.smsLogin.count = 5;
43 } 44 }
44 45
45 - let template = 'sms/login';  
46 - let viewData = {  
47 - module: 'passport',  
48 - page: 'sms-login',  
49 - title: '手机短信登录',  
50 - isPassportPage: true,  
51 - headerText: '手机号码快捷登录',  
52 - captchaUrl: helpers.urlFormat('/passport/sms_login/captcha.png', {t: Date.now()}),  
53 - areaCode: '+86', // 默认的区号  
54 - countrys: RegService.getAreaData() // 地区信息列表  
55 - }; 46 + imgcheckAPI.gen()
  47 + .then(captcha => {
  48 + _.set(req.session, 'captcha.code', captcha.data.code);
  49 +
  50 + let template = 'sms/login';
  51 + let viewData = {
  52 + width750: true,
  53 + module: 'passport',
  54 + page: 'sms-login',
  55 + title: '手机短信登录',
  56 + isPassportPage: true,
  57 + headerText: '手机号码快捷登录',
  58 + captchaUrl: helpers.urlFormat('/passport/sms_login/captcha.png', {t: Date.now()}),
  59 + areaCode: '+86', // 默认的区号
  60 + countrys: RegService.getAreaData(), // 地区信息列表
  61 + captsrc: captcha.data.src
  62 + };
  63 +
  64 + res.render(template, viewData);
  65 + })
  66 + .catch(next);
56 67
57 - res.render(template, viewData);  
58 }; 68 };
59 69
60 // 短信登录 第二步: 输入 校验码 70 // 短信登录 第二步: 输入 校验码
@@ -118,44 +128,59 @@ exports.loginPage = (req, res, next) => { @@ -118,44 +128,59 @@ exports.loginPage = (req, res, next) => {
118 } 128 }
119 }; 129 };
120 130
121 -exports.tokenBefore = (req, res, next) => { 131 +
  132 +/**
  133 + * step1 的表单提交验证
  134 + */
  135 +exports.indexCheck = (req, res, next) => {
  136 + _.set(req.session, 'smsLogin.step', 1);
  137 +
122 let area = req.query.area = (req.query.area || '').trim(); 138 let area = req.query.area = (req.query.area || '').trim();
123 let mobile = req.query.mobile = (req.query.mobile || '').trim(); 139 let mobile = req.query.mobile = (req.query.mobile || '').trim();
124 - let step = _.get(req.session, 'smsLogin.step');  
125 - let count = _.get(req.session, 'smsLogin.count');  
126 - let interval = _.get(req.session, 'smsLogin.interval');  
127 - let captcha1 = _.get(req.session, 'smsLogin.captcha');  
128 - let captcha2 = (req.query.captcha || '').trim(); 140 + let captcode = (req.body.captcode || '').trim();
  141 + let captcodeValid = _.get(req.session, 'captcha.code');
129 142
  143 + let em = new EventEmitter();
130 144
131 - if (!req.xhr) {  
132 - return next(404);  
133 - } 145 + // 校验 成功
  146 + em.on('resolve', () => {
  147 + // 1. 将信息放入 session
  148 + _.set(req.session, 'smsLogin.area', area);
  149 + _.set(req.session, 'smsLogin.mobile', mobile);
  150 + _.set(req.session, 'smsLogin.step', 2);
134 151
135 - if ([area, mobile].some(val => val === '')) {  
136 - return res.json({  
137 - code: 401,  
138 - message: '手机号 必填' 152 + res.json({
  153 + redirect: '/passport/sms_login?step=2'
139 }); 154 });
  155 + });
  156 +
  157 + // 校验 失败
  158 + em.on('reject', error => {
  159 + _.set(req.session, 'smsLogin.step', 1);
  160 +
  161 + res.status(400).json(error);
  162 + });
  163 +
  164 + // 验证
  165 + if ([area, mobile].some(val => val === '')) {
  166 + em.emit('reject', {message: '请填写手机号'});
  167 + } else if (captcode !== captcodeValid) {
  168 + em.emit('reject', {message: '请将图片旋转到正确位置'});
140 } 169 }
141 170
142 - delete req.session.smsLogin.captcha; // 图形验证码 一次性 171 + // congratulation~~
  172 + em.emit('resolve');
  173 +};
143 174
144 - // step1 要 校验图形验证码  
145 - if (step === 1) {  
146 - if (!captcha2) {  
147 - return res.json({  
148 - code: 400,  
149 - message: '请填写验证码'  
150 - });  
151 - } 175 +exports.tokenBefore = (req, res, next) => {
152 176
153 - if (captcha1 !== captcha2) {  
154 - return res.json({  
155 - code: 400,  
156 - message: VERIFY_ERROR  
157 - });  
158 - } 177 + let step = _.get(req.session, 'smsLogin.step');
  178 + let count = _.get(req.session, 'smsLogin.count');
  179 + let interval = _.get(req.session, 'smsLogin.interval');
  180 +
  181 +
  182 + if (!req.xhr || step !== 2) {
  183 + return next(404);
159 } 184 }
160 185
161 let now = Date.now(); 186 let now = Date.now();
@@ -186,8 +211,8 @@ exports.tokenBefore = (req, res, next) => { @@ -186,8 +211,8 @@ exports.tokenBefore = (req, res, next) => {
186 211
187 // AJAX 获取验证码 212 // AJAX 获取验证码
188 exports.token = (req, res, next) => { 213 exports.token = (req, res, next) => {
189 - let area = req.query.area;  
190 - let mobile = req.query.mobile; 214 + let area = _.get(req.session, 'smsLogin.area');
  215 + let mobile = _.get(req.session, 'smsLogin.mobile');
191 216
192 PhoneService.sendSMS(mobile, area, 1).then(result => { 217 PhoneService.sendSMS(mobile, area, 1).then(result => {
193 if (result.code === 200) { 218 if (result.code === 200) {
@@ -376,6 +401,7 @@ exports.password = (req, res, next) => { @@ -376,6 +401,7 @@ exports.password = (req, res, next) => {
376 /** 401 /**
377 * 生成 校验码 402 * 生成 校验码
378 */ 403 */
  404 +/*
379 exports.genCaptcha = (req, res) => { 405 exports.genCaptcha = (req, res) => {
380 let captcha = captchaService.generateCaptcha(90, 52, 4); 406 let captcha = captchaService.generateCaptcha(90, 52, 4);
381 407
@@ -386,3 +412,4 @@ exports.genCaptcha = (req, res) => { @@ -386,3 +412,4 @@ exports.genCaptcha = (req, res) => {
386 .status(200) 412 .status(200)
387 .send(captcha.image); 413 .send(captcha.image);
388 }; 414 };
  415 +*/
@@ -41,6 +41,7 @@ router.post('/passport/login/auth', login.local.login); @@ -41,6 +41,7 @@ router.post('/passport/login/auth', login.local.login);
41 // SMS 短信 41 // SMS 短信
42 router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn); 42 router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn);
43 router.get('/passport/sms_login', smsLogin.loginPage); 43 router.get('/passport/sms_login', smsLogin.loginPage);
  44 +router.post('/passport/sms_login/step1_check', smsLogin.indexCheck);
44 router.get('/passport/sms_login/token.json', 45 router.get('/passport/sms_login/token.json',
45 smsLogin.tokenBefore, 46 smsLogin.tokenBefore,
46 smsLogin.token); // only ajax; 47 smsLogin.token); // only ajax;
@@ -48,7 +49,6 @@ router.get('/passport/sms_login/check.json', @@ -48,7 +49,6 @@ router.get('/passport/sms_login/check.json',
48 smsLogin.checkBefore, 49 smsLogin.checkBefore,
49 smsLogin.check); // only ajax 50 smsLogin.check); // only ajax
50 router.post('/passport/sms_login/password.json', smsLogin.password); 51 router.post('/passport/sms_login/password.json', smsLogin.password);
51 -router.get('/passport/sms_login/captcha.png', smsLogin.genCaptcha);  
52 52
53 // 微信登录 53 // 微信登录
54 router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); 54 router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login);
@@ -7,12 +7,11 @@ @@ -7,12 +7,11 @@
7 <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> 7 <input id="phone-num" class="input phone-num" type="text" placeholder="手机号">
8 <button class="clear-input" type="button"></button> 8 <button class="clear-input" type="button"></button>
9 </div> 9 </div>
10 - <div class="passport-captcha row">  
11 - <div class="passport-captcha-img"><img src="{{captchaUrl}}" alt=""></div>  
12 - <div class="passport-captcha-input">  
13 - <input id="js-captcha" type="text" placeholder="验证码">  
14 - </div> 10 + {{!--图片验证 start--}}
  11 + <div id="js-img-check">
  12 + <input type="hidden" name="captsrc" value="{{captsrc}}">
15 </div> 13 </div>
  14 + {{!--图片验证 end--}}
16 <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button> 15 <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button>
17 </div> 16 </div>
18 </div> 17 </div>
  1 +exports.gen = () => {
  2 + // TODO
  3 + return Promise.resolve({
  4 + code: '200',
  5 + data: {
  6 + src: 'http://portal.mogujie.com/api/validate/captcha/pc/zie3qc7b1tia',
  7 + code: '9999'
  8 + }
  9 + });
  10 +};
1 'use strict'; 1 'use strict';
2 2
3 const fs = require('fs'); 3 const fs = require('fs');
4 -let devHost = '127.0.0.1'; 4 +let devHost = '172.16.10.122';
5 5
6 fs.readFile('.devhost', (err, buf)=> { 6 fs.readFile('.devhost', (err, buf)=> {
7 if (!err) { 7 if (!err) {
  1 + {{!--图片验证--}}
  2 +<div class="img-check">
  3 + <div class="img-check-header">
  4 + <span>请将下列图片点击翻转至正确方向</span>
  5 + <a class="img-check-refresh">换一批</a>
  6 + </div>
  7 + <div class="img-check-main">
  8 + <ul class="img-check-pics">
  9 + <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li>
  10 + <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li>
  11 + <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li>
  12 + <li class="img-check-pic" data-val="0" style="background-image:url('{{imgSrc}}');"></li>
  13 + </ul>
  14 + </div>
  15 +</div>
@@ -17,6 +17,23 @@ tip = require('plugin/tip'); @@ -17,6 +17,23 @@ tip = require('plugin/tip');
17 api = require('./api'); 17 api = require('./api');
18 checkPoint = require('./smslogin/check-point'); 18 checkPoint = require('./smslogin/check-point');
19 19
  20 +
  21 +// 图片验证码
  22 +let ImgCheck = require('plugin/img-check');
  23 +
  24 +let imgCheck = new ImgCheck('#js-img-check', {
  25 + useREM: {
  26 + rootFontSize: 40,
  27 + picWidth: 150
  28 + }
  29 +});
  30 +
  31 +imgCheck.init({
  32 + imgSrc: $('#js-img-check').find('input').val()
  33 +});
  34 +
  35 +
  36 +
20 page = { 37 page = {
21 init: function() { 38 init: function() {
22 this.domInit(); 39 this.domInit();
@@ -28,8 +45,6 @@ page = { @@ -28,8 +45,6 @@ page = {
28 $nextBtn = $('#btn-next'); 45 $nextBtn = $('#btn-next');
29 $phoneNum = $('#phone-num'); 46 $phoneNum = $('#phone-num');
30 $resetBtn = $('.clear-input'); 47 $resetBtn = $('.clear-input');
31 - $captcha = $('.passport-captcha input');  
32 - $captchaPNG = $('.passport-captcha-img img');  
33 }, 48 },
34 bindEvent: function() { 49 bindEvent: function() {
35 var self = this; 50 var self = this;
@@ -41,12 +56,6 @@ page = { @@ -41,12 +56,6 @@ page = {
41 self.toggleNextBtn(); 56 self.toggleNextBtn();
42 }); 57 });
43 58
44 - $captcha.on('input', function() {  
45 - self.toggleNextBtn();  
46 - });  
47 -  
48 - $captchaPNG.on('click', $.proxy(this.refreshCapatch, this));  
49 -  
50 $nextBtn.on('click', function() { 59 $nextBtn.on('click', function() {
51 self.goNext(); 60 self.goNext();
52 }); 61 });
@@ -62,7 +71,7 @@ page = { @@ -62,7 +71,7 @@ page = {
62 71
63 // 切换$nextBtn disable状态 72 // 切换$nextBtn disable状态
64 toggleNextBtn: function() { 73 toggleNextBtn: function() {
65 - var bool = Boolean($.trim($phoneNum.val())) && Boolean($.trim($captcha.val())); 74 + var bool = Boolean($.trim($phoneNum.val()));
66 75
67 $nextBtn 76 $nextBtn
68 .toggleClass('disable', !bool) 77 .toggleClass('disable', !bool)
@@ -71,17 +80,11 @@ page = { @@ -71,17 +80,11 @@ page = {
71 $resetBtn.toggle(bool); 80 $resetBtn.toggle(bool);
72 }, 81 },
73 82
74 - refreshCapatch: function() {  
75 - $captchaPNG.attr('src', '/passport/sms_login/captcha.png?t=' + Date.now());  
76 - $captcha.val('');  
77 - },  
78 -  
79 // 提交按钮 83 // 提交按钮
80 goNext: function() { 84 goNext: function() {
81 - var self = this;  
82 var areaCode = $countrySelect.val(); 85 var areaCode = $countrySelect.val();
83 var phone = $.trim($phoneNum.val()); 86 var phone = $.trim($phoneNum.val());
84 - var captcha = $.trim($captcha.val()); 87 + var captcha = $.trim(imgCheck.getResults());
85 88
86 if ($nextBtn.prop('disabled')) { 89 if ($nextBtn.prop('disabled')) {
87 return; 90 return;
@@ -92,11 +95,16 @@ page = { @@ -92,11 +95,16 @@ page = {
92 return; 95 return;
93 } 96 }
94 97
  98 + if (captcha === '0000') {
  99 + tip.show('请将图片旋转到正确位置');
  100 + return;
  101 + }
  102 +
95 $nextBtn.prop('disabled', true); 103 $nextBtn.prop('disabled', true);
96 - $.get('/passport/sms_login/token.json', { 104 + $.post('/passport/sms_login/step1_check', {
97 area: areaCode.replace('+', ''), 105 area: areaCode.replace('+', ''),
98 mobile: phone, 106 mobile: phone,
99 - captcha: captcha 107 + captcode: captcha
100 }) 108 })
101 .done(function(data) { 109 .done(function(data) {
102 if (data.code === 200) { 110 if (data.code === 200) {
@@ -104,12 +112,14 @@ page = { @@ -104,12 +112,14 @@ page = {
104 $nextBtn.off(); 112 $nextBtn.off();
105 location.href = data.redirect; 113 location.href = data.redirect;
106 } else { 114 } else {
107 - self.refreshCapatch(); 115 + imgCheck.refresh();
108 tip.show(data.message); 116 tip.show(data.message);
109 } 117 }
110 }) 118 })
111 - .fail(function() {  
112 - tip.show('出错了, 请重试'); 119 + .fail(function(error) {
  120 + var message = error && error.message || '';
  121 +
  122 + tip.show(message || '出错了, 请重试');
113 }) 123 })
114 .always(function() { 124 .always(function() {
115 $nextBtn.prop('disabled', false); 125 $nextBtn.prop('disabled', false);
  1 +/**
  2 + * Plugin: 图片旋转验证;
  3 + * @example
  4 + * pc:
  5 + * var ImgCheck = require('path/to/img-check')
  6 + * var imgCheck = new ImgCheck('#js-img-check', {
  7 + * template: require('path/to/hbs')
  8 + * }, {
  9 + * imgSrc
  10 + * })
  11 + *
  12 + * imgCheck.init({imgSrc})
  13 + *
  14 + * imgCheck.getResult() // '1230'
  15 + *- ----------------------------------------
  16 + * @example
  17 + * wap:
  18 + * var imgCheck = new ImgCheck('#js-img-check', {
  19 + * useREM: {
  20 + * rootFontSize: 40,
  21 + * picWidth: 150
  22 + * }
  23 + * })
  24 + * imgCheck.init({
  25 + * imgSrc
  26 + * })
  27 + *
  28 + * imgCheck.getResult() // '1112'
  29 + */
  30 +
  31 +
  32 +
  33 +/**
  34 + * @param selector|jQuery|Element container
  35 + * @param object options 配置选项
  36 + * pc:
  37 + * {
  38 + * template,
  39 + * refreshURI
  40 + * }
  41 + *
  42 + * wap:
  43 + * {
  44 + * useREM: {
  45 + * rootFontSize, // 设计稿基准字体大小
  46 + * picWidth // 设计稿的验证图片宽度
  47 + * },
  48 + * template,
  49 + * refreshURI
  50 + * }
  51 + *
  52 + * @param object data 初始值
  53 + * {
  54 + * imgSrc: '图片src'
  55 + * }
  56 + *
  57 + */
  58 +const ImgCheck = function(container, options) {
  59 + let optionDefault = {
  60 + useREM: null,
  61 + template: require('common/img-check.hbs'),
  62 + refreshURI: '/api/captcha/get'
  63 + };
  64 +
  65 + $.extend(this, optionDefault, options);
  66 +
  67 + this.$container = $(container);
  68 + this.$imgCheck = null;
  69 + this.$imgPics = null;
  70 + this.picWidth = null;
  71 +
  72 + return this;
  73 +};
  74 +
  75 +ImgCheck.prototype = {
  76 + /**
  77 + * method:初始化
  78 + * @param object data
  79 + * {
  80 + * imgSrc
  81 + * }
  82 + */
  83 + init: function(data) {
  84 + if (this.useREM) {
  85 + this.picWidth = this.useREM.picWidth / this.useREM.rootFontSize;
  86 + }
  87 +
  88 +
  89 + this.render(data);
  90 + this.bindEvents();
  91 + },
  92 +
  93 + /**
  94 + * method: 绑定事件
  95 + */
  96 + bindEvents: function() {
  97 + this.$container
  98 + .on('click.refresh', '.img-check-refresh', $.proxy(this.refresh, this))
  99 + .on('click.rotate', '.img-check-pic', $.proxy(this.rotateImg, this));
  100 + },
  101 +
  102 + /**
  103 + * method: 渲染 dom
  104 + * @param obj data 渲染数据
  105 + * {
  106 + * imgSrc: 'src' //图片src
  107 + * }
  108 + */
  109 + render: function(data) {
  110 + var self = this;
  111 +
  112 + this.$container.html(this.template(data));
  113 + this.$imgPics = this.$container.find('.img-check-pic');
  114 +
  115 + if (!this.useREM && !this.picWidth) {
  116 + this.picWidth = this.$imgPics.width();
  117 + }
  118 +
  119 + this.$imgPics.each(function(index, elem) {
  120 + var $elem = $(elem);
  121 + var position = self.calcPosition($elem);
  122 +
  123 + $elem.css('backgroundPosition', position);
  124 + });
  125 + },
  126 +
  127 + /**
  128 + * method: 计算 background-position
  129 + * @param num index img-check-pic 的index
  130 + * @param num count img-check-pic
  131 + */
  132 + calcPosition: function($elem) {
  133 + var positionX, positionY;
  134 + var index = $elem.index();
  135 + var count = parseInt($elem.attr('data-val'), 10);
  136 + var unit = this.useREM ? 'rem' : 'px';
  137 +
  138 + count = count % 4;
  139 +
  140 + positionX = -index * this.picWidth + unit;
  141 + positionY = -count * this.picWidth + unit;
  142 +
  143 +
  144 + return [positionX, positionY].join(' ');
  145 + },
  146 +
  147 + /**
  148 + * Handler method: 刷新验证码
  149 + */
  150 + refresh: function() {
  151 + this.render({
  152 + imgSrc: 'http://portal.mogujie.com/api/validate/captcha/pc/zie3qc7b1tia?' + Date.now()
  153 + });
  154 + },
  155 +
  156 +
  157 + /**
  158 + * Handler method: 旋转图片
  159 + */
  160 + rotateImg: function(event) {
  161 + var $pic = $(event.target);
  162 + var prevRotateCount = parseInt($pic.attr('data-val'), 10);
  163 +
  164 + $pic.attr('data-val', prevRotateCount + 1);
  165 +
  166 + $pic.css({
  167 + backgroundPosition: this.calcPosition($pic)
  168 + });
  169 + },
  170 +
  171 + /**
  172 + * method: 获取结果
  173 + * @return string '0123'
  174 + */
  175 + getResults: function() {
  176 + var result = [];
  177 +
  178 + this.$container.find('.img-check-pic')
  179 + .each(function() {
  180 + var $elem = $(this);
  181 +
  182 + result.push($elem.attr('data-val'));
  183 + });
  184 +
  185 + return result.join('');
  186 + }
  187 +};
  188 +
  189 +ImgCheck.prototype.construct = ImgCheck;
  190 +
  191 +
  192 +module.exports = ImgCheck;
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 12
13 /* component */ 13 /* component */
14 @import "layout/modal"; 14 @import "layout/modal";
  15 +@import "layout/img-check";
15 16
16 /* module */ 17 /* module */
17 18
  1 +/* ======================= *\
  2 + Module: 图片旋转验证
  3 +\* ======================= */
  4 +.img-check {
  5 + margin-top: 45px;
  6 + margin-bottom: 30px;
  7 +}
  8 +
  9 +.img-check-header {
  10 + font-size: 28px;
  11 + line-height: 35px;
  12 + text-align: left;
  13 + margin-bottom: 30px;
  14 + color: #B0B0B0;
  15 +}
  16 +
  17 +.img-check-refresh {
  18 + float: right;
  19 + font-size: 22px;
  20 + color: #36A74C;
  21 +}
  22 +
  23 +.img-check-pics {
  24 + display: flex;
  25 + justify-content: space-between;
  26 + list-style: none;
  27 + padding: 0;
  28 + margin: 0;
  29 +
  30 + li {
  31 + background-size: 600px 600px;
  32 + background-repeat: no-repeat;
  33 + background-color: #575757;
  34 + width: 150px;
  35 + height: 150px;
  36 + }
  37 +}