detail.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <template>
  2. <div id="detail">
  3. <el-row>
  4. <el-col :span="24" class="main">
  5. <div class="w_1200">
  6. <el-col :span="24" class="one">
  7. <el-row>
  8. <el-col :span="24" class="info">
  9. <el-col :span="24" class="title">
  10. {{ question.title }}
  11. </el-col>
  12. <el-col :span="24" class="brief">
  13. {{ question.brief }}
  14. </el-col>
  15. </el-col>
  16. <el-col :span="24" class="form">
  17. <el-form :model="answer" label-position="top" ref="form">
  18. <el-form-item v-if="!user || !user.id" label="您是否注册成为平台用户">
  19. <el-radio-group v-model="userForm.user">
  20. <el-radio :label="true">是</el-radio>
  21. <el-radio :label="false">否</el-radio>
  22. </el-radio-group>
  23. </el-form-item>
  24. <el-form-item v-if="userForm.user" label="手机号">
  25. <el-input v-model="userForm.phone" placeholder="请填写手机号"></el-input>
  26. </el-form-item>
  27. <!-- 0单选,1多选,2简答 -->
  28. <template v-for="(i, index) in question.questions">
  29. <el-form-item
  30. v-if="i.type === '0'"
  31. :prop="`${index}`"
  32. :key="`question${index}`"
  33. :label="`${index + 1}.${i.title}`"
  34. :rules="[{ required: true, message: '请选择一个选项', trigger: 'blur' }]"
  35. >
  36. <el-radio-group v-model="answer[index]" :disabled="disabled">
  37. <el-radio v-for="(s, si) in i.selects" :key="`s_${index}_${si}`" :label="s.name">{{ s.num }}.{{ s.name }}</el-radio>
  38. </el-radio-group>
  39. </el-form-item>
  40. <el-form-item
  41. v-else-if="i.type === '1'"
  42. :prop="`${index}`"
  43. :key="`question${index}`"
  44. :label="`${index + 1}.${i.title}`"
  45. :rules="[{ required: true, message: '请至少选择一个选项', trigger: 'blur' }]"
  46. >
  47. <el-checkbox-group :value="answer[index]" @input="data => toCheck(data, index)" :disabled="disabled">
  48. <el-checkbox v-for="(s, si) in i.selects" :key="`c_${index}_${si}`" :label="s.name">{{ s.num }}.{{ s.name }}</el-checkbox>
  49. </el-checkbox-group>
  50. </el-form-item>
  51. <el-form-item v-else :key="`question${index}`" :label="`${index + 1}.${i.title}`">
  52. <el-input v-model="answer[index]" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" :readonly="disabled"></el-input>
  53. </el-form-item>
  54. </template>
  55. </el-form>
  56. </el-col>
  57. <el-col :span="24" style="text-align:center">
  58. <el-button type="primary" @click="toSubmit" v-if="!disabled">提交</el-button>
  59. </el-col>
  60. </el-row>
  61. </el-col>
  62. </div>
  63. </el-col>
  64. </el-row>
  65. </div>
  66. </template>
  67. <script>
  68. import { mapState, createNamespacedHelpers } from 'vuex';
  69. const { mapActions: questionnaire } = createNamespacedHelpers('questionnaire');
  70. const { mapActions: answer } = createNamespacedHelpers('answer');
  71. export default {
  72. name: 'detail',
  73. props: {},
  74. components: {},
  75. data: function() {
  76. return {
  77. question: {},
  78. answer: {},
  79. disabled: false,
  80. userForm: {},
  81. };
  82. },
  83. created() {
  84. this.search();
  85. },
  86. methods: {
  87. ...questionnaire(['fetch']),
  88. ...answer(['create', 'findAnswer']),
  89. async search() {
  90. const res = await this.fetch(this.id);
  91. if (this.$checkRes(res)) {
  92. const { questions } = res.data;
  93. for (let i = 0; i < questions.length; i++) {
  94. const e = questions[i];
  95. const { select, type } = e;
  96. if (type === '1') {
  97. this.answer[i] = [];
  98. }
  99. }
  100. this.$set(this, `question`, res.data);
  101. }
  102. this.getAnswer();
  103. },
  104. async getAnswer() {
  105. if (!this.user || !this.user.id) return;
  106. const res = await this.findAnswer({ user_id: this.user.id, questionnaire_id: this.id });
  107. if (this.$checkRes(res)) {
  108. if (res.data) {
  109. this.disabled = true;
  110. // 还原数据
  111. const { answer } = res.data;
  112. const questions = this.question.questions;
  113. const reply = {};
  114. for (const i of answer) {
  115. const { answer: a, quest } = i;
  116. const r = questions.findIndex(f => f.title === quest);
  117. if (r > -1) reply[r] = a;
  118. }
  119. this.$set(this, 'answer', reply);
  120. }
  121. }
  122. },
  123. // 因为层级过深(只要不是在this下,就属于过深),所以需要手动更新视图
  124. toCheck(data, model) {
  125. this.answer[model] = data;
  126. this.$forceUpdate();
  127. },
  128. async toSubmit() {
  129. this.$refs.form.validate(valid => {
  130. if (valid) {
  131. this.submit();
  132. } else {
  133. console.log('error submit!!');
  134. return false;
  135. }
  136. });
  137. },
  138. async submit() {
  139. let dup = _.cloneDeep(this.answer);
  140. const keys = Object.keys(dup);
  141. const questions = this.question.questions;
  142. const answer = [];
  143. for (const i of keys) {
  144. const a = dup[i];
  145. const quest = questions[i];
  146. if (a && quest) {
  147. const obj = { answer: a, quest: quest.title };
  148. answer.push(obj);
  149. }
  150. }
  151. const data = {
  152. questionnaire_id: this.id,
  153. answer,
  154. };
  155. if (this.user && this.user.id) {
  156. data.user_id = this.user.id;
  157. } else {
  158. const userForm = this.userForm;
  159. if (userForm.user) data.phone = userForm.phone;
  160. }
  161. const res = await this.create(data);
  162. if (this.$checkRes(res, '提交成功', '提交失败')) {
  163. // 返回列表
  164. this.$router.push('/questionnaire/index');
  165. }
  166. },
  167. },
  168. computed: {
  169. ...mapState(['user', 'menuParams']),
  170. pageTitle() {
  171. return `${this.$route.meta.title}`;
  172. },
  173. id() {
  174. return this.$route.query.id;
  175. },
  176. },
  177. metaInfo() {
  178. return { title: this.$route.meta.title };
  179. },
  180. };
  181. </script>
  182. <style lang="less" scoped>
  183. .main {
  184. padding: 15px 0;
  185. .one {
  186. margin: 0 0 10px 0;
  187. .info {
  188. border-bottom: 1px dashed #ccc;
  189. padding: 0 20px;
  190. .title {
  191. font-size: 30px;
  192. font-weight: bold;
  193. margin: 20px 0;
  194. text-align: center;
  195. }
  196. .brief {
  197. font-size: 16px;
  198. padding: 0 0 20px 0;
  199. }
  200. }
  201. .form {
  202. padding: 20px 0;
  203. /deep/.el-form-item {
  204. margin-bottom: 5px;
  205. }
  206. /deep/.el-form-item__label {
  207. padding: 0 0;
  208. font-weight: bold;
  209. color: #000;
  210. font-size: 16px;
  211. }
  212. }
  213. }
  214. }
  215. </style>