main
hcj 3 months ago
parent 4b1c07088e
commit c7e3f0db08
  1. 1
      .env.development
  2. BIN
      admin_prod.zip
  3. BIN
      admin_test.zip
  4. 15
      src/api/trainService/index.js
  5. 2
      src/components/ImageUpload/index.vue
  6. 47
      src/components/formatForm/drective.js
  7. 2
      src/components/formatForm/formSource.vue
  8. 12
      src/utils/index.js
  9. 10
      src/views/components/CrowdsourceAudit.vue
  10. 11
      src/views/components/TaskInfo.vue
  11. 324
      src/views/trainService/assignWork.vue
  12. 68
      src/views/trainService/courseManage.vue
  13. 45
      src/views/trainService/signupStudent.vue

@ -6,6 +6,7 @@ VUE_APP_BASE_API = '/prod-api'
# VUE_APP_BASE_TARGET = 'http://www.bjkeyware.com/test-api'
VUE_APP_BASE_TARGET = 'http://192.168.0.229:9999'
# VUE_APP_BASE_TARGET = 'http://192.168.0.129:9999'
# VUE_APP_BASE_TARGET = 'http://www.bjkeyware.com/prod-api'
# VUE_APP_BASE_TARGET = 'http://192.168.0.129:9999'

Binary file not shown.

Binary file not shown.

@ -379,3 +379,18 @@ export function expLearnNum(courseId) {
responseType: "blob",
});
}
export function assignHomeWork(data) {
return request({
url: "course/admin/setting/homework",
method: "post",
data,
});
}
// export function updateHomeWork(data) {
// return request({
// url: "/course/admin/course/updateHomework",
// method: "post",
// data
// });
// }

@ -65,6 +65,8 @@ export default {
this.$emit('input', '')
},
handleUploadSuccess(res) {
console.log(res);
this.$emit('input', res.fileName)
this.loading.close()
},

@ -0,0 +1,47 @@
/**
* 自定义拖拽指令
* 生命周期指令包括
* bind 第一次绑定在元素上时调用只调用一次
* inserted 元素被插入父节点时调用
* update
* componentUpdate 指令所在组件的 VNode 及其子 VNode 全部更新后调用
* unbind 解绑时调用
*
* mouseEvent类型的事件有
* client 提供事件发生时的应用客户端区域的水平坐标也就是无论是否滚动都会最上方都是0
* ctrlKey ctrl 键被按下返回 true否则返回 false
* layer 往上找有定位属性的父元素的左上角自身有定位属性的话就是相对于自身都没有的话就是相对于body的左上角
* metaKey mac为Matawindows为windows键
* movement 相当于上一次mouseMove的偏移量
* offset 事件对象与目标节点的内填充边padding edge的偏移量
* page 相对于文档的坐标如果向上滚动了200px点击最上方的值为200
* screen 提供鼠标在全局屏幕中的坐标偏移量
*/
export default {
install(Vue) {
Vue.directive("dragme", {
// 指令全局命名为v-dragme
inserted(el) {
el.onmousedowm = function (ev) {
// 获取鼠标按下去时候变量
const disX = ev.clientX - el.offsetLeft;
const disY = ev.clientY - el.offsetTop;
el.onmousemove = function (ev) {
const l = ev.clientX - disX;
const t = ev.clientY - disY;
// 实时设置元素位置
el.style.left = l + "px";
el.style.top = t + "px";
// 获取鼠标移动时的变量
};
el.onmouseup = function () {
// 获取鼠标松开时,销毁所有变量
document.onmousemove = null;
document.onmouseup = null;
};
};
},
});
},
};

@ -2,7 +2,7 @@
<div class="sourceWrap">
<h3 class="sourceTitle">选择组件</h3>
<div v-for="(form, fIndex) in fomrmSourceList" :key="fIndex">
<div class="diyInpWrap">
<div class="diyInpWrap" v-drageme>
<label>{{ form.label }}</label>
<diyInput :form="form"></diyInput>
</div>

@ -390,3 +390,15 @@ export function isNumberStr(str) {
export function downPdf(val) {
fetch(val).then(respose => {
return respose.blob()
}).then(blob => {
const url = URL.createObjectURL(blob)
const a = document.createElement("a")
const name = val.substr(val.lastIndexOf('/') + 1, val.length)
a.href = url
a.download = name
a.click()
})
}

@ -22,6 +22,7 @@
<onsite-type :type="task.onsiteType"></onsite-type>
</el-descriptions-item>
<el-descriptions-item label="地域要求">{{ task.area }}</el-descriptions-item>
<el-descriptions-item label="等级要求">{{ levelMap[task.level] }}</el-descriptions-item>
<el-descriptions-item label="联系人">{{ task.contactName }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ task.contactTel }}</el-descriptions-item>
<el-descriptions-item label="项目描述">
@ -136,6 +137,13 @@ import TestType from './enum/TestType'
import OnsiteType from './enum/OnsiteType'
import TesterType from './enum/TesterType'
const levelMap = {
'0':'无门槛',
'1':'一级',
'2':'二级',
'3':'三级',
}
export default {
name: 'CrowdsourceAudit',
components: { TesterType, OnsiteType, TestType },
@ -157,6 +165,8 @@ export default {
form: {},
task: {},
rules: {},
levelMap:levelMap
}
},
methods: {

@ -183,6 +183,10 @@
<div class="lefttext">地域要求</div>
<div class="rightinfo">{{ task.area }}</div>
</div>
<div class="contentinfo">
<div class="lefttext">等级要求</div>
<div class="rightinfo">{{ levelMap[task.level] }}</div>
</div>
<!-- <div class="contentinfo">
<div class="lefttext">备注信息</div>
<div class="rightinfo">{{ task.remark }}</div>
@ -213,6 +217,12 @@ import TestType from "@/views/components/enum/TestType";
import OnsiteType from "@/views/components/enum/OnsiteType";
import AuditStatus from "@/views/components/enum/AuditStatus";
import mixin from '@/mixin/index.js'
const levelMap = {
'0':'无门槛',
'1':'一级',
'2':'二级',
'3':'三级',
}
export default {
name: "TaskInfo",
mixins: [mixin],
@ -230,6 +240,7 @@ export default {
data() {
return {
task: {},
levelMap:levelMap
};
},
methods: {

@ -0,0 +1,324 @@
<template>
<el-dialog title="布置作业" :visible.sync="dialogVisible" width="width" @close="beforeClose"
:close-on-click-modal="false">
<div class="homeWork">
<ImageUpload v-show="false" id="imgUploadQuill" :igonreMin="true" v-model="quillImg" @input="getImg">
</ImageUpload>
<quill-editor v-model="editContent" ref="myQuillEditor" :options="editorOption" @blur="onEditorBlur($event)"
@focus="onEditorFocus($event)" @change="onEditorChange($event)">
</quill-editor>
</div>
<div slot="footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</div>
</el-dialog>
</template>
<script>
import ImageUpload from '@/components/ImageUpload/index.vue'
import { Quill, quillEditor } from "vue-quill-editor"; //
// import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
// import { ImageExtend, QuillWatch } from 'quill-image-extend-module'
import ImageResize from 'quill-image-resize-module';
//
const fontSizeStyle = Quill.import("attributors/style/size"); // style
fontSizeStyle.whitelist = ["12px", "14px", "16px", "18px", "20px", "24px", "28px", "32px", "36px",];
Quill.register(fontSizeStyle, true);
// //
const Font = Quill.import("attributors/style/font"); // style
const fonts = ["SimSun", "SimHei", "Microsoft-YaHei", "KaiTi", "FangSong"];
Font.whitelist = fonts; //
Quill.register(Font, true);
Quill.register('modules/imageResize', ImageResize);
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop)
const AlignStyle = Quill.import("attributors/style/align");
AlignStyle.whitelist = ["right", "center", "justify"];
Quill.register(AlignStyle, true);
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // 线 线 -----['bold', 'italic', 'underline', 'strike']
[{ color: [] }, { background: [] }], // -----[{ color: [] }, { background: [] }]
[{ align: [] }], // -----[{ align: [] }]
// [{ size: ["12px","14px","16px","18px","20px","24px","28px","32px","36px",true] }], // -----[{ size: ['small', false, 'large', 'huge'] }]
// [{ font: ["SimSun", "SimHei", "Microsoft-YaHei", "KaiTi", "FangSong",true] }], // -----[{ font: [] }]
[{ size: fontSizeStyle.whitelist }], // -----[{ size: ['small', false, 'large', 'huge'] }]
[{ font: fonts }], // -----[{ font: [] }]
[{ header: [1, 2, 3, 4, 5, 6, true] }], //
[{ direction: "ltl" }], // -----[{'direction': 'rtl'}]
[{ direction: "rtl" }], // -----[{'direction': 'rtl'}]
[{ indent: "-1" }, { indent: "+1" }], // -----[{ indent: '-1' }, { indent: '+1' }]
[{ list: "ordered" }, { list: "bullet" }], // -----[{ list: 'ordered' }, { list: 'bullet' }]
[{ script: "sub" }, { script: "super" }], // /-----[{ script: 'sub' }, { script: 'super' }]
["blockquote", "code-block"], // -----['blockquote', 'code-block']
["clean"], // -----['clean']
["link", "image"], // -----['link', 'image', 'video']
];
export default {
components: { quillEditor, ImageUpload },
data() {
return {
dialogVisible: false,
editContent: '',
quillImg: '',
editorOption: {
placeholder: "请输入作业内容",
modules: {
toolbar: {
container: toolbarOptions,
// handlers: {
// image: this.handleImgUpload,
// },
handlers: { //使
'image': function (value) {
console.log(value)
if (value) { //
document.querySelector('#imgUploadQuill .el-upload').click()
}
}
}
},
//
// imageDrop: true,
imageResize: {
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: ['Resize', 'DisplaySize', 'Toolbar']
},
},
},
}
},
mounted() {
},
methods: {
submit() {
this.$emit('subWork', this.editContent)
console.log(this.editContent);
},
beforeClose() {
this.editContent = ''
},
onEditorReady(editor) {
//
},
getImg(url) {
console.log(process.env.VUE_APP_BASE_API + url);
if (url) {
const quill = this.$refs.myQuillEditor.quill
//
const pos = quill.getSelection().index
//
quill.insertEmbed(pos, 'image', process.env.VUE_APP_BASE_API + url)
} else {
this.$essage.error('图片插入失败')
}
},
onEditorBlur() { }, //
onEditorFocus() { }, //
//
onEditorChange({ quill, html, text }) {
if (text.length - 1 > 2000) {
let event = this.$refs.myQuillEditor
event.quill.deleteText(2000, 1);
this.$message({
type: 'warning',
message: '长度超出,无法输入!'
});
// this.content = html
return
}
// this.newsobj.content = this.escapeStringHTML(this.editContent);
// console.log('', this.editContent)
},
//
escapeStringHTML(content) {
content = content.replace(/&lt;/g, "<");
content = content.replace(/&gt;/g, ">");
return content;
},
}
}
</script>
<style>
.ql-editor {
min-height: 250px;
max-height: 400px;
}
.homeWork .ql-editor{
margin-left: 0;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "默认";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {
content: "宋体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Microsoft-YaHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Microsoft-YaHei"]::before {
content: "微软雅黑";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {
content: "楷体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="FangSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="FangSong"]::before {
content: "仿宋";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {
content: "黑体";
}
.ql-toolbar.ql-snow+.ql-container.ql-snow {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.ql-toolbar.ql-snow {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.ql-snow .ql-stroke,
.ql-snow .ql-picker {
/* color: #999;
stroke: #999; */
}
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill {
/* fill: #999; */
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
content: "12px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: "16px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: "20px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
content: "24px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {
content: "28px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="36px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36px"]::before {
content: "36px";
}
.ql-container {
font-size: 14px;
}
</style>

@ -55,8 +55,17 @@
}}</el-button>
</template>
</el-table-column>
<el-table-column v-if="queryParams.classType != 3" label="布置作业" align="center">
<template slot-scope="scope">
<el-button v-if="!scope.row.homework" size="mini" type="text"
@click="toAssignHomework(scope.row)">新增</el-button>
<el-button v-else size="mini" type="text" @click="toAssignHomework(scope.row)">修改</el-button>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<!-- <el-button size="mini" type="text" v-show="scope.row.classType != 3"
@click="toAssignHomework(scope.row)">布置作业</el-button> -->
<el-button size="mini" type="text" @click="option(scope.row, 'motify')">修改</el-button>
<el-button size="mini" type="text" @click="option(scope.row, 'delete')">删除</el-button>
<el-button size="mini" type="text" v-show="scope.row.classType != 4"
@ -176,6 +185,7 @@
</el-form-item>
</el-form>
</el-dialog>
<assignWork ref="assignWork" @subWork="subWork"></assignWork>
</div>
</template>
<script>
@ -186,14 +196,17 @@ import {
delCourse,
listTeacherAll,
getClassList,
getInComeInfo
getInComeInfo,
assignHomeWork,
updateHomeWork
} from '@/api/trainService/index'
import fileUpload from '@/components/FileUpload/index.vue'
import { encodeChinese } from '@/utils/encodeChinese'
import buttonUpload from '@/components/buttonUpload/index.vue'
import vueQr from '@/components/vueQr/index.vue'
import { deepClone } from '@/utils'
import router from '../../router'
import assignWork from './assignWork.vue'
import store from '../../store'
const titleMap = {
motify: '修改',
delete: '删除',
@ -228,7 +241,7 @@ const courseRule = {
payMethods: [{ required: true, message: '请输入支付方式', trigger: 'change' }]
}
export default {
components: { fileUpload, vueQr, buttonUpload },
components: { fileUpload, vueQr, buttonUpload, assignWork },
data() {
return {
classMap: classMap,
@ -388,6 +401,53 @@ export default {
// importCourse(){
// this.$router.push('/course/courseImport')
// },
toAssignHomework(row) {
console.log(row);
this.currentCourse = row
this.$refs.assignWork.dialogVisible = true
if (row.homework) {
this.$refs.assignWork.editContent = row.homework
} else {
}
},
async subWork(content) {
const data = {
courseId: this.currentCourse.courseId,
// teacherId: store.getters.userId,
homework: content
}
const res = await assignHomeWork(data)
if (res.code == 200) {
this.$refs.assignWork.dialogVisible = false
this.getList()
this.$message.success('操作成功')
}
console.log(res);
return
/* 未布置过作业 */
if (!this.currentCourse.content) {
const res = await assignHomeWork(data)
if (res.code == 200) {
this.$refs.assignWork.dialogVisible = false
this.getList()
this.$message.success('作业布置成功')
}
}
/* 修改作业 */
else {
const res = await updateHomeWork(data)
if (res.code == 200) {
this.$refs.assignWork.dialogVisible = false
this.getList()
this.$message.success('作业修改成功')
}
}
},
async option(row, type) {
this.optionType = type
this.currentCourse = row
@ -473,7 +533,7 @@ export default {
this.getList()
},
timeChange(val) {
if(this.queryParams.classType != 4){
if (this.queryParams.classType != 4) {
return
}
if (this.courseForm.courseTime && this.courseForm.dateTime) {

@ -32,7 +32,9 @@
<el-button icon="el-icon-download" type="success" size="small" style="margin-bottom: 20px"
@click="exportEvaReport('multify')">导出评价</el-button>
<el-button icon="el-icon-download" type="primary" size="small" style="margin-bottom: 20px"
@click="downloadReport('multify')">下载</el-button>
@click="downloadReport('multify')">下载结课报告</el-button>
<el-button icon="el-icon-download" size="small" style="margin-bottom: 20px"
@click="downloadAttachment('multify')">下载附件简历</el-button>
<!-- 详细学生信息弹层 -->
<el-table v-if="$route.query.type != 3" :data="studentList" v-loading="loading"
:default-sort="{ prop: 'asseGradeVag', order: 'descending' }" @selection-change="handleSelectionChange">
@ -52,6 +54,7 @@
<el-table-column label="辅导员" align="center" prop="counsellor" v-if="$route.query.type == 0" />
<el-table-column label="辅导员联系方式" align="center" prop="counsellorTel" v-if="$route.query.type == 0" />
<el-table-column label="报名时间" align="center" prop="registrationTime" />
<el-table-column label="结课报告" align="center" prop="registrationTime">
<template slot-scope="scope">
<div style="color: #1890ff;cursor: pointer;" @click="downloadReport(scope.row.reportAttachment)">{{
@ -66,6 +69,13 @@
scope.row.asseGradeVag + '(' + scope.row.asseCount + ')') : '' }}</el-button>
</template>
</el-table-column>
<el-table-column label="附件简历" align="center" prop="registrationTime">
<template slot-scope="scope">
<div style="color: #1890ff;cursor: pointer;" @click="downloadReport(scope.row.attResume)">{{
scope.row.attResume ? '下载' : '' }}
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button size="mini" type="text" v-if="scope.row.remark"
@ -176,6 +186,7 @@ import {
} from '@/api/trainService/index.js'
import { saveAs } from 'file-saver'
import store from '@/store'
import { downPdf } from '../../utils';
// 1 2 3 4 5 status
export default {
name: 'peixunbaoming',
@ -483,19 +494,27 @@ export default {
const blob = new Blob([res])
saveAs(blob, this.$route.query.name + '评价表.xlsx')
},
downloadAttachment() {
this.multipleSelection.forEach(item => {
if (item.attResume) {
downPdf(this.base + item.attResume)
// const iframe = document.createElement("iframe");
// iframe.style.display = "none"; //
// iframe.style.height = "0"; // 0
// iframe.src = this.base + item.reportAttachment; //
// document.body.appendChild(iframe); // iframedom
// // this.$nextTick(()=>{
// // document.body.removeChild(iframe)
// // })
// setTimeout(() => {
// document.body.removeChild(iframe);
// }, 1000)
// }
}
})
},
downloadReport(val) {
function downPdf(val) {
fetch(val).then(respose => {
return respose.blob()
}).then(blob => {
const url = URL.createObjectURL(blob)
const a = document.createElement("a")
const name = val.substr(val.lastIndexOf('/') + 1, val.length)
a.href = url
a.download = name
a.click()
})
}
// return
if (val === 'multify') {
const self = this

Loading…
Cancel
Save