index.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
  8. <script type="text/javascript" async
  9. src="https://mingxuejingbang.oss-cn-beijing.aliyuncs.com/MathJaxFiles/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"></script>
  10. <script type="text/javascript" async src="js/globalVariable.js"></script>
  11. <script type="text/javascript" async src="js/html2canvas.min.js"></script>
  12. <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  13. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  14. <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
  15. <title></title>
  16. <style>
  17. html,
  18. body {
  19. margin: 0;
  20. padding: 0
  21. }
  22. .el-radio--medium.is-bordered {
  23. height: auto;
  24. padding-bottom: 8px;
  25. }
  26. #title::after {
  27. display: table;
  28. content: "";
  29. clear: both;
  30. }
  31. </style>
  32. </head>
  33. <body>
  34. <div id="app">
  35. <div style="min-height:300px;">
  36. <div id="title" style="background:#fff;max-width:1024px">
  37. <div id="qs" style="padding-bottom: 15px" v-html="data.title"></div>
  38. <div id="ans" style="background:#fff">
  39. <template v-for="(itemOpt, idx) in data.options">
  40. <div :key="idx">
  41. <el-radio style="margin-bottom: 15px" :label="selectOpt[idx]" border size="medium">
  42. {{ selectOpt[idx] + ' 、 ' }}<span style="white-space: normal" v-html="itemOpt"></span>
  43. </el-radio>
  44. </div>
  45. </template>
  46. </div>
  47. </div>
  48. </div>
  49. <div style="margin-bottom:20px;padding: 15px;background: rgb(255, 255, 255); max-width: 1024px;">
  50. <el-input v-model="questionId" style="width: 150px;" placeholder="请输入题目编号"></el-input>
  51. <el-button type="primary" :disabled="isAuto" @click="search">搜索</el-button>
  52. <el-button type="primary" :disabled="isAuto" @click="upLoad">手动上传</el-button>
  53. <el-button type="primary" @click="auto">{{isAuto?'暂停':'自动运行'}}</el-button>
  54. </div>
  55. <div v-if="imgUri" style="margin-top:30px;padding: 15px;background: rgb(255, 255, 255); max-width: 1024px;">
  56. 图片展示:
  57. <img :src="imgUri" alt="" crossorigin="anonymous">
  58. </div>
  59. </div>
  60. <script>
  61. var exampleData = {
  62. selectOpt: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
  63. data: {},
  64. time: null,
  65. domain: '',
  66. isAuto: false,
  67. questionId: '51748',
  68. imgUri: '',
  69. times: 1
  70. }
  71. // window.onload = function(){
  72. new Vue({
  73. el: '#app',
  74. data: exampleData,
  75. created() {
  76. // if(this.domain == 'localhost:9800'){
  77. this.domain = 'https://front.mingxuejinbang.com'
  78. // }
  79. // this.getData()
  80. },
  81. methods: {
  82. convertImgToBase64(img) {
  83. return new Promise((resolve, reject) => {
  84. let canvas = document.createElement('canvas');
  85. const ctx = canvas.getContext('2d');
  86. canvas.height = img.height;
  87. canvas.width = img.width;
  88. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  89. let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
  90. const base64 = canvas.toDataURL("image/" + ext);
  91. canvas = null;
  92. const holder = new Image();
  93. holder.setAttribute('crossOrigin', 'anonymous')
  94. holder.onload = (e) => {
  95. resolve(holder)
  96. }
  97. holder.src = base64;
  98. // return base64;
  99. });
  100. },
  101. hasImg(dom) {
  102. for (let i of dom?.children || []) {
  103. if (i.nodeName === 'IMG') {
  104. return true;
  105. }
  106. }
  107. return false;
  108. },
  109. getCanvasWrap(width, height) {
  110. const canvasWrap = document.createElement('canvas')
  111. canvasWrap.width = this.times * width
  112. canvasWrap.height = this.times * height
  113. canvasWrap.getContext('2d').scale(this.times, this.times)
  114. return canvasWrap;
  115. },
  116. waitingLoaingImg(cb) {
  117. let doms;
  118. const qs = document.querySelector('#qs');
  119. // 每次重置容器高度
  120. qs.style.height = 'auto';
  121. if (this.hasImg(qs)) {
  122. doms = qs?.children ?? [];
  123. } else {
  124. doms = qs.firstChild?.children ?? [];
  125. }
  126. const promiseArr = [];
  127. for (let i of doms) {
  128. if (i.nodeName === 'IMG') {
  129. const promise = new Promise((resolve, reject) => {
  130. i.onload = async (e) => {
  131. // 如果图片存在浮动,需要手动设置容器的高度
  132. if (i.style.float) {
  133. qs.style.height = Math.max(qs.getBoundingClientRect().height, i.height) + 'px'
  134. }
  135. const { width, height } = qs.getBoundingClientRect();
  136. html2canvas(qs, {
  137. canvas: this.getCanvasWrap(width, height),
  138. useCORS: true,
  139. }).then((canvas) => {
  140. resolve(canvas)
  141. })
  142. }
  143. });
  144. promiseArr.push(promise);
  145. }
  146. }
  147. if (promiseArr.length === 0) {
  148. const { width, height } = qs.getBoundingClientRect();
  149. html2canvas(qs, {
  150. canvas: this.getCanvasWrap(width, height),
  151. useCORS: true,
  152. }).then((canvas) => {
  153. if (cb) {
  154. cb(canvas)
  155. }
  156. })
  157. } else {
  158. Promise.all(promiseArr).then(res => {
  159. // 虽然用了Promise.all,但实际假设只有一张图片
  160. if (cb) {
  161. cb(res[0])
  162. }
  163. });
  164. }
  165. },
  166. search() {
  167. if (this.questionId) {
  168. this.getData(this.questionId)
  169. } else {
  170. this.$message({
  171. message: '请输入题目编号',
  172. type: 'warning'
  173. });
  174. }
  175. },
  176. auto() {
  177. this.isAuto = !this.isAuto;
  178. if (this.isAuto) {
  179. this.getData()
  180. }
  181. },
  182. upLoad() {
  183. if (this.questionId && this.imgUri) {
  184. this.uploadQuestionImage(this.imgUri, 1)
  185. } else {
  186. this.$message({
  187. message: '请先搜索题目',
  188. type: 'warning'
  189. });
  190. }
  191. },
  192. getData(questionId) {
  193. axios.defaults.withCredentials = true;
  194. let str = ''
  195. if (questionId) {
  196. str = '?questionId=' + questionId
  197. }
  198. axios.get(this.domain + '/prod-api/front/questionCollection/getNextQuestionForImageGenerate' + str).then(response => {
  199. if (response.data.code == 200) {
  200. this.data = response.data.data
  201. this.$nextTick(() => {
  202. this.MathQueueTitle(str)
  203. })
  204. } else {
  205. this.isAuto = false
  206. this.$message({
  207. message: '获取题目信息失败',
  208. type: 'warning'
  209. });
  210. }
  211. }).catch(function (error) { // 请求失败处理
  212. this.isAuto = false
  213. this.$message.error('网络请求异常!');
  214. });
  215. },
  216. uploadQuestionImage(src, type) {
  217. axios.defaults.withCredentials = true;
  218. var formData = new FormData()
  219. formData.append('questionId', this.data.questionId)
  220. formData.append('imageBase64', src)
  221. if (this.isAuto == false) {
  222. formData.append('manual', true)
  223. }
  224. axios.post(this.domain + '/prod-api/front/questionCollection/uploadQuestionImage', formData).then(response => {
  225. console.log(response)
  226. if (response.data.code == 200) {
  227. if (this.isAuto) {
  228. setTimeout(() => {
  229. this.getData()
  230. }, 1000);
  231. }
  232. if (type) {
  233. this.$message({
  234. message: '上传题目信息成功!',
  235. type: 'success'
  236. });
  237. }
  238. } else {
  239. this.isAuto = false
  240. this.$message({
  241. message: '上传题目信息失败!',
  242. type: 'warning'
  243. });
  244. }
  245. }).catch(function (error) { // 请求失败处理
  246. this.isAuto = false
  247. this.$message.error('网络请求异常!');
  248. });
  249. },
  250. getCookie(str) {//获取cookie
  251. let cookie = document.cookie.split('; ');
  252. let cookies = {}
  253. cookie.forEach(item => {
  254. cookies[item.split('=')[0]] = item.split('=')[1]
  255. })
  256. return cookies[str]
  257. },
  258. MathQueueTitle(str) {//初始化公式
  259. if (MathQueue) {
  260. clearInterval(this.time)
  261. MathQueue('title')
  262. // setTimeout(() => {
  263. // this.$nextTick(() => {
  264. // this.downLoad(str)
  265. this.waitingLoaingImg((canvas) => { this.downLoad(str, canvas) });
  266. // })
  267. // }, 1000)
  268. } else {
  269. this.time = setInterval(() => {
  270. this.MathQueueTitle()
  271. }, 5)
  272. }
  273. },
  274. downLoad(type, canvas1) {
  275. if (!this.data.questionId) {
  276. this.$message({
  277. message: '请先搜索题目!',
  278. type: 'warning'
  279. });
  280. return
  281. }
  282. this.questionId=this.data.questionId
  283. const times = 2 // 图片放大倍数,能提升清晰度
  284. let _this = this
  285. _this.imgUri = ''
  286. document.getElementById('qs').style.display = 'none'
  287. let _canvas = document.getElementById('ans')
  288. const { width, height } = _canvas.getBoundingClientRect();
  289. html2canvas(_canvas, {
  290. canvas: this.getCanvasWrap(width, height),
  291. useCORS: true,
  292. }).then((canvas2) => {
  293. document.getElementById('qs').style.display = 'block'
  294. var canvas3 = document.createElement("canvas");
  295. canvas3.width = Math.max(canvas1?.width*times ?? 0, canvas2.width*times)
  296. canvas3.height = (canvas1?.height*times ?? 0) + (canvas2.width*times && canvas2.height*times ? canvas2.height*times : 0)
  297. var ctx = canvas3.getContext("2d");
  298. // ctx.scale(times, times) ///缩放等级
  299. // 绘制题目
  300. canvas1 && ctx.drawImage(canvas1, 0, 0, canvas1.width*times, canvas1.height*times);
  301. if (canvas2.width && canvas2.height) {
  302. // 绘制答案
  303. ctx.drawImage(canvas2, 0, canvas1?.height*times ?? 0, canvas2.width*times, canvas2.height*times);
  304. }
  305. _this.imgUri = canvas3.toDataURL('image/png')
  306. canvas1 = null
  307. canvas2 = null
  308. canvas3 = null
  309. if (!type) {
  310. _this.uploadQuestionImage(_this.imgUri)
  311. }
  312. })
  313. },
  314. }
  315. });
  316. // }
  317. </script>
  318. </body>
  319. </html>