Compare commits

..

No commits in common. 'master' and 'V2.1.9' have entirely different histories.

  1. 10
      package-lock.json
  2. 2
      package.json
  3. 18
      src/App.vue
  4. 159
      src/api/http.js
  5. 36
      src/api/index.js
  6. 675
      src/components/TestPanel.vue
  7. 53
      src/components/breadcrumb/index.vue
  8. 344
      src/components/codemirror.vue
  9. 157
      src/components/tinymceConfig.js
  10. 46
      src/components/upload/config.js
  11. 49
      src/components/upload/upload.js
  12. 95
      src/config/index.js
  13. 18
      src/styles/common.scss
  14. 236
      src/util/index.js
  15. 295
      src/views/Home.vue
  16. 220
      src/views/Report.vue

10
package-lock.json generated

@ -4666,11 +4666,6 @@
"randomfill": "^1.0.3" "randomfill": "^1.0.3"
} }
}, },
"crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"css": { "css": {
"version": "2.2.4", "version": "2.2.4",
"resolved": "https://registry.npm.taobao.org/css/download/css-2.2.4.tgz", "resolved": "https://registry.npm.taobao.org/css/download/css-2.2.4.tgz",
@ -8917,11 +8912,6 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true "dev": true
}, },
"jsencrypt": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
"integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
},
"jsesc": { "jsesc": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",

@ -13,14 +13,12 @@
"axios": "^0.19.2", "axios": "^0.19.2",
"clipboard": "^2.0.10", "clipboard": "^2.0.10",
"core-js": "^3.19.3", "core-js": "^3.19.3",
"crypto-js": "^4.2.0",
"element-ui": "^2.15.6", "element-ui": "^2.15.6",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"image-webpack-loader": "^8.1.0", "image-webpack-loader": "^8.1.0",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"jsencrypt": "^3.3.2",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"lib-flexible": "^0.3.2", "lib-flexible": "^0.3.2",
"mavon-editor": "^2.10.4", "mavon-editor": "^2.10.4",

@ -5,10 +5,9 @@
</template> </template>
<script> <script>
import Util from '@/util'
export default { export default {
name: "App", name: "App",
created () { created() {
//sessionStorage //sessionStorage
if (sessionStorage.getItem("store")) { if (sessionStorage.getItem("store")) {
this.$store.replaceState( this.$store.replaceState(
@ -18,20 +17,10 @@ export default {
JSON.parse(sessionStorage.getItem("store")) JSON.parse(sessionStorage.getItem("store"))
) )
); );
} } //vuexsessionStorage
//
if (!document.referrer) {
Util.exit()
return false
}
//vuexsessionStorage
window.addEventListener("beforeunload", () => { window.addEventListener("beforeunload", () => {
localStorage.removeItem('opened')
sessionStorage.setItem("store", JSON.stringify(this.$store.state)); sessionStorage.setItem("store", JSON.stringify(this.$store.state));
}); });
} }
}; };
</script> </script>
@ -43,8 +32,9 @@ export default {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: #2c3e50; color: #2c3e50;
} }
body { body {
margin: 0; margin: 0;
} }
</style> </style>

@ -1,121 +1,108 @@
import axios from 'axios'; import axios from 'axios';
import { import {
Message Message
} from 'element-ui' } from 'element-ui'
import router from '../router/index' import router from '../router/index'
import Cookie from 'js-cookie' import Cookie from 'js-cookie'
import config from '@/config' import config from '@/config'
import Util from '@/util'
const service = axios.create({ const service = axios.create({
baseURL: config.host, baseURL: config.host,
timeout: 10000000 timeout: 10000000
}) })
// post请求头 // post请求头
service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
// 请求拦截器 // 请求拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(config => {
const token = Cookie.get('admin-token') const token = Cookie.get('admin-token')
if (token) { if (token) {
config.headers.token = token config.headers.token = token
}
return config;
}, err => {
Message.error({
message: '退出登陆',
onClose: function () {
router.push({ name: 'login' });
} }
}) return config;
return Promise.reject(err); }, err => {
Message.error({
message: '退出登陆',
onClose: function () {
router.push({name: 'login'});
}
})
return Promise.reject(err);
}) })
let logouted = 0;
// 响应拦截器 // 响应拦截器
service.interceptors.response.use( service.interceptors.response.use(
response => { response => {
const res = response.data; const res = response.data;
if (res.status == 200 || res.status == 10000 || res.status == 30001) { if (res.status == 200 || res.status == 10000 || res.status == 30001) {
return Promise.resolve(res).catch(e => { }); return Promise.resolve(res).catch(e => {});
} else if (res.code === 401) { } else if (!res.status) {
// 账号互踢 return Promise.resolve(res).catch(e => {});
if (!logouted) { } else {
Message.error(res.msg.includes('顶') ? '您的账号已在其他设备登录,您已被迫下线!' : '登录过期,请重新登录!') Message.error(res.message)
setTimeout(() => { return Promise.reject(res)
Util.exit() }
}, 1500) },
logouted = 1 // 服务器状态码不是200的情况
} error => {
} else if (!res.status) { if (error.response.status) {
return Promise.resolve(res).catch(e => { }); switch (error.response.status) {
} else { // 401: 未登录
Message.error(res.message) case 401:
return Promise.reject(res) Message.error('登录过期,请重新登录')
} setTimeout(() => {
}, history.back()
// 服务器状态码不是200的情况 }, 1500)
error => { break;
if (error.response.status) { default:
switch (error.response.status) { // Message.error(error.response.data.message)
// 401: 未登录 Promise.reject(error.response);
case 401: }
if (!logouted) { return Promise.reject(error.response);
Message.error('登录过期,请重新登录') }
setTimeout(() => {
history.back()
}, 1500)
logouted = 1
}
break;
default:
Promise.reject(error.response);
}
return Promise.reject(error.response);
} }
}
); );
function get (url, params) { function get(url, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
service.get(url, { params: params }).then(res => { service.get(url, { params: params }).then(res => {
resolve(res); resolve(res);
}).catch(err => { }).catch(err => {
reject(err); reject(err);
});
}); });
});
} }
function post (url, params) { function post(url, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
service.post(url, params).then(res => { service.post(url, params).then(res => {
resolve(res); resolve(res);
}).catch(err => { }).catch(err => {
reject(err.data); reject(err.data);
});
}); });
});
} }
function del (url, params) { function del(url, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
service.delete(url, { service.delete(url, {
params params
}).then(res => { }).then(res => {
resolve(res); resolve(res);
}).catch(err => { }).catch(err => {
reject(err.data); reject(err.data);
});
}); });
});
} }
function put (url, params) { function put(url, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
service.put(url, params).then(res => { service.put(url, params).then(res => {
resolve(res); resolve(res);
}).catch(err => { }).catch(err => {
reject(err.data); reject(err.data);
});
}); });
});
} }
export { get, post, del, put } export { get, post, del, put }

@ -1,7 +1,6 @@
import config from '@/config' import config from '@/config'
export default { export default {
encrypt: `nakadai/data/encrypt`, getCurrentTime : `competition/competition/management/getCurrentTime`,
getCurrentTime: `competition/competition/management/getCurrentTime`,
getProjectDetail: 'occupationlab/occupationlab/projectManage/getProjectDetail', getProjectDetail: 'occupationlab/occupationlab/projectManage/getProjectDetail',
submit: 'python/python/submit', submit: 'python/python/submit',
runPythonCode: 'python/python/runPythonCode', runPythonCode: 'python/python/runPythonCode',
@ -15,10 +14,10 @@ export default {
getPurchasedTableByCategory: `data/data/myDate/getPurchasedTableByCategory`, getPurchasedTableByCategory: `data/data/myDate/getPurchasedTableByCategory`,
previewData: `data/data/preview`, previewData: `data/data/preview`,
lookupTableFile: `occupationlab/python/table/data/lookupTableFile`, lookupTableFile: `occupationlab/python/table/data/lookupTableFile`,
downloadData: `${config.host}data/data/download`, downloadData:`${config.host}data/data/download`,
getDetailById: 'occupationlab/occupationlab/assessment/getDetailById', getDetailById: 'occupationlab/occupationlab/assessment/getDetailById',
pageStuAssessment: 'occupationlab/occupationlab/assessment/pageStuAssessment', pageStuAssessment: 'occupationlab/occupationlab/assessment/pageStuAssessment',
queryUserInfoDetails: `users/users/userAccount/queryUserInfoDetails`, queryUserInfoDetails: `users/users/userAccount/queryUserInfoDetails`,
modelClassList: `nakadai/nakadai/model/reference/modelClassList`, modelClassList: `nakadai/nakadai/model/reference/modelClassList`,
studentModelList: `nakadai/nakadai/model/student/studentModelList`, studentModelList: `nakadai/nakadai/model/student/studentModelList`,
referenceDemoList: `nakadai/nakadai/model/reference/demo/referenceDemoList`, referenceDemoList: `nakadai/nakadai/model/reference/demo/referenceDemoList`,
@ -33,19 +32,18 @@ export default {
exportLabReport: `occupationlab/occupationlab/achievement/exportLabReport`, exportLabReport: `occupationlab/occupationlab/achievement/exportLabReport`,
reportDetail: `occupationlab/occupationlab/achievement/reportDetail`, reportDetail: `occupationlab/occupationlab/achievement/reportDetail`,
getCompetition: `competition/competition/management/getCompetition`, getCompetition: `competition/competition/management/getCompetition`,
whetherCanPaste: `nakadai/nakadai/model/demo/whetherCanPaste`, whetherCanPaste: `nakadai/nakadai/model/demo/whetherCanPaste`,
displayListOrNotByStudent: `nakadai/nakadai/model/demo/displayListOrNotByStudent`, displayListOrNotByStudent: `nakadai/nakadai/model/demo/displayListOrNotByStudent`,
modelClassListByStudent: `nakadai/nakadai/model/student/modelClassListByStudent`, modelClassListByStudent: `nakadai/nakadai/model/student/modelClassListByStudent`,
studentModelListBySystem: `nakadai/nakadai/model/student/studentModelListBySystem`, studentModelListBySystem: `nakadai/nakadai/model/student/studentModelListBySystem`,
detailsOfGoods: `nakadai/mall/detailsOfGoods`, detailsOfGoods: `nakadai/mall/detailsOfGoods`,
importCode: `occupationlab/occupationlab/experimentalReport/importCode`, importCode: `occupationlab/occupationlab/experimentalReport/importCode`,
removeImport: `occupationlab/occupationlab/experimentalReport/removeImport`, removeImport: `occupationlab/occupationlab/experimentalReport/removeImport`,
getStartTime: `python/python/getStartTime`, getStartTime: `python/python/getStartTime`,
getProductSystemTheme: `nakadai/mall/getProductSystemTheme`, getProductSystemTheme: `nakadai/mall/getProductSystemTheme`,
heartbeatDetection: `nakadai/message/heartbeatDetection`, heartbeatDetection : `nakadai/message/heartbeatDetection`,
heartbeatDetectionRabbit: `python/rabbitMessage/heartbeatDetection`, heartbeatDetectionRabbit : `python/rabbitMessage/heartbeatDetection`,
createQueue: `python/rabbitMessage/createQueue`, createQueue : `python/rabbitMessage/createQueue`,
endRunningProcess: `python/python/endRunningProcess`, endRunningProcess : `python/python/endRunningProcess`,
sendMessageToUser: `python/rabbitMessage/sendMessageToUser`, sendMessageToUser : `python/rabbitMessage/sendMessageToUser`,
deleteTheLastUncommittedRecord: `python/python/deleteTheLastUncommittedRecord`,
} }

File diff suppressed because it is too large Load Diff

@ -3,12 +3,15 @@
<div class="breadcrumb"> <div class="breadcrumb">
<el-breadcrumb separator=">"> <el-breadcrumb separator=">">
<template v-for="(item, index) in pages"> <template v-for="(item, index) in pages">
<el-breadcrumb-item v-if="index != pages.length - 1" <el-breadcrumb-item
:key="index"> v-if="index != pages.length - 1"
:key="index"
>
<span @click="toPath">{{item}}</span> <span @click="toPath">{{item}}</span>
</el-breadcrumb-item> </el-breadcrumb-item>
<el-breadcrumb-item v-else <el-breadcrumb-item
:key="index"> v-else
:key="index">
{{item}} {{item}}
</el-breadcrumb-item> </el-breadcrumb-item>
</template> </template>
@ -18,25 +21,33 @@
<script> <script>
export default { export default {
props: { props: {
data: { data: {
type: String, type: String,
required: true required: true
},
route: {
type: String,
default: '/'
},
query: {
type: Object
}
}, },
}, data() {
data () { return {
return { pages: this.data.split('/')
pages: this.data.split('/') };
};
},
methods: {
update (data) {
this.pages = data.split('/')
}, },
toPath () { methods: {
this.$router.back() update(data){
this.pages = data.split('/')
},
toPath() {
console.log(33)
this.$router.back()
}
} }
}
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -52,7 +63,7 @@ export default {
} }
&:last-child { &:last-child {
.is-link { .is-link {
color: #0b1d30; color: #0B1D30;
} }
} }
} }

@ -1,18 +1,37 @@
<template> <template>
<div class="code-wrap flex"> <div class="code-wrap flex">
<div class="left"> <div class="left">
<codemirror v-model="codeVal" :options="cmOption" class="code-mirror" @ready="ready" ref="codemirror"> <codemirror v-model="codeVal"
</codemirror> :options="cmOption"
<div v-if="isSubmit" class="code-mask"></div> class="code-mirror"
@ready="ready"
ref="codemirror"></codemirror>
<div v-if="isSubmit"
class="code-mask"></div>
<div class="btns"> <div class="btns">
<template v-if="!pid"> <template v-if="!pid">
<span class="el-icon-delete del" @click="clearCode"></span> <span class="el-icon-delete del"
<el-button v-if="isPrac" class="btn" type="danger" @click="myCode">我的代码</el-button> @click="clearCode"></span>
<el-button v-if="modelIsShow" class="btn" type="warning" @click="importModel">导入模型</el-button> <el-button v-if="isPrac"
<el-button class="run btn" type="primary" @click="runCode(false)" :disabled="runEnable">运行</el-button> class="btn"
type="danger"
@click="myCode">我的代码</el-button>
<el-button v-if="modelIsShow"
class="btn"
type="warning"
@click="importModel">导入模型</el-button>
<el-button class="run btn"
type="primary"
@click="runCode(false)"
:disabled="runEnable">运行</el-button>
</template> </template>
<el-popconfirm v-else title="确定终止运行本次代码?" @confirm="stopRunCode"> <el-popconfirm v-else
<el-button slot="reference" class="run" type="danger" :disabled="runEnable">终止运行</el-button> title="确定终止运行本次代码?"
@confirm="stopRunCode">
<el-button slot="reference"
class="run"
type="danger"
:disabled="runEnable">终止运行</el-button>
</el-popconfirm> </el-popconfirm>
</div> </div>
@ -20,28 +39,50 @@
<div class="line"></div> <div class="line"></div>
<div class="code-right answer"> <div class="code-right answer">
<p :class="['text-wrapper', 'pic-num' + picSrcList.length]">{{ runResult }}</p> <p :class="['text-wrapper', 'pic-num' + picSrcList.length]">{{ runResult }}</p>
<div :class="['pic-wrap', { wrong: isError === 0 }]" v-if="picSrcList.length"> <div :class="['pic-wrap', {wrong: isError === 0}]"
<div class="pic-item" v-for="(img, i) in picSrcList" :key="i"> v-if="picSrcList.length">
<div class="pic-item"
v-for="(img, i) in picSrcList"
:key="i">
<div class="pic-inner"> <div class="pic-inner">
<el-image class="pic" :src="img" :preview-src-list="picSrcList"> <el-image class="pic"
:src="img"
:preview-src-list="picSrcList">
</el-image> </el-image>
</div> </div>
<el-button class="download-btn btn" type="primary" size="mini" @click="downloadPic(i)">下载图片</el-button> <el-button class="download-btn btn"
<a :ref="'picLink' + i" style="display: none;" download="运行结果.png" :href="img">下载图片</a> type="primary"
size="mini"
@click="downloadPic(i)">下载图片</el-button>
<a :ref="'picLink' + i"
style="display: none;"
download="运行结果.png"
:href="img">下载图片</a>
</div> </div>
</div> </div>
<div class="result-right t-color" v-show="isError"> <div class="result-right t-color"
<img :src="require(`@/assets/images/system/${$themeId}/yes.png`)" alt />运行成功 v-show="isError">
<el-button class="tips-btn" @click="exportResult">导出结果</el-button> <img :src="require(`@/assets/images/system/${$themeId}/yes.png`)"
alt />运行成功
<el-button class="tips-btn"
@click="exportResult">导出结果</el-button>
</div> </div>
<div class="result-wrong" v-show="isError === 0"> <div class="result-wrong"
<img src="@/assets/images/error.png" alt /> v-show="isError === 0">
{{ errLine }}行出现错误 <img src="@/assets/images/error.png"
<el-button class="tips-btn" @click="getTips" v-show="isPrac">提示</el-button> alt />
<el-dialog title="答案提示" center :close-on-click-modal="false" :visible.sync="tipsVisible"> {{errLine}}行出现错误
<el-button class="tips-btn"
@click="getTips"
v-show="isPrac">提示</el-button>
<el-dialog title="答案提示"
center
:close-on-click-modal="false"
:visible.sync="tipsVisible">
<el-tabs> <el-tabs>
<el-tab-pane label="参考答案"> <el-tab-pane label="参考答案">
<div :class="['answer-wrap', { client: !fromManager }]" v-html="correctAnswer"></div> <div :class="['answer-wrap', {client: !fromManager}]"
v-html="correctAnswer"></div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-dialog> </el-dialog>
@ -49,10 +90,18 @@
</div> </div>
<!-- 导入模型 --> <!-- 导入模型 -->
<el-dialog title="请选择要导入的模型" :visible.sync="modelVisible" width="400px" :close-on-click-modal="false" <el-dialog title="请选择要导入的模型"
custom-class="model-dia"> :visible.sync="modelVisible"
<el-select class="w-100" v-model="modelType" size="mini"> width="400px"
<el-option v-for="item in modelOp" :key="item.id" :label="item.name" :value="item.id"> :close-on-click-modal="false"
custom-class="model-dia">
<el-select class="w-100"
v-model="modelType"
size="mini">
<el-option v-for="item in modelOp"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option> </el-option>
</el-select> </el-select>
<!-- <el-radio-group v-model="modelType" <!-- <el-radio-group v-model="modelType"
@ -66,80 +115,161 @@
</el-radio-group> --> </el-radio-group> -->
<!-- <el-divider></el-divider> --> <!-- <el-divider></el-divider> -->
<div class="model-wrap"> <div class="model-wrap">
<el-tree v-if="!modelType" :data="schoolModel" ref="tree" default-expand-all @check-change="treeCheckChange" <el-tree v-if="!modelType"
show-checkbox :check-strictly="true" node-key="id" :data="schoolModel"
:props="{ children: 'children', label: 'categoryName', isLeaf: 'leaf' }" v-loading="modelLoading"> ref="tree"
default-expand-all
@check-change="treeCheckChange"
show-checkbox
:check-strictly="true"
node-key="id"
:props="{children: 'children', label: 'categoryName', isLeaf: 'leaf'}"
v-loading="modelLoading">
</el-tree> </el-tree>
<el-tree v-if="modelType" :data="systemModel" ref="tree" default-expand-all @check-change="treeCheckChange" <el-tree v-if="modelType"
show-checkbox :check-strictly="true" node-key="id" :data="systemModel"
:props="{ children: 'children', label: 'categoryName', isLeaf: 'leaf' }" v-loading="modelLoading"> ref="tree"
default-expand-all
@check-change="treeCheckChange"
show-checkbox
:check-strictly="true"
node-key="id"
:props="{children: 'children', label: 'categoryName', isLeaf: 'leaf'}"
v-loading="modelLoading">
</el-tree> </el-tree>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer"
<el-button size="small" @click="modelVisible = false">取消</el-button> class="dialog-footer">
<el-button size="small" type="primary" @click="submit">导入</el-button> <el-button size="small"
@click="modelVisible = false">取消</el-button>
<el-button size="small"
type="primary"
@click="submit">导入</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="我的代码" :visible.sync="codeVisible" width="1200px" :close-on-click-modal="false" <el-dialog title="我的代码"
custom-class="code-dia"> :visible.sync="codeVisible"
<el-tooltip class="item" content="列表中展示当前课程已提交的实验代码" placement="right"> width="1200px"
<i class="info el-icon-warning" style="margin-right: 10px"></i> :close-on-click-modal="false"
custom-class="code-dia">
<el-tooltip class="item"
content="列表中展示当前课程已提交的实验代码"
placement="right">
<i class="info el-icon-warning"
style="margin-right: 10px"></i>
</el-tooltip> </el-tooltip>
<div class="tool"> <div class="tool">
<el-input style="width: 250px" placeholder="请输入项目名称、判分点名称" v-model="keyword" suffix-icon="el-icon-search" <el-input style="width: 250px"
clearable size="small"></el-input> placeholder="请输入项目名称、判分点名称"
v-model="keyword"
suffix-icon="el-icon-search"
clearable
size="small"></el-input>
<div class="action"> <div class="action">
<el-button class="cus-btn" type="primary" size="small" @click="delAll">批量删除</el-button> <el-button class="cus-btn"
type="primary"
size="small"
@click="delAll">批量删除</el-button>
</div> </div>
</div> </div>
<el-table :data="codeList" class="cus-table" ref="table" stripe max-height="400" header-align="center" <el-table :data="codeList"
@selection-change="handleSelectionChange"> class="cus-table"
<el-table-column type="selection" width="60" align="center"></el-table-column> ref="table"
<el-table-column type="index" label="序号" width="55" align="center"></el-table-column> stripe
<el-table-column prop="judgmentName" label="判分点" min-width="250" align="center" max-height="400"
show-overflow-tooltip></el-table-column> header-align="center"
<el-table-column prop="projectName" label="项目名称" min-width="250" align="center" @selection-change="handleSelectionChange">
show-overflow-tooltip></el-table-column> <el-table-column type="selection"
<el-table-column prop="submitTime" label="提交时间" width="140" align="center"></el-table-column> width="60"
<el-table-column prop="score" label="是否得分" width="80" align="center"></el-table-column> align="center"></el-table-column>
<el-table-column width="190" label="操作" align="center"> <el-table-column type="index"
label="序号"
width="55"
align="center"></el-table-column>
<el-table-column prop="judgmentName"
label="判分点"
min-width="250"
align="center"
show-overflow-tooltip></el-table-column>
<el-table-column prop="projectName"
label="项目名称"
min-width="250"
align="center"
show-overflow-tooltip></el-table-column>
<el-table-column prop="submitTime"
label="提交时间"
width="140"
align="center"></el-table-column>
<el-table-column prop="score"
label="是否得分"
width="80"
align="center"></el-table-column>
<el-table-column width="190"
label="操作"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="showCode(scope.row)">查看代码</el-button> <el-button type="text"
<el-button type="text" @click="importCode(scope.row)">插入代码</el-button> @click="showCode(scope.row)">查看代码</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button> <el-button type="text"
@click="importCode(scope.row)">插入代码</el-button>
<el-button type="text"
@click="del(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination background layout="total,prev, pager, next" :current-page="page" <el-pagination background
@current-change="handleCurrentChange" :total="total"></el-pagination> layout="total,prev, pager, next"
:current-page="page"
@current-change="handleCurrentChange"
:total="total"></el-pagination>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer"
<el-button size="small" type="primary" @click="codeVisible = false">关闭</el-button> class="dialog-footer">
<el-button size="small"
type="primary"
@click="codeVisible = false">关闭</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog :title="curRow.judgmentName" :visible.sync="showVisible" width="700px" :close-on-click-modal="false" <el-dialog :title="curRow.judgmentName"
custom-class="code-dia"> :visible.sync="showVisible"
<el-tabs class="code-tab" v-model="showActive"> width="700px"
<el-tab-pane label="代码" name="code"> :close-on-click-modal="false"
<codemirror class="code" v-model="curCode" :options="cmOptionDia"></codemirror> custom-class="code-dia">
<el-tabs class="code-tab"
v-model="showActive">
<el-tab-pane label="代码"
name="code">
<codemirror class="code"
v-model="curCode"
:options="cmOptionDia"></codemirror>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="结果" name="result"> <el-tab-pane label="结果"
name="result">
<div style="position: relative"> <div style="position: relative">
<div class="result" v-html="curRow.runResults"></div> <div class="result"
<div v-if="curPhotoUrl.length" class="pics"> v-html="curRow.runResults"></div>
<div class="pic-item" v-for="(img, i) in curPhotoUrl" :key="i"> <div v-if="curPhotoUrl.length"
<el-image class="pic" :src="img" :preview-src-list="curPhotoUrl"> class="pics">
<div class="pic-item"
v-for="(img, i) in curPhotoUrl"
:key="i">
<el-image class="pic"
:src="img"
:preview-src-list="curPhotoUrl">
</el-image> </el-image>
</div> </div>
</div> </div>
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<span slot="footer" class="dialog-footer"> <span slot="footer"
<el-button size="small" type="primary" @click="showSubmit">插入代码</el-button> class="dialog-footer">
<el-button size="small"
type="primary"
@click="showSubmit">插入代码</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@ -461,11 +591,8 @@ export default {
// //
async stopRunCode () { async stopRunCode () {
this.isStopRunCode = 1 this.isStopRunCode = 1
if (this.pid) { if (this.pid) await this.$post(`${this.api.endRunningProcess}?pid=${this.pid}`)
const { pid } = this this.pid = ''
this.pid = ''
await this.$post(`${this.api.endRunningProcess}?pid=${pid}`)
}
if (this.loadIns) this.loadIns.close() if (this.loadIns) this.loadIns.close()
}, },
inputRunCode (data) { inputRunCode (data) {
@ -522,7 +649,7 @@ export default {
bcId: this.judgmentId, bcId: this.judgmentId,
cid: this.courseId, cid: this.courseId,
projectId: this.projectId, projectId: this.projectId,
type: Cookie.get('admin-language'), type: 0,
sort: this.index sort: this.index
}, { }, {
headers: { headers: {
@ -574,6 +701,7 @@ export default {
if (data) { if (data) {
const photo = data.photoUrl const photo = data.photoUrl
const result = data.runResult || '' const result = data.runResult || ''
// this.$emit('cache') //
if (this.loadIns) this.loadIns.close() if (this.loadIns) this.loadIns.close()
this.picSrcList = [] this.picSrcList = []
this.$emit('update:photoUrl', '') this.$emit('update:photoUrl', '')
@ -652,7 +780,7 @@ export default {
bcId, bcId,
cid, cid,
projectId, projectId,
type: Cookie.get('admin-language'), type: 0,
sort: this.index sort: this.index
}).then(res => { }).then(res => {
this.$emit('update:finalCode', code) this.$emit('update:finalCode', code)
@ -680,7 +808,7 @@ export default {
bcId, bcId,
cid, cid,
projectId, projectId,
type: Cookie.get('admin-language'), type: 0,
sort: this.index sort: this.index
}).then(res => { }).then(res => {
this.$emit('update:finalCode', code) this.$emit('update:finalCode', code)
@ -838,20 +966,16 @@ export default {
.code-wrap { .code-wrap {
position: relative; position: relative;
} }
.left { .left {
position: relative; position: relative;
width: 60%; width: 60%;
} }
.text-wrapper { .text-wrapper {
white-space: pre-wrap; white-space: pre-wrap;
} }
/deep/.CodeMirror-code { /deep/.CodeMirror-code {
font-family: 'Microsoft Yahei'; font-family: 'Microsoft Yahei';
} }
/deep/.answer { /deep/.answer {
.el-tab-pane { .el-tab-pane {
padding: 0 10px; padding: 0 10px;
@ -860,48 +984,38 @@ export default {
overflow-y: auto; overflow-y: auto;
white-space: pre-wrap; white-space: pre-wrap;
} }
.el-dialog--center { .el-dialog--center {
width: 500px; width: 500px;
height: 500px; height: 500px;
} }
.el-dialog__title { .el-dialog__title {
font-size: 22px; font-size: 22px;
font-weight: 500; font-weight: 500;
} }
.el-tabs__nav-wrap::after { .el-tabs__nav-wrap::after {
background-color: #333; background-color: #333;
} }
.el-tabs__active-bar { .el-tabs__active-bar {
height: 0; height: 0;
background-color: #fff; background-color: #fff;
} }
.el-tabs__header { .el-tabs__header {
background-color: #333; background-color: #333;
} }
.el-dialog--center .el-dialog__body { .el-dialog--center .el-dialog__body {
padding: 0; padding: 0;
} }
.el-tabs__item { .el-tabs__item {
width: 80px; width: 80px;
color: #fff; color: #fff;
} }
.el-tabs--top .el-tabs__item.is-top:nth-child(2) { .el-tabs--top .el-tabs__item.is-top:nth-child(2) {
padding-left: 20px; padding-left: 20px;
} }
.el-tabs__item.is-active { .el-tabs__item.is-active {
color: #fff !important; color: #fff !important;
background-color: #333 !important; background-color: #333 !important;
} }
.tips-btn { .tips-btn {
margin-top: 10px; margin-top: 10px;
height: 40px; height: 40px;
@ -911,7 +1025,6 @@ export default {
right: 0; right: 0;
background: rgba(255, 49, 49, 1); background: rgba(255, 49, 49, 1);
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
&:hover, &:hover,
&:focus, &:focus,
&:active { &:active {
@ -920,7 +1033,6 @@ export default {
} }
} }
} }
.del { .del {
width: 40px; width: 40px;
margin: 0 10px; margin: 0 10px;
@ -930,21 +1042,17 @@ export default {
border-radius: 50%; border-radius: 50%;
background-color: #f00; background-color: #f00;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
opacity: 0.9; opacity: 0.9;
} }
} }
.result-right { .result-right {
background-color: rgba(43, 40, 22, 1); background-color: rgba(43, 40, 22, 1);
} }
.result-wrong { .result-wrong {
background-color: rgba(43, 22, 22, 1); background-color: rgba(43, 22, 22, 1);
color: #f00; color: #f00;
} }
.result-wrong, .result-wrong,
.result-right { .result-right {
position: absolute; position: absolute;
@ -953,7 +1061,6 @@ export default {
display: flex; display: flex;
bottom: 10px; bottom: 10px;
padding: 0 10px; padding: 0 10px;
img { img {
width: 40px; width: 40px;
height: 40px; height: 40px;
@ -961,7 +1068,6 @@ export default {
margin-right: 10px; margin-right: 10px;
} }
} }
.line { .line {
z-index: 2; z-index: 2;
position: absolute; position: absolute;
@ -971,7 +1077,6 @@ export default {
height: 100%; height: 100%;
cursor: e-resize; cursor: e-resize;
} }
.code-right { .code-right {
width: 40%; width: 40%;
color: #fff; color: #fff;
@ -979,7 +1084,6 @@ export default {
display: inline-block; display: inline-block;
position: relative; position: relative;
overflow-x: auto; overflow-x: auto;
p { p {
font-size: 18px; font-size: 18px;
margin: 10px; margin: 10px;
@ -988,16 +1092,13 @@ export default {
height: calc(100vh - 387px); height: calc(100vh - 387px);
overflow: auto; overflow: auto;
} }
.pic-num0 { .pic-num0 {
height: calc(100vh - 247px); height: calc(100vh - 247px);
} }
.pic-num1 { .pic-num1 {
height: calc(100vh - 520px); height: calc(100vh - 520px);
} }
} }
.pic-wrap { .pic-wrap {
position: absolute; position: absolute;
left: 0; left: 0;
@ -1008,30 +1109,24 @@ export default {
margin: 0 auto; margin: 0 auto;
text-align: center; text-align: center;
overflow: auto; overflow: auto;
&.wrong { &.wrong {
bottom: 60px; bottom: 60px;
} }
.pic-item { .pic-item {
margin: 0 5px 5px; margin: 0 5px 5px;
.pic-inner { .pic-inner {
height: 100px; height: 100px;
} }
&:only-child { &:only-child {
.pic-inner { .pic-inner {
height: auto; height: auto;
} }
.pic { .pic {
width: 50%; width: 50%;
max-height: none; max-height: none;
} }
} }
} }
.pic { .pic {
display: block; display: block;
width: 100px; width: 100px;
@ -1040,7 +1135,6 @@ export default {
margin: 0 auto 10px; margin: 0 auto 10px;
} }
} }
.code-mask { .code-mask {
z-index: 2; z-index: 2;
position: absolute; position: absolute;
@ -1049,7 +1143,6 @@ export default {
bottom: 0; bottom: 0;
right: 0; right: 0;
} }
.btns { .btns {
z-index: 99; z-index: 99;
position: absolute; position: absolute;
@ -1057,78 +1150,63 @@ export default {
bottom: 15px; bottom: 15px;
display: flex; display: flex;
} }
.run { .run {
width: 100px; width: 100px;
color: #fff; color: #fff;
} }
.download-btn { .download-btn {
color: #fff; color: #fff;
} }
/deep/.answer-wrap { /deep/.answer-wrap {
&.client { &.client {
user-select: none; user-select: none;
} }
pre { pre {
width: 100%; width: 100%;
white-space: pre-wrap; white-space: pre-wrap;
} }
img { img {
max-width: 100%; max-width: 100%;
} }
} }
/deep/.model-dia { /deep/.model-dia {
.el-dialog__body { .el-dialog__body {
padding: 0 20px; padding: 0 20px;
} }
.el-divider--horizontal { .el-divider--horizontal {
margin: 15px 0; margin: 15px 0;
} }
} }
.model-wrap { .model-wrap {
max-height: 400px; max-height: 400px;
overflow: auto; overflow: auto;
} }
/deep/.code-dia { /deep/.code-dia {
.el-dialog__header { .el-dialog__header {
padding: 0 40px 0 20px; padding: 0 40px 0 20px;
} }
.el-dialog__body { .el-dialog__body {
padding: 0 20px; padding: 0 20px;
} }
.info { .info {
position: absolute; position: absolute;
top: 18px; top: 18px;
left: 100px; left: 100px;
color: #88aef5; color: #88aef5;
} }
.code-tab { .code-tab {
.el-tabs__item.is-active { .el-tabs__item.is-active {
color: #333 !important; color: #333 !important;
background-color: transparent; background-color: transparent;
} }
} }
.tool { .tool {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.code { .code {
margin-top: 10px; margin-top: 10px;
} }
.result { .result {
max-height: 300px; max-height: 300px;
font-size: 18px; font-size: 18px;
@ -1137,15 +1215,12 @@ export default {
color: #333; color: #333;
overflow: auto; overflow: auto;
} }
.pics { .pics {
display: flex; display: flex;
margin-top: 20px; margin-top: 20px;
overflow: auto; overflow: auto;
.pic-item { .pic-item {
margin: 0 5px 5px; margin: 0 5px 5px;
&:only-child { &:only-child {
.pic { .pic {
width: 50%; width: 50%;
@ -1153,7 +1228,6 @@ export default {
} }
} }
} }
.pic { .pic {
display: block; display: block;
width: 100px; width: 100px;

@ -2,9 +2,9 @@ import Oss from '@/components/upload/upload.js'
import { Loading } from 'element-ui' import { Loading } from 'element-ui'
export default { export default {
//skin:'oxide-dark', //skin:'oxide-dark',
language: 'zh_CN', language:'zh_CN',
language_url: './styles/tinymce/langs/zh_CN.js', language_url: './styles/tinymce/langs/zh_CN.js',
plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autoresize', plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave autoresize',
toolbar: 'code undo redo restoredraft | cut copy pastetext | forecolor backcolor headings fontsize lineHeight bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify | \ toolbar: 'code undo redo restoredraft | cut copy pastetext | forecolor backcolor headings fontsize lineHeight bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify | \
styleselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \ styleselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em', table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em',
@ -20,40 +20,40 @@ export default {
{ {
title: '行高', title: '行高',
items: [{ items: [{
title: '1', title: '1',
styles: { styles: {
'line-height': '1' 'line-height': '1'
},
inline: 'span'
}, },
inline: 'span' {
}, title: '1.5',
{ styles: {
title: '1.5', 'line-height': '1.5'
styles: { },
'line-height': '1.5' inline: 'span'
},
inline: 'span'
},
{
title: '2',
styles: {
'line-height': '2'
}, },
inline: 'span' {
}, title: '2',
{ styles: {
title: '2.5', 'line-height': '2'
styles: { },
'line-height': '2.5' inline: 'span'
}, },
inline: 'span' {
}, title: '2.5',
{ styles: {
title: '3', 'line-height': '2.5'
styles: { },
'line-height': '3' inline: 'span'
}, },
inline: 'span' {
} title: '3',
styles: {
'line-height': '3'
},
inline: 'span'
}
] ]
}, },
//默认的配置 //默认的配置
@ -186,34 +186,33 @@ export default {
fontsize_formats: '12px 14px 16px 19px 24px 36px 48px 56px 72px', fontsize_formats: '12px 14px 16px 19px 24px 36px 48px 56px 72px',
font_formats: '苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;知乎配置=BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif;小米配置=Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif', font_formats: '苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;知乎配置=BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif;小米配置=Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif',
link_list: [ link_list: [
{ title: '预置链接1', value: 'http://www.tinymce.com' }, { title: '预置链接1', value: 'http://www.tinymce.com' },
{ title: '预置链接2', value: 'http://tinymce.ax-z.cn' } { title: '预置链接2', value: 'http://tinymce.ax-z.cn' }
], ],
image_list: [ image_list: [
{ title: '预置图片1', value: 'https://www.tiny.cloud/images/glyph-tinymce@2x.png' }, { title: '预置图片1', value: 'https://www.tiny.cloud/images/glyph-tinymce@2x.png' },
{ title: '预置图片2', value: 'https://www.baidu.com/img/bd_logo1.png' } { title: '预置图片2', value: 'https://www.baidu.com/img/bd_logo1.png' }
], ],
image_class_list: [ image_class_list: [
{ title: 'None', value: '' }, { title: 'None', value: '' },
{ title: 'Some class', value: 'class-name' } { title: 'Some class', value: 'class-name' }
], ],
//importcss_append: true, //importcss_append: true,
//自定义文件选择器的回调内容 //自定义文件选择器的回调内容
file_picker_callback: function (callback, value, meta) { file_picker_callback: function (callback, value, meta) {
if (meta.filetype === 'file') { if (meta.filetype === 'file') {
callback('https://www.baidu.com/img/bd_logo1.png', { text: 'My text' }); callback('https://www.baidu.com/img/bd_logo1.png', { text: 'My text' });
} }
if (meta.filetype === 'image') { if (meta.filetype === 'image') {
callback('https://www.baidu.com/img/bd_logo1.png', { alt: 'My alt text' }); callback('https://www.baidu.com/img/bd_logo1.png', { alt: 'My alt text' });
} }
if (meta.filetype === 'media') { if (meta.filetype === 'media') {
callback('movie.mp4', { source2: 'alt.ogg', poster: 'https://www.baidu.com/img/bd_logo1.png' }); callback('movie.mp4', { source2: 'alt.ogg', poster: 'https://www.baidu.com/img/bd_logo1.png' });
} }
}, },
//为内容模板插件提供预置模板 //为内容模板插件提供预置模板
templates: [ templates: [
{ { title: '个股分析报告', description: '', content: `
title: '个股分析报告', description: '', content: `
<div class="tiny-report"> <div class="tiny-report">
<h2>个股分析报告</h2> <h2>个股分析报告</h2>
<h6>1.引言</h6> <h6>1.引言</h6>
@ -270,10 +269,9 @@ export default {
</ul> </ul>
</div> </div>
` `
}, },
{ { title: '行业数据分析报告', description: '', content: `
title: '行业数据分析报告', description: '', content: `
<div class="tiny-report"> <div class="tiny-report">
<h2>行业数据分析报告</h2> <h2>行业数据分析报告</h2>
<h6>1.引言</h6> <h6>1.引言</h6>
@ -344,10 +342,9 @@ export default {
</ul> </ul>
</div> </div>
` `
}, },
{ { title: '宏观数据分析报告', description: '', content: `
title: '宏观数据分析报告', description: '', content: `
<div class="tiny-report"> <div class="tiny-report">
<h2>宏观数据分析报告</h2> <h2>宏观数据分析报告</h2>
<h6>1.引言</h6> <h6>1.引言</h6>
@ -404,10 +401,9 @@ export default {
</ul> </ul>
</div> </div>
` `
}, },
{ { title: '可视化报告', description: '', content: `
title: '可视化报告', description: '', content: `
<div class="tiny-report"> <div class="tiny-report">
<h2>可视化报告</h2> <h2>可视化报告</h2>
<h6>1.封面</h6> <h6>1.封面</h6>
@ -476,10 +472,9 @@ export default {
</ul> </ul>
</div> </div>
` `
}, },
{ { title: '数据分析报告', description: '', content: `
title: '数据分析报告', description: '', content: `
<div class="tiny-report"> <div class="tiny-report">
<h2>数据分析报告</h2> <h2>数据分析报告</h2>
<h6>1.引言</h6> <h6>1.引言</h6>
@ -554,7 +549,7 @@ export default {
</ul> </ul>
</div> </div>
` `
}, },
], ],
// content_security_policy: "https://cdn.tiny.cloud/1/rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda/tinymce/6/tinymce.min.js", // content_security_policy: "https://cdn.tiny.cloud/1/rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda/tinymce/6/tinymce.min.js",
// extended_valid_elements:'script[src]', // extended_valid_elements:'script[src]',
@ -562,7 +557,7 @@ export default {
// template_cdate_format: '[CDATE: %m/%d/%Y : %H:%M:%S]', // template_cdate_format: '[CDATE: %m/%d/%Y : %H:%M:%S]',
// template_mdate_format: '[MDATE: %m/%d/%Y : %H:%M:%S]', // template_mdate_format: '[MDATE: %m/%d/%Y : %H:%M:%S]',
// autosave_ask_before_unload: false, // autosave_ask_before_unload: false,
toolbar_mode: 'wrap', toolbar_mode : 'wrap',
// automatic_uploads: true, // automatic_uploads: true,
// images_upload_base_path: '/demo', // images_upload_base_path: '/demo',
// images_upload_url: 'http://10.10.11.7:10000/iasf/sysFiles/upload', // images_upload_url: 'http://10.10.11.7:10000/iasf/sysFiles/upload',
@ -572,15 +567,15 @@ export default {
powerpaste_html_import: 'clean', powerpaste_html_import: 'clean',
// 自定义上传 // 自定义上传
images_upload_handler: function (blobInfo, succFun, failFun) { images_upload_handler: function (blobInfo, succFun, failFun) {
const blob = blobInfo.blob() const blob = blobInfo.blob()
// blob转换为file // blob转换为file
const file = new File([blob], blobInfo.filename(), { const file = new File([blob], blobInfo.filename(), {
type: 'application/json', type: 'application/json',
lastModified: Date.now() lastModified: Date.now()
}); });
Oss.upload(file).then(res => { Oss.upload(file).then(res => {
succFun(res.url) succFun(res.url)
}) })
}, },
//自定义文件选择器的回调内容 此方法只有在点击上方图片按钮才会触发 //自定义文件选择器的回调内容 此方法只有在点击上方图片按钮才会触发
file_picker_callback: function (callback, value, meta) { file_picker_callback: function (callback, value, meta) {
@ -596,23 +591,23 @@ export default {
let input = document.createElement('input');//创建一个隐藏的input let input = document.createElement('input');//创建一个隐藏的input
input.setAttribute('type', 'file'); input.setAttribute('type', 'file');
input.setAttribute("accept", ".mp4"); input.setAttribute("accept", ".mp4");
input.onchange = function () { input.onchange = function(){
let file = this.files[0]; let file = this.files[0];
const load = Loading.service() const load = Loading.service()
Oss.upload(file).then(res => { Oss.upload(file).then(res => {
load.close() load.close()
callback(res.url) callback(res.url)
}).catch(e => { }).catch(e => {
load.close() load.close()
}) })
} }
//触发点击 //触发点击
input.click(); input.click();
} }
}, },
// 初始化事件 // 初始化事件
setup: function (editor) { setup: function(editor) {
editor.on('init', function (ed) { editor.on('init', function(ed) {
// 设置默认字体 // 设置默认字体
ed.target.editorCommands.execCommand("fontName", false, "Microsoft Yahei") ed.target.editorCommands.execCommand("fontName", false, "Microsoft Yahei")
ed.target.editorCommands.execCommand("fontSize", false, "19px") ed.target.editorCommands.execCommand("fontSize", false, "19px")

@ -1,41 +1,15 @@
/** /**
* 阿里云oss配置 * 阿里云oss配置
* */ * */
import { get } from '@/api/http'
import api from '@/api'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
const A = (key, encryptedData) => { export default {
const keyHex = CryptoJS.enc.Base64.parse(key) // oss账号信息
const decrypted = CryptoJS.AES.decrypt(encryptedData, keyHex, { config: {
mode: CryptoJS.mode.ECB, region: 'oss-cn-shenzhen',
padding: CryptoJS.pad.Pkcs7 accessKeyId: 'LTAI4FzqQHnk4rozqLZ8jCNj',
}) accessKeySecret: 'mveW7B1OyFoKUkHm8WsxmrjHmkJWHq',
return decrypted.toString(CryptoJS.enc.Utf8) bucket: 'huoran'
} },
// 上传成功url前置部分(成功回调没有返回url)
const R = (encryptedKey, privateKey) => { preUrl: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/'
const decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
const decryptedKey = decrypt.decrypt(encryptedKey)
return decryptedKey
}
export default async function () {
try {
const res = await get(api.encrypt)
const RE = A(R(res.encryptedKey, res.privateKey), res.encryptedData).split('/')
return {
// oss账号信息
config: {
region: 'oss-cn-shenzhen',
accessKeyId: RE[0],
accessKeySecret: RE[1],
bucket: 'huoran'
},
// 上传成功url前置部分(成功回调没有返回url)
preUrl: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/'
}
} catch (e) { }
} }

@ -5,36 +5,33 @@ import OssConfig from './config'
import Util from '@/util' import Util from '@/util'
let client = null let client = null
let Oss
// 初始化oss // 初始化oss
const initOss = async () => { const initOss = () => {
Oss = await OssConfig() if (!client) client = new OSS(OssConfig.config)
if (!client) client = new OSS(Oss.config)
} }
initOss()
export default { export default {
// 上传文件 // 上传文件
upload (file) { upload(file) {
initOss() initOss()
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
// 上传到阿里云oss // 上传到阿里云oss
const res = await client.multipartUpload(Date.now() + '.' + Util.getFileExt(file.name), file); const res = await client.multipartUpload(Date.now() + '.' + Util.getFileExt(file.name), file);
resolve({ resolve({
format: Util.getFileExt(file.name), format: Util.getFileExt(file.name),
name: file.name, name: file.name,
url: Oss.preUrl + res.name, url: OssConfig.preUrl + res.name,
size: file.size, size: file.size,
}) })
} catch (error) { } catch (error) {
reject() reject()
} }
}) })
}, },
// 删除文件(传完整url,不是没有https的name,因为很多接口没有存name,只存url,所以统一使用url) // 删除文件(传完整url,不是没有https的name,因为很多接口没有存name,只存url,所以统一使用url)
async del (url) { async del(url) {
initOss() initOss()
await client.delete(url.replace(Oss.preUrl, '')); await client.delete(url.replace(OssConfig.preUrl, ''));
} }
} }

@ -6,67 +6,66 @@ const isTest = url.includes('121.37.12.51') //测试服
const isHh = url.includes('10.196.131.73') //是否是河海版本 const isHh = url.includes('10.196.131.73') //是否是河海版本
const isPro = url.includes('occupationlab.com') //是否职站生产 const isPro = url.includes('occupationlab.com') //是否职站生产
const isZxy = url.includes('izhixinyun.com') //是否智信云 const isZxy = url.includes('izhixinyun.com') //是否智信云
let vscodeUrl = 'http://172.16.40.56:8088/' let vscodeUrl = 'http://10.60.32.77:8888'
let host = location.origin + '/' let host = location.origin + '/'
// let host = `https://izhixinyun.com/` // let host = `https://izhixinyun.com/`
let bankPath = `${location.origin}/banksystem` // 银行系统 let bankPath = `${location.origin}/banksystem` // 银行系统
// 121.37.12.51 | 192.168.31.151 // 121.37.12.51 | 192.168.31.151
if (isDev) { if (isDev) {
// host = 'http://192.168.31.51:9000/' host = 'http://192.168.31.51:9000/'
host = 'http://121.37.12.51/' // host = 'http://121.37.12.51:9000/'
// host = 'https://izhixinyun.com/' // host = 'https://occupationlab.com/'
bankPath = `http://${location.hostname}:8093` bankPath = `http://${location.hostname}:8093`
} else if (isPro) { } else if (isPro) {
host = 'https://occupationlab.com/' host = 'https://occupationlab.com/'
bankPath = `https://www.huorantech.cn/banksystem` bankPath = `https://www.huorantech.cn/banksystem`
vscodeUrl = 'https://vscode.occupationlab.com' vscodeUrl = 'https://vscode.occupationlab.com'
} else if (isZxy) { } else if (isZxy) {
vscodeUrl = 'https://vscode.izhixinyun.com' vscodeUrl = 'https://vscode.izhixinyun.com'
} }
vscodeUrl += `?folder=/home/coder/workspace` vscodeUrl += `?folder=/home/coder/workspace`
const systemId = Cookie.get('admin-systemId') const systemId = Cookie.get('admin-systemId')
export default { export default {
/** /**
* @description 域名 * @description 域名
*/ */
host, host,
/** /**
* @description 是否本地 * @description 是否本地
*/ */
isDev, isDev,
/** /**
* @description 测试服 * @description 测试服
*/ */
isTest, isTest,
/** /**
* @description 是否是河海版本 * @description 是否是河海版本
*/ */
isHh, isHh,
/** /**
* @description 是否是职站生产 * @description 是否是职站生产
*/ */
isPro, isPro,
/** /**
* @description 是否智信云 * @description 是否智信云
*/ */
isZxy, isZxy,
/** /**
* @description 系统主题色 * @description 系统主题色
* 如果有多个systemId则显示系统7的主题色 * 如果有多个systemId则显示系统7的主题色
*/ */
defaultSystem: systemId.includes(',') ? 7 : systemId, defaultSystem: systemId.includes(',') ? 7 : systemId,
/** /**
* 银行系统 * 银行系统
**/ **/
bankPath, bankPath,
/** /**
* vscode地址 * vscode地址
**/ **/
vscodeUrl, vscodeUrl,
/** /**
* @description 长时间未操作自动退出登录时间 * @description 长时间未操作自动退出登录时间
*/ */
autoLogoutTime: 1000 * 60 * 60 * 3 autoLogoutTime: 1000 * 60 * 60 * 3
} }

@ -103,21 +103,3 @@ body .cus-table.el-table {
.code-load { .code-load {
bottom: 50px !important; bottom: 50px !important;
} }
.markdown-body {
ul {
list-style: disc;
li {
list-style: inherit;
}
}
ol {
list-style: decimal;
li {
list-style: inherit;
}
}
}

@ -1,124 +1,118 @@
import Config from '@/config'
import Cookie from 'js-cookie'
export default { export default {
// 返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss" getCookie(cookie_name) {
formatDate (fmt, date) { //获取cookie中指定key的value
var date = date ? date : new Date() var allcookies = document.cookie; //索引长度,开始索引的位置
var o = { var cookie_pos = allcookies.indexOf(cookie_name); // 如果找到了索引,就代表cookie存在,否则不存在
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日 if (cookie_pos != -1) {
"h+": date.getHours(), //小时 // 把cookie_pos放在值的开始,只要给值加1即可
"m+": date.getMinutes(), //分 //计算取cookie值得开始索引,加的1为“=”
"s+": date.getSeconds(), //秒 cookie_pos = cookie_pos + cookie_name.length + 1; //计算取cookie值得结束索引
"q+": Math.floor((date.getMonth() + 3) / 3), //季度 var cookie_end = allcookies.indexOf(";", cookie_pos);
"S": date.getMilliseconds() //毫秒
}; if (cookie_end == -1) {
if (/(y+)/.test(fmt)) { cookie_end = allcookies.length;
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); } //得到想要的cookie的值
} var value = unescape(allcookies.substring(cookie_pos, cookie_end));
for (var k in o) { }
if (new RegExp("(" + k + ")").test(fmt)) { return value;
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); },
} // 返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
} formatDate(fmt,date) {
return fmt var date = date ? date : new Date()
}, var o = {
// 传入文件后缀判断是否是视频 "M+" : date.getMonth()+1, //月份
isVideo (ext) { "d+" : date.getDate(), //日
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(ext)) return true; "h+" : date.getHours(), //小时
return false; "m+" : date.getMinutes(), //分
}, "s+" : date.getSeconds(), //秒
// 传入文件后缀判断是否是图片 "q+" : Math.floor((date.getMonth()+3)/3), //季度
isImg (ext) { "S" : date.getMilliseconds() //毫秒
if ("jpg,jpeg,png,gif,svg,psd".includes(ext)) return true; };
return false; if(/(y+)/.test(fmt)) {
}, fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
// 传入文件后缀判断是否是pdf以外的文档 }
isDoc (ext) { for(var k in o) {
if ("xls,xlsx,doc,docx,pdf,ppt,pptx".includes(ext)) return true; if(new RegExp("("+ k +")").test(fmt)){
return false; fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}, }
// 传入文件名获取文件后缀 }
getFileExt (fileName) { return fmt
return fileName.substring(fileName.lastIndexOf('.') + 1) },
}, // 传入文件后缀判断是否是视频
// 下载文件 isVideo(ext) {
downloadFile (fileName, url) { if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(ext)) return true;
var x = new XMLHttpRequest() return false;
x.open("GET", url, true) },
x.responseType = 'blob' // 传入文件后缀判断是否是图片
x.onload = function (e) { isImg(ext) {
var url = window.URL.createObjectURL(x.response) if ("jpg,jpeg,png,gif,svg,psd".includes(ext)) return true;
var a = document.createElement('a') return false;
a.href = url },
a.download = fileName // 传入文件后缀判断是否是pdf以外的文档
a.click() isDoc(ext) {
} if ("xls,xlsx,doc,docx,pdf,ppt,pptx".includes(ext)) return true;
x.send() return false;
}, },
// 下载图片 // 传入文件名获取文件后缀
downloadPic (fileName, src) { getFileExt(fileName) {
const canvas = document.createElement('canvas') return fileName.substring(fileName.lastIndexOf('.') + 1)
const img = document.createElement('img') },
// 解决跨域 Canvas 污染问题 // 下载文件
img.setAttribute('crossOrigin', 'anonymous') downloadFile(fileName,url) {
//将资源链接赋值过去,才能触发img.onload事件 var x = new XMLHttpRequest()
img.src = src x.open("GET", url, true)
img.onload = function (e) { x.responseType = 'blob'
canvas.width = img.width x.onload=function(e) {
canvas.height = img.height var url = window.URL.createObjectURL(x.response)
const context = canvas.getContext('2d') var a = document.createElement('a')
//绘制图片 a.href = url
context.drawImage(img, 0, 0, img.width, img.height) a.download = fileName
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height) a.click()
//将canvas转base64码,然后创建一个a连接自动下载图片 }
canvas.toBlob((blob) => { x.send()
const link = document.createElement('a') },
link.href = window.URL.createObjectURL(blob) // 下载图片
link.download = fileName downloadPic(fileName, src) {
link.click() const canvas = document.createElement('canvas')
}) const img = document.createElement('img')
} // 解决跨域 Canvas 污染问题
}, img.setAttribute('crossOrigin', 'anonymous')
// 传入文件名和数据,下载文件 //将资源链接赋值过去,才能触发img.onload事件
downloadFileDirect (fileName, data) { img.src = src
if ('download' in document.createElement('a')) { // 非IE下载 img.onload = function (e) {
const elink = document.createElement('a') canvas.width = img.width
elink.download = fileName canvas.height = img.height
elink.style.display = 'none' const context = canvas.getContext('2d')
elink.href = URL.createObjectURL(data) //绘制图片
document.body.appendChild(elink) context.drawImage(img, 0, 0, img.width, img.height)
elink.click() canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height)
URL.revokeObjectURL(elink.href) // 释放URL 对象 //将canvas转base64码,然后创建一个a连接自动下载图片
document.body.removeChild(elink) canvas.toBlob((blob) => {
} else { // IE10+下载 const link = document.createElement('a')
navigator.msSaveBlob(data, fileName) link.href = window.URL.createObjectURL(blob)
} link.download = fileName
}, link.click()
// 小于0前面加上0 })
handleZero (num) { }
return num < 10 ? '0' + num : num },
}, // 传入文件名和数据,下载文件
// 退出实验 downloadFileDirect(fileName,data) {
exit () { if ('download' in document.createElement('a')) { // 非IE下载
let href = Config.isDev ? const elink = document.createElement('a')
`http://${location.hostname}:8082/#/` : elink.download = fileName
`${location.origin}${Cookie.get('admin-fromManager') ? elink.style.display = 'none'
'/admin' : elink.href = URL.createObjectURL(data)
(!Config.isTest) ? document.body.appendChild(elink)
'' : elink.click()
'/student'}/#/` URL.revokeObjectURL(elink.href) // 释放URL 对象
// 考核 document.body.removeChild(elink)
if (Cookie.get('admin-assessmentId')) { } else { // IE10+下载
href += `ass/list` navigator.msSaveBlob(data, fileName)
} else if (Cookie.get('admin-competitionId')) { }
// 竞赛 },
href += `match/list` // 小于0前面加上0
} else { handleZero (num) {
// 练习 return num < 10 ? '0' + num : num
href += `station/preview?courseId=${Cookie.get('admin-courseId')}&curriculumName=${Cookie.get('admin-curriculumName') ? decodeURIComponent(Cookie.get('admin-curriculumName')) : 'python'}&mallId=${Cookie.get('admin-mallId')}`
} }
location.href = href
}
} }

@ -1,63 +1,100 @@
<template> <template>
<div v-show="loaded"> <div v-show="loaded">
<div class="header" :class="{ hh: $config.isHh }"> <div class="header"
<img v-if="$config.isHh" src="@/assets/images/logo-hh.png" alt="" class="logo"> :class="{hh: $config.isHh}">
<p v-else>{{ curriculumName }}</p> <img v-if="$config.isHh"
<p v-if="third === 'ai'">账号{{ account }}密码112233aa</p> src="@/assets/images/logo-hh.png"
<el-button class="back btn" type="primary" @click="back">退出实验</el-button> alt=""
class="logo">
<p v-else>{{curriculumName}}</p>
<el-button class="back btn"
type="primary"
@click="back">退出实验</el-button>
</div> </div>
<template v-if="!notAllowed">
<iframe v-if="third" class="AI" :src="iframeSrc" frameborder="0" width="100%"></iframe>
<template v-else>
<div class="top">
<div class="language">
<p v-if="$config.isHh" style="font-size: 18px">{{ $config.title }}</p>
<p>编程语言</p>
<el-select v-model="language" @change="languageChange">
<el-option v-for="(item, i) in languages" :key="i" :value="item.name"></el-option>
</el-select>
<el-button v-if="language === 'vscode'" class="open-vs" type="primary" size="small" <div class="top">
@click="openVscode">打开Vscode新窗口</el-button> <div class="language">
</div> <p v-if="$config.isHh"
<div class="inline-center"> style="font-size: 18px">{{$config.title}}</p>
<el-tooltip class="item" effect="dark" content="支持导入其它数据用于实验,总上传的文件大小不可以超过10M" placement="bottom"> <p>编程语言</p>
<i class="info el-icon-warning" style="margin-right: 10px"></i> <el-select v-model="language"
</el-tooltip> @change="languageChange">
<el-button type="primary" size="small" icon="el-icon-document" @click="toData">我的数据</el-button> <el-option v-for="(item, i) in languages"
</div> :key="i"
</div> :label="item.name"
:value="item.id"></el-option>
</el-select>
<el-button v-if="language"
class="open-vs"
type="primary"
size="small"
@click="openVscode">打开Vscode新窗口</el-button>
</div>
<div class="inline-center">
<el-tooltip class="item"
effect="dark"
content="支持导入其它数据用于实验,总上传的文件大小不可以超过10M"
placement="bottom">
<i class="info el-icon-warning"
style="margin-right: 10px"></i>
</el-tooltip>
<el-button type="primary"
size="small"
icon="el-icon-document"
@click="toData">我的数据</el-button>
</div>
</div>
<div class="tab"> <div class="tab">
<el-tabs v-model="curTab" type="card" @tab-click="judChange"> <el-tabs v-model="curTab"
<el-tab-pane v-for="(item, i) in workbench" :key="item.judgmentId" :label="item.name" type="card"
:value="item.judgmentId"> @tab-click="judChange">
<codemirror v-if="language !== 'vscode'" :ref="'code' + i" :key="codeKey" :projectId.sync="projectId" <el-tab-pane v-for="(item, i) in workbench"
:systemId.sync="systemId" :code.sync="item.code" :finalCode.sync="item.finalCode" :key="item.judgmentId"
:judgmentId="item.judgmentId" :codeId.sync="item.codeId" :answer.sync="item.answer" :label="item.name"
:retResult.sync="item.retResult" :photoUrl.sync="item.photoUrl" :index="i" :curTab.sync="curTab" :value="item.judgmentId">
:modelIsShow.sync="modelIsShow"></codemirror> <codemirror v-if="!language"
<iframe v-else class="vscode" :src="Config.vscodeUrl" frameborder="0" width="100%"></iframe> :ref="'code' + i"
</el-tab-pane> :key="codeKey"
</el-tabs> :projectId.sync="projectId"
</div> :systemId.sync="systemId"
</template> :code.sync="item.code"
:finalCode.sync="item.finalCode"
:judgmentId="item.judgmentId"
:codeId.sync="item.codeId"
:answer.sync="item.answer"
:retResult.sync="item.retResult"
:photoUrl.sync="item.photoUrl"
:index="i"
:curTab.sync="curTab"
:modelIsShow.sync="modelIsShow"
@cache="leavePage"></codemirror>
<iframe v-else
class="vscode"
:src="Config.vscodeUrl"
frameborder="0"
width="100%"></iframe>
</el-tab-pane>
</el-tabs>
</div>
<div class="menu"> <div class="menu">
<testPanel @tell="setPoints" @recoveryCode="recoveryCode" ref="mainindex" :workbench.sync="workbench"> <testPanel @tell="setPoints"
</testPanel> @recoveryCode="recoveryCode"
</div> ref="mainindex"
:workbench.sync="workbench"></testPanel>
</div>
<div v-if="isSubmit" class="mask"></div> <div v-if="isSubmit"
</template> class="mask"></div>
</div> </div>
</template> </template>
<script> <script>
import newmain from "../util/newMain" import newmain from "../util/newMain";
import Util from '@/util' import testPanel from "../components/TestPanel";
import testPanel from "../components/TestPanel" import codemirror from "../components/codemirror";
import codemirror from "../components/codemirror"
import Cookie from 'js-cookie' import Cookie from 'js-cookie'
import { Loading } from 'element-ui' import { Loading } from 'element-ui'
import Config from '@/config' import Config from '@/config'
@ -65,8 +102,6 @@ export default {
data () { data () {
return { return {
Config, Config,
third: Cookie.get('admin-third'), // iframe
iframeSrc: '',
isSubmit: Cookie.get('admin-isSubmit') == 'true' ? true : false, // isSubmit: Cookie.get('admin-isSubmit') == 'true' ? true : false, //
loaded: false, // loaded: false, //
loadIns: null, // loading loadIns: null, // loading
@ -76,33 +111,24 @@ export default {
curriculumName: Cookie.get('admin-curriculumName') ? decodeURIComponent(Cookie.get('admin-curriculumName')) : 'python', // curriculumName: Cookie.get('admin-curriculumName') ? decodeURIComponent(Cookie.get('admin-curriculumName')) : 'python', //
assessmentId: Cookie.get('admin-assessmentId'), // id assessmentId: Cookie.get('admin-assessmentId'), // id
mallId: Cookie.get('admin-mallId'), mallId: Cookie.get('admin-mallId'),
language: Cookie.get('admin-language') || 'python3.7.9', // language: +Cookie.get('admin-language') || 0, //
projectId: '', projectId: '',
systemId: '', systemId: '',
modelIsShow: false, // modelIsShow: false, //
projectPermissions: 0, // (0 1 2) projectPermissions: 0, // (0 1 2)
languages: [ languages: [
{ {
name: 'python3.7.9' id: 0,
name: 'Python'
}, },
{ {
name: 'python3.9' id: 1,
}, name: 'Vscode'
{
name: 'python3.10.9'
},
{
name: 'python3.12.4'
},
{
name: 'vscode'
}, },
], ],
curTab: '', // curTab: '', //
workbench: [], // workbench: [], //
codeKey: 1, // codeKey: 1 //
notAllowed: 0,
account: '',
}; };
}, },
components: { components: {
@ -110,59 +136,46 @@ export default {
testPanel testPanel
}, },
mounted () { mounted () {
if (this.third) { document.onkeydown = function (event) {
this.language = 'vscode' var e = event || window.event || arguments.callee.caller.arguments[0];
this.third === 'ai' && this.handleAI()
this.iframeSrc = this.third === 'ai' ? 'https://ai.huorantech.cn/' : 'https://lowcode.izhixinyun.com/'
document.body.style.overflow = 'hidden'
this.loaded = true
} else {
Cookie.set('admin-language', 'python3.7.9')
// const opened = +localStorage.getItem('opened')
// if (opened) {
// localStorage.setItem('opened', opened + 1)
// this.$alert('', '', {
// confirmButtonText: '退',
// showClose: false,
// beforeClose: () => {
// Util.exit()
// },
// })
// } else {
// this.notAllowed = 0
// localStorage.setItem('opened', 1)
// }
this.notAllowed = 0
document.onkeydown = function (event) { if (e && e.keyCode == 123) {
var e = event || window.event || arguments.callee.caller.arguments[0]; e.returnValue = false;
return (false);
if (e && e.keyCode == 123) {
e.returnValue = false;
return (false);
}
} }
this.loadIns = Loading.service({
background: 'rgba(255, 255, 255, .1)'
})
//
newmain.$on("isSubmit", isSubmit => {
this.isSubmit = isSubmit
})
} }
this.loadIns = Loading.service({
background: 'rgba(255, 255, 255, .1)'
})
//
newmain.$on("isSubmit", isSubmit => {
this.isSubmit = isSubmit
})
this.autoLogout() this.autoLogout()
//
window.onbeforeunload = () => {
this.leavePage()
}
},
beforeRouteLeave (to, from, next) {
next(this.leavePage())
}, },
methods: { methods: {
// ai //
async handleAI () { leavePage () {
const res = await this.$get(`${this.api.getTheMostRecentlyRunProject}`, { const list = this.workbench
ai: 1, //
cid: Cookie.get('admin-courseId') if (!this.$refs.mainindex.isSubmit && list.length) {
}) const cache = {
if (res.account) { projectId: Number(this.projectId),
this.account = res.account judgmentIdList: this.workbench.map(e => e.judgmentId)
}
//
if (!list.some(e => e.code)) {
cache.empty = true //
}
localStorage.setItem('codeCache', JSON.stringify(cache)) // ididid
} }
}, },
// //
@ -197,7 +210,7 @@ export default {
if ((new Date().getTime() - lastTime) > this.$config.autoLogoutTime) { if ((new Date().getTime() - lastTime) > this.$config.autoLogoutTime) {
logout || this.$message.error('用户登录过期,请重新登录') logout || this.$message.error('用户登录过期,请重新登录')
logout = true logout = true
setTimeout(Util.exit, 1500) setTimeout(this.back, 1500)
} }
}, 1000) }, 1000)
}, },
@ -216,7 +229,24 @@ export default {
}, },
// 退 // 退
back () { back () {
Util.exit() let href = this.$config.isDev ?
`http://${location.hostname}:8082/#/` :
`${location.origin}${this.fromManager ?
'/admin' :
(!this.$config.isTest) ?
'' :
'/student'}/#/`
//
if (this.assessmentId) {
href += `ass/list`
} else if (this.competitionId) {
//
href += `match/list`
} else {
//
href += `station/preview?courseId=${this.courseId}&curriculumName=${this.curriculumName}&mallId=${this.mallId}`
}
location.href = href
}, },
// id // id
setPoints (projectId, systemId, workbench) { setPoints (projectId, systemId, workbench) {
@ -232,42 +262,31 @@ export default {
[v-cloak] { [v-cloak] {
display: none; display: none;
} }
.header { .header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
height: 58px; height: 58px;
line-height: 58px; line-height: 58px;
background-color: #f8f8f8; background-color: #f8f8f8;
&.hh { &.hh {
padding: 10px 0; padding: 10px 0;
line-height: normal; line-height: normal;
} }
p { p {
margin-left: 18px; margin-left: 18px;
font-size: 20px; font-size: 20px;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
} }
.logo { .logo {
width: 200px; width: 200px;
margin-left: 10px; margin-left: 10px;
} }
.back { .back {
padding: 23px 50px; padding: 23px 50px;
border: none; border: none;
border-radius: 0; border-radius: 0;
} }
} }
.AI {
height: calc(100vh - 58px);
}
/deep/.top { /deep/.top {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -275,25 +294,20 @@ export default {
height: 60px; height: 60px;
padding: 0 15px; padding: 0 15px;
line-height: 60px; line-height: 60px;
.language { .language {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
} }
p { p {
font-size: 16px; font-size: 16px;
margin-right: 15px; margin-right: 15px;
} }
.el-input { .el-input {
width: 200px; width: 200px;
} }
.el-input .el-input__inner { .el-input .el-input__inner {
border-radius: 30px; border-radius: 30px;
} }
.open-vs { .open-vs {
margin-left: 20px; margin-left: 20px;
} }
@ -302,60 +316,47 @@ export default {
.vscode { .vscode {
height: calc(100vh - 186px); height: calc(100vh - 186px);
} }
.menu { .menu {
position: relative; position: relative;
z-index: 1000; z-index: 1000;
} }
::v-deep .el-dialog--center { ::v-deep .el-dialog--center {
width: 400px; width: 400px;
} }
::v-deep .el-dialog__headerbtn .el-icon-close:before { ::v-deep .el-dialog__headerbtn .el-icon-close:before {
padding: 3px; padding: 3px;
border-radius: 50%; border-radius: 50%;
} }
/deep/.tab { /deep/.tab {
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
.el-tabs__header { .el-tabs__header {
margin-bottom: 0; margin-bottom: 0;
} }
.el-tabs__item.is-active { .el-tabs__item.is-active {
color: #333; color: #333;
} }
.el-icon-circle-plus-outline:before { .el-icon-circle-plus-outline:before {
font-size: 16px; font-size: 16px;
} }
.el-tabs--card > .el-tabs__header {
.el-tabs--card>.el-tabs__header {
border-bottom: none; border-bottom: none;
} }
.el-tabs--card > .el-tabs__header .el-tabs__nav {
.el-tabs--card>.el-tabs__header .el-tabs__nav {
border: none; border: none;
} }
.el-tabs--card > .el-tabs__header .el-tabs__item {
.el-tabs--card>.el-tabs__header .el-tabs__item {
border-left: none; border-left: none;
border-bottom: none; border-bottom: none;
} }
} }
.info { .info {
color: #bfbfbf; color: #bfbfbf;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
opacity: 0.9; opacity: 0.9;
} }
} }
.mask { .mask {
z-index: 999; z-index: 999;
position: absolute; position: absolute;

@ -2,144 +2,218 @@
<!-- 实验报告 --> <!-- 实验报告 -->
<div class="wrap"> <div class="wrap">
<breadcrumb data="返回实验/我的数据"></breadcrumb> <breadcrumb data="返回实验/我的数据"></breadcrumb>
<div class="content" :class="{ loading }" id="pdfDom"> <div class="content"
<div style="text-align: right" v-if="!loading"> :class="{loading}"
<el-button size="mini" @click="editReport"> id="pdfDom">
<div style="text-align: right"
v-if="!loading">
<el-button size="mini"
@click="editReport">
{{ editing ? "保存" : "编辑" }} {{ editing ? "保存" : "编辑" }}
</el-button> </el-button>
<el-button type="primary" size="mini" @click="exportPage">导出报告</el-button> <el-button type="primary"
size="mini"
@click="exportPage">导出报告</el-button>
</div> </div>
<h6 class="r-title">标准实验报告</h6> <h6 class="r-title">标准实验报告</h6>
<div class="info"> <div class="info">
<h6 class="l-title"> <h6 class="l-title">
<img src="@/assets/images/report1.png" alt=""> <img src="@/assets/images/report1.png"
alt="">
基本信息 基本信息
</h6> </h6>
<ul :class="['info-list', { edit: editing }]"> <ul :class="['info-list', {edit: editing}]">
<li> <li>
<label>学生姓名</label> <label>学生姓名</label>
<el-input v-if="editing" v-model="infoData.userName" disabled></el-input> <el-input v-if="editing"
v-model="infoData.userName"
disabled></el-input>
<span v-else>{{ infoData.userName }}</span> <span v-else>{{ infoData.userName }}</span>
</li> </li>
<li> <li>
<label>学生学号</label> <label>学生学号</label>
<el-input v-if="editing" v-model="infoData.workNumber" disabled></el-input> <el-input v-if="editing"
v-model="infoData.workNumber"
disabled></el-input>
<span v-else>{{ infoData.workNumber }}</span> <span v-else>{{ infoData.workNumber }}</span>
</li> </li>
<li> <li>
<label>实验时间</label> <label>实验时间</label>
<el-input v-if="editing" v-model="infoData.submitTime" disabled></el-input> <el-input v-if="editing"
v-model="infoData.submitTime"
disabled></el-input>
<span v-else>{{ infoData.submitTime }}</span> <span v-else>{{ infoData.submitTime }}</span>
</li> </li>
<li> <li>
<label>实验成绩</label> <label>实验成绩</label>
<el-input v-if="editing" v-model="infoData.score" disabled></el-input> <el-input v-if="editing"
<div v-else class="score-wrap"> v-model="infoData.score"
disabled></el-input>
<div v-else
class="score-wrap">
<em>{{ infoData.score }}</em> <em>{{ infoData.score }}</em>
<img src="@/assets/images/point.png" alt=""> <img src="@/assets/images/point.png"
alt="">
</div> </div>
</li> </li>
<li> <li>
<label>学生班级</label> <label>学生班级</label>
<el-input v-if="editing" v-model="infoData.className"></el-input> <el-input v-if="editing"
v-model="infoData.className"></el-input>
<span v-else>{{ infoData.className }}</span> <span v-else>{{ infoData.className }}</span>
</li> </li>
<li> <li>
<label>指导老师</label> <label>指导老师</label>
<el-input v-if="editing" v-model="infoData.instructor"></el-input> <el-input v-if="editing"
v-model="infoData.instructor"></el-input>
<span v-else>{{ infoData.instructor }}</span> <span v-else>{{ infoData.instructor }}</span>
</li> </li>
<li> <li>
<label>实验学时</label> <label>实验学时</label>
<el-input v-if="editing" v-model="infoData.period"></el-input> <el-input v-if="editing"
v-model="infoData.period"></el-input>
<span v-else>{{ infoData.period }}</span> <span v-else>{{ infoData.period }}</span>
</li> </li>
</ul> </ul>
<div class="m-b-20"> <div class="m-b-20">
<h6 class="l-title"> <h6 class="l-title">
<img src="@/assets/images/report2.png" alt=""> <img src="@/assets/images/report2.png"
alt="">
实验项目名称 实验项目名称
</h6> </h6>
<el-input v-if="editing" v-model="infoData.projectName" type="textarea"></el-input> <el-input v-if="editing"
<div v-else class="pre-wrap" v-html="infoData.projectName"></div> v-model="infoData.projectName"
type="textarea"></el-input>
<div v-else
class="pre-wrap"
v-html="infoData.projectName"></div>
</div> </div>
<div class="m-b-20"> <div class="m-b-20">
<h6 class="l-title"> <h6 class="l-title">
<img src="@/assets/images/report3.png" alt=""> <img src="@/assets/images/report3.png"
alt="">
实验目的 实验目的
</h6> </h6>
<quill v-if="editing" :border="true" v-model="infoData.purpose" :height="150" /> <quill v-if="editing"
<div v-else :class="['pre-wrap', { edit: editing }]" v-html="infoData.purpose"></div> :border="true"
v-model="infoData.purpose"
:height="150" />
<div v-else
:class="['pre-wrap', {edit: editing}]"
v-html="infoData.purpose"></div>
</div> </div>
<div class="m-b-20"> <div class="m-b-20">
<h6 class="l-title"> <h6 class="l-title">
<img src="@/assets/images/report4.png" alt=""> <img src="@/assets/images/report4.png"
alt="">
实验数据 实验数据
</h6> </h6>
<el-table :data="expData" class="table" border stripe header-align="center"> <el-table :data="expData"
<el-table-column type="index" label="序号" align="center" width="60"> class="table"
border
stripe
header-align="center">
<el-table-column type="index"
label="序号"
align="center"
width="60">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.$index + 1 }} {{ scope.$index + 1 }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="judgmentName" label="判分点" width="200" align="center"></el-table-column> <el-table-column prop="judgmentName"
<el-table-column v-if='project' prop="judgmentName" label="考核点" align="center" width="150"> label="判分点"
width="200"
align="center"></el-table-column>
<el-table-column v-if='project'
prop="judgmentName"
label="考核点"
align="center"
width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index"> <div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span> <span>
<span>{{ index + 1 }}. </span>{{ item.name }} <span>{{index+1}}. </span>{{item.name}}
</span> </span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ruleAnswer" label="参考答案" style='word-wrap: break-word'> <el-table-column prop="ruleAnswer"
label="参考答案"
style='word-wrap: break-word'>
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'> <div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index"> <div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span> <span>
<span>{{ index + 1 }}. </span>{{ item.ruleAnswer }} <span>{{index+1}}. </span>{{item.ruleAnswer}}
</span> </span>
</div> </div>
</div> </div>
<div v-else v-html="scope.row.referenceAnswer"></div> <div v-else
v-html="scope.row.referenceAnswer"></div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="userAnswer" label="学生答案"> <el-table-column prop="userAnswer"
label="学生答案">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'> <div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index"> <div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span v-if='item.userAnswer'> <span v-if='item.userAnswer'>
<span>{{ index + 1 }}. </span>{{ item.userAnswer }} <span>{{index+1}}. </span>{{item.userAnswer}}
</span> </span>
<span v-else> <span v-else>
<span>{{ index + 1 }}. </span>未填写 <span>{{index+1}}. </span>未填写
</span> </span>
</div> </div>
</div> </div>
<div v-else class="pre-code">{{ scope.row.answer }}</div> <div v-else
v-html='scope.row.answer'
style='white-space: pre-wrap'></div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="runResult" label="学生运行结果" align="center"> <el-table-column prop="runResult"
label="学生运行结果"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<div class="m-b-20 pre-code">{{ scope.row.runResult }}</div> <div class="m-b-20"
v-html='scope.row.runResult'
style='white-space: pre-wrap'></div>
<template v-if="scope.row.runThePictureList"> <template v-if="scope.row.runThePictureList">
<img v-for="(img, i) in scope.row.runThePictureList" :key="i" width="200" class="result-pic" <img v-for="(img, i) in scope.row.runThePictureList"
:src="img" alt=""> :key="i"
width="200"
class="result-pic"
:src="img"
alt="">
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="quesScore" label="分值" width="80" align="center"></el-table-column> <el-table-column prop="quesScore"
<el-table-column prop="score" label="得分" width="80" align="center"></el-table-column> label="分值"
width="80"
align="center"></el-table-column>
<el-table-column prop="score"
label="得分"
width="80"
align="center"></el-table-column>
</el-table> </el-table>
</div> </div>
<div class="m-b-20"> <div class="m-b-20">
<h6 class="l-title"> <h6 class="l-title">
<img src="@/assets/images/report5.png" alt=""> <img src="@/assets/images/report5.png"
alt="">
实验总结与体会 实验总结与体会
</h6> </h6>
<Editor v-if="editing" api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="infoData.summarize" <Editor v-if="editing"
:init="editorConfig" /> api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda'
<div v-show="!editing" class="pre-wrap" v-html="infoData.summarize"></div> v-model="infoData.summarize"
:init="editorConfig" />
<div v-show="!editing"
class="pre-wrap"
v-html="infoData.summarize"></div>
</div> </div>
</div> </div>
</div> </div>
@ -198,18 +272,17 @@ export default {
purpose: form.purpose, purpose: form.purpose,
summarize: form.summarize summarize: form.summarize
} }
let { data } = report const data = report.data
this.userScores = userScores
// data使 // data使
if (!data) { if (!data) {
this.userScores = userScores
this.handleList(userScores) this.handleList(userScores)
this.$post(this.api.editExperimentalData, { this.$post(this.api.editExperimentalData, {
reportId, reportId,
data: JSON.stringify(userScores) data: JSON.stringify(userScores)
}).then(res => { }).catch(err => { }) }).then(res => { }).catch(err => { })
} else { } else {
data = JSON.parse(data) this.handleList(userScores.find(e => e.lcRuleRecords) ? userScores : JSON.parse(data))
this.handleList(data)
} }
}).catch(res => { }) }).catch(res => { })
}, },
@ -286,19 +359,12 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import '/styles/css/editor.css'; @import '/styles/css/editor.css';
.m-b-20 { .m-b-20 {
margin-bottom: 20px; margin-bottom: 20px;
} }
.wrap { .wrap {
padding: 12px 300px 20px; padding: 12px 300px 20px;
} }
.pre-code {
white-space: pre-wrap;
}
code, code,
kbd, kbd,
samp { samp {
@ -307,18 +373,12 @@ samp {
word-wrap: break-word; word-wrap: break-word;
white-space: pre-wrap; white-space: pre-wrap;
} }
/deep/ pre { /deep/ pre {
white-space: pre-wrap; white-space: pre-wrap; /* css-3 */
/* css-3 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -moz-pre-wrap; white-space: pre-wrap; /* Opera 4-6 */
/* Mozilla, since 1999 */ white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; word-wrap: break-word; /* Internet Explorer 5.5+ */
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
word-break: break-all; word-break: break-all;
overflow: hidden; overflow: hidden;
font-size: 12px; font-size: 12px;
@ -326,27 +386,22 @@ samp {
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei',
arial, STHeiTi, sans-serif; arial, STHeiTi, sans-serif;
} }
.content { .content {
padding: 16px 0; padding: 16px 0;
background: #fff; background: #fff;
&.loading { &.loading {
padding-top: 30px; padding-top: 30px;
} }
.r-title { .r-title {
margin-bottom: 40px; margin-bottom: 40px;
font-size: 24px; font-size: 24px;
text-align: center; text-align: center;
color: #333; color: #333;
} }
.info { .info {
padding: 20px 16px; padding: 20px 16px;
border: 1px solid #e1e6f2; border: 1px solid #e1e6f2;
} }
.l-title { .l-title {
display: flex; display: flex;
align-items: center; align-items: center;
@ -355,52 +410,43 @@ samp {
font-size: 14px; font-size: 14px;
color: #333; color: #333;
background-color: #f7f9fc; background-color: #f7f9fc;
img { img {
margin-right: 5px; margin-right: 5px;
} }
} }
.info-list { .info-list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding: 10px 0 0 20px; padding: 10px 0 0 20px;
li { li {
display: inline-flex; display: inline-flex;
width: 25%; width: 25%;
padding: 0 10px; padding: 0 10px;
margin-bottom: 34px; margin-bottom: 34px;
} }
&.edit { &.edit {
li { li {
align-items: center; align-items: center;
} }
} }
label { label {
font-size: 14px; font-size: 14px;
color: #333; color: #333;
white-space: nowrap; white-space: nowrap;
} }
span { span {
min-width: 150px; min-width: 150px;
padding: 0 10px 3px; padding: 0 10px 3px;
border-bottom: 1px solid #e1e6f2; border-bottom: 1px solid #e1e6f2;
} }
/deep/.el-input { /deep/.el-input {
width: 174px; width: 174px;
} }
} }
.score-wrap { .score-wrap {
position: relative; position: relative;
min-width: 150px; min-width: 150px;
border-bottom: 1px solid #e1e6f2; border-bottom: 1px solid #e1e6f2;
em { em {
position: absolute; position: absolute;
top: -12px; top: -12px;
@ -410,21 +456,18 @@ samp {
font-weight: 600; font-weight: 600;
color: #0b1d30; color: #0b1d30;
} }
img { img {
position: absolute; position: absolute;
bottom: -15px; bottom: -15px;
left: 0; left: 0;
} }
} }
/deep/.el-textarea .el-textarea__inner, /deep/.el-textarea .el-textarea__inner,
.pre-wrap { .pre-wrap {
min-height: 72px; min-height: 72px;
padding: 10px 16px; padding: 10px 16px;
font-size: 14px; font-size: 14px;
color: #333; color: #333;
&.edit { &.edit {
color: #abb3c6; color: #abb3c6;
border: 1px solid #cacfdb; border: 1px solid #cacfdb;
@ -432,27 +475,22 @@ samp {
background-color: #f6f7f9; background-color: #f6f7f9;
} }
} }
/deep/ .table th { /deep/ .table th {
background-color: #e1eaff !important; background-color: #e1eaff !important;
.cell { .cell {
line-height: 35px; line-height: 35px;
color: #555555; color: #555555;
} }
} }
} }
.result-pic { .result-pic {
margin: 10px 0; margin: 10px 0;
} }
@media (max-width: 1650px) { @media (max-width: 1650px) {
.wrap { .wrap {
padding: 12px 200px 20px; padding: 12px 200px 20px;
} }
} }
@media (max-width: 1430px) { @media (max-width: 1430px) {
.wrap { .wrap {
padding: 12px 100px 20px; padding: 12px 100px 20px;

Loading…
Cancel
Save