123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- <template>
- <div>
- <!-- page title -->
- <div v-if="stage == 0">
- <mt-header type="default" title="问卷调查-问候语" fixed></mt-header>
- </div>
- <div v-else-if="stage == 1">
- <mt-header title="问卷调查-问卷题目" fixed></mt-header>
- </div>
- <div v-else-if="stage == 2">
- <mt-header title="问卷调查-结束语" fixed></mt-header>
- </div>
- <!-- 问候语 -->
- <div v-if="stage == 0">
- <p style="margin: 80px 0;">{{questionaire.info.hello}}</p>
- <mt-button type="primary" @click="start" class="button-bottom">继续</mt-button>
- </div>
- <!-- 问卷题目 -->
- <div rows="auto * auto" v-else-if="stage==1">
- <!-- 题目问题 -->
- <div style="margin:20px 0 40px 0">
- <!-- <Progress :value="questionHEAD" :maxValue="questionaire.questions.length" /> -->
- <mt-progress :value="percent" :bar-height="5" style="margin-top: -30px;"></mt-progress>
- <div>
- <span class="h3">{{questionHEAD + 1}}、</span>
- <span class="h3" style="margin-left: 5;">[</span>
- <span class="h3">{{questionType}}</span>
- <span class="h3" style="margin-right: 5;">]</span>
- </div>
- <p class="h3">{{questionBody}}</p>
- <span class="h3">{{questionRemark}}</span>
- </div>
- <mt-radio v-if="questionType == '单选题'" v-model="selectedSingle" :options="questionOptions"
- @change="onOptionSelected">
- </mt-radio>
- <mt-checklist v-else-if="questionType == '多选题'" v-model="selectedMultiple" :options="questionOptions"
- @change="onOptionSelected">
- </mt-checklist>
- <textarea v-model="answerValue" placeholder="请在此输入答案" v-else-if="questionType == '开放题'"
- style="width: 96%;height: 160px;" />
- <mt-button type="primary" @click="onQuestionConfirm" class="button-bottom" v-show="nextBtnVisible">继续
- </mt-button>
- </div>
- <!-- <div rows="* auto" v-else class="margin">
- <Label class="body" :text="questionaire.info.bye" textWrap="true" verticalAlignment="top" />
- <Button text="继续" @tap="onFinishTap" row="1" />
- </div> -->
- <div v-if="stage == 2">
- <p style="margin: 80px 0;">{{questionaire.info.bye}}</p>
- </div>
- </div>
- </template>
- <script>
- import axios from 'axios';
- import dateFormat from '../dateFormat.js'
- import indicatorBiz from '../indicatorBiz.js'
- import Vue from 'vue'
- import { MessageBox } from 'mint-ui';
- // CREATED(0, "已创建"),
- // CLICKED(1, "已点击"),
- // STARTED(2, "已开始"),
- // COMPLETE(3, "已完成");
- export default {
- name: 'WebQn',
- data: function () {
- return {
- }
- },
- data: function () {
- return {
- webQuestionaire: {},
- questionaire: { info: {} },
- questionHEAD: 0,
- answerSheet: {
- // questionaireId: this.questionaire.info.id,
- questionaireId: 0,
- sheetName: '',
- status: 0,
- startTime: null,
- endTime: null,
- locationLong: this.long,
- locationLat: this.lat,
- },
- answers: {
- },
- answerValue: '',
- answerNote: {},
- selectedSingle: '',
- selectedMultiple: [],
- recorder: null,
- isRecording: false,
- indicators: {},
- historyStack: [],
- nextBtnVisible: true,
- webQnUrl: '',
- lastCheckList: []
- }
- },
- mounted: function () {
- let id = this.getParam('id');
- if (!id) {
- alert('无效的问卷地址');
- return;
- }
- this.webQnUrl = this.$baseUrl + '/web-qn/' + id;
- console.log('webQnUrl', this.webQnUrl);
- axios.get(this.webQnUrl).then(webQnResponse => {
- console.log(webQnResponse.data);
- let qnId = webQnResponse.data.qnId;
- let qnDataUrl = this.webQnUrl + '/complete-info';
- console.log('qnDataUrl', qnDataUrl);
- axios.get(qnDataUrl).then(r => {
- this.questionaire = r.data;
- this.webQuestionaire = webQnResponse.data;
- // this.questionaire.info = r.data.info;
- console.log(this.questionaire);
- })
- // 获取最新的配额
- // let $this = this;
- // axios.get(`${this.$baseUrl}/questionaire/${this.questionaire.info.id}/indicator`).then(function (response) {
- // // $this.indicators = response.data
- // for (let i = 0; i < response.data.length; i++) {
- // $this.indicators[response.data[i].id] = response.data[i];
- // }
- // });
- // // 将本次运行写入数据库
- // if (this.questionaire.info.status >= 3) {
- // this.insertAnswerSheet();
- // }
- // this.onQuestionLoaded();
- })
- let time = new Date();
- this.answerSheet.startTime = dateFormat.formatDate('yyyy-MM-dd HH:mm:ss', time);
- this.answerSheet.sheetName = this.generateSheetName(time);
- },
- computed: {
- stage() {
- if (this.webQuestionaire.status == 3) {
- // 显示结束语
- return 2;
- } else if (this.webQuestionaire.status == 2) {
- // 显示题目
- return 1;
- } else {
- // 显示问候语
- return 0;
- }
- },
- // pageTitle() {
- // console.log('compute page title');
- // let title = '';
- // switch (this.stage) {
- // case 0:
- // title = "问候语";
- // break;
- // case 1: title = "问卷内容";
- // break;
- // case 2: title = "问卷已结束";
- // break;
- // }
- // if (this.isRecording) {
- // return `${title}(录音中...)`
- // } else {
- // return title;
- // }
- // },
- currentQuestion() {
- return this.questionaire.questions[this.questionHEAD];
- },
- percent(){
- let perc = (this.questionHEAD + 1) / this.questionaire.questions.length * 100;
- console.log('percent', perc)
- return perc;
- },
- questionType() {
- let type = this.currentQuestion.type;
- if (type == 1) {
- if (this.currentQuestion.minOptions == 1 && this.currentQuestion.maxOptions == 1) {
- return '单选题';
- } else {
- return '多选题';
- }
- } else if (type == 3) {
- return '排序题';
- } else if (type == 4) {
- return '开放题';
- }
- },
- questionBody() {
- // 处理${ID}的情况
- return this.replaceDollarId(this.currentQuestion.body);
- },
- questionRemark() {
- // 处理${ID}的情况
- return this.replaceDollarId(this.currentQuestion.remark);
- },
- upperDatasourceQuestion() {
- console.log('call upperDatasourceQuestion');
- // 获取上一级的数据源所在的题目id(同一个id,但列数小1的题目)
- if (!this.currentQuestion.datasourceId) {
- return 0;
- } else {
- let dsId = this.currentQuestion.datasourceId
- let dsColumn = this.currentQuestion.datasourceColumn;
- for (let i = 0; i < this.questionHEAD; i++) {
- if (this.questionaire.questions[i].datasourceId == dsId
- && this.questionaire.questions[i].datasourceColumn == dsColumn - 1) {
- return this.questionaire.questions[i].id;
- }
- }
- return 0;
- }
- },
- questionOptions() {
- console.log('call questionOptions');
- let opts = [];
- if (this.upperDatasourceQuestion == 0) {
- opts = this.currentQuestion.options;
- } else {
- let dsId = this.currentQuestion.datasourceId
- let dsColumn = this.currentQuestion.datasourceColumn;
- let targetOptionId = this.answers[this.upperDatasourceQuestion].answer;
- let dsFilter = this.findOptionContent(this.upperDatasourceQuestion, targetOptionId);
- let subDataColumn = [];
- let datasource = null;
- for (let i in this.questionaire.datasource) {
- if (this.questionaire.datasource[i].id == dsId) {
- datasource = this.questionaire.datasource[i];
- break;
- }
- }
- if (!datasource) {
- return this.currentQuestion.options;
- }
- for (let i in datasource.contentList) {
- if (datasource.contentList[i]['c' + (dsColumn - 1)] == dsFilter) {
- subDataColumn.push(datasource.contentList[i]['c' + dsColumn])
- }
- }
- let subOptions = [];
- for (let i in this.currentQuestion.options) {
- if (this.currentQuestion.options[i].datasourceId == 0 ||
- subDataColumn.indexOf(this.currentQuestion.options[i].optionContent) >= 0) {
- subOptions.push(this.currentQuestion.options[i]);
- }
- }
- opts = subOptions;
- }
- // 组装成 mt-radio 或 mt-checklist 组件需要的格式
- for (let i = 0; i < opts.length; i++) {
- // let label = `${i + 1}、${opts[i].optionContent}`;
- let label = `${opts[i].optionContent}`;
- let value = i.toString();
- Vue.set(opts[i], 'label', label);
- Vue.set(opts[i], 'value', value);
- }
- return opts;
- }
- },
- methods: {
- getParam: function (name) {
- if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search))
- return decodeURIComponent(name[1]);
- },
- // backEventHandler(args) {
- // console.log('activityBackPressedEvent......')
- // debugger;
- // if (this.stage < 2) {
- // args.cancel = true;
- // this.onQuitTap();
- // } else if (this.stage == 2) {
- // args.cancel = true;
- // this.onFinishTap();
- // }
- // },
- start() {
- this.webQuestionaire.status = 2;
- axios.put(this.webQnUrl, { status: 2 }).then(() => console.log('update status success'));
- },
- getUserName() {
- return this.webQuestionaire.phoneNumber;
- },
- getOrgCode() {
- let orgCode = 'webqn';
- return orgCode
- },
- generateSheetName(time) {
- let orgCode = this.getOrgCode();
- let userName = this.getUserName();
- return `${orgCode}-${dateFormat.formatDate('yyyyMMddHHmmss', time)}-${userName}`
- },
- replaceDollarId(body) {
- // 处理${ID}的情况
- let regex = /\$\{(\d+)\}/m;
- let match = regex.exec(body);
- while (match && match[0]) {
- let targetQuestionId = match[1];
- let targetOptionId = this.answers[targetQuestionId].answer;
- let targetOptionContent = this.findOptionContent(targetQuestionId, targetOptionId);
- body = body.replace(match[0], targetOptionContent)
- match = regex.exec(body);
- }
- return body;
- },
- onQuitTap() {
- confirm({
- title: "请确认",
- message: "确定要结束问卷吗?",
- okButtonText: "确定",
- cancelButtonText: "取消"
- }).then(result => {
- if (result) {
- // 中途拒访
- this.finishQuestionaire(2);
- }
- })
- },
- onPreTap() {
- let lastIndex = this.historyStack.pop();
- this.questionHEAD = lastIndex;
- this.onQuestionLoaded(true)
- },
- onListItemTap(event) {
- let selectedOpt = event.item;
- selectedOpt.isSelected = !selectedOpt.isSelected;
- console.log('onListItemTap', `select option: ${selectedOpt.optionContent}, selected? ${selectedOpt.isSelected}`);
- this.onOptionChange(selectedOpt);
- },
- onOptionSelected(index) {
- console.log('option changed : ', typeof index);
- let _type = typeof index;
- let selectedOpt = null;
- if (_type == 'object') {
- // 多选
- let isUnselect = this.lastCheckList.length > index.length
- if (!isUnselect) {
- let lastIndex = index[index.length - 1];
- selectedOpt = this.questionOptions[lastIndex]
- }
- // 将本次选项写入this.lastCheckList
- this.lastCheckList.length = 0;
- for (let i = 0; i < index.length; i++) {
- this.lastCheckList.push(index[i]);
- }
- if (isUnselect) {
- return;
- }
- } else if (_type == 'string') {
- selectedOpt = this.questionOptions[index]
- }
- // 处理开放选项
- if (selectedOpt.open) {
- MessageBox.prompt(selectedOpt.openOptionTips, '请填写')
- .then(({ value }) => {
- console.log(`Dialog value: ${value}, `)
- this.answerNote[selectedOpt.id] = value;
- });
- }
- },
- onQuestionLoaded(isBack) {
- console.log('call onQuestionLoaded')
- if (isBack) {
- let lastQuestionId = this.questionaire.questions[this.questionHEAD].id;
- let lastAnswer = this.answers[lastQuestionId];
- this.answerValue = lastAnswer.answer;
- if (this.currentQuestion.type == 1 && lastAnswer.answerNote) {
- this.answerNote[lastAnswer.answer] = lastAnswer.answerNote;
- }
- delete this.answers[lastQuestionId];
- } else {
- this.answerValue = '';
- this.answerNote = {};
- this.selectedSingle = '';
- this.selectedMultiple = [];
- }
- // 根据题目类型,动态展示对应的答题方式
- // ---- 已在页面绑定中体现了
- // 处理${ID}的情况
- // ---- 已在computed questionBody()中处理
- // 处理数据源绑定(如果绑定了数据源并且上一列已经选中,则根据上一列的结果筛选选项)
- // ---- 已在computed questionOptions()中处理
- // 如果某选项会跳转到结束问卷,则提示出来
- // ---- 已在页面绑定中体现了
- },
- findOptionContent(targetQuestionId, targetOptionId) {
- for (let i in this.questionaire.questions) {
- if (this.questionaire.questions[i].id == targetQuestionId) {
- console.log('target qeustion', this.questionaire.questions[i].body);
- for (let j in this.questionaire.questions[i].options) {
- if (this.questionaire.questions[i].options[j].id == targetOptionId) {
- console.log('target option', this.questionaire.questions[i].options[j].optionContent);
- return this.questionaire.questions[i].options[j].optionContent;
- }
- }
- }
- }
- },
- onQuestionConfirm() {
- console.log('onQuestionConfirm...')
- // let selections = [];
- let selectionIds = []
- let questionId = this.questionaire.questions[this.questionHEAD].id;
- if (this.currentQuestion.type == 1) {
- if (this.questionType == '单选题') {
- if (this.selectedSingle) {
- selectionIds.push(this.questionOptions[this.selectedSingle].id);
- }
- } else {
- for (let i = 0; i < this.selectedMultiple.length; i++) {
- selectionIds.push(this.questionOptions[this.selectedMultiple[i]].id);
- }
- }
- console.log('selectionIds', selectionIds);
- if (this.currentQuestion.maxOptions && this.currentQuestion.maxOptions < selectionIds.length) {
- alert(`最多可选中${this.currentQuestion.maxOptions}项`);
- return;
- }
- if (this.currentQuestion.minOptions && this.currentQuestion.minOptions > selectionIds.length) {
- alert(`最少需选中${this.currentQuestion.minOptions}项`);
- return;
- }
- // 确定答案
- // this.answers[questionId] = selectionIds.join(',');
- this.answers[questionId] = {
- questionId: questionId,
- answer: selectionIds.join(',')
- };
- if (this.currentQuestion.maxOptions == 1 && this.answerNote[selectionIds[0]]) {
- this.answers[questionId].answerNote = this.answerNote[selectionIds[0]]
- } else if (this.currentQuestion.maxOptions > 1) {
- let answerNoteObj = {}
- for (let index in selectionIds) {
- let selectedId = selectionIds[index];
- if (this.answerNote[selectedId]) {
- answerNoteObj[selectedId] = this.answerNote[selectedId];
- }
- }
- this.answers[questionId].answerNote = JSON.stringify(answerNoteObj);
- }
- // 判断是否配额不足
- let isIndicartorOut = indicatorBiz.isIndicartorOut(this.currentQuestion, this.indicators, this.answers);
- if (isIndicartorOut) {
- // 配额不足,跳转至结束
- this.finishQuestionaire(4);
- return;
- }
- // 判断是否需要跳题以及是否需要结束问卷
- let hopToQuestionId = 0;
- if (this.currentQuestion.type == 1 && this.currentQuestion.maxOptions == 1) {
- for (let i in this.questionOptions) {
- let opt = this.questionOptions[i];
- if (opt.id == selectionIds[0] && opt.redirectTo != 0) {
- hopToQuestionId = opt.redirectTo;
- break;
- }
- }
- }
- console.log('hop to question', hopToQuestionId);
- if (hopToQuestionId == -2) {
- // 甄别不过,跳转至结束
- this.finishQuestionaire(3);
- return;
- } else if (hopToQuestionId == -1) {
- // 正常结束
- this.finishQuestionaire(1);
- return;
- } else if (hopToQuestionId > 0) {
- // 跳转到某道题
- // for (let i in this.questionaire.questions) {
- for (let i = 0; i < this.questionaire.questions.length; i++) {
- if (this.questionaire.questions[i].id == hopToQuestionId) {
- this.questionHEAD = i;
- this.onQuestionLoaded();
- return;
- }
- }
- }
- } else if (this.currentQuestion.type == 3) {
- // 排序题
- } else if (this.currentQuestion.type == 4) {
- // 开放题
- if (this.currentQuestion.required && !this.answerValue) {
- alert('此项必填');
- return;
- }
- this.answers[questionId] = {
- questionId: questionId,
- answer: this.answerValue
- };
- }
- if (this.questionHEAD == this.questionaire.questions.length - 1) {
- // 所有题目都回答完了,问卷正常结束
- this.finishQuestionaire(1);
- return;
- } else {
- // 进入下一道题
- this.historyStack.push(this.questionHEAD);
- this.questionHEAD++;
- }
- this.onQuestionLoaded();
- },
- finishQuestionaire(status) {
- if (this.questionaire.info.status >= 3) {
- this.answerSheet.status = status;
- this.answerSheet.endTime = dateFormat.formatDate('yyyy-MM-dd HH:mm:ss', new Date());
- let arr = [];
- for (let i in this.answers) {
- arr.push(this.answers[i])
- }
- // 持久化answerSheet数据
- // this.updateAnswerSheetData(JSON.stringify(arr));
- axios.post(this.webQnUrl, {
- sheet: this.answerSheet,
- answers: arr
- }).then(() => {
- // this.updateAnswerSheetDataUploaded(true);
- // alert('问卷结果已提交');
- this.webQuestionaire.status = 3;
- })
- }
- },
- onFinishTap() {
- if (app.android) {
- app.android.off(app.AndroidApplication.activityBackPressedEvent, this.backEventHandler);
- console.log('backEventHandler off')
- }
- if (this.isRecord) {
- this.recorder.stop().catch(ex => {
- console.log('recorder stop failed', ex);
- this.isRecording = false;
- });
- }
- this.$modal.close();
- },
- insertAnswerSheet() {
- this.$db.execSQL('insert into answer_sheet values(?,?,?,?,?,?,?,?,?,?,?,?)',
- [
- this.answerSheet.sheetName,
- this.answerSheet.questionaireId,
- this.answerSheet.status,
- this.answerSheet.startTime,
- null,
- this.answerSheet.locationLong,
- this.answerSheet.locationLat,
- null,
- 0,
- this.isRecord ? 1 : 0,
- 0,
- this.getUserName()
- ], function (err) {
- if (err) {
- console.error('insertAnswerSheet error', err)
- }
- })
- },
- // updateAnswerSheetData(answerJson) {
- // this.$db.execSQL('update answer_sheet set endTime = ?, answerJson = ?, status = ? where sheetName = ?',
- // [
- // this.answerSheet.endTime,
- // answerJson,
- // this.answerSheet.status,
- // this.answerSheet.sheetName,
- // ], function (err) {
- // if (err) {
- // console.error('updateAnswerSheetData error', err)
- // }
- // })
- // },
- // updateAnswerSheetDataUploaded(isDataUploaded) {
- // this.$db.execSQL('update answer_sheet set dataUploaded = ? where sheetName = ?',
- // [
- // isDataUploaded ? 1 : 0,
- // this.answerSheet.sheetName,
- // ], function (err) {
- // if (err) {
- // console.error('updateAnswerSheetDataUploaded error', err)
- // }
- // })
- // }
- },
- }
- </script>
- <style scoped>
- .button-bottom {
- width: 96%;
- /* position: absolute; */
- /* left: 2%; */
- /* bottom: 2%; */
- margin-top: 40px;
- margin-left: 2%;
- }
- </style>
|