Переглянути джерело

答题卡PDF的blob上传与下载

OnePsycho 3 роки тому
батько
коміт
5517bfe78f

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/evaluation.js

@@ -191,6 +191,8 @@ export default {
 		paperAnalysis:'试卷分析',
 		setPaperScore:'设置试卷总分',
 		goAnswerSheet:'打印答题卡',
+		createSheet:'生成答题卡',
+		reCreateSheet:'重新生成',
 		choosePaper:'选择试卷',
 		choosed:'已选择',
 		searchPaper:'输入试卷名称进行搜索...'

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/evaluation.js

@@ -191,6 +191,8 @@ export default {
 		paperAnalysis: '試卷分析',
 		setPaperScore: '設定試卷總分',
 		goAnswerSheet: '列印答題卡',
+		createSheet:'生成答題卡',
+		reCreateSheet:'重新生成',
 		choosePaper: '選擇試卷',
 		choosed: '已選擇',
 		searchPaper: '輸入試卷名稱進行搜尋…'

+ 2 - 2
TEAMModelOS/ClientApp/src/utils/html2pdf.js

@@ -29,7 +29,7 @@ export default {
 								//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
 								let imgWidth = a4Width
 								let imgHeight = a4Width / contentWidth * contentHeight
-								console.log(pageData)
+								// console.log(pageData)
 								let PDF = new JsPDF({
 									orientation: 'p',
 									unit: 'mm',
@@ -53,7 +53,7 @@ export default {
 									}
 								}
 								PDF.save(title + '.pdf')
-								r(200)
+								r(PDF.output('blob'))
 							}
 						})
 						.catch(function(error) {

+ 3 - 0
TEAMModelOS/ClientApp/src/view/evaluation/components/BasePasteTool.vue

@@ -54,9 +54,12 @@
 					if (item.kind === "string" && item.type === 'text/rtf') {
 						item.getAsString(function(str) {
 							console.log(str)
+							str = str.replace('\n','')
 							var pattern = /\\pngblip.*?\}\{/g;
+							// var pattern = /(?:\\pngblip[\s\S].+\})([\s\S].[\s\S])+(?=\})/g;
 							var srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/ig;
 							let result = str.match(pattern)
+							console.log(result)
 							let base64Arr = result.map(i => hexToBase64(i.split('}')[1]))
 							let html = stemEditor.txt.html()
 							if(html.match(srcReg).length){

+ 388 - 335
TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue

@@ -1,368 +1,421 @@
 <template>
-  <div class="paper-container">
-    <div class="back-to-top flex-col-center" :title="$t('evaluation.backToTop')" v-if="isShowBackToTop" @click="handleBackToTop">
-      <Icon type="ios-arrow-up" />
-    </div>
-    <div class="paper-main-wrap">
-      <!-- 试卷内容 -->
-      <div class="paper-content">
-        <div class="paper-body">
-          <!-- 试卷基础信息 -->
-          <div class="paper-base-info" v-show="!isPreview">
-            <div style="display: flex;">
-              <div class="paper-info-items">
-                <span class="base-info-item">{{$t('evaluation.paperList.paperScore')}}:<span class="analysis-info" style="cursor: pointer;">{{ paperInfo.score }}</span>{{$t('evaluation.paperList.score')}}</span>
-                <span class="base-info-item" @click="onShowScoreTable" style="cursor: pointer;">{{$t('evaluation.paperList.alreadyScore')}}:<span class="analysis-info">{{ allocatedScore || 0 }}</span>{{$t('evaluation.paperList.score')}}</span>
-              </div>
-              <div class="paper-info-items">
-                <span class="base-info-item">{{$t('evaluation.filter.diff')}}:
-                  <Rate allow-half v-model="paperInfo.item.length ? +paperDiff : 0" disabled />
-                </span>
-                <span class="base-info-item">{{$t('evaluation.paperList.itemCount')}}:<span class="analysis-info">{{ paperInfo.item ? paperInfo.item.length : 0 }}</span></span>
-              </div>
-            </div>
-            <div v-if="isShowBaseInfo && !isExamPaper">
-              <Button class="base-info-btn" type="info" @click="addNewModal = true" v-show="!isShowAnalysis">{{ $t('evaluation.index.addExercise') }}</Button>
-              <Button class="base-info-btn" type="info" @click="onHandleToggle" v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
-              <Button class="base-info-btn" type="info" @click="onSetScoreByType" v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.exerciseList.typeScore')}}</Button>
-              <!-- <Button class="base-info-btn" type="info" @click="onCleanPaper" v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.paperList.cleanItems')}}</Button> -->
-              <Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
-              <Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="paperInfo.item.length">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
-              <Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="paperInfo.item.length && paperInfo.id">{{  $t('evaluation.paperList.goAnswerSheet') }}</Button>
-            </div>
-            <div v-if="isExamPaper">
-              <Button class="base-info-btn" type="info" @click="onHandleToggle" v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
-              <Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
-              <Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="paperInfo.item.length && !isHideAnalysis">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
-              <Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="paperInfo.item.length && paperInfo.id">{{  $t('evaluation.paperList.goAnswerSheet') }}</Button>
-            </div>
-          </div>
-          <!-- 试卷头部信息 -->
-          <div class="paper-header flex-col-center">
-            <p class="paper-title">{{paperInfo.name}}</p>
-          </div>
-          <!-- 试卷分析部分 -->
-          <ExamPaperAnalysis :testPaper="paperInfo" v-if="isShowAnalysis" :hidePie="hidePie"></ExamPaperAnalysis>
-          <!-- 题目类型及列表 -->
-          <BaseExerciseList :paper="paperInfo" @dataUpdate="onListUpdate" v-show="!isShowAnalysis" ref="exList" :isShowTools="!isPreview" :isExamPaper="isExamPaper" @toggleChange="onToggleChange" @scoreUpdate="scoreUpdate"></BaseExerciseList>
-        </div>
-      </div>
-    </div>
+	<div class="paper-container">
+		<div class="back-to-top flex-col-center" :title="$t('evaluation.backToTop')" v-if="isShowBackToTop"
+			@click="handleBackToTop">
+			<Icon type="ios-arrow-up" />
+		</div>
+		<div class="paper-main-wrap">
+			<!-- 试卷内容 -->
+			<div class="paper-content">
+				<div class="paper-body">
+					<!-- 试卷基础信息 -->
+					<div class="paper-base-info" v-show="!isPreview">
+						<div style="display: flex;">
+							<div class="paper-info-items">
+								<span class="base-info-item">{{$t('evaluation.paperList.paperScore')}}:<span
+										class="analysis-info"
+										style="cursor: pointer;">{{ paperInfo.score }}</span>{{$t('evaluation.paperList.score')}}</span>
+								<span class="base-info-item" @click="onShowScoreTable"
+									style="cursor: pointer;">{{$t('evaluation.paperList.alreadyScore')}}:<span
+										class="analysis-info">{{ allocatedScore || 0 }}</span>{{$t('evaluation.paperList.score')}}</span>
+							</div>
+							<div class="paper-info-items">
+								<span class="base-info-item">{{$t('evaluation.filter.diff')}}:
+									<Rate allow-half v-model="paperInfo.item.length ? +paperDiff : 0" disabled />
+								</span>
+								<span class="base-info-item">{{$t('evaluation.paperList.itemCount')}}:<span
+										class="analysis-info">{{ paperInfo.item ? paperInfo.item.length : 0 }}</span></span>
+							</div>
+						</div>
+						<div v-if="isShowBaseInfo && !isExamPaper">
+							<Button class="base-info-btn" type="info" @click="addNewModal = true"
+								v-show="!isShowAnalysis">{{ $t('evaluation.index.addExercise') }}</Button>
+							<Button class="base-info-btn" type="info" @click="onHandleToggle"
+								v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
+							<Button class="base-info-btn" type="info" @click="onSetScoreByType"
+								v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.exerciseList.typeScore')}}</Button>
+							<!-- <Button class="base-info-btn" type="info" @click="onCleanPaper" v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.paperList.cleanItems')}}</Button> -->
+							<Button class="base-info-btn" type="info" @click="onViewModelChange"
+								v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
+							<Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis"
+								v-show="paperInfo.item.length">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+							<Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading"
+								v-show="paperInfo.item.length && paperInfo.id && paper.sheet">{{ $t('evaluation.paperList.goAnswerSheet') }}</Button>
+							<Button class="base-info-btn" type="info" @click="goAnswerSheet"
+								v-show="paperInfo.item.length && paperInfo.id">{{ paper.sheet ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
+						</div>
+						<div v-if="isExamPaper">
+							<Button class="base-info-btn" type="info" @click="onHandleToggle"
+								v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
+							<Button class="base-info-btn" type="info" @click="onViewModelChange"
+								v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
+							<Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis"
+								v-show="paperInfo.item.length && !isHideAnalysis">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+							<Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading"
+								v-show="paperInfo.item.length && paperInfo.id && paper.sheet">{{ $t('evaluation.paperList.goAnswerSheet') }}</Button>
+							<Button class="base-info-btn" type="info" @click="goAnswerSheet"
+								v-show="paperInfo.item.length && paperInfo.id">{{ paper.sheet ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
+						</div>
+					</div>
+					<!-- 试卷头部信息 -->
+					<div class="paper-header flex-col-center">
+						<p class="paper-title">{{paperInfo.name}}</p>
+					</div>
+					<!-- 试卷分析部分 -->
+					<ExamPaperAnalysis :testPaper="paperInfo" v-if="isShowAnalysis" :hidePie="hidePie">
+					</ExamPaperAnalysis>
+					<!-- 题目类型及列表 -->
+					<BaseExerciseList :paper="paperInfo" @dataUpdate="onListUpdate" v-show="!isShowAnalysis"
+						ref="exList" :isShowTools="!isPreview" :isExamPaper="isExamPaper" @toggleChange="onToggleChange"
+						@scoreUpdate="scoreUpdate"></BaseExerciseList>
+				</div>
+			</div>
+		</div>
 
-    <!-- 新建试题 -->
-    <Modal v-model="addNewModal" :title="$t('evaluation.index.addExercise')" width="1000px" class="related-point-modal" footer-hide>
-	  <Tabs value="name1" name="newExerciseTab" @on-click="onTabChange">
-		  <TabPane label="手动出题" name="name1" tab="newExerciseTab">
-			  <BaseCreateChild @addFinish="onAddNewFinish" v-if="addNewModal" :curPeriodIndex="paperInfo.paperPeriod" :curSubjectIndex="paperInfo.paperSubject"></BaseCreateChild>
-		  </TabPane>
-		  <TabPane label="快速出题" name="name2" tab="newExerciseTab">
-			  <BasePasteTool></BasePasteTool>
-		  </TabPane>
-	  </Tabs>
-    </Modal>
+		<!-- 新建试题 -->
+		<Modal v-model="addNewModal" :title="$t('evaluation.index.addExercise')" width="1000px"
+			class="related-point-modal" footer-hide>
+			<Tabs value="name1" name="newExerciseTab" @on-click="onTabChange">
+				<TabPane label="手动出题" name="name1" tab="newExerciseTab">
+					<BaseCreateChild @addFinish="onAddNewFinish" v-if="addNewModal"
+						:curPeriodIndex="paperInfo.paperPeriod" :curSubjectIndex="paperInfo.paperSubject">
+					</BaseCreateChild>
+				</TabPane>
+				<TabPane label="快速出题" name="name2" tab="newExerciseTab">
+					<BasePasteTool></BasePasteTool>
+				</TabPane>
+			</Tabs>
+		</Modal>
 
-  </div>
+	</div>
 </template>
 <script>
-import ExamPaperAnalysis from '@/view/learnactivity/ExamPaperAnalysis.vue'
-import AnswerSheet from '@/view/answersheet/index.vue'
-export default {
-  components: {
-    ExamPaperAnalysis,
-    AnswerSheet,
-  },
-  props: {
-    paper: {
-      type: Object,
-      default: null
-    },
-    isShowTools: {
-      type: Boolean,
-      default: true
-    },
-    isPreview: {
-      type: Boolean,
-      default: false
-    },
-    isShowBaseInfo: {
-      type: Boolean,
-      default: true
-    },
-    isExamPaper: {
-      type: Boolean,
-      default: false
-    },
-    hidePie: {
-      type: Boolean,
-      default: false
-    },
-    isHideAnalysis: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      addNewModal: false,
-      scoreTableModal: false,
-      isShowAnswerSheet: false,
-      isShowBackToTop: false,
-      isAllOpen: false,
-      isShowAnalysis: false,
-      isSetPaperName: false,
-      isSetScore: false,
-      isSetRules: false,
-      isShowSave: false,
-      exersicesList: [],
-      allocatedScore: 0,
-      list: [],
-      schoolInfo: {},
-      paperInfo: {
-        name: "",
-        score: 100,
-        answers: [],
-        multipleRule: 1,
-        item: [],
-		paperSubject:0,
-		paperPeriod:0
-      },
-      exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
-      exersicesDiff: this.$GLOBAL.EXERCISE_DIFFS(),
-      exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
-      diffColors: ['#32CF74', '#E8BE15', '#F19300', '#EB5E00', '#D30000'],
-      filterType: '0',
-      filterDiff: '0',
-      filterSort: '0',
-      pageSize: 5,
-      pageNum: 1,
-      totalNum: 100,
-      allList: [],
-      isShowAnswer: false,
-      isShowPart: false,
-      isShowConcept: false,
-      isShowTitle: true,
-      isShowInfo: false,
-      analysisColumns: [{
-        title: '题型',
-        key: 'name'
-      },
-      {
-        title: '数量(占比)',
-        key: 'value'
-      }
-      ],
-      analysisTableData: [],
-      viewModel: 'type',
-      paperDiff: 0
+	import ExamPaperAnalysis from '@/view/learnactivity/ExamPaperAnalysis.vue'
+	import AnswerSheet from '@/view/answersheet/index.vue'
+	export default {
+		components: {
+			ExamPaperAnalysis,
+			AnswerSheet,
+		},
+		props: {
+			paper: {
+				type: Object,
+				default: null
+			},
+			isShowTools: {
+				type: Boolean,
+				default: true
+			},
+			isPreview: {
+				type: Boolean,
+				default: false
+			},
+			isShowBaseInfo: {
+				type: Boolean,
+				default: true
+			},
+			isExamPaper: {
+				type: Boolean,
+				default: false
+			},
+			hidePie: {
+				type: Boolean,
+				default: false
+			},
+			isHideAnalysis: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				addNewModal: false,
+				scoreTableModal: false,
+				isShowAnswerSheet: false,
+				isShowBackToTop: false,
+				isAllOpen: false,
+				isShowAnalysis: false,
+				isSetPaperName: false,
+				isSetScore: false,
+				isSetRules: false,
+				isShowSave: false,
+				exersicesList: [],
+				allocatedScore: 0,
+				list: [],
+				schoolInfo: {},
+				paperInfo: {
+					name: "",
+					score: 100,
+					answers: [],
+					multipleRule: 1,
+					item: [],
+					paperSubject: 0,
+					paperPeriod: 0
+				},
+				exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
+				exersicesDiff: this.$GLOBAL.EXERCISE_DIFFS(),
+				exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
+				diffColors: ['#32CF74', '#E8BE15', '#F19300', '#EB5E00', '#D30000'],
+				filterType: '0',
+				filterDiff: '0',
+				filterSort: '0',
+				pageSize: 5,
+				pageNum: 1,
+				totalNum: 100,
+				allList: [],
+				isShowAnswer: false,
+				isShowPart: false,
+				isShowConcept: false,
+				isShowTitle: true,
+				isShowInfo: false,
+				downLoading:false,
+				analysisColumns: [{
+						title: '题型',
+						key: 'name'
+					},
+					{
+						title: '数量(占比)',
+						key: 'value'
+					}
+				],
+				analysisTableData: [],
+				viewModel: 'type',
+				paperDiff: 0
 
-    }
-  },
-  methods: {
-	  onTabChange(val){
-		  if(val === 'name1'){
-			  document.removeEventListener('paste')
-		  }
-	  },
-    goAnswerSheet() {
-      if (!this.isExamPaper) {
-        localStorage.setItem('c_edit_paper', JSON.stringify(this.paperInfo))
-      }
-      console.log(this.paperInfo)
-      this.$router.push({
-        name: 'answerSheet',
-        params: {
-          paper: this.paperInfo
-        }
-      })
-    },
-    onShowScoreTable() {
-      this.$refs.exList.scoreTableModal = true
-    },
-    /* 新增题目回调 */
-    onAddNewFinish(item) {
-      console.log(item);
-      sessionStorage.setItem('isSave', 0)
-      this.paperInfo.item.push(item)
-      this.addNewModal = false
-    },
-    /**
-     * 标题切换
-     * @param e
-     */
-    titleChange(e) {
-      this.paperInfo.name = e.target.innerHTML
-    },
+			}
+		},
+		methods: {
+			onTabChange(val) {
+				if (val === 'name1') {
+					document.removeEventListener('paste')
+				}
+			},
+			/* 下载Blob答题卡 */
+			async downloadSheet() {
+				console.log(this.paperInfo)
+				this.downLoading = true
+				let examId = this.paperInfo.examId
+				let pdfName = `${this.paperInfo.name}-${this.paperInfo.sheet}.pdf`
+				let path = examId ? `exam/${examId}/paper/${this.paperInfo.name}/` : `paper/${this.paperInfo.name}/`
+				let curScope = examId ? this.paperInfo.examScope : this.paperInfo.scope
+				let cntr = curScope === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+				let sasData = curScope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+				let blobHost = this.$evTools.getBlobHost()
+				let fullPath = blobHost + '/' + cntr + '/' + path + pdfName + sasData.sas
+				const downloadRes = async () => {
+				      let response = await fetch(fullPath); // 内容转变成blob地址
+				      let blob = await response.blob();  // 创建隐藏的可下载链接
+				      let objectUrl = window.URL.createObjectURL(blob);
+				      let a = document.createElement('a');
+				      a.href = objectUrl;
+				      a.download = pdfName;
+				      a.click()
+				      a.remove(); 
+					  this.downLoading = false
+				   }
+				downloadRes();
+				console.log(fullPath);
+			},
+			goAnswerSheet() {
+				if (!this.isExamPaper) {
+					localStorage.setItem('c_edit_paper', JSON.stringify(this.paperInfo))
+				}
+				console.log(this.paperInfo)
+				this.$router.push({
+					name: 'answerSheet',
+					params: {
+						paper: this.paperInfo
+					}
+				})
+			},
+			onShowScoreTable() {
+				this.$refs.exList.scoreTableModal = true
+			},
+			/* 新增题目回调 */
+			onAddNewFinish(item) {
+				console.log(item);
+				sessionStorage.setItem('isSave', 0)
+				this.paperInfo.item.push(item)
+				this.addNewModal = false
+			},
+			/**
+			 * 标题切换
+			 * @param e
+			 */
+			titleChange(e) {
+				this.paperInfo.name = e.target.innerHTML
+			},
 
-    handleBackToTop() {
-      console.log(this)
-      this.$EventBus.$emit('onBackToTop')
-    },
+			handleBackToTop() {
+				console.log(this)
+				this.$EventBus.$emit('onBackToTop')
+			},
 
-    onSetMarkingRules() {
-      this.isSetRules = false
-    },
+			onSetMarkingRules() {
+				this.isSetRules = false
+			},
 
-    onShowAnalysis() {
-      this.isShowAnalysis = true
-    },
+			onShowAnalysis() {
+				this.isShowAnalysis = true
+			},
 
-    /** 切换全部展开与折叠 */
-    onHandleToggle() {
-      this.$refs.exList.onHandleToggle(this.isAllOpen)
-      this.isAllOpen = !this.isAllOpen
-    },
+			/** 切换全部展开与折叠 */
+			onHandleToggle() {
+				this.$refs.exList.onHandleToggle(this.isAllOpen)
+				this.isAllOpen = !this.isAllOpen
+			},
 
-    /**
-     * exList的collapseList变化
-     * @param list
-     */
-    onToggleChange(list) {
-      this.isAllOpen = list.length !== 0
-    },
+			/**
+			 * exList的collapseList变化
+			 * @param list
+			 */
+			onToggleChange(list) {
+				this.isAllOpen = list.length !== 0
+			},
 
-    /** 返回试卷库 */
-    onBackToBank() {
-      this.$router.push({
-        name: 'testPaperList',
-        params: {
-          tabName: 'paper'
-        }
-      })
-    },
+			/** 返回试卷库 */
+			onBackToBank() {
+				this.$router.push({
+					name: 'testPaperList',
+					params: {
+						tabName: 'paper'
+					}
+				})
+			},
 
-    /* 清空试卷试题 */
-    onCleanPaper() {
-      this.paperInfo.item = []
-      this.$refs.exList.errorList = []
-      this.$refs.exList.noAnswerList = []
-      this.$EventBus.$emit('onPaperItemChange', [])
-    },
+			/* 清空试卷试题 */
+			onCleanPaper() {
+				this.paperInfo.item = []
+				this.$refs.exList.errorList = []
+				this.$refs.exList.noAnswerList = []
+				this.$EventBus.$emit('onPaperItemChange', [])
+			},
 
-    onSetScore() {
-      this.isSetScore = false
-      this.$refs.exList.exerciseList.map(item => item.score = 0)
-    },
+			onSetScore() {
+				this.isSetScore = false
+				this.$refs.exList.exerciseList.map(item => item.score = 0)
+			},
 
-    /**
-     * 组件更新删除题目时的处理
-     * @param list
-     */
-    onListUpdate(list) {
-      this.paperInfo.item = list
-    },
+			/**
+			 * 组件更新删除题目时的处理
+			 * @param list
+			 */
+			onListUpdate(list) {
+				this.paperInfo.item = list
+			},
 
-    /**
-     * 处理试题分析数据
-     * @param list 试题列表
-     */
-    handleAnalysisData(list) {
-      let that = this
-      this.analysisTableData = []
-      this.exersicesList = list // 给试题列表组件传的值
-      this.paperInfo.item = list
-      const groupList = this._.groupBy(list, 'type')
-      this._.mapKeys(groupList, function (value, key) {
-        that.analysisTableData.push({
-          name: that.exersicesType[key],
-          value: value.length
-        })
-      });
-    },
+			/**
+			 * 处理试题分析数据
+			 * @param list 试题列表
+			 */
+			handleAnalysisData(list) {
+				let that = this
+				this.analysisTableData = []
+				this.exersicesList = list // 给试题列表组件传的值
+				this.paperInfo.item = list
+				const groupList = this._.groupBy(list, 'type')
+				this._.mapKeys(groupList, function(value, key) {
+					that.analysisTableData.push({
+						name: that.exersicesType[key],
+						value: value.length
+					})
+				});
+			},
 
-    /** 重新挑题 */
-    goToPickExercise() {
-      this.$router.push({
-        name: 'exercisesList',
-        params: {
-          paperInfo: this.paperInfo
-        }
-      })
-    },
+			/** 重新挑题 */
+			goToPickExercise() {
+				this.$router.push({
+					name: 'exercisesList',
+					params: {
+						paperInfo: this.paperInfo
+					}
+				})
+			},
 
-    /** 点击题型配分 */
-    onSetScoreByType() {
-      this.$refs.exList.onSetScoreByType()
-    },
+			/** 点击题型配分 */
+			onSetScoreByType() {
+				this.$refs.exList.onSetScoreByType()
+			},
 
 
-    /**
-     * 试卷的视图模式切换
-     * @param val
-     */
-    onViewModelChange(val) {
-      this.viewModel = this.viewModel === 'type' ? 'list' : 'type'
-      this.$refs.exList.viewModel = this.viewModel
-      this.$refs.exList.collapseList = []
-      // this.$refs.exList.doRenderMathJax()
-      this.$emit('onViewModelChange', this.viewModel)
-    },
+			/**
+			 * 试卷的视图模式切换
+			 * @param val
+			 */
+			onViewModelChange(val) {
+				this.viewModel = this.viewModel === 'type' ? 'list' : 'type'
+				this.$refs.exList.viewModel = this.viewModel
+				this.$refs.exList.collapseList = []
+				// this.$refs.exList.doRenderMathJax()
+				this.$emit('onViewModelChange', this.viewModel)
+			},
 
-    /**
-     * 计算试卷题目平均难度
-     * @param arr 试题集合
-     */
-    handleDiffCalc(arr) {
-      let levelArr = arr.map(i => i.level)
-      return this._.meanBy(levelArr).toFixed(1)
-    },
+			/**
+			 * 计算试卷题目平均难度
+			 * @param arr 试题集合
+			 */
+			handleDiffCalc(arr) {
+				let levelArr = arr.map(i => i.level)
+				return this._.meanBy(levelArr).toFixed(1)
+			},
 
-    scoreUpdate(score) {
-      this.allocatedScore = this.paperInfo.score - score
-    }
+			scoreUpdate(score) {
+				this.allocatedScore = this.paperInfo.score - score
+			}
 
 
 
-  },
-  mounted() {
-    // this.isShowSave = window.location.pathname === '/home/evaluation/testPaper'
-    let paper = this.paper || this.$route.params.paper || JSON.parse(localStorage.getItem('c_edit_paper'))
-    if (!paper || !paper.item) return
-    console.log('xxxx', paper)
-	this.$EventBus.$emit('getNewPaper', paper)
-    // localStorage.setItem('_paperInfo', JSON.stringify(paper))
-    this.paperInfo = paper // 自己页面的值
-    this.paperDiff = paper.item ? this.handleDiffCalc(paper.item) : 0
+		},
+		mounted() {
+			// this.isShowSave = window.location.pathname === '/home/evaluation/testPaper'
+			let paper = this.paper || this.$route.params.paper || JSON.parse(localStorage.getItem('c_edit_paper'))
+			if (!paper || !paper.item) return
+			console.log('xxxx', paper)
+			this.$EventBus.$emit('getNewPaper', paper)
+			// localStorage.setItem('_paperInfo', JSON.stringify(paper))
+			this.paperInfo = paper // 自己页面的值
+			this.paperDiff = paper.item ? this.handleDiffCalc(paper.item) : 0
 
-  },
-  computed: {
-    isAuto() {
-      return this.paperInfo.markConfig ? this.paperInfo.markConfig.auto : false
-    },
-    ruleType() {
-      return this.paperInfo.markConfig ? this.paperInfo.markConfig.type : 0
-    },
-    isSchool() {
-      return this.$route.name === 'newSchoolPaper'
-    },
-  },
-  watch: {
-    paper: {
-      handler(newValue, oldValue) {
-		if(newValue.item && newValue.item.length){
-			this.$nextTick(() => {
-			  console.log('TestPaper组件接受的paper', newValue.item)
-			  this.$EventBus.$emit('getNewPaper', newValue)
-			})
-			this.paperInfo = newValue
+		},
+		computed: {
+			isAuto() {
+				return this.paperInfo.markConfig ? this.paperInfo.markConfig.auto : false
+			},
+			ruleType() {
+				return this.paperInfo.markConfig ? this.paperInfo.markConfig.type : 0
+			},
+			isSchool() {
+				return this.$route.name === 'newSchoolPaper'
+			},
+		},
+		watch: {
+			paper: {
+				handler(newValue, oldValue) {
+					if (newValue.item && newValue.item.length) {
+						this.$nextTick(() => {
+							console.log('TestPaper组件接受的paper', newValue.item)
+							this.$EventBus.$emit('getNewPaper', newValue)
+						})
+						this.paperInfo = newValue
+					}
+					this.paperDiff = newValue.item ? this.handleDiffCalc(newValue.item) : 4
+				},
+				immediate: true,
+				deep: true
+			}
 		}
-		this.paperDiff = newValue.item ? this.handleDiffCalc(newValue.item) : 4
-      },
-      immediate: true,
-      deep: true
-    }
-  }
-}
+	}
 </script>
 <style src="../index/TestPaper.less" lang="less" scoped>
 </style>
 <style>
-.ex-score-modal {
-  font-family: "NotoSerif", "微软正黑体", "Microsoft JhengHei UI",
-    "Microsoft JhengHei", Sans-serif;
-}
+	.ex-score-modal {
+		font-family: "NotoSerif", "微软正黑体", "Microsoft JhengHei UI",
+			"Microsoft JhengHei", Sans-serif;
+	}
 
-.complete-line {
-  padding: 0 45px;
-  border-bottom: 2px solid rgb(128, 128, 128);
-}
+	.complete-line {
+		padding: 0 45px;
+		border-bottom: 2px solid rgb(128, 128, 128);
+	}
 </style>

+ 2 - 1
TEAMModelOS/ClientApp/src/view/newsheet/BaseSvgBg.vue

@@ -1,6 +1,6 @@
 <template>
 	<div
-		style="position:relative; width: 100%; height: 100%; overflow: hidden; margin-top: 0;border-bottom: 1px solid #b1b1b1;">
+		style="position:relative; width: 100%; height: 100%; overflow: hidden; margin-top: 0;border-bottom: 0px solid #b1b1b1;">
 		<div v-show="ids === 'svg0'" class="sheet-paper-title">
 			<BaseTitleEditor :ids="'sheetName' + ids" :content="sheetPaperName"></BaseTitleEditor>
 		</div>
@@ -104,6 +104,7 @@
 			},
 
 			doRenderId(snap) {
+				console.error(this.sheetId);
 				this.sheetIdBox.remove(); // 先清除之前的绘制内容
 				this.sheetIdBox = this.snap.paper.g();
 				var page = snap

+ 1 - 0
TEAMModelOS/ClientApp/src/view/newsheet/SheetBaseInfo.vue

@@ -96,6 +96,7 @@
 				console.log(this.svgPosArr);
 				this.$store.commit('setInfoMode', 'number')
 				this.$store.commit('setInfoPos', this.svgPosArr)
+				this.$EventBus.$emit('baseInfoModify')
 			},
 
 			// 渲染准考证号填涂区域

+ 0 - 2
TEAMModelOS/ClientApp/src/view/newsheet/SheetObjective.vue

@@ -207,7 +207,6 @@
 						this.leftItems = items.slice(index, items.length)
 					}
 					let optionX = this.getStartX(number, this.leftItems, item.id,index);
-					console.log(index + 1,optionX);
 					let optionY = startY + GAP * (index + 1 <= number ? index : index % number) + ((itemsPositionArr[index].lineIndex + 1) * (this.blockHeight + this.everyOptionH))
 					optionX = xArr[itemsPositionArr[index].xArrIndex] + 15
 					// 渲染选项下标
@@ -243,7 +242,6 @@
 							NUMBER_ITEM_W,
 							NUMBER_ITEM_H
 						);
-						console.log(item.order,[xArr[itemsPositionArr[index].xArrIndex + optionIndex + 1],optionY - 10])
 						this.objectiveGroup.add(c3);
 						curXArrIndex = itemsPositionArr[index].xArrIndex + optionIndex + 1
 						

+ 63 - 23
TEAMModelOS/ClientApp/src/view/newsheet/index.vue

@@ -202,14 +202,17 @@
 					complete: vm.$t('answerSheet.complete'),
 					subjective: vm.$t('answerSheet.subjective')
 				},
-				hasModify:false
+				hasModify:false,
+				examId:null
 			};
 		},
 		created() {
 			let routerPaper = this.$route.params.paper || this.paper
 			console.log('答题卡路由数据:', routerPaper)
+			this.sheetId = routerPaper.sheet || null
 			this.curPaper = routerPaper
-			this.isFromExam = Boolean(routerPaper && routerPaper.examCode)
+			this.isFromExam = Boolean(routerPaper && routerPaper.examId)
+			this.examId = routerPaper.examId
 			this.$store.commit('clearAllConfig')
 			if (routerPaper) {
 				this.$store.commit('clearFixArr')
@@ -292,24 +295,22 @@
 			},
 			/* 打印答题卡 */
 			doDownload() {
-				// this.getPdf().then(r => {
-				// 	this.isLoading = false
-				// })
-				// return
+				
 				if(this.curPaper.sheet && this.hasModify){
 					this.$Modal.confirm({
 						title: '更新提示',
-						content: '检测到答题卡有更新,打印答题卡会覆盖原本答题卡数据,是否继续打印?',
+						content: '检测到答题卡有更新,打印答题卡会生成新的答题卡数据,是否继续打印?',
 						onOk: () => {
 							this.isLoading = true
 							this.$EventBus.$emit('onCreateSheet')
-							this.doSaveSheet().then(async res => {
+							this.doSaveSheet(false).then(async res => {
 								let paperInfo = this.$store.state.answerSheet.paperItem
-								this.sheetId = res.config.id
+								this.sheetId = res.config.id 
 								if (this.isFromExam) {
 									this.$EventBus.$emit('createSheetId', res.config.id)
 								}
-								this.getPdf().then(r => {
+								this.getPdf().then(async r => {
+									await this.doUploadPDF(r)
 									this.isLoading = false
 								})
 							}).catch(err => {
@@ -321,31 +322,64 @@
 				}else{
 					this.isLoading = true
 					this.$EventBus.$emit('onCreateSheet')
-					this.doSaveSheet().then(async res => {
-						let paperInfo = this.$store.state.answerSheet.paperItem
-						this.sheetId = res.config.id
-						if (this.isFromExam) {
-							this.$EventBus.$emit('createSheetId', res.config.id)
-						}
-						this.getPdf().then(r => {
+					// 有答题卡ID但是没有修改
+					if(this.sheetId){
+						this.getPdf().then(async r => {
+							await this.doUploadPDF(r)
 							this.isLoading = false
 						})
-					}).catch(err => {
-						console.log(err)
-						this.isLoading = false
-					})
+					}else{
+						// 没有答题卡ID 也无修改 就是新增答题卡
+						this.doSaveSheet(false).then(async res => {
+							let paperInfo = this.$store.state.answerSheet.paperItem
+							this.sheetId = res.config.id
+							if (this.isFromExam) {
+								this.$EventBus.$emit('createSheetId', res.config.id)
+							}
+							this.getPdf().then(async r => {
+								await this.doUploadPDF(r)
+								this.isLoading = false
+							})
+						}).catch(err => {
+							console.log(err)
+							this.isLoading = false
+						})
+					}
 				}
 				
 			},
+			
+			doUploadPDF(blob){
+				return new Promise(async (r,j) => {
+					let paperInfo = this.$store.state.answerSheet.paperItem
+					let file = new File([blob],`${paperInfo.name}-${this.sheetId}.pdf`,{type:'application/pdf'})
+					let curScope = this.examId ? paperInfo.examScope : paperInfo.scope
+					let sasData = curScope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+					let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, curScope)
+					let path = this.examId ? `exam/${this.examId}/paper/${paperInfo.name}` : `paper/${paperInfo.name}`
+					try {
+						// 等待上传blob的返回结果
+						let blobFile = await containerClient.upload(file, path)
+						if (blobFile.blob) {
+							r(200)
+						} else {
+							j(500)
+						}
+					}catch(e){
+						j(e)
+					}
+				})
+			},
+			
 			/* 保存答题卡模板数据 */
-			doSaveSheet() {
+			doSaveSheet(withId) {
 				return new Promise((r, j) => {
 					let paperInfo = this.$store.state.answerSheet.paperItem
 					let configParams = this.$store.state.answerSheet.config
 					console.log(configParams.infoPos)
 					let curCode = paperInfo.examCode || paperInfo.code
 					let curScope = paperInfo.examScope || paperInfo.scope
-					if (paperInfo.sheet) {
+					if (paperInfo.sheet && withId) {
 						configParams.id = paperInfo.sheet
 					}
 					configParams.pageHeight = Number(configParams.pageHeight.toFixed())
@@ -507,6 +541,7 @@
 					this.groups = this.groups.filter(i => i.items.length)
 				}
 				this.$EventBus.$emit('doRefresh')
+				this.hasModify = true
 			})
 			this.$EventBus.$off('titleMovePage')
 			this.$EventBus.$on('titleMovePage', val => {
@@ -525,6 +560,11 @@
 			this.$EventBus.$on("hasDrag", () => {
 			  this.hasModify = true
 			});
+			
+			this.$EventBus.$off("baseInfoModify")
+			this.$EventBus.$on("baseInfoModify", () => {
+			  this.hasModify = true
+			});
 		},
 		beforeRouteEnter(to, from, next) {
 			next(vm => {