CreatePaper.vue 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393
  1. <template>
  2. <div class="create-evaluation-container">
  3. <div class="create-header">
  4. <p class="create-header-title">
  5. {{ isEditPaper ? $t('evaluation.paperList.editPaper') : evaluationInfo.createType === 'auto' ? $t('evaluation.index.autoCreate') : evaluationInfo.createType === 'import' ? $t('evaluation.index.importCreate') : $t('evaluation.index.manualCreate') }}
  6. </p>
  7. <div style="float: right;" class="common-save-btn">
  8. <Button class="btn-save" type="text" icon="md-arrow-round-back"
  9. @click="goBack">{{$t('evaluation.paperList.backToBank')}}</Button>
  10. <Button class="btn-save" type="text" icon="md-folder" :loading="isLoading"
  11. @click="saveTestPaper">{{ isLoading ? $t('evaluation.paperList.isSaving') : $t('evaluation.paperList.savePaper')}}</Button>
  12. </div>
  13. </div>
  14. <div class="create-body dark-iview-split">
  15. <Split v-model="split1">
  16. <div slot="left" class="demo-split-pane">
  17. <div class="evaluation-attr-wrap">
  18. <p class="wrap-label">{{$t('evaluation.paperList.baseInfo')}}</p>
  19. <div style="width:100%; height:calc(100% - 45px);padding-top:30px;">
  20. <Form ref="evaluationInfo" :model="evaluationInfo" label-position="top"
  21. class="evaluation-attr-form" label-colon>
  22. <FormItem :label="$t('evaluation.paperList.paperType')" prop="type">
  23. <Select v-model="evaluationInfo.type" disabled>
  24. <Option value="private">{{$t('evaluation.paperList.praviteBank')}}</Option>
  25. <Option value="school">{{$t('evaluation.paperList.schoolBank')}}</Option>
  26. </Select>
  27. </FormItem>
  28. <FormItem :label="$t('evaluation.paperList.paperName')" prop="name">
  29. <Input v-model="evaluationInfo.name"></Input>
  30. </FormItem>
  31. <FormItem :label="$t('evaluation.newExercise.choosePeriod')" prop="paperPeriod"
  32. v-if="isSchool">
  33. <Select v-model="evaluationInfo.paperPeriod" @on-change="onPeriodChange">
  34. <Option v-for="(period,index) in schoolInfo.period" :value="index" :key="index">
  35. {{ period.name }}</Option>
  36. </Select>
  37. </FormItem>
  38. <FormItem :label="$t('evaluation.newExercise.chooseGrade')" prop="publish"
  39. v-if="isSchool">
  40. <Select v-model="evaluationInfo.paperGrade" multiple
  41. :placeholder="$t('evaluation.newExercise.gradePlaceholder')">
  42. <Option v-for="(grade,index) in gradeList" :value="index" :key="grade">
  43. {{ grade }}</Option>
  44. </Select>
  45. </FormItem>
  46. <FormItem :label="$t('evaluation.newExercise.chooseSubject')" class="dark-iview-select"
  47. v-if="isSchool">
  48. <Select v-model="evaluationInfo.paperSubject">
  49. <Option v-for="(subject,index) in subjectList" :value="index" :key="index">
  50. {{ subject.name }}</Option>
  51. </Select>
  52. </FormItem>
  53. <FormItem :label="$t('evaluation.paperList.paperScore')" prop="name"
  54. class="evaluation-attr-wrap-inputNumber">
  55. <InputNumber :max="200" :min="1" v-model="evaluationInfo.score"></InputNumber>
  56. </FormItem>
  57. </Form>
  58. </div>
  59. </div>
  60. </div>
  61. <div slot="right" class="demo-split-pane">
  62. <div class="evaluation-question-wrap">
  63. <div class="evaluation-question-main">
  64. <!-- <div class="create-type-wrap" v-show="!isEditPaper">
  65. <span>创建方式:</span>
  66. <RadioGroup v-model="evaluationInfo.createType" style="margin-left:15px;" @on-change="setActiveTab">
  67. <Radio label="auto" v-if="!isEditPaper">自动组题</Radio>
  68. <Radio label="manual">手动挑题</Radio>
  69. <Radio label="import" v-if="!isEditPaper">试题导入</Radio>
  70. </RadioGroup>
  71. </div> -->
  72. <p class="save-tips">*
  73. {{ viewModel === 'list' ? $t('evaluation.paperList.saveRule2') : $t('evaluation.paperList.saveRule2') }}
  74. </p>
  75. <Tabs v-model="activeTab" type="card" class="question-main-tabs" name="createTest">
  76. <TabPane :label="$t('evaluation.paperList.tab1')" name="auto"
  77. v-if="evaluationInfo.createType == 'auto'" :index="1" tab="createTest">
  78. <AutoCreate :subject="propSubject" :period="propPeriod" @goToPreview="goToPreview"
  79. @autoQuestions="getAutoQuestions"></AutoCreate>
  80. </TabPane>
  81. <TabPane :label="$t('evaluation.paperList.tab2')" name="manual"
  82. v-if="evaluationInfo.createType == 'manual'" :index="2" tab="createTest">
  83. <ManualCreate :questionList="questionList" :subjectCode="propSubject"
  84. :periodCode="propPeriod" :selQue="evaluationInfo.item"
  85. @goToPreview="goToPreview" @selectedQuestion="getSelectedQuestion">
  86. </ManualCreate>
  87. </TabPane>
  88. <TabPane
  89. :label="evaluationInfo.item.length ? $t('evaluation.paperList.tab3') : $t('evaluation.paperList.tab4')"
  90. name="import" v-if="evaluationInfo.createType == 'import'" :index="3"
  91. tab="createTest">
  92. <BaseImport @importFinish="onImportFinish"></BaseImport>
  93. </TabPane>
  94. <TabPane :label="$t('evaluation.paperList.tab5')" name="preview" :index="4"
  95. tab="createTest">
  96. <vuescroll ref="paperRef" @handle-scroll="handleScroll">
  97. <TestPaper v-if="!examAnalysisStatus" :paper="evaluationInfo"
  98. :class="examAnalysisStatus ? '':'animated fadeIn'" ref="testPaper"
  99. @onViewModelChange="onViewModelChange"></TestPaper>
  100. </vuescroll>
  101. </TabPane>
  102. <!-- <TabPane :label="$t('evaluation.paperList.tab6')" name="student" :index="5"
  103. tab="createTest">
  104. <StudentPreview></StudentPreview>
  105. </TabPane> -->
  106. </Tabs>
  107. </div>
  108. </div>
  109. </div>
  110. </Split>
  111. </div>
  112. </div>
  113. </template>
  114. <script>
  115. import blobTool from '@/utils/blobTool.js'
  116. import AutoCreate from '@/view/learnactivity/AutoCreateNew.vue'
  117. import ManualCreate from '@/view/learnactivity/ManualCreate.vue'
  118. import StudentPreview from '@/view/learnactivity/StudentPreview.vue'
  119. import BaseImport from '../components/BaseImport.vue'
  120. import TestPaper from './TestPaper.vue'
  121. export default {
  122. components: {
  123. AutoCreate,
  124. ManualCreate,
  125. StudentPreview,
  126. TestPaper,
  127. BaseImport
  128. },
  129. data() {
  130. return {
  131. split1: 0.2,
  132. isLoading: false,
  133. isEditPaper: false,
  134. viewModel: 'type',
  135. examAnalysisStatus: false,
  136. comfirmPreviewStatus: false,
  137. goToManageStatus: false,
  138. examInfo: {},
  139. editPaper: null,
  140. schoolInfo: {},
  141. paperPeriod: 0,
  142. paperGrade: [],
  143. paperSubject: 0,
  144. periodList: [],
  145. gradeList: [],
  146. subjectList: [],
  147. deleteIndex: -1,
  148. testSubjects: [],
  149. activeTab: 'auto',
  150. addSubjectStatus: false,
  151. addSubjectBefore: [],
  152. newAddSubjects: [],
  153. questionList: [],
  154. currentSubjectIndex: 0,
  155. evaluationInfo: {
  156. name: this.$t('evaluation.paperList.defaultName'),
  157. target: [],
  158. type: 'private',
  159. scope: 'private',
  160. publish: '',
  161. paperPeriod: 0,
  162. paperGrade: [],
  163. paperSubject: 0,
  164. score: 100,
  165. item: [],
  166. startTime: 0,
  167. endTime: 0,
  168. createType: 'auto'
  169. },
  170. errorList: [],
  171. noAnswerList: [],
  172. oldPaper:null
  173. }
  174. },
  175. async created() {
  176. /* 查询当前是否有保存的组卷方式,如果已经保存则直接读取,优先读取传过来的参数 */
  177. let curCreateType = localStorage.getItem('curCreateType')
  178. this.evaluationInfo.createType = this.$route.params.type || curCreateType || 'auto'
  179. this.setActiveTab(this.evaluationInfo.createType)
  180. localStorage.setItem('curCreateType', this.evaluationInfo.createType)
  181. this.evaluationInfo.type = this.$route.name === 'newSchoolPaper' ? 'school' : 'private'
  182. this.evaluationInfo.scope = this.evaluationInfo.type
  183. this.getSchoolBaseInfo().then(res => {
  184. if (!res) return
  185. this.schoolInfo = res
  186. this.onPeriodChange(0)
  187. })
  188. },
  189. methods: {
  190. /**
  191. * 学段切换
  192. * @param val
  193. */
  194. onPeriodChange(val) {
  195. this.gradeList = this.schoolInfo.period[val].grades
  196. this.subjectList = this.schoolInfo.period[val].subjects
  197. this.evaluationInfo.paperGrade = []
  198. this.paperGrade = 0
  199. this.evaluationInfo.paperSubject = 0
  200. this.paperSubject = 0
  201. },
  202. /* 返回试卷库 */
  203. goBack() {
  204. this.$router.push({
  205. name: this.isSchool ? 'schoolBank' : 'personalBank',
  206. params: {
  207. tabName: 'paper'
  208. }
  209. })
  210. },
  211. /* 返回顶部 */
  212. handleBackToTop() {
  213. this.$nextTick(() => {
  214. if (this.$refs.paperRef) {
  215. this.$refs['paperRef'].scrollTo({
  216. y: '0'
  217. },
  218. 500
  219. )
  220. }
  221. })
  222. },
  223. onViewModelChange(val) {
  224. this.viewModel = val
  225. },
  226. // 判断容器滚动距离
  227. handleScroll(vertical, horizontal, nativeEvent) {
  228. this.$store.commit('updatePaperScroll', vertical.scrollTop)
  229. },
  230. /**
  231. * 导入试题结束
  232. * @param list
  233. */
  234. async onImportFinish(list) {
  235. this.errorList = []
  236. this.$refs.testPaper.$refs.exList.errorList = []
  237. this.evaluationInfo.item = []
  238. try {
  239. let importList = await this.refreshImportItems(list)
  240. this.evaluationInfo.item = importList
  241. this.activeTab = 'preview'
  242. this.$Message.success(this.$t('evaluation.importFile.warningTips3'))
  243. console.log(this.evaluationInfo)
  244. if (this.errorList.length) {
  245. this.$EventBus.$emit('importFinish', this.errorList)
  246. }
  247. } catch (e) {
  248. this.$Message.error(this.$t('evaluation.importFile.warningTips5'))
  249. }
  250. },
  251. /* 给导入的试题 补充最新的试卷学段年级以及科目信息 */
  252. refreshImportItems(list) {
  253. return new Promise((r, reject) => {
  254. let objectiveTypes = ['single', 'multiple']
  255. let code = this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo
  256. .TEAMModelId
  257. let gradeIds = this.isSchool ? (this.evaluationInfo.paperGrade.length ? this.evaluationInfo
  258. .paperGrade.map(i => i+'') : this.gradeList.map((i,index) => index+'')) : []
  259. let subjectId = this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].id : null
  260. let periodId = this.isSchool ? this.schoolInfo.period[this.evaluationInfo.paperPeriod].id : null
  261. for (let j = 0; j < list.length; j++) {
  262. let i = list[j]
  263. if (i.blob && i.id) {
  264. continue;
  265. }
  266. /* 如果是导入的试题 没有ID 则试题的信息和当前试卷的学段信息保持一致 */
  267. i.id = i.id || this.$tools.guid()
  268. i.code = code
  269. i.level = i.level || 3
  270. i.field = i.field || 1
  271. i.scope = this.isSchool ? 'school' : 'private'
  272. i.gradeIds = gradeIds
  273. i.subjectId = subjectId
  274. i.periodId = periodId
  275. if (i.children.length) {
  276. i.children.forEach(j => {
  277. if (this.isItemComplete(j)) {
  278. this.errorList.push(j)
  279. }
  280. j.id = j.id || this.$tools.guid()
  281. j.pid = i.id
  282. j.scope = i.scope
  283. j.code = code
  284. j.level = j.level || 3
  285. j.field = j.field || 1
  286. j.gradeIds = gradeIds
  287. j.subjectId = subjectId
  288. j.periodId = periodId
  289. })
  290. }
  291. // 如果导入的是客观题 则需要检测答案与选项是否为空
  292. if (this.isItemComplete(i)) {
  293. this.errorList.push(i)
  294. }
  295. }
  296. r(list)
  297. })
  298. },
  299. /* 检查导入的试题是否规范,否则提示错误 */
  300. isItemComplete(i){
  301. let objectiveTypes = ['single', 'multiple', 'judge']
  302. return objectiveTypes.includes(i.type) && (!i.option || !i.answer || i.option.length < 2 || !i.answer.length)
  303. },
  304. /**
  305. * 获取自动组题数据
  306. * @param questions
  307. */
  308. async getAutoQuestions(questions) {
  309. try{
  310. let autoQuestions = await this.$evTools.getFullItem(questions)
  311. let arr = autoQuestions
  312. // 拿到题目后 根据试卷总分给所有题目进行平均分配
  313. let scoreArr = this.averageTotalScore(this.evaluationInfo.score, arr.length)
  314. arr.forEach((i, index) => {
  315. i.score = scoreArr[index] || 0
  316. // 如果是综合题 则需要进行子题的分数平均分配
  317. if(i.type === 'compose' && i.children.length){
  318. let childrenScoreArr = this.averageTotalScore(i.score, i.children.length)
  319. i.children.forEach((child,childIndex) => {
  320. child.score = childrenScoreArr[childIndex]
  321. })
  322. }
  323. })
  324. this.evaluationInfo.item = []
  325. this.evaluationInfo.item = this.evaluationInfo.item.concat([...autoQuestions])
  326. this.activeTab = 'preview'
  327. }catch(e){
  328. this.$Message.error(e)
  329. }
  330. },
  331. /**
  332. * 获取手动组题的数据
  333. * @param data
  334. */
  335. getSelectedQuestion(data) {
  336. console.log(data)
  337. let arr = data.questions
  338. // 如果是编辑试卷 则往原试卷添加不包含的新题目进入
  339. if (this.isEditPaper) {
  340. let list = this.evaluationInfo.item
  341. arr.forEach(i => {
  342. if (list.map(j => j.id).indexOf(i.id) < 0) {
  343. list.push(i)
  344. }
  345. })
  346. } else {
  347. // 拿到题目后 根据试卷总分给所有题目进行平均分配
  348. let scoreArr = this.$tools.doAverage(this.evaluationInfo.score, arr.length, 0.5)
  349. arr.forEach((i, index) => {
  350. i.score = scoreArr[index] || 0
  351. // 如果是综合题 则需要进行子题的分数平均分配
  352. if(i.type === 'compose' && i.children.length){
  353. let childrenScoreArr = this.$tools.doAverage(i.score, i.children.length, 0.5)
  354. i.children.forEach((child,childIndex) => {
  355. child.score = childrenScoreArr[childIndex]
  356. })
  357. }
  358. })
  359. this.evaluationInfo.item = arr
  360. }
  361. },
  362. /* 根据总分给出固定长度的平均分配数组 */
  363. averageTotalScore(total, length) {
  364. let result = new Array(length).fill(0)
  365. // 先判断是否总分除以题目数量能否除尽
  366. let remainder = total % length
  367. // 如果可以整除 则直接计算
  368. if (remainder === 0) {
  369. result = result.map(i => total / length)
  370. } else {
  371. // 如果不能整除 则前面所有取整 最后一题加上余数 即可完成配分
  372. let integerScore = parseInt(total / length)
  373. result = result.map((i,index) => {
  374. return index + 1 > remainder ? integerScore : integerScore + 1
  375. })
  376. }
  377. return result
  378. },
  379. /** 预览试卷 */
  380. goToPreview() {
  381. this.activeTab = 'preview'
  382. },
  383. /**
  384. * 设置当前组题方式
  385. * @param data
  386. */
  387. setActiveTab(data) {
  388. if (this.evaluationInfo.item.length) {
  389. this.$Modal.confirm({
  390. title: '温馨提示',
  391. content: '<p>切换组题方式会清空当前所选试题,是否继续?</p>',
  392. onOk: () => {
  393. this.evaluationInfo.item = []
  394. this.$refs.testPaper.$refs.exList.errorList = []
  395. this.$refs.testPaper.$refs.exList.noAnswerList = []
  396. this.$EventBus.$emit('onPaperItemChange', [])
  397. this.activeTab = data
  398. },
  399. onCancel: () => {
  400. }
  401. })
  402. } else {
  403. this.activeTab = data
  404. }
  405. },
  406. /** 获取当前学校基础数据 */
  407. getSchoolBaseInfo() {
  408. return new Promise((r, j) => {
  409. this.$store.dispatch("user/getSchoolProfile").then((res) => {
  410. let schoolBaseInfo = res.school_base;
  411. if (schoolBaseInfo) {
  412. r(schoolBaseInfo)
  413. } else {
  414. r(null)
  415. }
  416. });
  417. })
  418. },
  419. /* 将list中的试题 保存到Cosmos以及Blob中 */
  420. async savePaperItems(list, modifyItems, isEdit) {
  421. let that = this
  422. console.log('保存的试题列表')
  423. console.log(list)
  424. let containerName = this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo
  425. .TEAMModelId
  426. /* 上传前进行试卷blob查询size */
  427. // let prefixArr = this.getListPrefixs(list)
  428. // let beforeSize = await blobTool.checkPrefixSize(prefixArr, containerName)
  429. // console.log('试题上传前的size', beforeSize)
  430. // return
  431. // 获取初始化Blob需要的数据
  432. let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
  433. let itemJsonFiles = []
  434. let blobFiles = []
  435. //初始化Blob
  436. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.evaluationInfo.type)
  437. return new Promise(async (resolve, j) => {
  438. let promiseArr = []
  439. for (let i = 0; i < list.length; i++) {
  440. let exerciseItem = list[i]
  441. console.log(exerciseItem)
  442. // 如果是编辑试卷状态 或者 从题目是来自题库
  443. if (isEdit || exerciseItem.blob) {
  444. if (exerciseItem.children.length) {
  445. // 如果是编辑状态下的综合题
  446. let composeArr = [exerciseItem, ...exerciseItem.children]
  447. composeArr.forEach(composeItem => {
  448. promiseArr.push(new Promise(async (r, j) => {
  449. if (composeItem.children.length &&
  450. composeItem.children[0].id) {
  451. composeItem.children = composeItem
  452. .children.map(i => i.id)
  453. }
  454. // 保存试题的blob链接
  455. const itemJsonFile = await this.$evTools
  456. .createBlobItem(composeItem)
  457. let file = new File([JSON.stringify(
  458. itemJsonFile)], composeItem
  459. .id + ".json");
  460. blobFiles.push(file)
  461. itemJsonFiles.push(composeItem)
  462. r({
  463. cosmosItem: composeItem,
  464. blobItem: itemJsonFile
  465. })
  466. console.log(composeItem)
  467. }))
  468. })
  469. } else {
  470. // 如果已有blob字段 说明是已经保存到blob的试题 只需要将最新试题更新到paper目录下(自动手动挑题情况)
  471. promiseArr.push(new Promise(async (r, j) => {
  472. // 保存试题的blob链接
  473. const itemJsonFile = await this.$evTools
  474. .createBlobItem(exerciseItem)
  475. let file = new File([JSON.stringify(itemJsonFile)],
  476. exerciseItem.id + ".json");
  477. blobFiles.push(file)
  478. itemJsonFiles.push(exerciseItem)
  479. r({
  480. cosmosItem: exerciseItem,
  481. blobItem: itemJsonFile
  482. })
  483. }))
  484. }
  485. } else if (exerciseItem.children.length) { //如果是导入的 综合题
  486. // 如果是综合题 则需要把题干和小题都进行保存操作
  487. let composeArr = [exerciseItem, ...exerciseItem.children]
  488. composeArr.forEach(composeItem => {
  489. promiseArr.push(new Promise(async (r, j) => {
  490. if (composeItem.children.length && composeItem
  491. .children[0].id) {
  492. composeItem.children = composeItem.children
  493. .map(i => i.id)
  494. }
  495. // 将当前的试题数据转化为BLOB内部的试题JSON格式
  496. let removeItem = await this.$editorTools
  497. .doRemoveMideaHost(composeItem)
  498. const itemJsonFile = await this.$evTools
  499. .createBlobItem(removeItem)
  500. const cosmosItem = await this.$evTools
  501. .createCosmosItem(composeItem)
  502. // 首先保存新题目的JSON文件到Blob 然后返回URL链接
  503. let file = new File([JSON.stringify(
  504. itemJsonFile)], composeItem.id +
  505. ".json");
  506. blobFiles.push(file)
  507. try {
  508. // 等待上传blob的返回结果
  509. let blobFile = await containerClient
  510. .upload(file, 'item/' + composeItem.id,
  511. undefined, false, false)
  512. if (blobFile.blob) {
  513. // 保存试题JSON文件到试卷文件夹需要
  514. itemJsonFiles.push(composeItem)
  515. // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
  516. cosmosItem.blob = blobFile.blob
  517. // 保存当前试题到数据库
  518. that.saveExercise(cosmosItem).then(
  519. res => {
  520. r({
  521. cosmosItem: cosmosItem,
  522. blobItem: blobFile
  523. })
  524. })
  525. } else {
  526. j(500)
  527. }
  528. } catch (e) {
  529. this.$Message.error(e.spaceError)
  530. this.isLoading = false
  531. }
  532. }))
  533. })
  534. } else {
  535. // 如果没有blob字段 说明试题还没有保存到item目录下 则需要进行保存item文件夹后再保存到paper文件夹(导入试题情况)
  536. promiseArr.push(new Promise(async (r, j) => {
  537. // 将当前的试题数据转化为BLOB内部的试题JSON格式
  538. let removeItem = await this.$editorTools.doRemoveMideaHost(
  539. exerciseItem)
  540. // removeItem.score = 0
  541. const itemJsonFile = await this.$evTools.createBlobItem(
  542. removeItem)
  543. const cosmosItem = await this.$evTools.createCosmosItem(
  544. exerciseItem)
  545. // 首先保存新题目的JSON文件到Blob 然后返回URL链接
  546. let file = new File([JSON.stringify(itemJsonFile)],
  547. exerciseItem.id + ".json");
  548. blobFiles.push(file)
  549. try {
  550. // 等待上传blob的返回结果
  551. let blobFile = await containerClient.upload(file,
  552. 'item/' + exerciseItem.id, undefined, false,
  553. false)
  554. if (blobFile.blob) {
  555. // 保存试题JSON文件到试卷文件夹需要
  556. itemJsonFiles.push(exerciseItem)
  557. // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
  558. cosmosItem.blob = blobFile.blob
  559. // 保存当前试题到数据库
  560. that.saveExercise(cosmosItem).then(res => {
  561. r({
  562. cosmosItem: exerciseItem,
  563. blobItem: blobFile
  564. })
  565. })
  566. } else {
  567. j(500)
  568. }
  569. } catch (e) {
  570. this.$Message.error(e.spaceError)
  571. this.isLoading = false
  572. }
  573. }))
  574. }
  575. }
  576. Promise.all(promiseArr).then(result => {
  577. console.log(result)
  578. // 子题保存之后 统一更新blobSize
  579. // blobTool.updateSize([{
  580. // url: 'item',
  581. // size: updateSize
  582. // }], containerName).then(res => {
  583. let slides = []
  584. // 主观题的answer为空数组
  585. let nullType = ['complete', 'subjective', 'compose', 'correct',
  586. 'connector'
  587. ]
  588. result.map(i => i.cosmosItem).forEach(item => {
  589. console.log(item)
  590. let o = {
  591. url: item.id + '.json',
  592. type: item.type,
  593. scoring: {
  594. score: item.score || 0,
  595. knowledge: item.knowledge || [],
  596. field: item.field || 1,
  597. ans: nullType.includes(item.type) ?
  598. [] : (item.answer || [])
  599. }
  600. }
  601. item.type === 'compose' && delete o.scoring
  602. slides.push(o)
  603. })
  604. resolve({
  605. slides: slides,
  606. files: itemJsonFiles
  607. })
  608. // }).catch(err => {
  609. // this.$Message.error(this.$t(
  610. // 'evaluation.newExercise.uploadErrorTip'));
  611. // })
  612. }).catch(err => {
  613. console.log(err)
  614. this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
  615. })
  616. })
  617. },
  618. /* 获取所有试题Blob前缀 */
  619. getListPrefixs(list) {
  620. let prefixArr = []
  621. list.forEach(item => {
  622. if (item.type === 'compose' && item.children.length) {
  623. prefixArr.push('item/' + item.id)
  624. prefixArr = prefixArr.concat(item.children.map(i => 'item/' + i.id))
  625. } else {
  626. prefixArr.push('item/' + item.id)
  627. }
  628. })
  629. console.log('试题的前缀集合', prefixArr)
  630. return prefixArr
  631. },
  632. // 提取富文本内容中的文本
  633. getSimpleText(html) {
  634. var r = /<(?!img|video|audio).*?>/g;
  635. return html.replace(r, "");
  636. },
  637. /* 保存单个试题 */
  638. saveExercise(item) {
  639. item.code = item.scope === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo
  640. .TEAMModelId
  641. return new Promise((r, j) => {
  642. this.$api.newEvaluation.SaveSingleExercise({
  643. itemInfo: item,
  644. option: this.isEditPaper ? 'update' : 'insert'
  645. }).then(res => {
  646. if (!res.error) {
  647. r(res)
  648. } else {
  649. j(res)
  650. this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
  651. }
  652. })
  653. })
  654. },
  655. // 判断试卷是否存在于Blob中
  656. isPaperExist(paperName) {
  657. return new Promise(async (r, j) => {
  658. // 获取初始化Blob需要的数据
  659. let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools
  660. .getPrivateSas()
  661. //初始化Blob
  662. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ?
  663. 'school' : 'private')
  664. containerClient.exists('paper/' + paperName + '/index.json').then(
  665. (res) => {
  666. r(res)
  667. },
  668. (err) => {
  669. j(err)
  670. this.$Message.error('API Error')
  671. }
  672. )
  673. })
  674. },
  675. // 判断试卷是否存在于Blob中
  676. isContainerFull() {
  677. return new Promise(async (r, j) => {
  678. let scope = this.isSchool ? 'school' : 'private'
  679. // 获取初始化Blob需要的数据
  680. let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools
  681. .getPrivateSas()
  682. //初始化Blob
  683. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, scope)
  684. containerClient.isContainerFull(scope).then(
  685. (res) => {
  686. r(res)
  687. },
  688. (err) => {
  689. j(err)
  690. this.$Message.error('API Error')
  691. }
  692. )
  693. })
  694. },
  695. /** 保存当前试卷数据 */
  696. async saveTestPaper() {
  697. let exListVm = this.$refs.testPaper.$refs.exList
  698. let hasSurplus = exListVm.surPlusScore // 判断是否有剩余分数未分配
  699. let noScoreList = exListVm.exerciseList.filter(item => item.score === 0) // 判断是否有未配分的题目
  700. let hasErrorItem = exListVm.errorList.length > 0
  701. let groupTypeList = exListVm.groupTypeList
  702. let list = this.evaluationInfo.item
  703. this.$refs.testPaper.isShowAnalysis = false
  704. if (this.evaluationInfo.name.trim() === '') {
  705. this.$Message.warning(this.$t('evaluation.paperList.emptyNameTip'))
  706. return
  707. }
  708. if (!hasErrorItem) {
  709. if (hasSurplus === 0) {
  710. if (!noScoreList.length) {
  711. this.isLoading = true
  712. let isPaperExist = await this.isPaperExist(this.evaluationInfo.name)
  713. let isContainerFull = await this.isContainerFull()
  714. if (!isPaperExist || (this.isEditPaper && this.evaluationInfo.name === this.oldPaper.name)) {
  715. if (list.length) {
  716. // 拿到题型顺序的试题数组进行拼接
  717. let arr = []
  718. groupTypeList.forEach(i => {
  719. arr = arr.concat(i.list)
  720. })
  721. if (!this.checkComposeScore(arr)) return
  722. if (isContainerFull) {
  723. this.$Message.warning(this.$t('evaluation.paperList.noSpaceTip'))
  724. } else {
  725. // 只按照默认顺序保存
  726. // let saveArr = this.viewModel === 'type' ? arr : list
  727. this.doSavePaper(arr)
  728. }
  729. } else {
  730. this.$Message.warning(this.$t('evaluation.paperList.noItemTip'))
  731. }
  732. } else {
  733. // 处理已存在同名称的试卷
  734. this.$Modal.confirm({
  735. title: this.$t('evaluation.newExercise.modalTip'),
  736. content: this.$t('evaluation.paperList.isExistPaperTip'),
  737. onOk: async () => {
  738. // 拿到题型顺序的试题数组进行拼接
  739. let arr = []
  740. groupTypeList.forEach(i => {
  741. arr = arr.concat(i.list)
  742. })
  743. this.isLoading = true
  744. if (!this.checkComposeScore(arr)) return
  745. // 如果是已存在相同名称的试卷,则进行覆盖,先删除原来的目录再进行保存
  746. let blobList = await this.getPaperFiles('paper/' + this
  747. .evaluationInfo.name + '/')
  748. let files = blobList.blobList.map(i => {
  749. return {
  750. blob:i.blob,
  751. size:i.size
  752. }
  753. })
  754. this.deleteNoUseItem(files,arr).then(r => {
  755. if (isContainerFull) {
  756. this.$Message.warning(this.$t(
  757. 'evaluation.paperList.noSpaceTip'))
  758. } else {
  759. // 只按照默认顺序保存 arr代表题型排序 list代表的是顺序排序
  760. // let saveArr = this.viewModel === 'type' ? arr : list
  761. this.doSavePaper(arr)
  762. }
  763. })
  764. },
  765. onCancel: () => {
  766. this.isLoading = false
  767. this.$Message.warning(this.$t(
  768. 'evaluation.paperList.cancelSaveTip'))
  769. }
  770. })
  771. }
  772. } else {
  773. this.$Message.warning(this.$t('evaluation.paperList.hasNoScoreTip'))
  774. this.isLoading = false
  775. }
  776. } else {
  777. this.$Message.warning(this.$t('evaluation.paperList.noCompleteScoreTip'))
  778. this.isLoading = false
  779. }
  780. } else {
  781. this.$Message.warning(this.$t('evaluation.paperList.hasErrorItemTip'))
  782. this.isLoading = false
  783. }
  784. },
  785. /* 删除同名试卷覆盖情况下 已被移除的试题 */
  786. deleteNoUseItem(blobList,arr){
  787. return new Promise(async (resolve,reject) => {
  788. let needDeleteUrlArr = []
  789. blobList.forEach(s => {
  790. let id = s.blob.split('/')[s.blob.split('/').length - 1].replace('.json','')
  791. if(id !== 'index' && arr.map(i => i.id).indexOf(id) === -1){
  792. needDeleteUrlArr.push(s)
  793. }
  794. })
  795. if(!needDeleteUrlArr.length){
  796. resolve(200)
  797. }else{
  798. let promiseArr = []
  799. let sas = this.evaluationInfo.scope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
  800. let blobClient = new blobTool(sas.url, sas.name, sas.sas,this.evaluationInfo.scope)
  801. needDeleteUrlArr.forEach(item => {
  802. promiseArr.push(new Promise((r,j) => {
  803. blobClient.deleteBlob(item.blob,item.size).then(
  804. (res) => {
  805. r(200)
  806. },
  807. (err) => {
  808. j(err)
  809. }
  810. )
  811. }))
  812. })
  813. Promise.all(promiseArr).then(result => {
  814. resolve(200)
  815. }).catch(e => {
  816. reject(e)
  817. })
  818. }
  819. })
  820. },
  821. /* 检查综合题配分是否正确 */
  822. checkComposeScore(arr) {
  823. let flag = true
  824. for (let index = 0; index < arr.length; index++) {
  825. let i = arr[index]
  826. if (i.type === 'compose' && i.children.length) {
  827. let childTotalScore = i.children.reduce((p, e) => parseInt(p) + parseInt(e.score), 0)
  828. let hasNoScoreChild = i.children.filter(j => !j.score).length > 0
  829. if (i.score !== childTotalScore || hasNoScoreChild) {
  830. console.log(i.score)
  831. console.log(childTotalScore)
  832. console.log(index)
  833. let exList = this.$refs.testPaper.$refs.exList
  834. let exerciseDom = Array.from(exList.$el.getElementsByClassName('exercise-item')).filter(item =>
  835. item.dataset.id ===
  836. i.id)[0]
  837. exerciseDom.style.backgroundColor = '#ffa7a7'
  838. this.$nextTick(() => {
  839. if (this.$refs.paperRef) {
  840. this.$refs['paperRef'].scrollTo({
  841. y: exerciseDom.offsetTop
  842. },
  843. 500
  844. )
  845. }
  846. })
  847. setTimeout(() => {
  848. exerciseDom.style.backgroundColor = '#fff'
  849. }, 2000)
  850. this.$Message.warning(
  851. `${ this.$t('evaluation.createPaper.tip1') } ${ index + 1 } ${ this.$t('evaluation.createPaper.tip2') }${ i.score > childTotalScore ? this.$t('evaluation.createPaper.tip3') : this.$t('evaluation.createPaper.tip4') },${ this.$t('evaluation.createPaper.tip5') }`
  852. )
  853. flag = false
  854. this.isLoading = false
  855. break
  856. }
  857. } else {
  858. flag = true
  859. }
  860. }
  861. return flag
  862. },
  863. /* 获取指定路径试卷下的所有文件 */
  864. getPaperFiles(path) {
  865. return new Promise(async (r, j) => {
  866. // 获取初始化Blob需要的数据
  867. let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools
  868. .getPrivateSas()
  869. //初始化Blob
  870. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ?
  871. 'school' : 'private')
  872. // 等待blob的返回结果
  873. containerClient.listBlob({
  874. prefix: path
  875. }).then(
  876. (res) => {
  877. r(res)
  878. },
  879. (err) => {
  880. this.$Message.error('API Error')
  881. }
  882. )
  883. })
  884. },
  885. onDeleteBlobPaper(files) {
  886. return new Promise(async (r, j) => {
  887. // 获取初始化Blob需要的数据
  888. let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools
  889. .getPrivateSas()
  890. //初始化Blob
  891. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ?
  892. 'school' : 'private')
  893. // 等待blob的返回结果
  894. containerClient.deleteBlobBatch(files).then(
  895. (res) => {
  896. r(res)
  897. },
  898. (err) => {
  899. this.$Message.error('API Error')
  900. }
  901. )
  902. })
  903. },
  904. /* 保存试卷业务 */
  905. async doSavePaper(list) {
  906. // console.log(this.oldPaper)
  907. // let blobList = await this.getPaperFiles('paper/' + this.oldPaper.name)
  908. // console.log(blobList)
  909. // return
  910. sessionStorage.setItem('isSave',1)
  911. console.log('试卷数据', this.evaluationInfo)
  912. this.isLoading = true
  913. let multipleRule = this.$refs.testPaper.$refs.exList.multipleRule
  914. let modifyItems = this.$refs.testPaper.$refs.exList.modifyItems
  915. // 将传进来的试题 如果是导入的试题 则需要补充年级学段等信息
  916. let refreshList = await this.refreshImportItems(list)
  917. // 保存导入的试题到BLOB以及COSMOS
  918. this.savePaperItems(refreshList, modifyItems, this.isEditPaper).then(async res => {
  919. let guid = this.$tools.guid()
  920. let paperItem = {
  921. id: this.evaluationInfo.id || guid,
  922. code: this.editPaper ? this.editPaper.code.replace('Paper-', '') : (this
  923. .isSchool ? this.$store.state.userInfo.schoolCode : this.$store
  924. .state.userInfo.TEAMModelId),
  925. scope: this.isSchool ? 'school' : 'private',
  926. gradeIds: this.isSchool ? (this.evaluationInfo.paperGrade.length ? this
  927. .evaluationInfo.paperGrade.map(i => i + '') : this.gradeList
  928. .map((i, index) => index + '')) : [],
  929. subjectId: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject]
  930. .id : null,
  931. subjectName: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject]
  932. .name : '',
  933. periodId: this.isSchool ? this.schoolInfo.period[this.evaluationInfo
  934. .paperPeriod].id : null,
  935. name: this.evaluationInfo.name,
  936. points: this.getPaperPoints(this.evaluationInfo.item),
  937. scoring: this.getAnswers(list),
  938. score: this.evaluationInfo.score,
  939. sheet:this.evaluationInfo.sheet || null,
  940. multipleRule: multipleRule || 1
  941. }
  942. let blobPaper = await this.$evTools.createBlobPaper(paperItem, res.slides)
  943. // 首先保存新题目的JSON文件到Blob 然后返回URL链接
  944. let paperFile = new File([JSON.stringify(blobPaper)], "index.json");
  945. // 获取初始化Blob需要的数据
  946. let sasData = this.evaluationInfo.type === 'private' ? await this.$tools
  947. .getPrivateSas() : await this.$tools.getSchoolSas()
  948. //初始化Blob
  949. let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this
  950. .evaluationInfo.type)
  951. let containerName = paperItem.scope === 'private' ? this.$store.state.userInfo
  952. .TEAMModelId : this.$store.state
  953. .userInfo.schoolCode
  954. /* 上传前进行试卷blob查询size */
  955. // let beforeSizeArr = await blobTool.checkPrefixSize(['paper/' + paperItem.name],
  956. // containerName)
  957. // let beforeSize = this._.sum(beforeSizeArr.map(i => i.size))
  958. // console.log('试卷上传前的size', beforeSize)
  959. try {
  960. let promiseArr = []
  961. let blobFile = null
  962. console.log('试卷题目的ID集合', res.files)
  963. console.log('试卷ITEM', paperItem)
  964. // return
  965. let privateSas = await this.$tools.getPrivateSas()
  966. let privateBlob = new blobTool(privateSas.url, privateSas.name, privateSas.sas,
  967. 'private')
  968. let schoolSas = await this.$tools.getSchoolSas()
  969. let schoolBlob = new blobTool(schoolSas.url, schoolSas.name, schoolSas.sas,
  970. 'school')
  971. // 放入试题json文件
  972. for (let i = 0; i < res.files.length; i++) {
  973. promiseArr.push(new Promise(async (r, j) => {
  974. // let result = await containerClient.upload(res.files[i], 'paper/' + paperItem.name, undefined, false)
  975. // r(result)
  976. try{
  977. let item = res.files[i]
  978. console.log(item)
  979. // 如果是修改试卷名称并且题目是来自原本试卷的 则直接从原本试卷复制副本
  980. let oldPaperName = this.isEditPaper ? this.oldPaper.name : ''
  981. if(this.isEditPaper && item.blob.includes(`paper/${oldPaperName}/`)){
  982. console.log(item.blob)
  983. containerClient.copyBlob('paper/' + paperItem.name + '/' + item.id + '.json', item.blob, sasData.sas)
  984. .then(res => {
  985. r(200)
  986. })
  987. }else{
  988. // 否则就是来自选的试题则从题库来进行复制
  989. if (item.scope == 'school') {
  990. containerClient.copyFolder('paper/' + paperItem.name +
  991. '/', 'item/' + item.id, schoolBlob, null, false
  992. )
  993. .then(res => {
  994. r(200)
  995. })
  996. } else {
  997. containerClient.copyFolder('paper/' + paperItem.name +
  998. '/', 'item/' + item.id, privateBlob, null,
  999. false).then(res => {
  1000. r(200)
  1001. })
  1002. }
  1003. }
  1004. }catch(e){
  1005. console.log(e)
  1006. }
  1007. }))
  1008. }
  1009. // 放入index.json文件
  1010. promiseArr.push(new Promise(async (r, j) => {
  1011. try {
  1012. blobFile = await containerClient.upload(paperFile,
  1013. 'paper/' + paperItem.name, undefined, false)
  1014. console.log('上传到试卷目录下', blobFile)
  1015. r(blobFile)
  1016. } catch (e) {
  1017. j(e)
  1018. this.$Message.error(e.spaceError)
  1019. this.isLoading = false
  1020. }
  1021. }))
  1022. if(this.isEditPaper && (this.oldPaper.name !== paperItem.name)){
  1023. promiseArr.push(new Promise(async (r,j) => {
  1024. let blobList = await this.getPaperFiles('paper/' + this
  1025. .oldPaper.name + '/')
  1026. let files = blobList.blobList.map(i => i.blob)
  1027. this.onDeleteBlobPaper(files).then(res => {
  1028. r(200)
  1029. }).catch(e => {
  1030. j(e)
  1031. })
  1032. }))
  1033. }
  1034. // 进行试卷文件上传Blob 先上传所有题目 再上传index.json文件
  1035. Promise.all(promiseArr).then(async result => {
  1036. try{
  1037. /* 上传前进行试卷blob查询size */
  1038. // let afterSizeArr = await blobTool.checkPrefixSize(['paper/' +
  1039. // paperItem.name
  1040. // ], containerName)
  1041. // let afterSize = this._.sum(afterSizeArr.map(i => i.size))
  1042. // console.log('试卷上传后的size', afterSize)
  1043. // console.log(paperItem.sheet)
  1044. if (blobFile.blob) {
  1045. // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
  1046. paperItem.blob = blobFile.blob.split('/index.json')[0]
  1047. if(paperItem.sheet){
  1048. await this.delPaperSheet(paperItem)
  1049. paperItem.sheet = null
  1050. }
  1051. let params = {
  1052. paper: await this.$evTools.createCosmosPaper(
  1053. paperItem),
  1054. option: this.isEditPaper ? 'update' : 'insert'
  1055. }
  1056. // 保存试卷到cosmos
  1057. this.$api.learnActivity.SaveExamPaper(params).then(
  1058. res => {
  1059. if (res.error == null) {
  1060. this.$Message.success(this.isEditPaper ? this
  1061. .$t('evaluation.paperList.editSuc') :
  1062. this.$t(
  1063. 'evaluation.paperList.saveSuc'))
  1064. this.isLoading = false
  1065. // 子题保存之后 统一更新blobSize
  1066. // blobTool.updateSize([{
  1067. // url: 'paper/' + paperItem.name,
  1068. // size: afterSize - beforeSize
  1069. // }], containerName).then(res => {
  1070. this.$router.push({
  1071. name: this
  1072. .evaluationInfo
  1073. .type ===
  1074. 'private' ?
  1075. 'personalBank' :
  1076. 'schoolBank',
  1077. params: {
  1078. tabName: 'paper'
  1079. }
  1080. })
  1081. sessionStorage.setItem('isSave',0)
  1082. // }).catch(err => {
  1083. // this.$Message.error(this.$t(
  1084. // 'evaluation.newExercise.uploadErrorTip'
  1085. // ));
  1086. // })
  1087. } else {
  1088. this.$Message.error(this.$t(
  1089. 'evaluation.paperList.saveFail'))
  1090. this.isLoading = false
  1091. }
  1092. },
  1093. err => {
  1094. this.$Message.error(this.$t(
  1095. 'evaluation.paperList.saveFail'))
  1096. this.isLoading = false
  1097. }
  1098. )
  1099. }else{
  1100. console.error(blobFile)
  1101. }
  1102. }catch(e) {
  1103. console.log(e)
  1104. }
  1105. })
  1106. } catch (e) {
  1107. console.log(e)
  1108. this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
  1109. this.isLoading = false
  1110. }
  1111. })
  1112. },
  1113. delPaperSheet(paper){
  1114. return new Promise((r,j) => {
  1115. this.$api.evaluation.deleteSheet({
  1116. ids:[paper.sheet],
  1117. code:paper.code,
  1118. scope:paper.scope
  1119. }).then(res => {
  1120. console.log(res)
  1121. r(200)
  1122. }).catch(e => {
  1123. console.log(e);
  1124. j(e)
  1125. })
  1126. })
  1127. },
  1128. /* 获取整张试卷的答案合计Answers */
  1129. getAnswers(items) {
  1130. let arr = []
  1131. // 主观题的answer为空数组
  1132. let nullType = ['complete', 'subjective', 'compose', 'correct', 'connector']
  1133. items.forEach((i, index) => {
  1134. arr.push({
  1135. type: i.type,
  1136. ans: nullType.includes(i.type) ? [] : i.answer,
  1137. score: i.score
  1138. })
  1139. })
  1140. return arr
  1141. },
  1142. /* 获取整张试卷的知识点集合 */
  1143. getPaperPoints(items) {
  1144. let arr = []
  1145. items.forEach((i, index) => {
  1146. if (i.knowledge) {
  1147. arr = arr.concat(i.knowledge)
  1148. }
  1149. })
  1150. return arr
  1151. },
  1152. /* 判断Blob容器内是否已存在相同容器 */
  1153. hasSamePaper(container, name) {
  1154. containerClient.listBlob({
  1155. prefix: 'paper'
  1156. }).then(
  1157. (res) => {
  1158. console.log(res)
  1159. },
  1160. (err) => {
  1161. this.$Message.error('API Error')
  1162. }
  1163. )
  1164. },
  1165. /* 渲染需要编辑的试卷信息 */
  1166. async doRender(paper) {
  1167. let schoolInfo = null
  1168. if(paper.paperGrade){
  1169. console.log('传进来缓存的paper')
  1170. console.log(paper)
  1171. this.evaluationInfo = paper
  1172. this.oldPaper = JSON.parse(JSON.stringify(this.evaluationInfo))
  1173. if (paper.scope === 'school') {
  1174. schoolInfo = await this.getSchoolBaseInfo()
  1175. // paper.paperGrade = paper.paperGrade.map(i => +i)
  1176. this.subjectList = schoolInfo ? this.schoolInfo.period[paper.paperPeriod]
  1177. .subjects : [],
  1178. this.gradeList = schoolInfo ? this.schoolInfo.period[paper.paperPeriod]
  1179. .grades : []
  1180. }
  1181. return
  1182. }
  1183. console.log('渲染的试卷',paper)
  1184. // localStorage.setItem('c_edit_paper',JSON.stringify(paper))
  1185. if (paper.scope === 'school') {
  1186. schoolInfo = await this.getSchoolBaseInfo()
  1187. this.subjectList = schoolInfo ? this.schoolInfo.period.filter(i => i.id === paper.periodId)[0]
  1188. .subjects : [],
  1189. this.gradeList = schoolInfo ? this.schoolInfo.period.filter(i => i.id === paper.periodId)[0]
  1190. .grades : []
  1191. }
  1192. this.evaluationInfo = {
  1193. id: paper.id,
  1194. name: paper.name,
  1195. code: paper.code,
  1196. type: paper.scope,
  1197. scope: paper.scope,
  1198. paperPeriod: schoolInfo && paper.scope === 'school' ? this.schoolInfo.period.map(i => i.id)
  1199. .indexOf(paper.periodId) : null,
  1200. paperGrade: schoolInfo && paper.scope === 'school' ? paper.gradeIds.map(i => +i) : [],
  1201. paperSubject: schoolInfo && paper.scope === 'school' ? this.subjectList.map(i => i.id).indexOf(
  1202. paper.subjectId) : [],
  1203. score: paper.score,
  1204. item: paper.item,
  1205. multipleRule: paper.multipleRule || 1,
  1206. sheet:paper.sheet || null,
  1207. startTime: 0,
  1208. endTime: 0,
  1209. createType: 'manual'
  1210. }
  1211. console.log(this.evaluationInfo.sheet)
  1212. this.oldPaper = JSON.parse(JSON.stringify(this.evaluationInfo))
  1213. }
  1214. },
  1215. mounted() {
  1216. let routerData = this.$route.params.paper
  1217. console.log('xxxx',routerData)
  1218. if (routerData) {
  1219. console.log(routerData)
  1220. this.doRender(routerData)
  1221. this.editPaper = routerData
  1222. this.isEditPaper = true
  1223. this.evaluationInfo.createType == 'manual'
  1224. this.activeTab = 'preview'
  1225. this.$EventBus.$emit('onPaperItemChange', routerData.item)
  1226. }
  1227. this.$EventBus.$off('onBackToTop')
  1228. this.$EventBus.$on('onBackToTop', () => {
  1229. this.handleBackToTop()
  1230. })
  1231. },
  1232. computed: {
  1233. paperScrollTop() {
  1234. return this.$store.state.totalAnalysis.paperScrollTop
  1235. },
  1236. isSchool() {
  1237. return this.$route.name === 'newSchoolPaper'
  1238. },
  1239. propPeriod() {
  1240. return this.$route.name === 'newSchoolPaper' && this.subjectList.length && (this.evaluationInfo.paperPeriod || this.evaluationInfo.paperPeriod === 0 ) ? this.schoolInfo.period[this
  1241. .evaluationInfo
  1242. .paperPeriod].id : null
  1243. },
  1244. propSubject() {
  1245. return this.$route.name === 'newSchoolPaper' && this.subjectList.length ? this.subjectList[this
  1246. .evaluationInfo.paperSubject]
  1247. .id : null
  1248. }
  1249. },
  1250. // beforeRouteEnter(to, from, next) {
  1251. // if (from.name === 'answerSheet' && (to.name === 'newSchoolPaper' || to.name === 'newPrivatePaper')) {
  1252. // to.meta.isKeep = true
  1253. // }
  1254. // next()
  1255. // },
  1256. // beforeRouteLeave(to, from, next) {
  1257. // if(to.name === 'answerSheet'){
  1258. // // 设置下一个路由的 meta
  1259. // // from.meta.isKeep = true; // 让 A 缓存,即不刷新
  1260. // }
  1261. // if(to.name === 'schoolBank' || to.name === 'personalBank'){
  1262. // to.meta.isKeep = false
  1263. // }
  1264. // next();
  1265. // },
  1266. watch: {
  1267. paperScrollTop: {
  1268. handler(n) {
  1269. this.$refs.testPaper.isShowBackToTop = n > 200
  1270. }
  1271. },
  1272. }
  1273. }
  1274. </script>
  1275. <style scoped lang="less">
  1276. @import "./CreatePaper.less";
  1277. </style>
  1278. <style>
  1279. .evaluation-attr-form .ivu-input,
  1280. .evaluation-attr-form .ivu-select-selection {
  1281. background: none;
  1282. color: white;
  1283. border-color: #999999;
  1284. font-size: 14px;
  1285. }
  1286. .evaluation-attr-form .ivu-input {
  1287. /*border:none;
  1288. border-bottom:1px solid #424242;
  1289. border-radius:0px;*/
  1290. }
  1291. .evaluation-attr-wrap .ivu-form .ivu-form-item-label {
  1292. color: #a5a5a5;
  1293. }
  1294. .evaluation-attr-wrap .ivu-tag {
  1295. background-color: #2db6f4;
  1296. border: none;
  1297. }
  1298. .evaluation-attr-wrap .ivu-tag .ivu-tag-text {
  1299. color: #fff;
  1300. }
  1301. .evaluation-attr-wrap .ivu-tag .ivu-icon-ios-close {
  1302. color: #fff;
  1303. }
  1304. .evaluation-attr-wrap-inputNumber .ivu-input-number-input {
  1305. color: #fff;
  1306. }
  1307. .evaluation-question-main .ivu-tabs-bar {
  1308. border-color: #404040;
  1309. }
  1310. .evaluation-question-main .ivu-tabs.ivu-tabs-card>.ivu-tabs-bar .ivu-tabs-tab {
  1311. border: none;
  1312. background-color: #303030;
  1313. color: white;
  1314. margin-right: 2px;
  1315. }
  1316. .evaluation-question-main .ivu-tabs.ivu-tabs-card>.ivu-tabs-bar .ivu-tabs-tab-active {
  1317. background-color: #404040;
  1318. color: white;
  1319. font-weight: 600;
  1320. }
  1321. .evaluation-question-main .ivu-tabs .ivu-tabs-content-animated {
  1322. height: 100%;
  1323. }
  1324. .evaluation-question-main .ivu-tabs-bar {
  1325. margin-bottom: 0px;
  1326. }
  1327. .create-evaluation-container .ivu-input-number-input,
  1328. .create-evaluation-container .ivu-input-number {
  1329. width: 100%;
  1330. background: none;
  1331. border-color: #999999;
  1332. }
  1333. </style>