Commit d3943e0ddc5d04ef2c3044c7bd9239906828b6ed

Authored by LH_PC
1 parent 06869a45

feat:错题打印

.gitignore
... ... @@ -28,3 +28,4 @@ pnpm-debug.log*
28 28 src/views/portrait/test.vue
29 29 /src/.vs
30 30 /.vs
  31 +/.vs/slnx.sqlite
... ...
.vs/slnx.sqlite deleted
No preview for this file type
src/config/index.js
1 1 const modeUrl = {
2 2 // 开发环境
3 3 development: {
4   - baseURL: "/",
  4 + baseURL: "/api/",
5 5 authBaseURL: "",
6 6 $cdn:""
7 7 },
8 8 // 生产环境
9 9 production: {
10   - baseURL: "/",
  10 + baseURL: "/api/",
11 11 authBaseURL: "",
12 12 $cdn:""
13 13 },
... ...
src/utils/index.js
... ... @@ -609,6 +609,17 @@ export function getBlob(url) {
609 609 );
610 610 });
611 611 }
  612 +export function fetchHTML(url) {
  613 + return new Promise((resolve) => {
  614 + resolve(
  615 + service({
  616 + url: url,
  617 + withCredentials: false,
  618 + method: "get"
  619 + })
  620 + );
  621 + });
  622 +}
612 623 /**
613 624 * 打包压缩下载
614 625 */
... ... @@ -867,10 +878,318 @@ export function formatGradeNameClass(data) {
867 878 });
868 879 return gradeNameArr;
869 880 }
870   -_
871 881  
872   -export function tablePrint(options) {
  882 +///试卷定制化打印
  883 +export async function paperPrint(paper) {
  884 + let printWin = window.open("", "_blank", "width=800,height=600,resizable=no");
  885 + var browser = getBrowserEngine(printWin);
  886 + var subjectName = paper.subjectName;
  887 + var paperTitle = paper.title;
  888 + var paperQuestions = paper.questionList;
  889 + function getBrowserEngine(windowParams) {
  890 + if (windowParams.navigator.userAgent.indexOf("Edge") > -1) {
  891 + return "EdgeHTML";
  892 + }
  893 + if (windowParams.navigator.userAgent.indexOf("Edg") > -1) {
  894 + return "Blink"; // Microsoft Edge (Chromium)
  895 + }
  896 + if (windowParams.navigator.userAgent.indexOf("Firefox") > -1) {
  897 + return "Gecko";
  898 + }
  899 + if (windowParams.navigator.userAgent.indexOf("Trident") > -1) {
  900 + return "Trident"; // IE
  901 + }
  902 + if (/Chrome/.test(windowParams.navigator.userAgent) && /Google Inc/.test(windowParams.navigator.vendor)) {
  903 + return 'Google Chrome';
  904 + }
  905 + if (/360/.test(windowParams.navigator.userAgent) || /QIHU/.test(windowParams.navigator.userAgent)) {
  906 + return '360 Browser';
  907 + }
  908 + return "Blink"; // Assume it's Chrome, Safari, or an alternative Blink-based browser
  909 + }
  910 + function numberToChinese(num) {
  911 + const chineseDigits = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
  912 + const chineseUnits = ["", "十", "百", "千", "万", "亿"];
  913 +
  914 + let result = '';
  915 + let unitPos = 0; // 单位的位置
  916 + let zeroFlag = false; // 是否出现过零
  917 +
  918 + if (num === 0) {
  919 + return chineseDigits[0]; // 特殊情况,0 返回 "零"
  920 + }
  921 +
  922 + // 处理数字,每次取一位并加上单位
  923 + while (num > 0) {
  924 + const currentDigit = num % 10; // 取最后一位数字
  925 + if (currentDigit === 0) {
  926 + if (!zeroFlag) {
  927 + result = chineseDigits[currentDigit] + result; // 只在出现零时添加
  928 + zeroFlag = true; // 标记零已经出现
  929 + }
  930 + } else {
  931 + result = chineseDigits[currentDigit] + chineseUnits[unitPos] + result;
  932 + zeroFlag = false; // 重置零的标记
  933 + }
873 934  
  935 + num = Math.floor(num / 10); // 去掉最后一位数字
  936 + unitPos++;
  937 + }
  938 +
  939 + // 处理 '一十' 和 '一百' 等情况
  940 + if (result.startsWith('一十')) {
  941 + result = result.substring(1); // 去掉 '一',例如 '一十' -> '十'
  942 + }
  943 +
  944 + return result;
  945 + }
  946 + function htmlParseDom(html, getStyleScripts) {
  947 + var tempDom = document.createElement('div');
  948 + tempDom.innerHTML = html;
  949 + var doms = tempDom.querySelectorAll('p');
  950 + if (getStyleScripts == true) {
  951 + var styleDoms = tempDom.querySelectorAll('style');
  952 + var scriptDoms = tempDom.querySelectorAll('script');
  953 + return {
  954 + doms: doms,
  955 + styles: styleDoms,
  956 + scripts: scriptDoms
  957 + }
  958 + }
  959 + return { doms: doms }
  960 + }
  961 + function generatePageParams() {
  962 + const totalHeightPx = Math.max(
  963 + printWin.document.documentElement.scrollHeight, // 整个文档高度
  964 + printWin.document.body.scrollHeight // Body 的高度
  965 + );
  966 + const totalHeightMM = totalHeightPx * 25.4 / 96;
  967 + // ie浏览器高度
  968 + var A4HeightMM = 287;
  969 + if (browser == "Google Chrome") {
  970 + A4HeightMM = 297;
  971 + }
  972 + var pages = Math.ceil(totalHeightMM / A4HeightMM) + 1;
  973 + for (var page = 0; page < pages; page++) {
  974 + var pageFooteDiv = printWin.document.createElement('div');
  975 + pageFooteDiv.classList.add('page-footer');
  976 + pageFooteDiv.innerText = `${paperTitle} ${subjectName} 第${page + 1}页(共${pages}页)`;
  977 + pageFooteDiv.style.top = (page + 1) * A4HeightMM + (page * 5.5) + 'mm';
  978 + printWin.document.body.appendChild(pageFooteDiv);
  979 + }
  980 + }
  981 + // size: A4 portrait;
  982 + // size: A3 landscape;
  983 +
  984 + printWin.document.title = "中天易教";
  985 + const style = printWin.document.createElement('style');
  986 + style.innerHTML = `
  987 + @media print
  988 + {
  989 + @page {
  990 + size: A4 portrait;
  991 + height: 300mm;
  992 + margin-top:5mm;
  993 + margin-bottom:10mm;
  994 + margin-left:2mm;
  995 + margin-right:2mm;
  996 + }
  997 +
  998 + body {
  999 + counter-reset: page-number; /* 重置页码计数器 */
  1000 + }
  1001 +
  1002 + mn {
  1003 + padding-top:2px;
  1004 + }
  1005 + }
  1006 + table tfoot {
  1007 + height: 0px;
  1008 + display: table-footer-group;
  1009 + }
  1010 + table thead {
  1011 + height: 20px;
  1012 + display: table-header-group;
  1013 + }
  1014 + .student-input {
  1015 + text-align:center;
  1016 + margin-bottom:10px;
  1017 + span
  1018 + {
  1019 + margin-right:10px;
  1020 + }
  1021 + }
  1022 + .page-left {
  1023 + height: 1100px;
  1024 + width:30px;
  1025 + position:fixed;
  1026 + top:0;
  1027 + left:0;
  1028 + }
  1029 + .page-right {
  1030 + height:1100px;
  1031 + width:30px;
  1032 + position:fixed;
  1033 + top:0;
  1034 + right:0;
  1035 + }
  1036 + .page-header {
  1037 + height:20px;
  1038 + width:100%;
  1039 + text-align:center;
  1040 + position:fixed;
  1041 + top:0;
  1042 + left:0;
  1043 + }
  1044 + .page-footer {
  1045 + height:20px;
  1046 + width:100%;
  1047 + text-align:center;
  1048 + position: absolute;
  1049 + }
  1050 + h3,h2
  1051 + {
  1052 + margin:3px 0px 3px 0px;
  1053 + }
  1054 + .title-header
  1055 + {
  1056 + .title-content {
  1057 + text-align:center;
  1058 + }
  1059 + }
  1060 + b
  1061 + {
  1062 + font-weight:500;
  1063 + margin:10px 0px;
  1064 + }
  1065 + p,table
  1066 + {
  1067 + font-size:16px;
  1068 + margin:0px;
  1069 + padding:0px 0px 2px 0px;
  1070 +
  1071 + margin-block-start:0px;
  1072 + margin-block-end: 0px;
  1073 + margin-inline-start: 0px;
  1074 + margin-inline-end: 0px;
  1075 + span,*,image,img,tr,td
  1076 + {
  1077 + font-size:16px;
  1078 + line-height:20px !important;
  1079 + }
  1080 + img,image
  1081 + {
  1082 + margin:0px;
  1083 + padding:0px;
  1084 + transform: scale(0.65);
  1085 + transform-origin: center;
  1086 + }
  1087 + }`;
  1088 +
  1089 + printWin.document.head.appendChild(style);
  1090 +
  1091 + const titleBoxDom = printWin.document.createElement('div');
  1092 + titleBoxDom.classList.add('title-header');
  1093 + const titleDom = printWin.document.createElement('h3');
  1094 + titleDom.innerText = paperTitle;
  1095 + titleDom.classList.add('title-content');
  1096 + const subjectDom = printWin.document.createElement('h2');
  1097 + subjectDom.innerText = subjectName;
  1098 + subjectDom.classList.add('title-content');
  1099 + titleBoxDom.appendChild(titleDom);
  1100 + titleBoxDom.appendChild(subjectDom);
  1101 + printWin.document.body.appendChild(titleBoxDom);
  1102 +
  1103 + const studentInputBoxDom = printWin.document.createElement('div');
  1104 + studentInputBoxDom.classList.add('student-input');
  1105 + const studentClassInputDom = printWin.document.createElement('span');
  1106 + studentClassInputDom.innerHTML = '班级:________________';
  1107 + const studentNameInputDom = printWin.document.createElement('span');
  1108 + studentNameInputDom.innerHTML = '姓名:________________';
  1109 + const studentNoInputDom = printWin.document.createElement('span');
  1110 + studentNoInputDom.innerHTML = '学号:________________';
  1111 + studentInputBoxDom.appendChild(studentClassInputDom);
  1112 + studentInputBoxDom.appendChild(studentNameInputDom);
  1113 + studentInputBoxDom.appendChild(studentNoInputDom);
  1114 + printWin.document.body.appendChild(studentInputBoxDom);
  1115 +
  1116 + const tableDom = printWin.document.createElement('table');
  1117 + const theadDom = printWin.document.createElement('thead');
  1118 + const theadTrDom = printWin.document.createElement('tr');
  1119 + theadTrDom.appendChild(printWin.document.createElement('th'));
  1120 + theadTrDom.appendChild(printWin.document.createElement('th'));
  1121 + theadTrDom.appendChild(printWin.document.createElement('th'));
  1122 + theadDom.appendChild(theadTrDom);
  1123 + tableDom.appendChild(theadDom);
  1124 +
  1125 + const tbodyDom = printWin.document.createElement('tbody');
  1126 +
  1127 + for (var iof = 0; iof < paperQuestions.length; iof++) {
  1128 + var item = paperQuestions[iof];
  1129 + if (!item || !item.subQuestions) continue;
  1130 +
  1131 + const tbodyTrDom = printWin.document.createElement('tr');
  1132 + const tbodyLeftAltTdDom = printWin.document.createElement('td');
  1133 + const tbodyContentTdDom = printWin.document.createElement('td');
  1134 + const tbodyRightAltTdDom = printWin.document.createElement('td');
  1135 +
  1136 + const questionTitleDom = printWin.document.createElement('div');
  1137 + questionTitleDom.innerText = `${numberToChinese(iof + 1)}、${item.questionTitle}(本节共${item.subQuestions.length}小题,共${item.score}分)`;
  1138 +
  1139 + tbodyContentTdDom.appendChild(questionTitleDom);
  1140 + tbodyTrDom.appendChild(tbodyLeftAltTdDom);
  1141 + tbodyTrDom.appendChild(tbodyContentTdDom);
  1142 + tbodyTrDom.appendChild(tbodyRightAltTdDom);
  1143 + tbodyDom.appendChild(tbodyTrDom);
  1144 +
  1145 + for (var idof = 0; idof < item.subQuestions.length; idof++) {
  1146 + const qTbodyTrDom = printWin.document.createElement('tr');
  1147 + const qTbodyLeftAltTdDom = printWin.document.createElement('td');
  1148 + const qTbodyContentTdDom = printWin.document.createElement('td');
  1149 + const qTbodyRightAltTdDom = printWin.document.createElement('td');
  1150 +
  1151 + const questionDom = printWin.document.createElement('div');
  1152 + var subItem = item.subQuestions[idof];
  1153 + var screenshotHtml = await fetchHTML(subItem.screenshot);
  1154 + var getStyleScripts = iof == 0 && idof == 0;
  1155 + var screenshotObject = htmlParseDom(screenshotHtml, getStyleScripts);
  1156 + var screenshotDoms = screenshotObject.doms;
  1157 + if (screenshotDoms.length <= 0) continue;
  1158 + for (var dom = 0; dom < screenshotDoms.length; dom++) {
  1159 + var screenshotDom = screenshotDoms[dom];
  1160 + questionDom.appendChild(screenshotDom);
  1161 + }
  1162 + qTbodyContentTdDom.appendChild(questionDom);
  1163 + qTbodyTrDom.appendChild(qTbodyLeftAltTdDom);
  1164 + qTbodyTrDom.appendChild(qTbodyContentTdDom);
  1165 + qTbodyTrDom.appendChild(qTbodyRightAltTdDom);
  1166 + tbodyDom.appendChild(qTbodyTrDom);
  1167 + }
  1168 + }
  1169 + tableDom.appendChild(tbodyDom);
  1170 + printWin.document.body.appendChild(tableDom);
  1171 +
  1172 + const tfootDom = printWin.document.createElement('tfoot');
  1173 + const tfootTrDom = printWin.document.createElement('tr');
  1174 + tfootTrDom.appendChild(printWin.document.createElement('td'));
  1175 + tfootTrDom.appendChild(printWin.document.createElement('td'));
  1176 + tfootTrDom.appendChild(printWin.document.createElement('td'));
  1177 + tfootDom.appendChild(tfootTrDom);
  1178 + tableDom.appendChild(tfootDom);
  1179 + // generatePageParams();
  1180 + const iamges = printWin.document.querySelectorAll('img');
  1181 + if (iamges.length >= 1) {
  1182 + iamges[iamges.length - 1].onload = function () {
  1183 + printWin.print();
  1184 + printWin.close();
  1185 + }
  1186 + } else {
  1187 + printWin.print();
  1188 + printWin.close();
  1189 + }
  1190 +}
  1191 +
  1192 +export function tablePrint(options) {
874 1193 var id = options.id;
875 1194 var title = options.title;
876 1195 var lindex = options.lindex;
... ... @@ -880,7 +1199,7 @@ export function tablePrint(options) {
880 1199 var diffNumber = options.diffNumber ?? 0;
881 1200 var diffStNumber = options.diffStNumber ?? 0;
882 1201 let divs = document.getElementById(id);
883   - let awin = window.open("中天易教", "_blank");
  1202 + let awin = window.open("中天易教", "_blank", "width=800,height=600,resizable=no");
884 1203 awin.document.getElementsByTagName(
885 1204 "head"
886 1205 )[0].innerHTML = `<style>
... ... @@ -888,16 +1207,15 @@ export function tablePrint(options) {
888 1207 @page {
889 1208 size: A4 portrait;
890 1209 margin-top: 4mm;
891   - margin-left:2mm;
892   - margin-right:2mm;
  1210 + margin-left: 2mm;
  1211 + margin-right: 2mm;
893 1212 }
894 1213  
895 1214  
896 1215 body {
897 1216 margin: 2mm;
898 1217 font-size: 8px;
899   - }
900   -
  1218 + }
901 1219 }
902 1220  
903 1221 * :not(.tit) {
... ... @@ -1294,7 +1612,7 @@ export function tablePrint(options) {
1294 1612  
1295 1613 awin.print();
1296 1614  
1297   - awin.close()
  1615 + awin.close();
1298 1616 }
1299 1617  
1300 1618 export const cNum = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五",
... ...
src/views/basic/askTestQuestion/index.vue
... ... @@ -70,7 +70,9 @@
70 70 <el-dropdown-menu slot="dropdown">
71 71 <el-dropdown-item
72 72 @click.native="_detailQ(item.id)">查看</el-dropdown-item>
73   - <el-dropdown-item @click.native="_updateQ(item)">修改</el-dropdown-item>
  73 + <el-dropdown-item v-if="dataType != 1"
  74 + @click.native="_print(item)">打印</el-dropdown-item>
  75 + <el-dropdown-item @click.native="_updateQ(item)">修改</el-dropdown-item>
74 76 <el-dropdown-item @click.native="_copy(item)">复制</el-dropdown-item>
75 77 <el-dropdown-item>
76 78 <el-popconfirm style="color:gray !important;"
... ... @@ -317,6 +319,7 @@
317 319  
318 320 <script>
319 321 import { setDateRules, downloadFile } from "@/utils";
  322 +import { paperPrint } from "@/utils";
320 323 import example from "@/assets/images/example.png";
321 324 import example2 from "@/assets/images/example2.png";
322 325 import axios from "axios";
... ... @@ -646,6 +649,18 @@ export default {
646 649 _delete() {
647 650  
648 651 },
  652 + async _print(item){
  653 + this.$loading.open();
  654 + const { data, status, info } = await this.$request.tPaperDetail({
  655 + paperId: item.id
  656 + });
  657 + this.$loading.close();
  658 + if (status != 0) {
  659 + this.$message.error(info);
  660 + return;
  661 + }
  662 + await paperPrint(data);
  663 + },
649 664 _updateQ(item) {
650 665  
651 666 var currentClass = this.classList.find(item => item.classId == this.query.class);
... ...