|
@@ -0,0 +1,374 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh">
|
|
|
+
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
|
+ <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
|
|
|
+ <script type="text/javascript" async
|
|
|
+ src="https://mingxuejingbang.oss-cn-beijing.aliyuncs.com/MathJaxFiles/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"></script>
|
|
|
+ <script type="text/javascript" async src="js/globalVariable.js"></script>
|
|
|
+ <script type="text/javascript" async src="js/html2canvas.min.js"></script>
|
|
|
+ <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
|
|
+ <script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
|
|
+ <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
|
|
|
+ <title></title>
|
|
|
+ <style>
|
|
|
+ html,
|
|
|
+ body {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-radio--medium.is-bordered {
|
|
|
+ height: auto;
|
|
|
+ padding-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ #title::after {
|
|
|
+ display: table;
|
|
|
+ content: "";
|
|
|
+ clear: both;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div id="app">
|
|
|
+ <div style="min-height:300px;">
|
|
|
+ <div id="title" style="background:#fff;max-width:1024px">
|
|
|
+ <div style="padding-top: 10px; padding-left: 10px;">
|
|
|
+ <div id="qs" style="padding-bottom: 15px" v-html="data.title"></div>
|
|
|
+ <div id="ans" style="background:#fff;width: fit-content;">
|
|
|
+ <template v-for="(itemOpt, idx) in data.options">
|
|
|
+ <div :key="idx">
|
|
|
+ <el-radio style="margin-bottom: 15px" :label="selectOpt[idx]" border size="medium">
|
|
|
+ {{ selectOpt[idx] + ' 、 ' }}<span style="white-space: normal" v-html="itemOpt"></span>
|
|
|
+ </el-radio>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ <div style="height:15px"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="margin-bottom:20px;padding: 15px;background: rgb(255, 255, 255); max-width: 1024px;">
|
|
|
+ <el-input v-model="questionId" style="width: 150px;" placeholder="请输入题目编号"></el-input>
|
|
|
+ <el-button type="primary" :disabled="isAuto" @click="search">搜索</el-button>
|
|
|
+ <el-button type="primary" :disabled="isAuto" @click="upLoad">手动上传</el-button>
|
|
|
+ <el-button type="primary" @click="auto">{{ isAuto ? '暂停' : '自动运行' }}</el-button>
|
|
|
+ </div>
|
|
|
+ <div v-if="imgUri" style="margin-top:30px;padding: 15px;background: rgb(255, 255, 255); max-width: 1024px;">
|
|
|
+ <!-- 图片展示: -->
|
|
|
+ <img :src="imgUri" alt="" crossorigin="anonymous">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ <script>
|
|
|
+ var exampleData = {
|
|
|
+ selectOpt: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
|
|
|
+ data: {},
|
|
|
+ time: null,
|
|
|
+ domain: '',
|
|
|
+ isAuto: false,
|
|
|
+ questionId: '18342627',
|
|
|
+ imgUri: '',
|
|
|
+ times: 2,
|
|
|
+ qsHeight: null
|
|
|
+ }
|
|
|
+ // window.onload = function(){
|
|
|
+ new Vue({
|
|
|
+ el: '#app',
|
|
|
+ data: exampleData,
|
|
|
+ created() {
|
|
|
+ // if(this.domain == 'localhost:9800'){
|
|
|
+ this.domain = 'https://front.mingxuejinbang.com'
|
|
|
+ // }
|
|
|
+ this.getData()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ convertImgToBase64(img) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ let canvas = document.createElement('canvas')
|
|
|
+ const ctx = canvas.getContext('2d')
|
|
|
+ canvas.height = img.height
|
|
|
+ canvas.width = img.width
|
|
|
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
|
|
+ let ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase()
|
|
|
+ const base64 = canvas.toDataURL('image/' + ext)
|
|
|
+ canvas = null
|
|
|
+ const holder = new Image()
|
|
|
+ holder.setAttribute('crossOrigin', 'anonymous')
|
|
|
+ holder.onload = (e) => {
|
|
|
+ resolve(holder)
|
|
|
+ }
|
|
|
+ holder.src = base64
|
|
|
+ // return base64;
|
|
|
+ })
|
|
|
+ },
|
|
|
+ hasImg(dom) {
|
|
|
+ for (let i of dom?.children || []) {
|
|
|
+ if (i.nodeName === 'IMG') {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ getCanvasWrap(width, height) {
|
|
|
+ const canvasWrap = document.createElement('canvas')
|
|
|
+ canvasWrap.width = this.times * width
|
|
|
+ canvasWrap.height = this.times * height
|
|
|
+ canvasWrap.style.width = this.times * width + 'px'
|
|
|
+ canvasWrap.style.height = this.times * height + 'px'
|
|
|
+ canvasWrap.getContext('2d').scale(this.times, this.times)
|
|
|
+ return canvasWrap
|
|
|
+ },
|
|
|
+ getUnderline(num) {
|
|
|
+ const underline = document.createElement('div')
|
|
|
+ // 暂定于1个空格5像素
|
|
|
+ underline.setAttribute('style', `width: ${num * 5}px;border-bottom: 1px solid #000000;display: inline-block;vertical-align: baseline;transform: translateY(2px);`)
|
|
|
+ return underline
|
|
|
+ },
|
|
|
+ // 遍历所有子元素
|
|
|
+ findAllEle(promiseArr, parent) {
|
|
|
+ for (let i of parent.childNodes) {
|
|
|
+ if (i.nodeName === 'U') {
|
|
|
+ parent.insertBefore(this.getUnderline(i.innerText.length), i)
|
|
|
+ parent.removeChild(i)
|
|
|
+ } else if (i.nodeName === 'IMG') {
|
|
|
+ const cb = (i, resolve) => {
|
|
|
+ if (i.style.float && i.style.float !== 'none' && i.style.float !== 'unset') {
|
|
|
+ const qs = document.querySelector('#qs')
|
|
|
+ this.qsHeight = qs.getBoundingClientRect().height;
|
|
|
+ }
|
|
|
+ const title = document.querySelector('#title')
|
|
|
+ const ans = document.querySelector('#ans')
|
|
|
+ ans.style.display = 'none';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const { width, height } = title.getBoundingClientRect();
|
|
|
+ html2canvas(title, {
|
|
|
+ canvas: this.getCanvasWrap(width + 20, height),
|
|
|
+ useCORS: true,
|
|
|
+ onclone: (e) => {
|
|
|
+ const ans = e.getElementById('ans');
|
|
|
+ ans.parentNode.removeChild(ans);
|
|
|
+ }
|
|
|
+ }).then((canvas) => {
|
|
|
+ ans.style.display = 'block';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ resolve(canvas);
|
|
|
+ });
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+ const promise = new Promise((resolve, reject) => {
|
|
|
+ i.onload = (e) => {
|
|
|
+ // 如果图片存在浮动,需要手动设置容器的高度
|
|
|
+ cb(i, resolve)
|
|
|
+ }
|
|
|
+ if (i.complete) {
|
|
|
+ cb(i, resolve)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ promiseArr.push(promise)
|
|
|
+ }
|
|
|
+ if (i.hasChildNodes()) {
|
|
|
+ this.findAllEle(promiseArr, i)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ waitingLoadingImg(cb) {
|
|
|
+ this.qsHeight = null;
|
|
|
+ let doms
|
|
|
+ let parent
|
|
|
+ const title = document.querySelector('#title');
|
|
|
+ const qs = document.querySelector('#qs');
|
|
|
+ this.qsHeight = qs.getBoundingClientRect().height;
|
|
|
+ // 每次重置容器高度
|
|
|
+ title.style.height = 'auto'
|
|
|
+ const promiseArr = []
|
|
|
+ this.findAllEle(promiseArr, title)
|
|
|
+ if (promiseArr.length === 0) {
|
|
|
+ const { width, height } = qs.getBoundingClientRect()
|
|
|
+ html2canvas(title, {
|
|
|
+ canvas: this.getCanvasWrap(width + 20, height),
|
|
|
+ useCORS: true,
|
|
|
+ onclone: (e) => {
|
|
|
+ const ans = e.getElementById('ans');
|
|
|
+ ans.parentNode.removeChild(ans);
|
|
|
+ }
|
|
|
+ }).then((canvas) => {
|
|
|
+ if (cb) {
|
|
|
+ cb(canvas)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ Promise.all(promiseArr).then(res => {
|
|
|
+ // 虽然用了Promise.all,但实际假设只有一张图片
|
|
|
+ console.log(res)
|
|
|
+ if (cb) {
|
|
|
+ cb(res[0])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ search() {
|
|
|
+ if (this.questionId) {
|
|
|
+ this.getData(this.questionId)
|
|
|
+ } else {
|
|
|
+ this.$message({
|
|
|
+ message: '请输入题目编号',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ auto() {
|
|
|
+ this.isAuto = !this.isAuto
|
|
|
+ if (this.isAuto) {
|
|
|
+ this.getData()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ upLoad() {
|
|
|
+ if (this.questionId && this.imgUri) {
|
|
|
+ this.uploadQuestionImage(this.imgUri, 1)
|
|
|
+ } else {
|
|
|
+ this.$message({
|
|
|
+ message: '请先搜索题目',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getData(questionId) {
|
|
|
+ axios.defaults.withCredentials = true
|
|
|
+ let str = ''
|
|
|
+ if (questionId) {
|
|
|
+ str = '?questionId=' + questionId
|
|
|
+ }
|
|
|
+ axios.get(this.domain + '/prod-api/front/questionCollection/getNextQuestionForImageGenerate' + str).then(response => {
|
|
|
+ if (response.data.code == 200) {
|
|
|
+ this.data = response.data.data
|
|
|
+ this.$nextTick(() => {
|
|
|
+ MathQueue('title', () => {
|
|
|
+ // this.MathQueueTitle(str)
|
|
|
+ })
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.isAuto = false
|
|
|
+ this.$message({
|
|
|
+ message: '获取题目信息失败',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(function (error) { // 请求失败处理
|
|
|
+ this.isAuto = false
|
|
|
+ this.$message.error('网络请求异常!')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ uploadQuestionImage(src, type) {
|
|
|
+ axios.defaults.withCredentials = true
|
|
|
+ var formData = new FormData()
|
|
|
+ formData.append('questionId', this.data.questionId)
|
|
|
+ formData.append('imageBase64', src)
|
|
|
+ if (this.isAuto == false) {
|
|
|
+ formData.append('manual', true)
|
|
|
+ }
|
|
|
+ axios.post(this.domain + '/prod-api/front/questionCollection/uploadQuestionImage', formData).then(response => {
|
|
|
+ if (response.data.code == 200) {
|
|
|
+ if (this.isAuto) {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getData()
|
|
|
+ }, 1500)
|
|
|
+ }
|
|
|
+ if (type) {
|
|
|
+ this.$message({
|
|
|
+ message: '上传题目信息成功!',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.isAuto = false
|
|
|
+ this.$message({
|
|
|
+ message: '上传题目信息失败!',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ }).catch(function (error) { // 请求失败处理
|
|
|
+ this.isAuto = false
|
|
|
+ this.$message.error('网络请求异常!')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getCookie(str) {//获取cookie
|
|
|
+ let cookie = document.cookie.split('; ')
|
|
|
+ let cookies = {}
|
|
|
+ cookie.forEach(item => {
|
|
|
+ cookies[item.split('=')[0]] = item.split('=')[1]
|
|
|
+ })
|
|
|
+ return cookies[str]
|
|
|
+ },
|
|
|
+ MathQueueTitle(str) {//初始化公式
|
|
|
+ console.log(isMathjaxConfig)
|
|
|
+ if (isMathjaxConfig) {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.waitingLoadingImg((canvas) => {
|
|
|
+ this.downLoad(str, canvas)
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }, 0)
|
|
|
+ } else {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.MathQueueTitle(str)
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ downLoad(type, canvas1) {
|
|
|
+ if (!this.data.questionId) {
|
|
|
+ this.$message({
|
|
|
+ message: '请先搜索题目!',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.questionId = this.data.questionId
|
|
|
+ let _canvas = document.getElementById('ans')
|
|
|
+ const { width, height } = _canvas.getBoundingClientRect()
|
|
|
+ html2canvas(_canvas, {
|
|
|
+ canvas: this.getCanvasWrap(width + 40, height),
|
|
|
+ useCORS: true,
|
|
|
+ onclone: (e) => {
|
|
|
+ const qs = e.getElementById('qs');
|
|
|
+ qs.parentNode.removeChild(qs)
|
|
|
+ }
|
|
|
+ }).then((canvas2) => {
|
|
|
+ var canvas3 = document.createElement('canvas')
|
|
|
+ canvas3.width = Math.max(canvas1?.width ?? 0, canvas2.width)
|
|
|
+ canvas3.height = (canvas1?.height ?? 0) + (canvas2.width && canvas2.height ? canvas2.height : 0)
|
|
|
+ var ctx = canvas3.getContext('2d')
|
|
|
+ // 绘制题目
|
|
|
+ canvas1 && ctx.drawImage(canvas1, 0, 0, canvas1.width, canvas1.height)
|
|
|
+ if (canvas2.width && canvas2.height) {
|
|
|
+ // 绘制答案
|
|
|
+ ctx.drawImage(canvas2, 0, (this.qsHeight * this.times) || (canvas1?.height ?? 0), canvas2.width, canvas2.height)
|
|
|
+ }
|
|
|
+ this.imgUri = canvas3.toDataURL('image/png')
|
|
|
+ canvas1 = null
|
|
|
+ canvas2 = null
|
|
|
+ canvas3 = null
|
|
|
+ if (!type) {
|
|
|
+ this.uploadQuestionImage(this.imgUri)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // }
|
|
|
+
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+
|
|
|
+</html>
|