lrf402788946 4 years ago
parent
commit
5256c21850

+ 14 - 0
src/router/index.js

@@ -193,6 +193,20 @@ const live = [
         component: () => import('../views/userCenter/index.vue'),
       },
       ...admin,
+      // 问卷调查
+      {
+        path: '/questionnaire/index',
+        name: 'questionnaire',
+        meta: { title: '问卷调查' },
+        component: () => import('../views/questionnaire/index.vue'),
+      },
+      // 答问卷调查
+      {
+        path: '/questionnaire/answer',
+        name: 'questionnaire',
+        meta: { title: '完成问卷调查' },
+        component: () => import('../views/questionnaire/detail.vue'),
+      },
     ],
   },
 ];

+ 5 - 0
src/store/index.js

@@ -51,6 +51,9 @@ import personChat from '@common/src/store/person_chat';
 import category from '@common/src/store/category';
 import code from '@common/src/store/code';
 import place from '@common/src/store/place';
+// 问卷调查
+import questionnaire from '@common/src/store/question/questionnaire';
+import answer from '@common/src/store/question/answer';
 Vue.use(Vuex);
 
 export default new Vuex.Store({
@@ -86,5 +89,7 @@ export default new Vuex.Store({
     personRoom,
     personChat,
     dockChat,
+    questionnaire,
+    answer,
   },
 });

+ 168 - 0
src/views/questionnaire/detail.vue

@@ -0,0 +1,168 @@
+<template>
+  <div id="detail">
+    <el-row>
+      <el-col :span="24" class="main">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <el-row>
+              <el-col :span="24">{{ question.title }}</el-col>
+              <el-form :model="answer" label-position="top" ref="form">
+                <!-- 0单选,1多选,2简答 -->
+                <template v-for="(i, index) in question.questions">
+                  <el-form-item
+                    v-if="i.type === '0'"
+                    :prop="`${index}`"
+                    :key="`question${index}`"
+                    :label="`${index + 1}.${i.name}`"
+                    :rules="[{ required: true, message: '请选择一个选项', trigger: 'blur' }]"
+                  >
+                    <el-radio-group v-model="answer[index]" :disabled="disabled">
+                      <el-radio v-for="(s, si) in i.select" :key="`s_${index}_${si}`" :label="s.name">{{ s.num }}.{{ s.name }}</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item
+                    v-else-if="i.type === '1'"
+                    :prop="`${index}`"
+                    :key="`question${index}`"
+                    :label="`${index + 1}.${i.name}`"
+                    :rules="[{ required: true, message: '请至少选择一个选项', trigger: 'blur' }]"
+                  >
+                    <el-checkbox-group :value="answer[index]" @input="data => toCheck(data, index)" :disabled="disabled">
+                      <el-checkbox v-for="(s, si) in i.select" :key="`c_${index}_${si}`" :label="s.name">{{ s.num }}.{{ s.name }}</el-checkbox>
+                    </el-checkbox-group>
+                  </el-form-item>
+                  <el-form-item v-else :key="`question${index}`" :label="`${index + 1}.${i.name}`">
+                    <el-input v-model="answer[index]" type="textarea" :autosize="{ minRows: 3, maxRows: 5 }" :readonly="disabled"></el-input>
+                  </el-form-item>
+                </template>
+              </el-form>
+              <el-col :span="24" style="text-align:center">
+                <el-button type="primary" @click="toSubmit" v-if="!disabled">提交</el-button>
+              </el-col>
+            </el-row>
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: questionnaire } = createNamespacedHelpers('questionnaire');
+const { mapActions: answer } = createNamespacedHelpers('answer');
+export default {
+  name: 'detail',
+  props: {},
+  components: {},
+  data: function() {
+    return {
+      question: {},
+      answer: {},
+      test: [],
+      disabled: false,
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...questionnaire(['fetch']),
+    ...answer(['create', 'findAnswer']),
+    async search() {
+      const res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        const { questions } = res.data;
+        for (let i = 0; i < questions.length; i++) {
+          const e = questions[i];
+          const { select, type } = e;
+          if (type === '1') {
+            this.answer[i] = [];
+          }
+        }
+        this.$set(this, `question`, res.data);
+      }
+      this.getAnswer();
+    },
+    async getAnswer() {
+      if (!this.user.id) return;
+      const res = await this.findAnswer({ user_id: this.user.id, questionnaire_id: this.id });
+      if (this.$checkRes(res)) {
+        if (res.data) {
+          this.disabled = true;
+          // TODO还原数据
+          const { answer } = res.data;
+          const questions = this.question.questions;
+          const reply = {};
+          for (const i of answer) {
+            const { answer: a, quest } = i;
+            const r = questions.findIndex(f => f.name === quest);
+            if (r > -1) reply[r] = a;
+          }
+          this.$set(this, 'answer', reply);
+        }
+      }
+    },
+    // 因为层级过深(只要不是在this下,就属于过深),所以需要手动更新视图
+    toCheck(data, model) {
+      this.answer[model] = data;
+      this.$forceUpdate();
+    },
+    async toSubmit() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.submit();
+        } else {
+          console.log('error submit!!');
+          return false;
+        }
+      });
+    },
+    async submit() {
+      let dup = _.cloneDeep(this.answer);
+      const keys = Object.keys(dup);
+      const questions = this.question.questions;
+      const answer = [];
+      for (const i of keys) {
+        const a = dup[i];
+        const quest = questions[i];
+        if (a && quest) {
+          const obj = { answer: a, quest: quest.name };
+          answer.push(obj);
+        }
+      }
+      const data = {
+        questionnaire_id: this.id,
+        answer,
+        user_id: this.user.id,
+      };
+      const res = await this.create(data);
+      if (this.$checkRes(res, '提交成功', '提交失败')) {
+        // 返回列表
+        this.$router.push('/questionnaire/index');
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user', 'menuParams']),
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 15px 0;
+  .one {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 74 - 0
src/views/questionnaire/index.vue

@@ -0,0 +1,74 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <list-page title="问卷调查" :useSearch="false" :total="total" @toSearch="search" :pageSize="pageSize">
+              <div v-for="(i, index) in list" :key="`q${index}`" style="padding:5px" @click="toAnswer(i)">
+                <el-row>
+                  <el-col :span="24">{{ i.title }}</el-col>
+                  <el-col :span="24">{{ i.brief }}</el-col>
+                  <el-col :span="24">{{ i.create_time }}</el-col>
+                </el-row>
+              </div>
+            </list-page>
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import listPage from '@c/list/list-page.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: questionnaire } = createNamespacedHelpers('questionnaire');
+export default {
+  name: 'index',
+  props: {},
+  components: { listPage },
+  data: function() {
+    return {
+      list: [],
+      total: 0,
+      pageSize: 1,
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...questionnaire(['query']),
+    async search({ skip = 0, limit = 10 } = {}) {
+      const res = await this.query({ skip, limit });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+
+    async toAnswer(data) {
+      this.$router.push({ path: '/questionnaire/answer', query: { id: data._id } });
+    },
+  },
+  compute2ad: {
+    ...mapState(['user', 'menuParams']),
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 15px 0;
+  .one {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 4 - 1
src/views/techolchat/index.vue

@@ -147,7 +147,10 @@ export default {
       } else if (data.title == '在线咨询') {
         this.zxzxdialog = true;
       } else if (data.title == '网上调查') {
-        this.wsdcdialog = true;
+        // this.wsdcdialog = true;
+        // TODO跳转至问卷列表页
+        if (this.user && this.user.id) this.$router.push('/questionnaire/index');
+        else this.$message({ type: 'danger', message: '请登录后填写调查问卷!' });
       } else if (data.title == '举报邮箱') {
         this.jbyxdialog = true;
       }

+ 5 - 0
vue.config.js

@@ -32,6 +32,11 @@ module.exports = {
       '/files': {
         target: 'http://broadcast.waityou24.cn',
       },
+      '/api/question': {
+        target: 'http://127.0.0.1:9104', //http://192.168.1.19:9101
+        changeOrigin: true,
+        ws: false,
+      },
       '/api': {
         target: 'http://broadcast.waityou24.cn', //http://192.168.1.19:9101
         changeOrigin: true,