QuestionImportDialog.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <template>
  2. <div>
  3. <el-dialog
  4. custom-class="side-dialog"
  5. :visible.sync="modalIsShow"
  6. title="试题导入"
  7. width="700px"
  8. :modal="false"
  9. :close-on-click-modal="false"
  10. :close-on-press-escape="false"
  11. append-to-body
  12. destroy-on-close
  13. @open="visibleChange"
  14. >
  15. <el-form
  16. ref="modalFormComp"
  17. :model="modalForm"
  18. :rules="rules"
  19. label-width="120px"
  20. >
  21. <el-form-item label="导入类型">
  22. <el-radio-group v-model="importType" @change="importTypeChange">
  23. <el-radio
  24. v-for="item in importTypeList"
  25. :key="item.name"
  26. :label="item.name"
  27. >{{ item.name }}</el-radio
  28. >
  29. </el-radio-group>
  30. </el-form-item>
  31. <el-form-item
  32. v-if="importType !== 'zip'"
  33. prop="courseId"
  34. label="课程名称"
  35. >
  36. <course-select v-model="modalForm.courseId" @change="courseChange">
  37. </course-select>
  38. </el-form-item>
  39. <el-form-item v-if="importType !== 'excel'" label="是否使用原卷">
  40. <el-radio-group v-model="modalForm.useOriginalPaper">
  41. <el-radio :label="true">是</el-radio>
  42. <el-radio :label="false">否</el-radio>
  43. </el-radio-group>
  44. </el-form-item>
  45. <el-form-item
  46. v-if="modalForm.useOriginalPaper && importType === 'word'"
  47. prop="name"
  48. label="试卷名称"
  49. >
  50. <el-input
  51. v-model="modalForm.name"
  52. placeholder="请输入试卷名称"
  53. clearable
  54. >
  55. </el-input>
  56. </el-form-item>
  57. <el-form-item v-if="modalForm.useOriginalPaper" label="总分校验">
  58. <el-radio-group v-model="modalForm.checkTotalScore">
  59. <el-radio :label="true">开启</el-radio>
  60. <el-radio :label="false">关闭</el-radio>
  61. </el-radio-group>
  62. </el-form-item>
  63. <el-form-item
  64. v-if="modalForm.checkTotalScore && modalForm.useOriginalPaper"
  65. label="试卷总分"
  66. prop="totalScore"
  67. >
  68. <el-input-number
  69. v-model="modalForm.totalScore"
  70. style="width: 125px"
  71. :min="1"
  72. :max="1000"
  73. :step="1"
  74. step-strictly
  75. :controls="false"
  76. ></el-input-number
  77. ></el-form-item>
  78. <el-form-item prop="file">
  79. <import-file
  80. ref="ImportFile"
  81. :format="importFileTypes"
  82. :template-url="templateUrl"
  83. only-fetch-file
  84. @file-change="fileChange"
  85. @confirm="confirm"
  86. ></import-file>
  87. </el-form-item>
  88. </el-form>
  89. <div slot="footer"></div>
  90. </el-dialog>
  91. <el-dialog
  92. :visible.sync="errorMsgModalIsShow"
  93. title="错误信息"
  94. :close-on-click-modal="false"
  95. :close-on-press-escape="false"
  96. append-to-body
  97. @closed="excelErrorMsgs = []"
  98. >
  99. <div>
  100. <p v-for="(cont, index) in excelErrorMsgs" :key="index">{{ cont }}</p>
  101. </div>
  102. </el-dialog>
  103. </div>
  104. </template>
  105. <script>
  106. import ImportFile from "@/components/ImportFile.vue";
  107. import {
  108. questionImportWordFileUpload,
  109. questionImportExcelFileUpload,
  110. importQuestionApi,
  111. } from "../api";
  112. import { QUESTION_API } from "@/constants/constants";
  113. import { mapState } from "vuex";
  114. const initModalForm = {
  115. courseId: null,
  116. courseName: null,
  117. name: "",
  118. checkTotalScore: false,
  119. useOriginalPaper: false,
  120. totalScore: 0,
  121. };
  122. export default {
  123. name: "QuestionImportDialog",
  124. components: { ImportFile },
  125. data() {
  126. return {
  127. modalIsShow: false,
  128. importTypeList: [
  129. {
  130. name: "word",
  131. format: ["docx", "doc"],
  132. },
  133. {
  134. name: "excel",
  135. format: ["xlsx", "xls"],
  136. },
  137. {
  138. name: "zip",
  139. format: ["zip"],
  140. },
  141. ],
  142. importType: "word",
  143. modalForm: {
  144. ...initModalForm,
  145. },
  146. rules: {
  147. courseId: [
  148. {
  149. required: true,
  150. message: "请选择课程",
  151. trigger: "change",
  152. },
  153. ],
  154. name: [
  155. {
  156. required: true,
  157. message: "请输入试卷名称",
  158. trigger: "change",
  159. },
  160. ],
  161. totalScore: [
  162. {
  163. required: true,
  164. message: "请输入试卷总分",
  165. trigger: "change",
  166. },
  167. ],
  168. file: [
  169. {
  170. validate: (rule, value, callback) => {
  171. if (!this.fileData.file) {
  172. return callback(new Error(`请输入选择文件`));
  173. }
  174. callback();
  175. },
  176. trigger: "change",
  177. },
  178. ],
  179. },
  180. fileData: {},
  181. templateUrl: "",
  182. errorMsgModalIsShow: false,
  183. excelErrorMsgs: [],
  184. loading: false,
  185. };
  186. },
  187. computed: {
  188. ...mapState({ user: (state) => state.user }),
  189. importFileTypes() {
  190. const types = this.importTypeList.find(
  191. (item) => item.name === this.importType
  192. );
  193. return types ? types.format : [];
  194. },
  195. },
  196. watch: {
  197. "modalForm.useOriginalPaper": {
  198. handler(val) {
  199. if (!val) {
  200. this.modalForm.name = "";
  201. this.modalForm.totalScore = 0;
  202. }
  203. },
  204. },
  205. "modalForm.checkTotalScore": {
  206. handler(val) {
  207. if (!val) {
  208. this.modalForm.totalScore = 0;
  209. }
  210. },
  211. },
  212. importType(val) {
  213. if (val === "zip") {
  214. this.modalForm.courseId = null;
  215. }
  216. },
  217. },
  218. methods: {
  219. visibleChange() {
  220. this.modalForm = { ...initModalForm };
  221. this.fileData = {};
  222. this.importTypeChange();
  223. },
  224. cancel() {
  225. this.modalIsShow = false;
  226. },
  227. open() {
  228. this.modalIsShow = true;
  229. },
  230. importTypeChange() {
  231. this.modalForm.checkTotalScore = false;
  232. this.modalForm.useOriginalPaper = false;
  233. const urlBody =
  234. this.importType === "excel"
  235. ? "word/parse/excel_template_download"
  236. : "import/paper/template";
  237. this.templateUrl = `${QUESTION_API}/${urlBody}?$key=${this.user.key}&$token=${this.user.token}`;
  238. },
  239. fileChange(fileData) {
  240. this.fileData = fileData;
  241. this.$refs.modalFormComp.validateField("file", (err) => {
  242. console.log(err);
  243. });
  244. },
  245. courseChange(val) {
  246. this.modalForm.courseName = val ? val.name : "";
  247. },
  248. async confirm() {
  249. const valid = await this.$refs.modalFormComp.validate().catch(() => {});
  250. if (!valid) return;
  251. if (this.loading) return;
  252. this.loading = true;
  253. this.$refs.ImportFile.setLoading(true);
  254. let formData = new FormData();
  255. formData.append("file", this.fileData.file);
  256. if (this.importType !== "zip") {
  257. formData.append("courseId", this.modalForm.courseId);
  258. } else {
  259. Object.entries(this.modalForm).forEach(([key, val]) => {
  260. if (val !== null) formData.append(key, val);
  261. });
  262. }
  263. const uploadApi =
  264. this.importType === "zip"
  265. ? importQuestionApi
  266. : this.importType === "word"
  267. ? questionImportWordFileUpload
  268. : questionImportExcelFileUpload;
  269. const res = await uploadApi(formData, {
  270. md5: this.fileData.md5,
  271. }).catch((error) => {
  272. if (error.response?.data.desc) {
  273. this.errorMsgModalIsShow = true;
  274. this.excelErrorMsgs = error.response.data.desc.split("\n");
  275. if (
  276. this.excelErrorMsgs.some(
  277. (item) =>
  278. item.includes("no login") || item.includes("token is wrong")
  279. )
  280. ) {
  281. this.excelErrorMsgs = ["登陆失效,请重新登录!"];
  282. }
  283. }
  284. });
  285. this.loading = false;
  286. this.$refs.ImportFile.setLoading(false);
  287. if (!res) return;
  288. // this.$message.success("导入成功!");
  289. this.$emit("modified", {
  290. ...res.data,
  291. importData: this.modalForm,
  292. importType: this.importType,
  293. importFileTypes: this.importFileTypes,
  294. });
  295. this.cancel();
  296. },
  297. },
  298. };
  299. </script>