|
@@ -3,10 +3,17 @@
|
|
<detail-frame :title="pageTitle" :returns="toReturns">
|
|
<detail-frame :title="pageTitle" :returns="toReturns">
|
|
<el-card>
|
|
<el-card>
|
|
<template #header>
|
|
<template #header>
|
|
- <span>{{ quest.name }}</span>
|
|
|
|
- [<span>完成度:</span><span>{{ questionAnswer.percentage }}%</span> <span>已答:</span><span>{{ questionAnswer.yesAnswer }}</span> <span>未答:</span
|
|
|
|
- ><span @click="nostuBtn()" class="nostu">{{ questionAnswer.noAnswer }}</span
|
|
|
|
- >]
|
|
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="20">
|
|
|
|
+ <span>{{ quest.name }}</span>
|
|
|
|
+ [<span>完成度:</span><span>{{ questionAnswer.percentage }}%</span> <span>已答:</span><span>{{ questionAnswer.yesAnswer }}</span>
|
|
|
|
+ <span>未答:</span><span @click="nostuBtn()" class="nostu">{{ questionAnswer.noAnswer }}</span
|
|
|
|
+ >]
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="4">
|
|
|
|
+ <el-button type="primary" size="small" @click="eDialog = true">导出</el-button>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
</template>
|
|
</template>
|
|
<el-tabs v-model="tabs" :stretch="true" type="card">
|
|
<el-tabs v-model="tabs" :stretch="true" type="card">
|
|
<el-tab-pane label="图表分析" name="chart">
|
|
<el-tab-pane label="图表分析" name="chart">
|
|
@@ -42,12 +49,30 @@
|
|
</el-tabs>
|
|
</el-tabs>
|
|
</el-card>
|
|
</el-card>
|
|
</detail-frame>
|
|
</detail-frame>
|
|
|
|
+ <el-dialog title="导出" center :visible.sync="eDialog">
|
|
|
|
+ <export-range :usestudent="false" @close="eDialog = false" @toExport="toExportExcel">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="24" style="font-size:16px">
|
|
|
|
+ 表头排列方式:
|
|
|
|
+ <el-radio-group v-model="direction" class="btn_bar">
|
|
|
|
+ <el-radio label="horizontal">横向</el-radio>
|
|
|
|
+ <el-radio label="vertical">纵向</el-radio>
|
|
|
|
+ </el-radio-group>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="24">
|
|
|
|
+ <model-card v-model="selectModel" :modelList="modelList"></model-card>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </export-range>
|
|
|
|
+ </el-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
//组件全部转移到frame中,和班主任端共用
|
|
//组件全部转移到frame中,和班主任端共用
|
|
import _ from 'lodash';
|
|
import _ from 'lodash';
|
|
|
|
+import modelCard from '@/components/model-card.vue';
|
|
|
|
+import exportRange from '@frame/components/export-range';
|
|
import charts from '@frame/parts/statistics/quest-chart.vue';
|
|
import charts from '@frame/parts/statistics/quest-chart.vue';
|
|
import reports from '@frame/parts/statistics/report.vue';
|
|
import reports from '@frame/parts/statistics/report.vue';
|
|
import detailFrame from '@frame/layout/admin/detail-frame';
|
|
import detailFrame from '@frame/layout/admin/detail-frame';
|
|
@@ -56,13 +81,16 @@ const { mapActions: questionnaire } = createNamespacedHelpers('questionnaire');
|
|
const { mapActions: questionanswer } = createNamespacedHelpers('questionanswer');
|
|
const { mapActions: questionanswer } = createNamespacedHelpers('questionanswer');
|
|
const { mapActions: setting } = createNamespacedHelpers('setting');
|
|
const { mapActions: setting } = createNamespacedHelpers('setting');
|
|
const { mapActions: student } = createNamespacedHelpers('student');
|
|
const { mapActions: student } = createNamespacedHelpers('student');
|
|
|
|
+const { mapActions: util } = createNamespacedHelpers('util');
|
|
|
|
|
|
export default {
|
|
export default {
|
|
name: 'detail',
|
|
name: 'detail',
|
|
props: {},
|
|
props: {},
|
|
- components: { detailFrame, charts, reports },
|
|
|
|
|
|
+ components: { detailFrame, charts, reports, exportRange, modelCard },
|
|
data: function() {
|
|
data: function() {
|
|
return {
|
|
return {
|
|
|
|
+ test: '1',
|
|
|
|
+ eDialog: false,
|
|
mylb: null,
|
|
mylb: null,
|
|
tabs: 'chart',
|
|
tabs: 'chart',
|
|
collapse: '',
|
|
collapse: '',
|
|
@@ -70,23 +98,26 @@ export default {
|
|
cdata: [], //具体数据
|
|
cdata: [], //具体数据
|
|
nodata: false,
|
|
nodata: false,
|
|
questionAnswer: {},
|
|
questionAnswer: {},
|
|
|
|
+ // 导出
|
|
|
|
+ direction: 'horizontal',
|
|
|
|
+ selectModel: [],
|
|
|
|
+ modelList: [],
|
|
};
|
|
};
|
|
},
|
|
},
|
|
created() {
|
|
created() {
|
|
this.search();
|
|
this.search();
|
|
|
|
+ this.toFindModel();
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
- ...questionnaire(['fetch']),
|
|
|
|
|
|
+ ...util(['findModel']),
|
|
|
|
+ ...questionnaire(['fetch', 'export']),
|
|
...questionanswer(['query']),
|
|
...questionanswer(['query']),
|
|
...setting({ getSetting: 'fetch' }),
|
|
...setting({ getSetting: 'fetch' }),
|
|
...student({ findList: 'findList', studentQuery: 'query' }),
|
|
...student({ findList: 'findList', studentQuery: 'query' }),
|
|
async search() {
|
|
async search() {
|
|
- console.log(this.querys.questionnaireid);
|
|
|
|
let res = await this.fetch(this.querys.questionnaireid);
|
|
let res = await this.fetch(this.querys.questionnaireid);
|
|
if (!this.$checkRes(res)) return;
|
|
if (!this.$checkRes(res)) return;
|
|
- console.log(this.querys);
|
|
|
|
let ansres = await this.query(this.querys); //{ questionnaireid: this.id, termid: this.termid, batchid: this.batchid, classid: this.classid }
|
|
let ansres = await this.query(this.querys); //{ questionnaireid: this.id, termid: this.termid, batchid: this.batchid, classid: this.classid }
|
|
- console.log(ansres);
|
|
|
|
if (this.$checkRes(ansres)) {
|
|
if (this.$checkRes(ansres)) {
|
|
if (_.get(ansres.data, 'length', 0) <= 0) {
|
|
if (_.get(ansres.data, 'length', 0) <= 0) {
|
|
this.$set(this, `nodata`, true);
|
|
this.$set(this, `nodata`, true);
|
|
@@ -95,7 +126,6 @@ export default {
|
|
let quests = _.cloneDeep(_.get(res.data, `question`, []));
|
|
let quests = _.cloneDeep(_.get(res.data, `question`, []));
|
|
let allAnswer = _.cloneDeep(ansres.data);
|
|
let allAnswer = _.cloneDeep(ansres.data);
|
|
allAnswer = _.uniqBy(allAnswer, 'studentid');
|
|
allAnswer = _.uniqBy(allAnswer, 'studentid');
|
|
- console.log(allAnswer);
|
|
|
|
let naa = _.flatten(allAnswer.map(i => i.answers)).map(i => {
|
|
let naa = _.flatten(allAnswer.map(i => i.answers)).map(i => {
|
|
if (i.answer) i.answer = JSON.parse(i.answer);
|
|
if (i.answer) i.answer = JSON.parse(i.answer);
|
|
return i;
|
|
return i;
|
|
@@ -107,20 +137,17 @@ export default {
|
|
this.$set(this, `quest`, sta);
|
|
this.$set(this, `quest`, sta);
|
|
//具体数据
|
|
//具体数据
|
|
let concreteData = this.getConcreteData(quests, allAnswer);
|
|
let concreteData = this.getConcreteData(quests, allAnswer);
|
|
- console.log(concreteData);
|
|
|
|
this.$set(this, `cdata`, concreteData);
|
|
this.$set(this, `cdata`, concreteData);
|
|
// 查学生,算已答未答
|
|
// 查学生,算已答未答
|
|
const { questionnaireid, ...stuquery } = this.querys;
|
|
const { questionnaireid, ...stuquery } = this.querys;
|
|
- console.log(stuquery);
|
|
|
|
let studentList = await this.studentQuery(stuquery);
|
|
let studentList = await this.studentQuery(stuquery);
|
|
- console.log(studentList);
|
|
|
|
- console.log(allAnswer);
|
|
|
|
let answerDta = {
|
|
let answerDta = {
|
|
yesAnswer: allAnswer.length,
|
|
yesAnswer: allAnswer.length,
|
|
noAnswer: studentList.total - allAnswer.length,
|
|
noAnswer: studentList.total - allAnswer.length,
|
|
- percentage: _.ceil(allAnswer.length / studentList.total, 4) * 100,
|
|
|
|
|
|
+ percentage: _.round(_.ceil(allAnswer.length / studentList.total, 4) * 100, 2),
|
|
};
|
|
};
|
|
this.$set(this, `questionAnswer`, answerDta);
|
|
this.$set(this, `questionAnswer`, answerDta);
|
|
|
|
+ this.toSetQuestModelList();
|
|
}
|
|
}
|
|
},
|
|
},
|
|
//获取图表分析部分
|
|
//获取图表分析部分
|
|
@@ -244,6 +271,63 @@ export default {
|
|
query: { termid: this.querys.termid, questionnaireid: this.querys.questionnaireid, classid: this.querys.classid },
|
|
query: { termid: this.querys.termid, questionnaireid: this.querys.questionnaireid, classid: this.querys.classid },
|
|
});
|
|
});
|
|
},
|
|
},
|
|
|
|
+
|
|
|
|
+ // 找到model
|
|
|
|
+ async toFindModel() {
|
|
|
|
+ // 学生字段
|
|
|
|
+ const res = await this.findModel('student');
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ const { data } = res;
|
|
|
|
+ if (!(data && _.isObject(data))) return;
|
|
|
|
+ const keys = Object.keys(data);
|
|
|
|
+ const arr = [];
|
|
|
|
+ for (const key of keys) {
|
|
|
|
+ const o = data[key];
|
|
|
|
+ const { zh } = o;
|
|
|
|
+ if (zh) {
|
|
|
|
+ const ao = { zh };
|
|
|
|
+ ao['model'] = key;
|
|
|
|
+ ao['table'] = 'student';
|
|
|
|
+ ao['tableZh'] = '学生信息';
|
|
|
|
+ arr.push(ao);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ this.$set(this, `modelList`, [...this.modelList, ...arr]);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 找到题目
|
|
|
|
+ toSetQuestModelList() {
|
|
|
|
+ const { question } = this.quest;
|
|
|
|
+ if (!(question && _.isArray(question))) return;
|
|
|
|
+ const arr = [];
|
|
|
|
+ for (const quest of question) {
|
|
|
|
+ const { topic, _id } = quest;
|
|
|
|
+ if (topic) {
|
|
|
|
+ arr.push({ zh: topic, table: 'questionnaire', _id, tableZh: '问卷题目' });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ this.$set(this, `modelList`, [...this.modelList, ...arr]);
|
|
|
|
+ },
|
|
|
|
+ // 导出
|
|
|
|
+ async toExportExcel(range) {
|
|
|
|
+ // 数据有: range=>要导出问卷的学生的范围;
|
|
|
|
+ // direction=>导出表头的方向;
|
|
|
|
+ // questionnaireid=>要导出的问卷id;
|
|
|
|
+ // selectModel=>选择的字段,不过需要特殊处理下,因为选择完是中文,需要将对应的object找出来,传给服务端,这样便于服务端聚合数据
|
|
|
|
+ const direction = _.cloneDeep(this.direction);
|
|
|
|
+ const questionnaireid = _.cloneDeep(this.querys.questionnaireid);
|
|
|
|
+ let sml = _.cloneDeep(this.selectModel);
|
|
|
|
+ const modelList = [];
|
|
|
|
+ for (const zh of sml) {
|
|
|
|
+ const res = this.modelList.find(f => _.isEqual(zh, f.zh));
|
|
|
|
+ if (res) modelList.push(res);
|
|
|
|
+ }
|
|
|
|
+ const data = { range, direction, questionnaireid, modelList };
|
|
|
|
+ const res = await this.export(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ window.open(res.data);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
...mapState(['user']),
|
|
...mapState(['user']),
|