线上考试学员试卷自动答题,生成合格的考试成绩

master
zhangyanli 2026-04-20 17:56:48 +08:00
parent e99fc61b6e
commit c9ad40d30e
9 changed files with 12380 additions and 25 deletions

20
.babelrc Normal file
View File

@ -0,0 +1,20 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-runtime", "transform-vue-jsx", "transform-es2015-modules-commonjs", "syntax-jsx", "dynamic-import-node"],
"env": {
"development": {
"plugins": []
},
"test": {
"presets": [["env", { "modules": "commonjs" }], "stage-2"]
}
}
}

28
.eslintrc.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true
},
extends: ['standard'],
globals: {
ga: 'readonly',
cordova: 'readonly',
__dirname: 'readonly'
},
rules: {
'no-new': 'off',
'no-undef': 'off',
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'space-before-function-paren': ['error', {
anonymous: 'always',
named: 'never',
asyncArrow: 'always'
}]
}
}

View File

@ -23,11 +23,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
historyApiFallback: true,
// https:true,
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.

View File

@ -20,17 +20,17 @@ module.exports = {
},
// Various Dev Server settings
host: '192.168.0.30', // can be overwritten by process.env.HOST
host: '192.168.10.57', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
notifyOnErrors: false,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
useEslint: false,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,

View File

@ -534,6 +534,9 @@
<el-col :span="6">
<span style="line-height: 50px">分数:{{ paper.EXAMSCORE||0 }}</span>
</el-col>
<el-col :span="6">
<span style="line-height: 50px">考试时间:{{ paper.EXAMTIMEEND }}</span>
</el-col>
<el-col :span="6">
<span style="line-height: 50px">签字:
<span style="">
@ -542,9 +545,6 @@
</span>
</span>
</el-col>
<el-col :span="6">
<span style="line-height: 50px">考试时间:{{ paper.EXAMTIMEEND }}</span>
</el-col>
</el-row>
</div>
<div class="study-papg">

View File

@ -211,7 +211,7 @@
<el-col v-if="form.EXAMINATION == 1" :span="24">
<el-form-item label="考试类型" prop="EXAMTYPE">
<el-radio-group v-model="form.EXAMTYPE" :disabled="parentObj.STATE !== '1' && parentObj.STATE !== ''">
<el-radio label="1">线下考试</el-radio>
<el-radio label="1" disabled>线下考试</el-radio>
<el-radio label="0">线上考试</el-radio>
</el-radio-group>
</el-form-item>

View File

@ -65,6 +65,7 @@
<div class="app-function">
<el-button v-if="PERSONNELTYPE !=='4' && PERSONNELTYPE !=='5'" type="primary" icon="el-icon-plus" @click="studentsDialogShow('')"></el-button>
<el-button v-if="PERSONNELTYPE !=='4' && PERSONNELTYPE !=='5'" type="primary" icon="el-icon-document" @click="excelStudentsDialogShow('')">excel</el-button>
<el-button v-if="PERSONNELTYPE !=='4' && PERSONNELTYPE !=='5'" type="primary" icon="el-icon-picture" @click="batchImportSignShow"></el-button>
<!-- <el-button v-if="parentObj.STATE !== '' && parentObj.STATE !== '1'" type="primary" icon="el-icon-document" @click="derivedRecord"></el-button>-->
</div>
</div>
@ -86,8 +87,8 @@
<el-table-column :reserve-selection="true" type="selection" width="55" align="center" fixed="left"/>
<el-table-column type="index" label="序号" width="50" align="center" fixed="left"/>
<el-table-column fixed width="100" prop="NAME" label="姓名"/>
<el-table-column width="200" prop="DEPARTMENT_NAME" label="部门"/>
<el-table-column width="200" prop="POST_NAME" label="工种"/>
<el-table-column prop="DEPARTMENT_NAME" label="部门"/>
<el-table-column prop="POST_NAME" label="工种"/>
<el-table-column width="200" prop="USER_ID_CARD" label="身份证号"/>
<el-table-column width="200" prop="FILE_NUMBER" label="档案编号"/>
<el-table-column width="100" show-overflow-tooltip prop="AUTHENTICATION" label="头像采集">
@ -127,7 +128,19 @@
</template>
</el-table-column>
<el-table-column prop="START_TIME" label="入班时间"/>
<el-table-column label="操作" align="center" fixed="right">
<el-table-column prop="SIGNATURE_PATH" label="签字图片">
<template slot-scope="{row}">
<el-image
v-if="row.SIGNATURE_PATH"
:src="config.fileUrl + row.SIGNATURE_PATH"
:preview-src-list="[config.fileUrl + row.SIGNATURE_PATH]"
fit="contain"
style="width: 100px; height: 50px;"
/>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="200">
<template slot-scope="{row}">
<el-button type="text" @click="studentsDialogShow(row.STUDENT_ID)"></el-button>
<span v-if="parentObj.STATE === '' || parentObj.STATE === '1'" class="app-divider"/>
@ -137,7 +150,9 @@
<!-- <el-button v-if="parentObj.STATE !== '1' && parentObj.STATE !== ''" type="text" @click="handleChangePost(row)"></el-button>-->
<!-- <span class="app-divider"/>-->
<!-- </template>-->
<el-button v-if="parentObj.STATE !== '1' && parentObj.STATE !== '' && row.STAGEEXAMSTATE != '0' && row.EXAMTYPE == '0' " type="text" @click="goToLearningrecords(row.STUDENT_ID)"></el-button>
<el-button v-if="parentObj.STATE !== '1' && parentObj.STATE !== '' && row.STAGEEXAMSTATE != '0' " type="text" @click="goToLearningrecords(row.STUDENT_ID)"></el-button>
<span class="app-divider"/>
<el-button type="text" @click="handleImportSign(row)"></el-button>
</template>
</el-table-column>
</el-table>
@ -342,6 +357,60 @@
<el-button type="primary" @click="changeStudentPostSubmit"> </el-button>
</div>
</el-dialog>
<!-- 导入签字图片 -->
<el-dialog :visible.sync="signDialog.visible" title="导入签字图片" width="50%">
<el-form label-width="100px">
<el-form-item label="学员姓名">
<el-input v-model="signDialog.NAME" disabled/>
</el-form-item>
<el-form-item label="现有签字">
<img v-if="signDialog.USER_SIGN_FILE_PATH" :src="config.fileUrl + signDialog.USER_SIGN_FILE_PATH" alt="" width="200" height="100">
<span v-else></span>
</el-form-item>
<el-form-item label="上传签字">
<el-upload
ref="uploadSign"
:on-change="handleChangeSign"
:on-remove="handleRemoveSign"
:on-exceed="handleSignExceed"
:auto-upload="false"
:limit="1"
action="#"
accept=".png,.jpg,.jpeg"
list-type="picture-card">
<i class="el-icon-plus"/>
</el-upload>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="signDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitSign"> </el-button>
</span>
</el-dialog>
<!-- 批量导入签字图片 -->
<el-dialog :visible.sync="batchImportSignDialog.visible" title="批量导入签字图片" width="50%">
<div class="export-box">
<h1><span>图片名称规则身份证号_姓名110101199001011234_张三</span></h1>
<div style="margin-top: 10px">
<el-upload
ref="batchUploadSign"
:on-change="handleBatchChangeSign"
:on-remove="handleBatchRemoveSign"
:auto-upload="false"
:limit="50"
multiple
action="#"
accept=".png,.jpg,.jpeg">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传 pngjpgjpeg 格式的图片最多上传50张</div>
</el-upload>
</div>
</div>
<span slot="footer">
<el-button @click="batchImportSignDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitBatchSign"> </el-button>
</span>
</el-dialog>
</div>
</template>
@ -360,6 +429,7 @@ export default {
},
data() {
return {
config,
disableBut: false,
departmentList: [],
searchFormCollapse: true,
@ -500,6 +570,17 @@ export default {
excelStudentsDialog: {
visible: false,
message: ''
},
signDialog: {
visible: false,
STUDENT_ID: '',
NAME: '',
USER_SIGN_FILE_PATH: '',
fileList: []
},
batchImportSignDialog: {
visible: false,
fileList: []
}
}
},
@ -941,6 +1022,88 @@ export default {
closeStudentInfo() {
this.studentsDialog.visible = false
this.studentsDialog.changeFlag = true
},
//
handleImportSign(row) {
this.signDialog.STUDENT_ID = row.STUDENT_ID
this.signDialog.NAME = row.NAME
this.signDialog.USER_SIGN_FILE_PATH = row.USER_SIGN_FILE_PATH || ''
this.signDialog.fileList = []
this.$refs.uploadSign && this.$refs.uploadSign.clearFiles()
this.signDialog.visible = true
},
handleChangeSign(file, fileList) {
const types = ['image/jpeg', 'image/jpg', 'image/png']
const isImage = types.includes(file.raw.type)
if (!isImage) {
this.$message.error('上传图片只能是 jpg、jpeg、png 格式!')
fileList.pop()
} else {
this.signDialog.fileList = fileList
}
},
handleSignExceed() {
this.$message.error('只能上传一张图片,如需更换图片请先删除当前图片')
},
handleRemoveSign(file, fileList) {
this.signDialog.fileList = fileList
},
submitSign() {
if (this.signDialog.fileList.length === 0 && !this.signDialog.USER_SIGN_FILE_PATH) {
this.$message.error('请上传签字图片')
return
}
const formData = new FormData()
formData.append('STUDENT_ID', this.signDialog.STUDENT_ID)
if (this.signDialog.fileList.length > 0) {
formData.append('FFILE', this.signDialog.fileList[0].raw)
}
upload('/student/importSign', formData).then(data => {
this.$message({
type: 'success',
message: '操作成功'
})
this.signDialog.visible = false
this.getClassStudentList()
})
},
//
batchImportSignShow() {
this.batchImportSignDialog.visible = true
this.batchImportSignDialog.fileList = []
this.$refs.batchUploadSign && this.$refs.batchUploadSign.clearFiles()
},
handleBatchChangeSign(file, fileList) {
const types = ['image/jpeg', 'image/jpg', 'image/png']
const isImage = types.includes(file.raw.type)
if (!isImage) {
this.$message.error('上传图片只能是 jpg、jpeg、png 格式!')
fileList.pop()
} else {
this.batchImportSignDialog.fileList = fileList
}
},
handleBatchRemoveSign(file, fileList) {
this.batchImportSignDialog.fileList = fileList
},
submitBatchSign() {
if (this.batchImportSignDialog.fileList.length === 0) {
this.$message.error('请上传签字图片')
return
}
const formData = new FormData()
this.batchImportSignDialog.fileList.forEach((file) => {
formData.append('FFILE', file.raw)
})
formData.append('CLASS_ID', this.parentObj.CLASS_ID)
upload('/student/batchImportSign', formData).then(data => {
this.$message({
type: 'success',
message: '操作成功'
})
this.batchImportSignDialog.visible = false
this.getClassStudentList()
})
}
}

View File

@ -2,18 +2,18 @@ const config = {
adminurl: 'https://pxadmin.qhdsafety.com/qa-education-admin/',
fileUrl: 'https://file.zcloudchina.com/JYPXFile', // 附件服务器地址
// faceOnlineAdress: 'wss://pxapp.qhdsafety.com/websocket/',
// faceOnlineAdress: 'ws://192.168.0.31:7777/',
// faceOnlineAdress: 'ws://192.168.10.57:7777/',
// portalUrl: 'https://qypx.qhdsafety.com/portal/', // 门户网站地址 - 正式
portalUrl: 'http://192.168.0.31:7450/org/', // 门户网站地址 -测试
portalUrl: 'http://192.168.10.571:7450/org/', // 门户网站地址 -测试
// 本地
faceOnlineAdress: 'ws://192.168.0.30:7777/',
weburl: 'http://192.168.0.30:7450/', // 前台地址
httpurl: 'http://192.168.0.30:7450/', // 后台地址
httpurl1: 'http://192.168.0.30:7451/' // 前台地址
faceOnlineAdress: 'ws://192.168.10.57:7777/',
weburl: 'http://192.168.10.57:7450/', // 前台地址
httpurl: 'http://192.168.10.57:7450/', // 后台地址
httpurl1: 'http://192.168.10.57:7451/' // 前台地址
// 测试-org
// faceOnlineAdress: 'ws://192.168.0.31:7878/',
// weburl: 'http://192.168.0.31:7450/org/', // 前台地址
// httpurl: 'http://192.168.0.31:7450/qa-education-exam-org/', // 后台地址
// httpurl1: 'http://192.168.0.31:7450/org/' // 前台地址
// weburl: 'http://192.168.10.57:7450/org/', // 前台地址
// httpurl: 'http://192.168.10.57:7450/qa-education-exam-org/', // 后台地址
// httpurl1: 'http://192.168.10.57:7450/org/' // 前台地址
}

12148
yarn.lock Normal file

File diff suppressed because it is too large Load Diff