Authored by yyq

question

'use strict';
const questionModel = require('../models/question');
const headerModel = require('../../../doraemon/models/header'); // 头部model
exports.list = (req, res, next) => {
req.ctx(questionModel).getQuestionList().then(result => {
res.render('question/list', {
title: '调研中心',
module: '3party',
page: 'question-list',
pageHeader: headerModel.setNav({
navTitle: '调研中心'
}),
list: result,
isApp: req.yoho.isApp
});
}).catch(next);
};
exports.check = (req, res, next) => {
let params = req.body;
params.uid = req.user.uid || params.uid;
if (!params.uid) {
return res.send({code: 206, message: '请先登录!'});
}
req.ctx(questionModel).getQuestionStatus(params).then(result => {
res.send(result);
}).catch(next);
};
exports.submit = (req, res, next) => {
let params = req.body;
params.uid = req.user.uid || params.uid;
if (!params.uid) {
return res.send({code: 400, message: '请先登录!'});
}
req.ctx(questionModel).submitQuestion(params).then(result => {
res.send(result);
}).catch(next);
};
exports.detail = (req, res, next) => {
let id = parseInt(`0${req.params.id}`, 10);
req.ctx(questionModel).getQuestionDetail(id, req.user.uid).then(result => {
if (result) {
result.uid = req.user.uid;
}
res.render('question/detail', {
title: 'YOHOBUY!潮流大调查',
module: '3party',
page: 'question-detail',
pageHeader: headerModel.setNav({
navTitle: 'YOHOBUY!潮流大调查'
}),
detail: result,
isApp: req.yoho.isApp
});
}).catch(next);
};
... ...
/**
* question model
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2017/05/23
*/
const _ = require('lodash');
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
getQuestionList() {
return this.get({
url: 'activity/question/questionList',
api: global.yoho.ServiceAPI
}).then(result => {
let list = _.get(result, 'data.rows', []);
_.forEach(list, (value, key) => {
Object.assign(value, {
index: key + 1,
img: '//img11.static.yhbimg.com/sns/2017/05/25/14/0177e28a98f73417ae1a2a146aa2670dd2.png'
});
});
return list;
});
}
getQuestionStatus(params) {
return this.get({
url: '/activity/question/questionValidate',
data: params,
api: global.yoho.ServiceAPI
});
}
getQuestionDetail(id, uid) {
return Promise.all([
this.get({
url: '/activity/question/questionValidate',
data: {id: id, uid: uid},
api: global.yoho.ServiceAPI
}),
this.get({
url: 'activity/question/questionDetail',
data: {id: id},
api: global.yoho.ServiceAPI
})
]).then(result => {
if (_.get(result, '[0].code', '') !== 200) {
return false;
}
let data = _.get(result, '[1].data', {});
if (data.questions) {
_.forEach(data.questions, value => {
if (+value.questionType === 3) {
value.questionContents = _.fill(Array(value.fillBlankNum || 1), true);
}
});
}
return _.isEmpty(data) ? false : data;
});
}
submitQuestion(info) {
return this.post({
url: '/activity/question/submitQuestions',
data: info,
api: global.yoho.ServiceAPI
});
}
};
... ...
... ... @@ -10,7 +10,9 @@ const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const ads = require(`${cRoot}/ads`);
const check = require(`${cRoot}/check`);
const question = require(`${cRoot}/question`);
const validateCode = require('../passport/controllers/validateCode');
const auth = require('../../doraemon/middleware/auth');
// routers
... ... @@ -18,4 +20,10 @@ router.get('/ads', ads.index);
router.get('/check', validateCode.load, check.index);
router.post('/check/submit', validateCode.check, check.submit);
router.get('/questionnaire', auth, question.list);
router.post('/questionnaire/check', question.check);
router.post('/questionnaire/submit', question.submit);
router.get('/questionnaire/:id', auth, question.detail);
module.exports = router;
... ...
<div class="qs-detail-page">
{{# detail}}
<div class="error-tip"></div>
<div class="detail-wrap">
<p class="sub-title">{{title}}</p>
<p class="guide-tip">{{description}}</p>
<div id="qs-wrap" class="qs-wrap" data-id="{{id}}" data-cid="{{uid}}" data-title="{{share.title}} data-desc="{{share.subtitle}} data-img="{{share.img}}">
{{# questions}}
<dl class="qs-item" data-index="{{questionIndex}}" data-type="{{questionType}}">
<dt>{{questionTitle}}</dt>
{{#isEqualOr questionType 1}}
{{# questionContents}}
<dd class="radio-option" data-index="{{@index}}">
<span class="iconfont">&#xe6ea;</span>
{{option}}
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{#isEqualOr questionType 2}}
{{# questionContents}}
<dd class="check-option">
<span class="iconfont">&#xe6ea;</span>
{{option}}
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{#isEqualOr questionType 3}}
{{# questionContents}}
<dd><textarea class="text-input"></textarea></dd>
{{/ questionContents}}
{{/isEqualOr}}
</dl>
{{/ questions}}
</div>
<div class="submit">
<button class="submit-btn">提交</button>
</div>
</div>
{{/ detail}}
<div class="qs-err">
<a href="/3party/questionnaire">去做问卷</a>
</div>
<div id="tip-dialog" class="tip-dialog hide">
<div class="dg-wrap">
<div class="dg-content"><p>您的问卷还没有成功提交哦!<br>是否立刻返回!</p></div>
<div class="dg-btns clearfix">
<span class="back-btn">返回</span>
<span class="close-btn continue-btn">继续填写</span>
</div>
</div>
</div>
</div>
... ...
<div class="qs-list-page">
{{#if list}}
<ul id="qs-list" class="qs-list">
{{#each list}}
<li data-id="{{id}}" data-title="{{title}}" data-desc="{{description}}" data-img="{{img}}">{{index}}.{{title}}</li>
{{/each}}
</ul>
{{/if}}
<div id="tip-dialog" class="tip-dialog hide">
<div class="dg-wrap">
<div class="dg-content"></div>
<div class="dg-btns sure-btns clearfix hide">
<span class="close-btn sure-btn">确定</span>
</div>
<div class="dg-btns share-btns clearfix">
<span class="close-btn cancel-btn">取消</span>
<span class="share-btn">分享问卷</span>
</div>
</div>
</div>
</div>
... ...
require('3party/question-detail.page.css');
let $ = require('yoho-jquery');
let question = {
$base: $('#qs-wrap'),
init: function() {
let yoho = require('yoho-app');
this.$errTip = $('.error-tip');
this.$item = $('.qs-item', this.$base);
this.startTime = Date.parse(new Date()) / 1000;
if (yoho.isApp) {
let data = this.$base.data();
yoho.ready(function() {
yoho.invokeMethod('set.shareInfo', {
title: data.title,
link: 'http://m.yohobuy.com/3party/questionnaire/' + data.id,
desc: data.desc,
imgUrl: data.img
});
});
}
this.bindEvent();
},
bindEvent: function() {
let that = this;
this.$base.on('click', '.radio-option', function() {
let $this = $(this);
if (!$this.hasClass('on')) {
$this.siblings('.on').removeClass('on');
$this.addClass('on');
}
}).on('click', '.check-option', function() {
let $this = $(this);
if ($this.hasClass('on')) {
$this.removeClass('on');
} else {
$this.addClass('on');
}
}).on('click', 'input', function(e) {
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
});
$('.submit-btn').click(function() {
that.saveAnswers(that.packAnswersInfo());
});
},
packAnswersInfo: function() {
let that = this;
let answer = [];
let $errDom;
this.$item.each(function() {
if ($errDom) {
return;
}
let $this = $(this);
let data = $this.data();
let ans = [];
let errText = '';
if (+data.type === 3) {
$this.find('.text-input').each(function() {
let val = $.trim($(this).val());
if (val) {
ans.push({
questionIndex: data.index,
answerIndex: ans.length,
addon: val
});
}
if (val.length > 400) {
errText = '输入内容过长';
}
});
} else {
$this.find('.on').each(function() {
let $that = $(this),
$input = $that.find('input'),
a = {
questionIndex: data.index,
answerIndex: $that.data('index')
};
if ($input && $input.length) {
a.addon = $input.val();
}
ans.push(a);
});
if (data.type === '1') {
ans.length = 1;
}
}
if (errText || !ans.length) {
$errDom = $this;
if (!errText) {
errText = +data.type === 3 ? '请选择一个选项' : '请填写一条回答';
}
that.showError(errText, $errDom);
} else {
answer = $.merge(answer, ans);
}
});
if ($errDom) {
return [];
} else {
return answer;
}
},
showError: function(tip, $errDom) {
let that = this;
this.$errTip.html(tip);
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(function() {
that.$errTip.empty();
}, 5000);
if ($errDom) {
let offTop = $errDom.offset().top,
errHeight = this.$errTip.outerHeight();
$('html,body').animate({scrollTop: offTop - errHeight}, 500);
}
},
saveAnswers: function(info) {
if (!info || !info.length) {
return;
}
$.ajax({
type: 'POST',
url: '/3party/questionnaire/submit',
data: {
id: this.$base.data('id'),
uid: this.$base.data('cid'),
startTime: this.startTime,
endTime: Date.parse(new Date()) / 1000,
frontAnswers: JSON.stringify(info)
}
}).then(function(data) {
if (data.code === 200) {
window.history.go(-1);
}
});
}
};
let tipDialog = {
$base: $('#tip-dialog'),
init: function() {
var that = this;
this.$base.on('click', '.close-btn', function() {
that.hide();
});
this.$base.on('click', '.back-btn', function() {
window.history.go(-1);
});
},
show: function() {
this.$base.removeClass('hide');
},
hide: function() {
this.$base.addClass('hide');
}
};
tipDialog.init();
question.init();
$('.nav-back').removeAttr('href').click(function() {
tipDialog.show();
});
... ...
'use strict';
require('3party/question-list.page.css');
let $ = require('yoho-jquery'),
yoho = require('yoho-app');
const DETAIL_URI = '/3party/questionnaire';
require('../common');
let qs = window.queryString;
function getQuestionStatus(reqData, cb) {
if (qs.uid) {
reqData.uid = qs.uid;
}
$.ajax({
type: 'POST',
url: '/3party/questionnaire/check',
data: reqData
}).then(function(data) {
if (cb && typeof cb === 'function') {
return cb(data);
}
});
}
let tipDialog = {
$base: $('#tip-dialog'),
init: function() {
let that = this;
this.$content = $('.dg-content', this.$base);
this.$sureBtns = $('.sure-btns', this.$base);
this.$shareBtns = $('.share-btns', this.$base);
this.$base.on('click', '.close-btn', function() {
that.hide();
});
this.$base.on('click', '.share-btn', function() {
if (that.share && typeof that.share === 'function') {
that.share();
} else {
that.hide();
}
});
},
show: function(info) {
this.share = false;
if (typeof info === 'object') {
this.$content.html(info.content);
this.$sureBtns.addClass('hide');
this.$shareBtns.removeClass('hide');
this.share = this.setShareInfo(info.shareInfo);
} else if (typeof info === 'string') {
this.$content.html('<p>' + info + '</p>');
this.$sureBtns.removeClass('hide');
this.$shareBtns.addClass('hide');
} else {
return;
}
this.$base.removeClass('hide');
},
hide: function() {
this.$base.addClass('hide');
},
setShareInfo: function(info) {
if (!info) {
return false;
}
return function() {
yoho && yoho.invokeMethod('set.shareInfo', {
title: info.title,
link: '//www.yohobuy.com/3party/questionnaire/' + info.id,
desc: info.desc,
imgUrl: info.img
});
};
}
};
tipDialog.init();
$('#qs-list').on('click', 'li', function() {
let data = $(this).data();
if (!data.id) {
return;
}
getQuestionStatus({uid: qs.uid, id: data.id}, function(resData) {
if (resData.code === 200) {
if (qs && qs.uid) {
window.location.href = DETAIL_URI + '/' + data.id + '?uid=' + qs.uid;
} else {
window.location.href = DETAIL_URI + '/' + data.id;
}
} else if (resData.code === 206) {
if (!$('#yoho-header').length) {
tipDialog.show({
content: '<p>调查问卷已成功提交,<br>感谢您的帮助!</p>',
shareInfo: data
});
} else {
tipDialog.show('调查问卷已成功提交,<br>感谢您的帮助!');
}
} else if (resData.message) {
window.location.href = DETAIL_URI + '/0';
}
});
});
... ...
body {
background: #f0f0f0;
}
.nav-home {
display: none !important;
}
.qs-detail-page {
font-size: 24px;
$borderColor: #ececec;
.error-tip {
width: 100%;
background-color: #ff7e82;
color: #fff;
padding-left: 30px;
line-height: 50px;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.sub-title {
line-height: 2;
padding: 14px 20px;
background: #fff;
border-bottom: 1px solid $borderColor;
text-align: center;
}
.guide-tip {
line-height: 2;
padding: 0 30px;
color: #555;
}
.qs-item {
background: #fff;
margin-bottom: 30px;
padding-left: 30px;
border-top: 1px solid $borderColor;
border-bottom: 1px solid $borderColor;
> * {
line-height: 60px;
padding: 10px 0;
}
> dd {
border-top: 1px solid $borderColor;
input {
width: calc(100% - 60px);
height: 40px;
margin-left: 34px;
border: 0;
border-bottom: 1px solid $borderColor;
}
}
textarea {
width: calc(100% - 26px);
height: 100px;
resize: none;
border: 1px solid #ddd;
display: block;
}
.iconfont {
display: inline-block;
width: 34px;
height: 34px;
line-height: 34px;
border: 1px solid #444;
vertical-align: middle;
font-size: 18px;
text-align: center;
color: #fff;
position: relative;
top: -1px;
}
.radio-option .iconfont {
border-radius: 17px;
overflow: hidden;
}
.on > .iconfont {
background-color: #444;
}
}
.submit {
padding: 0 20px;
.submit-btn {
width: 100%;
height: 80px;
background: #3e3e3e;
color: #fff;
border: 0;
border-radius: 4px;
margin-bottom: 20px;
outline: none;
}
}
.detail-wrap + .qs-err {
display: none;
}
.qs-err {
&:before {
content: "";
width: 299px;
height: 245px;
background: resolve("3party/qs-lose.jpg") no-repeat;
display: block;
margin: 120px auto 50px;
background-size: 100%;
}
a {
width: 60%;
height: 80px;
line-height: 80px;
margin: 0 auto;
background: #3e3e3e;
color: #fff;
display: block;
text-align: center;
border-radius: 4px;
}
}
.tip-dialog {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 10;
&:before {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: -1;
}
.dg-wrap {
width: 70%;
background: #fff;
border-radius: 6px;
position: absolute;
left: 15%;
top: 50%;
margin-top: -95px;
}
.dg-content {
height: 140px;
line-height: 140px;
> p {
width: 100%;
line-height: 1.4;
display: inline-block;
text-align: center;
vertical-align: middle;
}
}
.dg-btns {
border-top: 1px solid #efefef;
> * {
width: 50%;
line-height: 60px;
text-align: center;
display: block;
float: left;
cursor: pointer;
box-sizing: border-box;
}
}
.continue-btn {
border-left: 1px solid #efefef;
box-sizing: border-box;
color: #d90005;
}
}
}
... ...
.nav-home {
display: none !important;
}
.qs-list-page {
font-size: 28px;
$borderColor: #ececec;
.qs-list {
line-height: 90px;
color: #444;
padding-left: 30px;
border-bottom: 1px solid $borderColor;
> li {
border-top: 1px solid $borderColor;
}
}
.tip-dialog {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 10;
&:before {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: -1;
}
.dg-wrap {
width: 70%;
background: #fff;
border-radius: 6px;
position: absolute;
left: 15%;
top: 50%;
margin-top: -95px;
}
.dg-content {
height: 140px;
line-height: 140px;
> p {
width: 100%;
line-height: 1.4;
display: inline-block;
text-align: center;
vertical-align: middle;
}
}
.dg-btns {
border-top: 1px solid #efefef;
> * {
width: 50%;
line-height: 60px;
text-align: center;
display: block;
float: left;
cursor: pointer;
}
}
.dg-btns .sure-btn {
width: 100%;
}
.share-btn {
border-left: 1px solid #efefef;
box-sizing: border-box;
color: #d90005;
}
}
}
... ...