添加vscode

openf12 V2.1.5
yujialong 1 year ago
parent f1d56abefe
commit 2599f0e6f3
  1. 245
      src/components/TestPanel.vue
  2. 12
      src/components/codemirror.vue
  3. 33
      src/components/quill/index.vue
  4. 4
      src/config/index.js
  5. 14
      src/store/index.js
  6. 18
      src/styles/common.scss
  7. 14
      src/views/Home.vue

@ -44,6 +44,8 @@
</div> </div>
</div> </div>
<div> <div>
<el-button @click="toggleReport"
v-if="$parent.language && !isSubmit && !competitionId">填写实验报告</el-button>
<el-button @click="toReport" <el-button @click="toReport"
v-if="isSubmit && !competitionId">查看实验报告</el-button> v-if="isSubmit && !competitionId">查看实验报告</el-button>
<el-button class="reload" <el-button class="reload"
@ -56,7 +58,42 @@
</div> </div>
</div> </div>
</el-header> </el-header>
<el-container> <div class="report-wrap"
v-if="reportVisible">
<i class="el-icon-caret-top close-report"></i>
<el-table class="report-table"
:data="taskList"
:max-height="tableHeight">
<el-table-column prop="name"
label="判分点"
width="210"
align="center"></el-table-column>
<el-table-column prop="score"
label="答案"
align="center">
<template slot-scope="scope">
<codemirror v-model="scope.row.code"
:options="cmOption"
class="code-mirror"
:ref="'codemirror' + scope.$index"
@ready="ready"></codemirror>
</template>
</el-table-column>
<el-table-column prop="score"
label="运行结果"
align="center">
<template slot-scope="scope">
<quill class="quill"
:tools="false"
:border="true"
v-model="scope.row.codeResult"
:height="300"
:index="1" />
</template>
</el-table-column>
</el-table>
</div>
<el-container v-else>
<el-aside width="30%"> <el-aside width="30%">
<div class="aside-header"> <div class="aside-header">
<div :class="['p-title color', 'system' + systemId]"> <div :class="['p-title color', 'system' + systemId]">
@ -78,7 +115,8 @@
<el-col :span="24"> <el-col :span="24">
<el-card shadow="never" <el-card shadow="never"
:border="false"> :border="false">
<el-table :data="taskList" <el-table class="task-table"
:data="taskList"
:stripe="true"> :stripe="true">
<el-table-column type="index"></el-table-column> <el-table-column type="index"></el-table-column>
<el-table-column prop="name" <el-table-column prop="name"
@ -121,7 +159,8 @@
</div> </div>
</el-aside> </el-aside>
<el-main> <el-main>
<el-tabs v-model="pannelTab" <el-tabs class="info-tab"
v-model="pannelTab"
type="card"> type="card">
<el-tab-pane label="项目背景" <el-tab-pane label="项目背景"
name="first"> name="first">
@ -145,7 +184,7 @@
</el-collapse> </el-collapse>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="实验提示" <el-tab-pane label="实验提示"
name="fifth" name="third"
v-if="hintOpen"> v-if="hintOpen">
<div class="ql-editor" <div class="ql-editor"
v-html="experimentHint"></div> v-html="experimentHint"></div>
@ -172,12 +211,54 @@
<script> <script>
import newmain from "../util/newMain"; import newmain from "../util/newMain";
import quill from "@/components/quill";
import util from '@/util' import util from '@/util'
import Config from '@/config' import Config from '@/config'
import Cookie from 'js-cookie' import Cookie from 'js-cookie'
import 'quill/dist/quill.core.css'; import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css'; import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css'; import 'quill/dist/quill.bubble.css';
import { codemirror } from "vue-codemirror";
import "codemirror/theme/ambiance.css"; //
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/python/python.js";
import "codemirror/lib/codemirror.css";
// require active-line.js
import "codemirror/addon/selection/active-line.js";
// styleSelectedText
import "codemirror/addon/selection/mark-selection.js";
// hint
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/sql-hint.js";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/javascript-hint.js";
// highlightSelectionMatches
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/match-highlighter.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/sublime.js";
// foldGutter
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/xml-fold.js";
//
import "codemirror/theme/monokai.css";
import "codemirror/theme/base16-light.css";
export default { export default {
data () { data () {
return { return {
@ -221,9 +302,43 @@ export default {
pannelTab: 'first', // pannelTab: 'first', //
isSelected: false, // true isSelected: false, // true
statusTimer: null, // statusTimer: null, //
reportId: '' reportId: '',
cmOption: {
scrollbarStyle: "native",
tabSize: 2, // tab
styleActiveLine: true, //
lineNumbers: true, //
styleSelectedText: true,
line: true,
foldGutter: true, //
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
highlightSelectionMatches: { showToken: /\w/, annotateScrollbar: true }, //
mode: 'python',
lineWrapping: true, //
autoCloseTags: true,//
autoCloseBrackets: true,//
// hint.js options
hintOptions: {
//
completeSingle: false
},
// sublimeemacsvim
keyMap: "sublime",
matchBrackets: true,
showCursorWhenSelecting: true,
// theme: "monokai" //
},
reportTab: '',
reportPoints: [],
reportVisible: false,
tableHeight: 0
}; };
}, },
components: {
codemirror,
quill
},
mounted () { mounted () {
// 210 // 210
this.projectPermissions = this.assessmentId ? this.projectPermissions = this.assessmentId ?
@ -256,6 +371,7 @@ export default {
} }
} }
this.drag() this.drag()
this.tableHeight = window.innerHeight - 360
}, },
methods: { methods: {
// //
@ -319,6 +435,14 @@ export default {
this.$parent.getModelStatus(systemId) this.$parent.getModelStatus(systemId)
this.curReq = curReq // judgmentIditem this.curReq = curReq // judgmentIditem
this.points = points this.points = points
const reportPoints = JSON.parse(JSON.stringify(points))
points.forEach(e => {
e.codeResult = ''
})
this.reportPoints = reportPoints
if (points.length) this.reportTab = reportPoints[0].judgmentId + ''
console.log("🚀 ~ file: TestPanel.vue:423 ~ returnnewPromise ~ this.reportTab:", points, this.reportTab)
this.taskList = points // this.taskList = points //
this.judgmentId = points[0].judgmentId // this.judgmentId = points[0].judgmentId //
this.experimentTarget = project.experimentTarget this.experimentTarget = project.experimentTarget
@ -532,12 +656,24 @@ export default {
this.countVal = 0 this.countVal = 0
this.grade = '00' this.grade = '00'
this.pannelTab = 'first' this.pannelTab = 'first'
this.clearReport()
this.$emit('recoveryCode') // this.$emit('recoveryCode') //
}, },
//
toggleReport () {
this.reportVisible = !this.reportVisible
},
//
clearReport () {
this.taskList.forEach(e => {
e.code = ''
e.codeResult = ''
})
},
// //
toReport () { toReport () {
Cookie.set('doneProjectId', this.projectId) // id,id Cookie.set('doneProjectId', this.projectId) // id,id
this.$router.push(`/report?reportId=${this.reportId}`) this.$router.push(`/report?reportId=${this.$store.state.reportId}`)
}, },
// //
reload () { reload () {
@ -556,25 +692,63 @@ export default {
this.$emit('tell', this.projectId, this.curSystemId, points) this.$emit('tell', this.projectId, this.curSystemId, points)
this.$emit('recoveryCode') this.$emit('recoveryCode')
this.startCount() this.startCount()
this.clearReport()
},
//
ready () {
for (let i = 0; i < this.points.length; i++) {
const code = this.$refs['codemirror' + i][0].codemirror
console.log('ready', code)
// code && code.setSize('auto', 'calc(100vh - 150px)')
code && code.setSize('auto', '300px')
}
}, },
// //
confirmSubmit () { confirmSubmit () {
const isVscode = this.$parent.language // vscode
const { taskList } = this
const pointList = this.$parent.workbench const pointList = this.$parent.workbench
let msg = '此操作将视为结束考试,是否继续?' let msg = '此操作将视为结束考试,是否继续?'
if (pointList.find(e => !e.codeId && e.code)) msg = '有代码没有运行,该代码将不得分,确定提交?' if (!isVscode && pointList.find(e => !e.codeId && e.code)) msg = '有代码没有运行,该代码将不得分,确定提交?'
if (isVscode && !taskList.find(e => e.code || e.codeResult)) msg = '实验报告未填写,实验成绩为零,是否确认提交?'
this.$confirm(msg, '提示', { this.$confirm(msg, '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning', type: 'warning',
center: true center: true
}).then(() => { }).then(() => {
// vscodecodeId
if (isVscode) {
const promises = []
taskList.map(async (e, i) => {
(e.code || e.codeResult) && promises.push(new Promise(async (resolve, reject) => {
const { code, codeId } = await this.$post(this.api.runPythonCode, {
code: e.code,
bcId: e.judgmentId,
cid: this.courseId,
projectId: this.projectId,
userAnswer: e.codeResult || null,
type: 1
})
this.$parent.workbench[i].codeId = codeId
this.$parent.workbench[i].answer = e.codeResult
this.$parent.workbench[i].retResult = 1
resolve()
}))
})
Promise.all(promises).then(_ => {
this.submit()
})
} else {
// //
if (!pointList.find(e => e.codeId)) { if (!pointList.find(e => e.codeId)) {
this.$post(this.api.runPythonCode, { this.$post(this.api.runPythonCode, {
code: '', code: '',
bcId: pointList[0].judgmentId, bcId: pointList[0].judgmentId,
cid: this.courseId, cid: this.courseId,
projectId: this.projectId projectId: this.projectId,
type: 0
}).then(({ codeId }) => { }).then(({ codeId }) => {
this.$parent.workbench[0].codeId = codeId this.$parent.workbench[0].codeId = codeId
this.submit() this.submit()
@ -582,6 +756,7 @@ export default {
} else { } else {
this.submit() this.submit()
} }
}
}).catch(() => { }) }).catch(() => { })
}, },
// //
@ -632,6 +807,7 @@ export default {
localStorage.removeItem('codeCache') localStorage.removeItem('codeCache')
this.setSubmit(true) this.setSubmit(true)
clearInterval(this.statusTimer) clearInterval(this.statusTimer)
this.reportVisible = false
let list = retInfo let list = retInfo
let taskList = this.taskList let taskList = this.taskList
let score = 0 let score = 0
@ -648,6 +824,7 @@ export default {
}) })
this.grade = util.handleZero(score) // 0() this.grade = util.handleZero(score) // 0()
this.reportId = reportId this.reportId = reportId
this.$store.commit('setReportId', reportId)
this.editReport(reportId) this.editReport(reportId)
// //
this.competitionId && this.resultsDetails == 0 && this.$alert('提交成功,成绩将在' + this.resultAnnouncementTime + '小时后发布,请去参赛信息模块查看', '提示', { this.competitionId && this.resultsDetails == 0 && this.$alert('提交成功,成绩将在' + this.resultAnnouncementTime + '小时后发布,请去参赛信息模块查看', '提示', {
@ -743,6 +920,7 @@ export default {
let gap = 10 // let gap = 10 //
let parent = document.body let parent = document.body
document.querySelector('#header').onmousedown = e => { document.querySelector('#header').onmousedown = e => {
console.log("🚀 ~ file: TestPanel.vue:746 ~ document.querySelector ~ e:", e)
var x = e.clientX - el.offsetLeft var x = e.clientX - el.offsetLeft
var y = e.clientY - el.offsetTop var y = e.clientY - el.offsetTop
var left = 0 var left = 0
@ -840,11 +1018,6 @@ export default {
/deep/.el-collapse-item__header { /deep/.el-collapse-item__header {
border-bottom: none; border-bottom: none;
} }
/deep/.el-tabs__content {
margin: 0 20px;
max-height: calc(60vh - 70px);
overflow: auto;
}
/deep/.el-icon-s-ticket:before { /deep/.el-icon-s-ticket:before {
padding: 5px; padding: 5px;
font-size: 16px; font-size: 16px;
@ -852,28 +1025,33 @@ export default {
/deep/.el-collapse-item__arrow { /deep/.el-collapse-item__arrow {
margin: 0 5px 0 0; margin: 0 5px 0 0;
} }
/deep/.el-tabs__item { /deep/.info-tab.el-tabs--card {
.el-tabs__item {
font-size: 16px; font-size: 16px;
} }
/deep/.el-tabs--card > .el-tabs__header .el-tabs__nav { .el-tabs__item.is-active {
color: #fff;
}
.el-tabs__header .el-tabs__nav {
border: none; border: none;
} }
/deep/.el-tabs--card > .el-tabs__header .el-tabs__item { .el-tabs__header .el-tabs__item {
border-left: none; border-left: none;
} }
/deep/.el-tabs--card > .el-tabs__header { .el-tabs__header {
padding: 5px 20px;
border-bottom: none; border-bottom: none;
} }
& > .el-tabs__content {
margin: 0 20px;
max-height: calc(60vh - 70px);
overflow: auto;
}
}
/deep/.el-collapse { /deep/.el-collapse {
border-bottom: none; border-bottom: none;
border-top: none; border-top: none;
} }
/deep/.el-tabs__item.is-active {
color: #fff;
}
/deep/.el-tabs__header {
padding: 5px 20px;
}
.el-aside { .el-aside {
margin-bottom: 10px; margin-bottom: 10px;
color: #333; color: #333;
@ -924,7 +1102,7 @@ export default {
/deep/.el-card__body { /deep/.el-card__body {
padding: 0; padding: 0;
} }
/deep/.el-table { /deep/.task-table {
font-size: 12px; font-size: 12px;
thead { thead {
color: #fff; color: #fff;
@ -975,6 +1153,7 @@ export default {
} }
} }
.panel { .panel {
z-index: 1000;
position: relative; position: relative;
top: 200px; top: 200px;
bottom: 20px; bottom: 20px;
@ -1020,4 +1199,22 @@ export default {
opacity: 0.9; opacity: 0.9;
} }
} }
/deep/.report-table.el-table {
th {
background-color: #c6daff !important;
}
}
.report-wrap {
position: relative;
padding-top: 5px;
}
.close-report {
z-index: 2;
position: absolute;
top: -21px;
right: 296px;
font-size: 32px;
color: #c6daff;
cursor: pointer;
}
</style> </style>

@ -397,7 +397,8 @@ export default {
code: this.sourceCode, code: this.sourceCode,
bcId: this.judgmentId, bcId: this.judgmentId,
cid: this.courseId, cid: this.courseId,
projectId: this.projectId projectId: this.projectId,
type: 0
}, { }, {
headers: { headers: {
token: this.token token: this.token
@ -465,7 +466,8 @@ export default {
code, code,
bcId, bcId,
cid, cid,
projectId projectId,
type: 0
}).then(res => { }).then(res => {
const data = res.code const data = res.code
const result = data.runResult const result = data.runResult
@ -501,7 +503,8 @@ export default {
code, code,
bcId, bcId,
cid, cid,
projectId projectId,
type: 0
}).then(res => { }).then(res => {
const data = res.code const data = res.code
const photo = data.photoUrl const photo = data.photoUrl
@ -608,9 +611,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.code-wrap { .code-wrap {
position: relative; position: relative;
.code-mirror {
line-height: 30px;
}
} }
.left { .left {
position: relative; position: relative;

@ -1,15 +1,18 @@
<template> <template>
<div class="quill" ref="quill" :class="classes"> <div class="quill"
<div ref="editor" :style="styles" v-loading="loading"></div> ref="quill"
:class="classes">
<div ref="editor"
:style="styles"
v-loading="loading"></div>
<el-upload <el-upload :headers="headers"
:headers="headers"
:action="this.api.fileuploadOss" :action="this.api.fileuploadOss"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:on-success="editorUploadSuccess" :on-success="editorUploadSuccess"
style="display: none" style="display: none">
> <el-button :id="'editorUpload' + index"
<el-button :id="'editorUpload' + index" type="primary">点击上传</el-button> type="primary">点击上传</el-button>
</el-upload> </el-upload>
</div> </div>
</template> </template>
@ -58,6 +61,11 @@ export default {
type: Number, type: Number,
default: 0 default: 0
}, },
//
tools: {
type: Boolean,
default: true
},
}, },
data () { data () {
const that = this const that = this
@ -96,7 +104,8 @@ export default {
classes () { classes () {
return [ return [
{ {
"quill-no-border": !this.border "quill-no-border": !this.border,
'bd': !this.tools
} }
]; ];
}, },
@ -144,7 +153,7 @@ export default {
init () { init () {
const editor = this.$refs.editor; const editor = this.$refs.editor;
// //
this.Quill = new Quill(editor, this.options); this.Quill = new Quill(editor, this.tools ? this.options : []);
const ins = this.Quill const ins = this.Quill
// //
ins.pasteHTML(this.currentValue); ins.pasteHTML(this.currentValue);
@ -187,7 +196,7 @@ export default {
const param = new FormData() const param = new FormData()
param.append('file', file) param.append('file', file)
// base64 // base64
this.$post(this.api.fileupload, param, { this.$post(this.api.fileuploadOss, param, {
headers: { "Content-Type": "multipart/form-data" } headers: { "Content-Type": "multipart/form-data" }
}).then(res => { }).then(res => {
var range = ins.getSelection() var range = ins.getSelection()
@ -235,6 +244,9 @@ export default {
border: none; border: none;
} }
} }
.bd {
border: 1px solid #ebeef5;
}
.else { .else {
.ql-toolbar.ql-snow { .ql-toolbar.ql-snow {
@ -253,5 +265,4 @@ export default {
transform: translateY(10px); transform: translateY(10px);
} }
} }
</style> </style>

@ -10,9 +10,9 @@ let host = location.origin + '/'
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.152:9000/' // host = 'http://192.168.31.152:9000/'
// host = 'http://192.168.31.53:9000/' // host = 'http://192.168.31.53:9000/'
// host = 'http://121.37.12.51:9000/' host = 'http://121.37.12.51:9000/'
// host = 'https://occupationlab.com/' // host = 'https://occupationlab.com/'
bankPath = `http://${location.hostname}:8093` bankPath = `http://${location.hostname}:8093`
} else if (isPro) { } else if (isPro) {

@ -2,7 +2,17 @@ import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
Vue.use(Vuex); Vue.use(Vuex);
const store = new Vuex.Store({ const store = new Vuex.Store({
state: {}, state: {
mutations: {} language: 0,
reportId: ''
},
mutations: {
setLanguage: (state, id) => {
state.language = id
},
setReportId: (state, id) => {
state.reportId = id
},
}
}); });
export default store; export default store;

@ -36,7 +36,7 @@ input::-ms-input-placeholder {
body .cus-table.el-table { body .cus-table.el-table {
border-radius: 4px; border-radius: 4px;
th { th {
background-color: #E8F0FF !important; background-color: #e8f0ff !important;
.cell { .cell {
color: #222326; color: #222326;
font-weight: normal; font-weight: normal;
@ -47,15 +47,16 @@ body .cus-table.el-table {
} }
} }
} }
th, td{ th,
td {
padding: 10px 0; padding: 10px 0;
border-bottom-color: #E1E6F2; border-bottom-color: #e1e6f2;
.cell { .cell {
font-size: 12px; font-size: 12px;
} }
} }
&.el-table--striped .el-table__body tr.el-table__row--striped td { &.el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: #FAFBFF !important; background-color: #fafbff !important;
} }
.el-button--text { .el-button--text {
padding: 0; padding: 0;
@ -74,7 +75,10 @@ body .cus-table.el-table {
.pagination { .pagination {
margin: 20px 0; margin: 20px 0;
text-align: center; text-align: center;
button,.number,.more,.el-input__inner{ button,
.number,
.more,
.el-input__inner {
min-width: 32px !important; min-width: 32px !important;
height: 32px !important; height: 32px !important;
line-height: 32px; line-height: 32px;
@ -91,3 +95,7 @@ body .cus-table.el-table {
background-color: #007eff !important; background-color: #007eff !important;
} }
} }
.code-mirror {
text-align: left;
line-height: 30px;
}

@ -60,14 +60,9 @@
:retResult.sync="item.retResult" :retResult.sync="item.retResult"
:modelIsShow.sync="modelIsShow" :modelIsShow.sync="modelIsShow"
@cache="leavePage"></codemirror> @cache="leavePage"></codemirror>
<!-- <img v-else
src="@/assets/images/vscode.png"
alt=""
width="100%"
height="700"> -->
<iframe v-else <iframe v-else
class="vscode" class="vscode"
src="https://vscode.occupationlab.com/" :src="Config.isPro ? 'https://vscode.occupationlab.com/' : 'http://121.37.12.51:8088/?folder=/home/coder'"
frameborder="0" frameborder="0"
width="100%"></iframe> width="100%"></iframe>
</el-tab-pane> </el-tab-pane>
@ -88,9 +83,11 @@ 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'
export default { export default {
data () { data () {
return { return {
Config,
loaded: false, // loaded: false, //
loadIns: null, // loading loadIns: null, // loading
competitionId: Cookie.get('admin-competitionId'), competitionId: Cookie.get('admin-competitionId'),
@ -99,6 +96,7 @@ export default {
curriculumName: Cookie.get('admin-curriculumName') ? unescape(Cookie.get('admin-curriculumName')) : 'python', // curriculumName: Cookie.get('admin-curriculumName') ? unescape(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') || 0, //
projectId: '', projectId: '',
systemId: '', systemId: '',
modelIsShow: false, // modelIsShow: false, //
@ -113,7 +111,6 @@ export default {
name: 'Vscode' name: 'Vscode'
}, },
], ],
language: 0, //
curTab: '', // curTab: '', //
workbench: [], // workbench: [], //
codeKey: 1 // codeKey: 1 //
@ -174,7 +171,8 @@ export default {
}, },
// //
languageChange (id) { languageChange (id) {
Cookie.set('admin-language', id)
this.$refs.mainindex.reportVisible = false
}, },
// //
toData () { toData () {

Loading…
Cancel
Save