提交 7ccf4f28 编写于 作者: guangjun.yang's avatar guangjun.yang

Merge branch 'dev-saas-phase3-0612' into release

* dev-saas-phase3-0612: (47 commits)
  SCRIPT445: 对象不支持此操作
  显示裁剪框
  兼容360的布局
  样式修改、审核修改时展开信息
  初始化kind参数
  关闭时,直接刷新页面
  去掉:上传取消按钮
  创建按钮没有手型
  解决样式问题
  选择课程鼠标的手型
  修改时没有医生时的处理
  滚动条样式等
  样式优化等
  样式问题等
  一级菜单的样式问题
  上传讲师图片
  剪裁及bug修改等
  取消按钮不要
  按钮不显示
  查询有问题等
  ...

# Conflicts:
#	package.json
#	src/router/router.js
#	src/utils/fetch.js
#	src/views/layout/slidebar.vue
...@@ -20,5 +20,6 @@ ...@@ -20,5 +20,6 @@
<script src="https://unpkg.com/qiniu-js@2.2.0/dist/qiniu.min.js"></script> <script src="https://unpkg.com/qiniu-js@2.2.0/dist/qiniu.min.js"></script>
<script src="https://cdn.bootcss.com/downloadjs/1.4.8/download.min.js"></script> <script src="https://cdn.bootcss.com/downloadjs/1.4.8/download.min.js"></script>
<script src="https://pv.sohu.com/cityjson?ie=utf-8"></script> <script src="https://pv.sohu.com/cityjson?ie=utf-8"></script>
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-5.1.1.min.js"></script>
</body> </body>
</html> </html>
文件已添加
<template>
<div class="rc-cropper" v-if="originImg">
<div :class="{'rc-cropper__canvasCrop1': cropOption.uploadType == 1, 'rc-cropper__canvasCrop2': cropOption.uploadType == 2}">
<img :src="originImg" v-if="!cropper">
<canvas :id="originImg" ref="canvas"/>
<div class="rc-cropper__iconCrop">
<el-tooltip content="确认裁剪" placement="right" v-if="cropper">
<el-button type="success" size="mini" @click="sureCropper()"><i class="el-icon-check"></i></el-button>
</el-tooltip>
</div>
</div>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'
export default {
name: 'rc-cropper2',
props: {
cropOption: {
type: Object,
required: true,
default: () => {}
},
originImg: {
required: true
},
},
data () {
return {
cropper: null,
croppShow: false
}
},
mounted () {
this.drawImg()
},
destroyed() {
this.cropper && this.cropper.destroy();
},
methods: {
// 在canvas上绘制图片
drawImg () {
const _this = this
this.$nextTick(() => {
let canvas = document.getElementById(this.originImg)
if (canvas) {
// canvas.width = 1000
// canvas.height = 800
canvas.width = _this.cropOption.cvWidth;
canvas.height = _this.cropOption.cvHeight;
let ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
let img = new Image()
img.crossOrigin = 'Anonymous'
img.src = this.originImg
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
_this.initCropper()
}
}
})
},
// 显示裁剪框
initCropper () {
this.croppShow = true
this.cropper = new Cropper(this.$refs.canvas, {
checkCrossOrigin: true,
viewMode: 3,
zoomOnWheel: true, // 是否可以通过移动鼠标来放大图像
dragMode: 'move',
// autoCropArea: 0.6,
// center: true,
// autoCrop: true,
restore: false,
modal: true,
guides: true,
highlight: true,
cropBoxMovable: true,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
// aspectRatio: 75/42,
// aspectRatio: 5/3,
ready: () => {
this.cropper.setData({
x: this.cropOption.offset_x,
y: this.cropOption.offset_y,
width: this.cropOption.width,
height: this.cropOption.height
})
// this.cropper.zoomTo(1);
},
// zoom: function (event) {
// // Keep the image in its natural size
// if (event.detail.oldRatio === 1) {
// event.preventDefault();
// }
// },
})
},
// 确认裁剪
sureCropper () {
let _this = this
const cropParam = this.cropper.getData()
console.log('cropParam', cropParam);
this.cropper.getCroppedCanvas().toBlob(function (blob) {
let files = new window.File([blob], 'cropper.jpg');
console.log(files);
let oFileReader = new FileReader()
oFileReader.onloadend = function (e) {
let base64 = e.target.result
_this.$emit('getCropImg', base64, cropParam, files, _this.cropper)
}
oFileReader.readAsDataURL(blob)
}, 'image/jpeg')
}
}
}
</script>
<style scoped lang="scss">
.rc-cropper__canvasCrop1 {
/* border: 1px solid red; */
width: 800px;
height: 540px;
}
.rc-cropper__canvasCrop2 {
/* border: 1px solid red; */
width: 400px;
height: 300px;
}
.rc-cropper__iconCrop {
position: absolute;
// left: 46%;
right: 13%;
top: 15%;
}
.el-tooltip {
margin: 20px 4px;
display: block;
z-index: 10000;
}
</style>
<template>
<div class="rc-cropper" v-if="originImg">
<div class="rc-cropper__canvasCrop2">
<img :src="originImg" v-if="!cropper">
<canvas :id="originImg" ref="canvas"/>
<div class="rc-cropper__iconCrop">
<el-tooltip content="确认裁剪" placement="right" v-if="cropper">
<el-button type="success" size="mini" @click="sureCropper()"><i class="el-icon-check"></i></el-button>
</el-tooltip>
</div>
</div>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'
export default {
name: 'rc-cropper2',
props: {
cropOption: {
type: Object,
required: true,
default: () => {}
},
originImg: {
required: true
},
previewImg: {
type: String
}
},
data () {
return {
cropper: null,
croppShow: false
}
},
mounted () {
this.drawImg()
},
destroyed() {
this.cropper && this.cropper.destroy();
},
methods: {
// 在canvas上绘制图片
drawImg () {
const _this = this
this.$nextTick(() => {
let canvas = document.getElementById(this.originImg)
if (canvas) {
canvas.width = 1000
canvas.height = 800
let ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
let img = new Image()
img.crossOrigin = 'Anonymous'
img.src = this.originImg
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
_this.initCropper()
}
}
})
},
// 显示裁剪框
initCropper () {
this.croppShow = true
this.cropper = new Cropper(this.$refs.canvas, {
checkCrossOrigin: true,
viewMode: 3,
zoomOnWheel: true, // 是否可以通过移动鼠标来放大图像
dragMode: 'move',
// autoCropArea: 0.6,
// center: true,
// autoCrop: true,
restore: false,
modal: true,
guides: true,
highlight: true,
cropBoxMovable: true,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
// aspectRatio: 75/42,
// aspectRatio: 5/3,
ready: () => {
this.cropper.setData({
x: this.cropOption.offset_x,
y: this.cropOption.offset_y,
width: this.cropOption.width,
height: this.cropOption.height
})
// this.cropper.zoomTo(1);
},
// zoom: function (event) {
// // Keep the image in its natural size
// if (event.detail.oldRatio === 1) {
// event.preventDefault();
// }
// },
})
},
// 确认裁剪
sureCropper () {
let _this = this
const cropParam = this.cropper.getData()
console.log('cropParam', cropParam);
this.cropper.getCroppedCanvas().toBlob(function (blob) {
let files = new window.File([blob], 'cropper.jpg');
console.log(files);
let oFileReader = new FileReader()
oFileReader.onloadend = function (e) {
let base64 = e.target.result
_this.$emit('getCropImg', base64, cropParam, files, _this.cropper)
}
oFileReader.readAsDataURL(blob)
}, 'image/jpeg')
}
}
}
</script>
<style scoped lang="scss">
// .rc-cropper {
// position: relative;
// margin-top: 10px;
// img {
// width: 100%;
// height: 100%;
// }
// }
/* img {
width: 100%;
height: 100%;
} */
.rc-cropper__canvasCrop2 {
/* border: 1px solid red; */
width: 800px;
height: 540px;
}
.rc-cropper__iconCrop {
position: absolute;
/* left: 8%; */
left: 46%;
top: 10%;
}
.el-tooltip {
margin: 20px 4px;
display: block;
z-index: 10000;
}
</style>
margin: 20px 4px;
display: block;
z-index: 10000;
}
</style>
<template>
<div class="rc-cropper" v-if="originImg">
<div :class="{'rc-cropper__canvasCrop1': cropOption.uploadType == 1, 'rc-cropper__canvasCrop2': cropOption.uploadType == 2}">
<img :src="originImg" v-if="!cropper">
<canvas :id="originImg" ref="canvas"/>
<div class="rc-cropper__iconCrop">
<el-tooltip content="确认裁剪" placement="right" v-if="cropper">
<el-button type="success" size="mini" @click="sureCropper()"><i class="el-icon-check"></i></el-button>
</el-tooltip>
</div>
</div>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'
export default {
name: 'rc-cropper2',
props: {
cropOption: {
type: Object,
required: true,
default: () => {}
},
originImg: {
required: true
},
},
data () {
return {
cropper: null,
croppShow: false
}
},
mounted () {
this.drawImg()
},
destroyed() {
this.cropper && this.cropper.destroy();
},
methods: {
// 在canvas上绘制图片
drawImg () {
const _this = this
this.$nextTick(() => {
let canvas = document.getElementById(this.originImg)
if (canvas) {
// canvas.width = 1000
// canvas.height = 800
canvas.width = _this.cropOption.cvWidth;
canvas.height = _this.cropOption.cvHeight;
let ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
let img = new Image()
img.crossOrigin = 'Anonymous'
img.src = this.originImg
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
_this.initCropper()
}
}
})
},
// 显示裁剪框
initCropper () {
if (!HTMLCanvasElement.prototype.toBlob) {
console.log('HTMLCanvasElement.prototype.toBlob');
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var canvas = this;
setTimeout(function () {
var binStr = window.atob(canvas.toDataURL(type, quality).split(',')[1]);
var len = binStr.length;
var arr = new window.Uint8Array(len);
for (var i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
callback(new window.Blob([arr], { type: type || 'image/jpeg' }));
});
}
});
}
this.croppShow = true
this.cropper = new Cropper(this.$refs.canvas, {
checkCrossOrigin: true,
viewMode: 3,
zoomOnWheel: true, // 是否可以通过移动鼠标来放大图像
dragMode: 'move',
// autoCropArea: 0.6,
// center: true,
// autoCrop: true,
restore: false,
modal: true,
guides: true,
highlight: true,
cropBoxMovable: true,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
// aspectRatio: 75/42,
// aspectRatio: 5/3,
ready: () => {
this.cropper.setData({
x: this.cropOption.offset_x,
y: this.cropOption.offset_y,
width: this.cropOption.width,
height: this.cropOption.height
})
// this.cropper.zoomTo(1);
},
// zoom: function (event) {
// // Keep the image in its natural size
// if (event.detail.oldRatio === 1) {
// event.preventDefault();
// }
// },
})
},
// 确认裁剪
sureCropper () {
let _this = this
const cropParam = this.cropper.getData()
console.log('cropParam', cropParam);
this.cropper.getCroppedCanvas().toBlob(function (blob) {
let files = new window.File([blob], 'cropper.jpg');
console.log(files);
let oFileReader = new FileReader()
oFileReader.onloadend = function (e) {
let base64 = e.target.result
_this.$emit('getCropImg', base64, cropParam, files, _this.cropper)
}
oFileReader.readAsDataURL(blob)
}, 'image/jpeg')
}
}
}
</script>
<style scoped lang="scss">
// .rc-cropper {
// margin-left: 20px;
// }
.rc-cropper__canvasCrop1 {
width: 800px;
height: 540px;
}
.rc-cropper__canvasCrop2 {
width: 400px;
height: 300px;
}
.rc-cropper__iconCrop {
position: absolute;
// left: 46%;
right: 13%;
top: 15%;
}
.el-tooltip {
margin: 20px 4px;
display: block;
z-index: 10000;
}
</style>
<template>
<div class="rc-cropper" v-if="originImg">
<el-row>
<el-col :span="12">
<div class="rc-cropper__canvasCrop2">
<img :src="originImg" v-if="!cropper">
<canvas :id="originImg" ref="canvas"/>
<div class="rc-cropper__iconCrop">
<el-tooltip content="确认裁剪" placement="right" v-if="cropper">
<el-button type="success" size="mini" @click="sureCropper()"><i class="el-icon-check"></i></el-button>
</el-tooltip>
</div>
</div>
</el-col>
<el-col :span="10">
<div class="rc-cropper__previewImg">
<img :src="previewImg" id="previewImg"/>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'
export default {
name: 'rc-cropper2',
props: {
cropOption: {
type: Object,
required: true,
default: () => {}
},
originImg: {
required: true
},
previewImg: {
type: String
}
},
data () {
return {
cropper: null,
croppShow: false
}
},
mounted () {
this.drawImg()
},
methods: {
// 在canvas上绘制图片
drawImg () {
const _this = this
this.$nextTick(() => {
let canvas = document.getElementById(this.originImg)
if (canvas) {
canvas.width = 720
canvas.height = 480
let ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
let img = new Image()
img.crossOrigin = 'Anonymous'
img.src = this.originImg
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
_this.initCropper()
}
}
})
},
// 显示裁剪框
initCropper () {
this.croppShow = true
this.cropper = new Cropper(this.$refs.canvas, {
checkCrossOrigin: true,
viewMode: 3,
zoomOnWheel: false, // 是否可以通过移动鼠标来放大图像
aspectRatio: 3 / 2,
ready: () => {
this.cropper.setData({
x: this.cropOption.offset_x,
y: this.cropOption.offset_y,
width: this.cropOption.width,
height: this.cropOption.height
})
}
})
// this.cropper = cropper
},
// 确认裁剪
sureCropper () {
let _this = this
const cropParam = this.cropper.getData()
this.cropper.getCroppedCanvas().toBlob(function (blob) {
let oFileReader = new FileReader()
oFileReader.onloadend = function (e) {
let base64 = e.target.result
_this.$emit('getCropImg', base64, cropParam)
}
oFileReader.readAsDataURL(blob)
}, 'image/jpeg')
}
}
}
</script>
<style >
/* .rc-cropper {
position: relative;
margin-top: 20px;
} */
/* img {
width: 100%;
height: 100%;
} */
.rc-cropper__canvasCrop2 {
width: 720px;
height: 480px;
}
.rc-cropper__iconCrop {
position: absolute;
left: 45%;
top: 0%;
}
.el-tooltip {
margin: 20px 4px;
display: block;
z-index: 10000;
}
.rc-cropper__previewImg {
width: 600px;
height: 400px;
}
</style>
<template>
<div class="edit-course-wrapper">
<el-dialog
class="dialog-title-border"
ref="testDialogRef"
title="上传课程"
:visible="dialogVisible"
@close="backToOrgCourse"
center
:close-on-click-modal="false"
:close-on-press-escape="false"
width="860px"
>
<div slot="title" style="text-align: left;">
<span style="font-weight: 700;">上传课程</span>
<span style="font-size: 12px;color: #ED3131;margin-left: 4px;">上传信息需要审核,请认真核对上传内容,一旦提交后将不能修改</span>
</div>
<div v-show="step == 1" class="course-content">
<el-form
ref="formDataRef"
:model="formData"
label-width="120px"
class="basic-form"
>
<div class="basic-item-icon">
<span class="require">*</span>
<el-form-item label="课程名称:" class="valid-msg">
<el-col :span="20">
<el-input
size="small"
v-model="formData.courseName"
placeholder="请输入课程名称"
style="width: 360px"
maxlength="25"
:disabled="disabled"
></el-input>
<span class="word-num">
{{(formData.courseName || '').replace(/\s+/g,"").length}}/25
</span>
<div v-show="!needShowAuditMsg && noCouseName" class="error" style="maring-top:2px">
<span>请输入课程名称</span>
</div>
<div v-show="needShowAuditMsg && formData.courseNameCheck" class="error" style="maring-top:2px">
<span>{{formData.courseNameCheck}}</span>
</div>
</el-col>
</el-form-item>
</div>
<div class="basic-item-icon">
<span class="require">*</span>
<el-form-item label="学科分类:" class="valid-msg">
<el-col :span="18">
<!-- :props="{ expandTrigger: 'hover' }" -->
<el-cascader
style="width: 360px"
size="small"
v-model="formData.subjectIdList"
:options="labelOptions"
:props="{ value: 'id', label: 'name', children: 'subList'}"
>
</el-cascader>
<div v-show="!needShowAuditMsg && noLabel" class="error" style="margin-top:4px;">
<span>请选择学科分类</span>
</div>
</el-col>
</el-form-item>
</div>
<div class="basic-item-icon">
<span class="require">*</span>
<el-form-item label="开放范围:">
<el-radio-group v-model="formData.shareType">
<el-radio :label="1">机构共享</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div class="basic-item-icon">
<span class="require">*</span>
<el-form-item label="课程视频:" prop="range" class="valid-msg">
<el-upload
ref="uploadFileCom"
class="upload-video"
:class="{'disabled': needShowUploadProcess || (formData.courseCustomChapterModels[0].courseCustomLectureModelList.length >= orgCourseInfo.limitModel.maxLimitVideoCount)}"
action="#"
:before-upload="beforeUploadVideo"
:show-file-list="false"
:disabled="needShowUploadProcess || (formData.courseCustomChapterModels[0].courseCustomLectureModelList.length >= orgCourseInfo.limitModel.maxLimitVideoCount)"
>
<el-button slot="trigger" ref="uploadFileBtn" type="primary"><img style="width:12px;height:12px;position:relative;top:1px;" src="../../../assets/image/phrase3/icon-upload.png" /> <span style="font-size:14px;"> 上传文件</span></el-button>
<div slot="tip" class="el-upload__tip">
<span class="upload-tips">只支持MP4格式,课程视频最多上传100个,单文件最大2G</span>
<ul v-show="formData.courseCustomChapterModels[0].courseCustomLectureModelList.length" class="custom-list">
<li v-for="(lecture, index) in formData.courseCustomChapterModels[0].courseCustomLectureModelList" :key="index" class="valid-msg video-wrappe">
<ul class="video">
<li style="height: 46px;line-height:48px;">
<span class="title">视频{{index + 1}}</span>
<img src="../../../assets/image/phrase3/icon-pin.png" />
<span class="name" @click="previewVideoAction(lecture)">{{lecture.resourceModel.name}}</span>
</li>
<li class="other-action">
<div>
<el-upload
ref="uploadFileCom"
class="upload-video"
action="#"
:before-upload="beforeUploadVideo"
:show-file-list="false"
>
<img @click="replaceLecture(index)" class="replace" src="../../../assets/image/phrase3/replace.png" />
</el-upload>
</div>
<img @click="deleteLecture(index)" class="delete" src="../../../assets/image/phrase3/close.png" />
</li>
<div style="color:red;;position:absolute;top:22px;" v-show="needShowAuditMsg && formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].contentCheck" class="error-video">
<span>{{formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].contentCheck}}</span>
</div>
</ul>
<div class="video-name">
<span class="title">
<span style="color:red;">*</span>
<span class="video-title">视频名称{{index + 1}}</span>
</span>
<el-input
size="small"
v-model="lecture.name"
placeholder="请输入课程名称"
style="width: 260px"
maxlength="25"
:disabled="disabled"
></el-input>
<span class="word-num">
{{(lecture.name || '').replace(/\s+/g,"").length}}/25
</span>
</div>
<div v-show="lecture.name && needShowAuditMsg && formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].nameCheck" class="error-video">
<span>{{formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].nameCheck}}</span>
</div>
<div v-show="!lecture.name" class="error-video">
请输入视频名称
</div>
</li>
</ul>
<div style="color:red;position:absolute;top:60px;" v-if="noLecture && !formData.courseCustomChapterModels[0].courseCustomLectureModelList.length">请上传课程视频</div>
<div v-show="needShowUploadProcess" style="position:absolute;top:10px;left:120px;display:flex;">
<div style="flex:1;width: 358px;">
<span class="upload-process" :style="{'width': (uploadProgress/100 * 300) + 'px'}"></span>
</div>
<!-- <img @click="cancleUpload" style="widht:16px;height:16px;margin-top:3px;margin-left:8px;" src="../../../assets/image/phrase3/close.png" /> -->
</div>
</div>
</el-upload>
</el-form-item>
</div>
<div class="other-content valid-msg" v-show="isShowOtherContent">
<div class="tips">注:以下信息为非必填项,您也可以根据实际情况修改</div>
<div class="basic-item-icon">
<!-- <span class="require">*</span> -->
<el-form-item label="课程封面:">
<el-upload
v-model="formData.courseIntroImage"
class="bg-uploader"
action="#"
accept="image/*"
:show-file-list="false"
:before-upload="beforeUploadForCourse"
:disabled="disabled"
>
<div class="bg-img-wrapper">
<img
v-if="formData.courseIntroImage"
@mouseover.stop="imgMouseOver=true"
:src="getOSSDomain(formData.courseIntroImage)"
class="bg-img"
/>
<img
v-if="!formData.courseIntroImage"
class="bg-img"
src="../../../assets/image/small.png"
/>
</div>
</el-upload>
<div class="limit-text">尺寸:750*420,只支持jpg、jpeg格式</div>
<!-- <div style="color:red;position:absolute;top:104px;" class="error">
课程难度课程难度
</div> -->
<div style="color:red;position:absolute;top:102px;" v-show="needShowAuditMsg && formData.courseIntroImageCheck" class="error">
<span>{{formData.courseIntroImageCheck}}</span>
</div>
</el-form-item>
<!-- <p class="upload-message" v-if="uploadImgMessage">请选择列表图片</p> -->
</div>
<el-form-item label="课程难度:">
<el-radio-group v-model="formData.difficultyLevel">
<el-radio :label="1">初级</el-radio>
<el-radio :label="2">中级</el-radio>
<el-radio :label="3">高级</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="formData.courseCustomDoctorModels[0]">
<el-form-item label="讲师名称:" class="valid-msg">
<el-col :span="18">
<el-autocomplete
size="small"
style="width: 360px"
      class="inline-input"
      v-model="formData.courseCustomDoctorModels[0].courseDoctorName"
      placeholder="请输入内容"
      :fetch-suggestions="querySearch"
:trigger-on-focus="true"
      @select="handleSelect">   
</el-autocomplete>
<span
class="word-num"
>{{(formData.courseCustomDoctorModels[0] && formData.courseCustomDoctorModels[0].courseDoctorName || '').replace(/\s+/g,"").length}}/25</span>
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorNameCheck" class="error">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorNameCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomDoctorModels[0], 'courseDoctorNameCheck')">X</span>
</div>
</el-col>
</el-form-item>
<div class="basic-item-icon">
<el-form-item label="讲师头像:">
<el-upload
v-model="formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl"
class="bg-uploader"
action="#"
accept="image/*"
:show-file-list="false"
:before-upload="beforeUploadForLecture"
:disabled="disabled"
>
<div class="bg-img-wrapper">
<img
v-if="formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl || ''"
@mouseover.stop="imgMouseOver=true"
:src="getOSSDomain(formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl)"
class="bg-img-doctor"
/>
<img
v-if="!(formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl || '')"
class="bg-img-doctor"
src="../../../assets/image/small.png"
/>
</div>
</el-upload>
<div class="limit-text" style="top: 80px;">尺寸:88*88,只支持jpg、jpeg格式</div>
<!-- <div class="error" style="position:absolute;top: 94px;">
所属机构所属机构:所属机构:
</div> -->
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrlCheck" class="error" style="position:absolute;top: 98px;">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorAvatarUrlCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomDoctorModels[0], 'courseDoctorAvatarUrlCheck')">X</span>
</div>
</el-form-item>
<!-- <p class="upload-message" v-if="uploadImgMessage">请选择列表图片</p> -->
</div>
<el-form-item label="所属机构:">
<el-col :span="18">
<el-input
size="small"
v-model="formData.courseCustomDoctorModels[0].courseDoctorHospital"
placeholder="请输入所属机构"
style="width: 360px"
maxlength="25"
:disabled="disabled"
></el-input>
<span
class="word-num"
>{{(formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorHospital || '').replace(/\s+/g,"").length}}/25</span>
<!-- <div class="error">
所属机构所属机构:所属机构:
</div> -->
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorHospitalCheck" class="error">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorHospitalCheck}}</span>
</div>
</el-col>
</el-form-item>
</div>
<el-form-item label="课程简介:">
<el-col :span="18">
<el-input
size="small"
type="textarea"
maxlength="200"
:autosize="{ minRows: 5}"
placeholder="请输入课程简介"
v-model="formData.courseIntro"
style="width:90%;"
></el-input>
<span
class="word-num"
>{{(formData.courseIntro || '').replace(/\s+/g,"").length}}/200</span>
<!-- <div class="error-area">
所属机构所属机构:所属机构:
</div> -->
<div v-show="needShowAuditMsg && formData.courseIntroCheck" class="error-area">
<span>{{formData.courseIntroCheck}}</span>
</div>
</el-col>
</el-form-item>
</div>
<!-- 更多信息 -->
<div class="separator-line">
<span class="line-left"></span>
<div @click="toggleOtherContent" class="center">
<span>{{isShowOtherContent ? '收起更多信息': '展开更多信息'}}</span>
<img v-show="isShowOtherContent" src="../../../assets/image/phrase3/arrow-up.png" />
<img v-show="!isShowOtherContent" src="../../../assets/image/phrase3/arrow-down.png" />
</div>
<span class="line-right"></span>
</div>
</el-form>
</div>
<div v-show="step == 2" class="course-content-step2">
<img class="success-img" src="../../../assets/image/phrase3/icon-audit-success.png" />
<span class="tips-1">您上传的课程已成功提交,预计在3-5个工作日内完成审核</span>
<span class="tips-2">审核通过后,您才可以选择课程完成项目配置。如有任何疑问可联系云鹊医400-920-8877</span>
<el-button class="back-btn" type="primary" icon="el-icon-back" @click="backToOrgCourse">返回机构课程</el-button>
</div>
<div v-show="step == 1" slot="footer" class="dialog-footer">
<el-button @click="dialogObj.visible=true">取 消</el-button>
<el-button type="primary" @click="submitForm('formDataRef')">提交审核</el-button>
</div>
</el-dialog>
<!-- // fetch-suggestions 是一个返回输入建议的方法属性 -->
<!-- //  false = >输入后匹配输入建议  true => 激活即列出输入建议 -->
<!-- // 点击选中建议项时触发  handleSelect -->
<DialogComponet :dialogObj="dialogObj" @hide="hideCancleTips" @confirm="dialogObj.visible=false"></DialogComponet>
<PreviewVideo :dialogVisible="isPreviewVideo" :videoUrl="videoUrl" @close="isPreviewVideo=false"></PreviewVideo>
<el-dialog
class="dialog-title-border-old"
title="图片裁剪"
:visible.sync="showCropper"
:width="currentOption.cropDialogWidth"
center>
<div slot="title" style="text-align: left;">
<span style="font-weight: 700;">图片裁剪</span>
</div>
<div v-if="showCropper" style="margin-bottom: 20px;">
<CropperImg
:cropOption="currentOption"
@getCropImg="getCropImg(arguments)"
:originImg="slide2.oriUrl"
/>
</div>
</el-dialog>
</div>
</template>
<script>
import PreviewVideo from "@/components/education/custom-resource/preview-video";
import DialogComponet from "@/components/education/template/dialog";
import CropperImg from '@/components/common/cropper-img.vue'
import { doUpload, getFilePath } from "@/utils/qiniu-util";
import { openLoading, closeLoading, getQiniuToken1 } from "@/utils/utils";
import { isEmptyUtils, getOSSImgUrl } from "@/utils/index";
import { mapActions } from 'vuex';
import { ossUpload, getFilePathForOSS } from "@/utils/oss/ossUtil";
let vm = null;
export default {
data() {
return {
slide2: {
oriUrl: '', // 原图
},
showCropper: false,
currentOption: {
offset_x: 120,
offset_y: 185,
width: 750,
height: 420,
cvWidth: 1000,
cvHeight: 800,
uploadType: 1,
cropDialogWidth: '900px'
},
cropOption: {
offset_x: 120,
offset_y: 185,
width: 750,
height: 420,
cvWidth: 1000,
cvHeight: 800,
uploadType: 1,
cropDialogWidth: '900px'
},
cropOption2: {
offset_x: 80,
offset_y: 60,
width: 88,
height: 88,
cvWidth: 249,
cvHeight: 200,
uploadType: 2,
cropDialogWidth: '500px'
},
isReplaceUpload: false,
replaceLectureIndex: 0,
step: 1,
needCheckField: false,
needShowAuditMsg: false,
needShowUploadProcess: false,
disabled: false,
formDataBase: {
checkStatus: 0,
courseCustomChapterModels: [
{
courseCustomLectureModelList: [],
id: null,
name: "视频课程"
}
],
courseCustomDoctorModels: [
{
courseDoctorAvatarUrl: "/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
}
],
courseId: null,
courseIntro: "",
courseIntroCheck: "",
courseIntroImage: "/h5/images/cme/project-banner.png",
courseIntroImageCheck: "",
courseName: "",
courseNameCheck: "",
deleteCustomLectureIds: [],
difficultyLevel: 1,
shareType: 1,
subjectIdList: []
},
formData: {
checkStatus: 0,
courseCustomChapterModels: [
{
courseCustomLectureModelList: [],
id: null,
name: "视频课程"
}
],
courseCustomDoctorModels: [
{
courseDoctorAvatarUrl: "/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
}
],
courseId: null,
courseIntro: "",
courseIntroCheck: "",
courseIntroImage: "/h5/images/cme/project-banner.png",
courseIntroImageCheck: "",
courseName: "",
courseNameCheck: "",
deleteCustomLectureIds: [],
difficultyLevel: 1,
shareType: 1,
subjectIdList: []
},
// uploadImgMessage: false,
imgMouseOver: false,
labelOptions: [],
isShowOtherContent: false,
fileList: [
],
doctorNameList: [
// { courseDoctorName: "333", show: true, seleted: false },
],
isShowDoctorList: false,
isPreviewVideo: false,
videoUrl: "",
orgCourseInfo: {
defaultDoctor: {
courseDoctorAvatarUrl: "/h5/images/cme/project-banner.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
},
doctorModelList: [
{
courseDoctorAvatarUrl: "/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
}
],
limitModel: {
maxLimitOneVideoSize: 2147483648,
maxLimitVideoCount: 100,
maxStorageSpace: 5368709120,
usedStorageSpace: 1021842989
}
},
uploadProgress: 0,
dialogObj: {
visible: false,
title: "确定取消吗?",
message: "取消后,将不保存该页面已填写的内容",
tip: "",
confirmMsg: "取 消",
hideMsg: "确 定"
},
noLecture: true, // 没有上传视频
noCouseName: true, // 没有课程名称
noLabel: true, // 没有选择分类
currentUploadType: 1,// 1: 封面图片; 2: 讲师头像
};
},
props: {
dialogVisible: {
type: Boolean,
default: false
},
courseId: {
type: String | Number,
default: 0
}
},
computed: {},
watch: {
dialogVisible(isVisible) {
this.formData = JSON.parse(JSON.stringify(this.formDataBase));
this.isShowOtherContent = false;
if (isVisible) {
if (this.courseId == 0) {
this.initAdd(this.courseId);
} else {
this.isShowOtherContent = true;
this.initModify(this.courseId);
}
}
this.isReplaceUpload = false;
this.noLecture = false;
this.noCouseName = false;
this.noLabel = false;
},
},
components: {
PreviewVideo,
DialogComponet,
CropperImg
},
created() {
vm = this;
},
mounted() {
this.getLabelList();
},
methods: {
...mapActions(['setKind']),
// 重新上传(替换视频)
replaceLecture(index) {
this.isReplaceUpload = true;
this.replaceLectureIndex = index;
},
// 获取裁剪的图片数据
getCropImg(argument) {
this.showCropper = false;
this.cropData = argument[1]
vm.doUploadOSS(argument[2], this.currentUploadType); //封面图片
argument[3] && argument[3].destroy();
},
//
// closeCropper() {
// this.showCropper = false;
// },
// 取消上传
cancleUpload() {
console.log('in cancleUpload');
if(window.QNSubscription) {
// console.log('QNSubscription', QNSubscription);
// window.QNSubscription.unsubscribe();
// window.QNSubscription = null;
}
// this.$refs.uploadFileCom.abort();
},
querySearch(queryString, cb) {
// this.doctorNameList;
let doctorNameList = JSON.parse(JSON.stringify(this.doctorNameList));
if(!queryString) {
cb(doctorNameList);
return;
}
let backList = [];
doctorNameList.forEach( item => {
if(item.courseDoctorName.indexOf(queryString) >= 0) {
backList.push(item);
}
})
cb(backList);
},
// 选择其中一个
handleSelect(selDoctor) {
this.formData.courseCustomDoctorModels[0] = selDoctor
},
// 创建课程页面的初始信息
initOrgCourseInfo() {
vm.GET("contents/course/custom/info/init", { setEntry: true }).then(
res => {
if (res.code == "000000") {
this.orgCourseInfo = res.data;
this.formData.courseCustomDoctorModels[0] = this.orgCourseInfo.defaultDoctor;
this.formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl =
this.orgCourseInfo.defaultDoctor.courseDoctorAvatarUrl || "/h5/images/cme/doctor-header.png";
this.doctorNameList = this.convertDNameToSelectOpt(
this.orgCourseInfo.doctorModelList
);
+this.courseId && this.getCourseInfoById(this.courseId);
}
}
);
},
// 将医生名称进行处理
convertDNameToSelectOpt(doctorModelList) {
doctorModelList.forEach(item => {
item.value = item.courseDoctorName
item.show = true;
item.seleted = false;
});
return doctorModelList;
},
// 添加时初始化
initAdd() {
this.step = 1;
this.needShowAuditMsg = false;
this.initOrgCourseInfo();
},
// 编辑时初始化
initModify() {
this.step = 1;
this.needShowAuditMsg = true;
this.initOrgCourseInfo();
},
// 创建课程页面的初始信息
getCourseInfoById(courseId) {
vm.GET(`contents/course/custom/info/${courseId}`)
.then( res => {
if ( res.code == "000000") {
this.formData = res.data;
}
}
);
},
// 关闭当前弹框
close() {
this.$emit("close");
},
// 获取学科列表
getLabelList() {
let req = {};
this.GET("aggregate/content/labelList", req).then(res => {
if (res.code == "000000") {
this.convertLabelList(res.data);
}
});
},
// 将所有子分类中的“全部”去掉
convertLabelList(labelList) {
let newLabelList = [];
labelList.forEach(item => {
item.subList = item.subList.slice(1);
});
this.labelOptions = labelList;
},
// 上传视频(mp4)
beforeUploadVideo(file) {
// this.$message({
// showClose: false,
// message: '您上传的文件大小已超限制,无法继续上传。如有疑问可拨打云鹊医电话咨询400-920-7788',
// type: 'error',
// duration: 10000
// });
// return;
console.log(file);
const isMP4 = file.type === "video/mp4";
const isGt = file.size > this.orgCourseInfo.limitModel.maxLimitOneVideoSize;
const isGtMaxNum = this.formData.courseCustomChapterModels[0].courseCustomLectureModelList.length >= 100;
const usedGtMaxStore = this.orgCourseInfo.limitModel.usedStorageSpace + file.size > this.orgCourseInfo.limitModel.maxStorageSpace;
if (isGtMaxNum || !isMP4) {
this.$message.error("视频不符合规范,请根据规范上传视频");
return;
}
if(usedGtMaxStore || isGt) {
this.$message({
showClose: true,
message: '您上传的文件大小已超限制,无法上传。如有疑问可拨打云鹊医电话:400-920-7788',
type: 'error',
duration: 10000
});
return;
}
// 直接上传
this.needShowUploadProcess = true;
vm.uploadProgress = 0;
doUpload(vm, file, getFilePath(file, null), "preview4", "progress", "")
.then(function(path) {
console.log(path);
let cName = path.name;
cName = cName.substr(0, cName.lastIndexOf('.'));
cName = cName.substring(0, 21);
let uploadResourceParam = {
formatType: path.ext,
name: cName + path.ext, //path.name,
qCloudUrl : path.fullPath,
size : path.size,
fileType : 1,
status : "success",
uid : new Date().getTime()
}
vm.needShowUploadProcess = false;
vm.uploadProgress = 0;
vm.insertResourceAction(uploadResourceParam);
});
},
// 上传资源(视频)后,生存对应的节
insertResourceAction(uploadResourceParam) {
this.POST("contents/course/custom/info/insertResource", [uploadResourceParam]).then(res => {
if (res.code == "000000") {
let cName = res.data.resourceModelList[0].name;
cName = cName.substr(0, cName.lastIndexOf('.'));
let lectureObjId = null;
if(this.isReplaceUpload) {
lectureObjId = this.formData.courseCustomChapterModels[0].courseCustomLectureModelList[this.replaceLectureIndex].id;
console.log('in isReplaceUpload', lectureObjId);
}
let lectureObj = {
id: lectureObjId,
name: cName,
nameCheck: "",
contentCheck: "",
resourceModel: {}
}
this.orgCourseInfo.limitModel = res.data.limitModel;
lectureObj.resourceModel = res.data && res.data.resourceModelList[0];
if(this.isReplaceUpload) {
this.formData.courseCustomChapterModels[0].courseCustomLectureModelList.splice(this.replaceLectureIndex, 1, lectureObj);
} else {
this.formData.courseCustomChapterModels[0].courseCustomLectureModelList.push(lectureObj);
}
// 重置是否替换视频的参数
this.isReplaceUpload = false;
this.replaceLectureIndex = 0;
}
});
},
// 展开/收起 更多信息
toggleOtherContent() {
this.isShowOtherContent = !this.isShowOtherContent;
},
// 表单校验
submitForm(formName) {
this.needShowAuditMsg = false;
this.noCouseName = false;
this.noLecture = false;
this.noLabel = false;
let hasLecture = this.formData.courseCustomChapterModels[0].courseCustomLectureModelList.length > 0;
let flag = false;
let lectureList = this.formData.courseCustomChapterModels[0].courseCustomLectureModelList;
for(let i = 0; i < lectureList.length; i ++) {
if(!lectureList[i].name) {
flag = true;
break;
}
}
console.log('flag', flag);
if(!hasLecture) {
this.noLecture = true;
}
if(!this.formData.courseName) {
this.noCouseName = true;
}
if(!this.formData.subjectIdList.length) {
this.noLabel = true;
}
if(this.noCouseName || this.noLabel || this.noLecture || flag) {
return;
}
this.insertOrUpdate();
},
// 添加或修改课程(kind = 3)
insertOrUpdate() {
let formData = JSON.parse(JSON.stringify(this.formData));
if(!formData.courseCustomDoctorModels[0]) {
formData.courseCustomDoctorModels = [];
} else if(!formData.courseCustomDoctorModels[0].courseDoctorName
&& !formData.courseCustomDoctorModels[0].courseDoctorHospital) {
formData.courseCustomDoctorModels = [];
}
this.POST("contents/course/custom/info/insertOrUpdate", formData).then(res => {
if (res.code == "000000") {
this.step = 2;
} else {
this.$message.error(res.message);
}
});
},
// 返回到课程选择页面(kind = 3)
backToOrgCourse() {
console.log('backToOrgCourse');
this.close();
this.setKind(3);
},
// 关闭(“取消”按钮弹出来的)弹框
hideCancleTips() {
this.dialogObj.visible = false;
this.close();
},
// 预览视频
previewVideoAction(lecture) {
this.videoUrl = lecture.resourceModel.filePath;
this.isPreviewVideo = true;
},
// 删除本节视频
deleteLecture(index) {
let lectureId = this.formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].id;
if(lectureId) {
this.formData.deleteCustomLectureIds.push(lectureId);
}
this.formData.courseCustomChapterModels[0].courseCustomLectureModelList.splice(index, 1);
},
// 上传课程封面图片
beforeUploadForCourse(file) {
const isJPG = file.type === 'image/jpeg'
if(!isJPG) {
this.$message.error('只支持jpg、jpeg格式')
return;
}
vm.currentUploadType = 1;
vm.currentOption = vm.cropOption;
var _img = new FileReader()
_img.readAsDataURL(file)
_img.onload = function(theFile) {
let image = new Image()
image.src = theFile.target.result
vm.slide2.oriUrl = theFile.target.result;
image.onload = function() {
let _this = this
// 图片大小不正常,则进行裁剪
if(_this.width != 750 || _this.height != 420) {
vm.showCropper = true;
// 图片大小正常,则直接上传
}else {
vm.doUploadOSS(file, 1); //封面图片
}
}
}
},
// 上传讲师图片
beforeUploadForLecture(file) {
// const isLt50kb = file.size / 1024 < 50;
const isJPG = file.type === 'image/jpeg'
if(!isJPG) {
this.$message.error('只支持jpg、jpeg格式')
return;
}
vm.currentUploadType = 2;
vm.currentOption = vm.cropOption2;
var _img = new FileReader()
_img.readAsDataURL(file)
_img.onload = function(theFile) {
let image = new Image()
image.src = theFile.target.result
vm.slide2.oriUrl = theFile.target.result;
image.onload = function() {
let _this = this
if(_this.width != 88 || _this.height != 88) {
vm.showCropper = true;
// vm.$message.info("上传图片尺寸大小不合适,请重新上传")
}else {
vm.doUploadOSS(file, 2); //封面图片
}
}
}
},
getOSSDomain(url) {
return getOSSImgUrl(url);
},
// (调用OSS API)开始上传
doUploadOSS(file, index) {
let self = this;
//上传 指定文件名
ossUpload(self, file, getFilePathForOSS(file), null, null, null).
then(function(path) {
console.log(path);
let list = [{}];
// list[0].name = file.name;
// list[0].url = localStorage.getItem("resource_url") + path;
// getOSSImgUrl(path)
if (index === 1) {
self.formData.courseIntroImage = path;
} else if (index === 2) {
self.formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl = path;
}
self.$message.success("上传成功");
});
return false;
},
}
};
</script>
<style scoped lang="scss">
.edit-course-wrapper {
.course-content {
// color: red;
.basic-item-icon {
position: relative;
margin-top: 20px;
.require {
position: absolute;
left: 40px;
top: 11px;
color: #f56c6c;
}
.upload-message {
position: absolute;
left: 160px;
top: 105px;
font-size: 12px;
color: #f56c6c;
}
.img-delete {
position: absolute;
left: 0px;
top: 0px;
width: 84px;
height: 100px;
background: #000;
opacity: 0.7;
z-index: 999;
i {
color: #fff;
margin-top: 39px;
margin-left: 0px;
}
}
.upload-tips {
width: 100%;
position: relative;
top: -10px;
font-size: 12px;
color: #979899;
// display: inline-block;
}
.custom-list {
position: relative;
left: 0px;
// left: -78px;
width: 580px;
display: flex;
flex-direction: column;
border-radius: 3px;
border: 1px solid rgba(228,231,237,1);
padding: 20px;
padding-top: 5px;
font-size: 14px;
& > li {
margin: 10px 0;
}
.video-wrappe {
&:nth-child(n+2)::before {
position: absolute;
top: -4px;
display: block;
content: "";
height: 0;
width: 100%;
border-top: 1px dashed #E4E7ED;
}
.video {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.title {
display: inline-block;
width: 80px;
text-align: right;
margin-right: 10px;
}
.name {
cursor: pointer;
color: #5890DD;
}
img {
width: 12px;
height: 12px;
}
.other-action {
width: 80px;
display: flex;
align-items: center;
text-align: right;
justify-content: flex-end;
.replace {
position: relative;
top: 5px;
margin-right: 20px;
cursor: pointer;
width: 16px;
height: 16px;
}
.delete {
position: relative;
top: 2px;
cursor: pointer;
width: 16px;
height: 16px;
}
}
}
}
.video-name {
.title {
display: inline-block;
width: 80px;
text-align: right;
margin-right: 10px;
}
}
}
}
.word-num {
font-size: 12px;
color: #999;
padding-top: 5px;
}
.bg-uploader {
img {
float: left;
}
.bg-img-wrapper {
.bg-img {
display: block;
width: 160px;
height: 90px;
}
.bg-img-doctor {
display: block;
width: 88px;
height: 88px;
}
}
.bg-video {
float: left;
width: 84px;
height: 100px;
}
}
.limit-text {
position: absolute;
top: 86px;
left: 0px;
font-size: 12px;
color: #979899;
}
.separator-line {
width: 100%;
display: flex;
flex-direction: row;
align-content: center;
align-items: center;
justify-content: space-between;
.center {
cursor: pointer;
width: 130px;
color: #666666;
img {
width: 12px;
}
}
.line-left {
flex: 1;
margin-left: 20px;
border-bottom: 1px dashed #e4e7ed;
}
.line-right {
flex: 1;
margin-right: 6px;
border-bottom: 1px dashed #e4e7ed;
}
}
.tips {
// margin-left: -20px;
// width: 810px;
// width: 100%;
height: 32px;
line-height: 32px;
margin-left: 20px;
margin-right: 5px;
padding-left: 12px;
background: rgba(254, 250, 245, 1);
border-radius: 3px;
color: #e6a23c;
}
.valid-msg {
position: relative;
.error {
width: 370px;
position: absolute;
display: flex;
justify-content: space-between;
top: 29px;
font-size: 13px;
color: #ed3131;
.text {
flex: 1;
}
.cancle {
cursor: pointer;
width: 20px;
}
}
.error-area {
position: absolute;
bottom: -32px;
font-size: 13px;
color: #ed3131;
.cancle {
width: 20px;
margin-left: 20px;
cursor: pointer;
}
}
.error-video {
position: absolute;
top: 74px;
left: 93px;
font-size: 13px;
color: #ed3131;
.cancle {
width: 20px;
margin-left: 20px;
cursor: pointer;
}
}
.edit-wrapper {
color: #449284;
.edit-img {
position: relative;
top: 2px;
width: 12px;
margin: 0 2px 0 4px;
}
}
.doctor-select-list {
width: 200px;
// max-height: 100px;
position: absolute;
z-index: 100;
background: #fff;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
// margin: 10px;
li {
padding-left: 20px;
cursor: pointer;
&:hover {
background: #f4f7fd;
}
&.doctor-selected {
background: #f4f7fd;
}
}
}
}
.upload-process {
margin: 10px 0 10px 10px;
display: block;
// width: 310px;
height: 4px;
background: #449284;
border-radius: 2px;
}
.upload-video.disabled {
.el-button--primary {
color: #bcbec2 !important;
background-color: #f4f4f5 !important;
border-color: #e9e9eb !important;
cursor: not-allowed !important;
}
// color: red;
}
}
.course-content-step2 {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
.success-img {
margin-top: 80px;
width: 60px;
height: 60px;
}
.back-btn {
margin-bottom: 70px;
}
.tips-1 {
margin-top: 30px;
font-size: 18px;
color: #303133;
}
.tips-2 {
margin-top: 4px;
margin-bottom: 40px;
font-size: 14px;
color: #999999;
}
}
}
</style>
<template>
<!-- 组件有问题 -->
<el-dialog
title="预览PDF文件"
:visible="dialogVisible"
@close="close"
center
:close-on-click-modal="false"
:close-on-press-escape="false"
width="800px"
>
<!-- <canvas v-for="page in pages" :id="'the-canvas'+page" :key="page"></canvas> -->
<div id="demo"></div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="close">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
// import Pdfh5 from "pdfh5";
export default {
data() {
return {
pdfh5: null
};
},
props: {
dialogVisible: {
type: Boolean,
default: false
}
},
computed: {},
components: {
// PDF
},
mounted() {
// //实例化
// this.pdfh5 = new Pdfh5("#demo", {
// pdfurl: "http://10.177.11.169:9000/test.pdf"
// });
// //监听完成事件
// this.pdfh5.on("complete", function(status, msg, time) {
// console.log(
// "状态:" +
// status +
// ",信息:" +
// msg +
// ",耗时:" +
// time +
// "毫秒,总页数:" +
// this.totalNum
// );
// });
},
methods: {
close() {
this.$emit("close");
}
}
};
</script>
<style scoped lang="scss">
// @import "pdfh5/css/pdfh5.css";
// * {
// padding: 0;
// margin: 0;
// }
// html,
// body,
// #app {
// width: 100%;
// height: 100%;
// }
</style>
<template>
<div class="preview-protocol-wrapper dialog-title-border">
<el-dialog
title="用户协议"
:visible="dialogVisible"
@close="close"
center
:close-on-click-modal="false"
:close-on-press-escape="false"
width="800px"
>
<div slot="title" style="text-align: left;">
<span style="font-weight: 700;">用户协议</span>
</div>
<div style="margin: 20px 20px;height: 400px;padding: 10px 0;" v-html="protocolContent"></div>
<div slot="footer" class="dialog-footer">
<el-button @click="close(false)">不同意</el-button>
<el-button type="primary" @click="signProtocol">同意</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
};
},
props: {
dialogVisible: {
type: Boolean,
default: false
},
protocolId: {
type: String | Number,
default: 1
},
protocolContent: {
type: String,
default: ''
}
},
computed: {
},
mounted() {
// this.getProtocolInfoById();
},
methods: {
// 签署协议
signProtocol() {
let req = {
setEntry: true,
};
this.POST("smartcontract/protocol/sign?type=" + this.protocolId, req).then(res => {
if (res.code == "000000") {
this.close(true);
} else {
vm.$message.info(res.message);
this.close(false);
}
}).catch(err => {
vm.$message.warning("请稍后重试");
this.close(false);
});
},
close(status) {
this.$emit('close', status);
},
}
};
</script>
<style scoped lang="scss">
</style>
<template>
<div class="preview-video-wrapper dialog-title-border-old">
<el-dialog
title="预览课程"
:visible="dialogVisible"
@close="close"
center
:close-on-click-modal="false"
:close-on-press-escape="false"
width="800px"
>
<video-player
class="video-player vjs-custom-skin"
ref="videoPlayer"
:playsinline="true"
:options="playerOptions"
@pause="onPlayerPause($event)"
/>
<div slot="title" style="text-align: left;">
<span style="font-weight: 700;">预览课程</span>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="close">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
// import video from '@/assets/test.mp4'
export default {
data() {
return {
playerOptions: {
playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
autoplay: false, //如果true,浏览器准备好时开始回放。
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: "zh-CN",
aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [
{
src: '', // 路径
type: "video/mp4" // 类型
},
// {
// src: "//path/to/video.webm",
// type: "video/webm"
// }
],
poster: "http://10.177.11.169:9000/750*1000-1.png", //你的封面地址
notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true,
durationDisplay: true,
remainingTimeDisplay: false,
fullscreenToggle: true //全屏按钮
}
}
};
},
props: {
dialogVisible: {
type: Boolean,
default: false
},
videoUrl: {
type: String,
default: ''
}
},
watch: {
videoUrl(newVideoUrl) {
this.playerOptions.sources[0].src = newVideoUrl;
}
},
computed: {
player() {
return this.$refs.videoPlayer.player
}
},
mounted() {
},
methods: {
close() {
this.$emit('close');
this.player.pause();
},
onPlayerPause(player) {
console.log(player);
}
}
};
</script>
<style scoped lang="scss">
</style>
<template>
<!-- 拒绝原因 暂时不做 -->
<el-dialog
title="拒绝原因"
:visible="dialogVisible"
@close="hideAuditForm"
width="600px"
center>
<el-form ref="auditForm" :model="auditForm" label-width="120px">
<el-form-item label="拒绝原因:">
<el-radio-group v-model="auditForm.label">
<div v-for="item in refuseReasonList" :key="item">
<div style="padding-top: 12px;">
<el-radio :label="item"></el-radio>
</div>
</div>
<!-- <div style="padding-top: 16px;">
<el-radio :label="refuseReasonList[1]"></el-radio>
</div> -->
<div style="padding-top: 16px;">
<el-radio label="其他"></el-radio>
</div>
</el-radio-group>
<div v-if="auditForm.label == '其他'">
<el-input type="textarea" v-model="auditForm.desc" maxlength="25" style="width: 310px;margin-top: 10px;"></el-input>
<span class="word-num">{{(auditForm.desc).replace(/\s+/g,"").length}}/25</span>
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="hideAuditForm">取 消</el-button>
<el-button type="primary" @click="submitForm()">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
data() {
return {
auditForm: {
label: '',
desc: ''
}
};
},
props: {
dialogVisible: {
type: Boolean,
default: false
},
refuseReasonList: {
type: Array,
default: () => ['含有政治类、医疗健康、社会事件类不实信息', '含有欺诈,色情,诱导、违法犯罪非法字符']
}
},
watch: {
dialogVisible(newVal) {
if(newVal) {
this.auditForm.label = '';
this.auditForm.desc = '';
}
}
},
computed: {
},
mounted() {
console.log(2222);
},
methods: {
hideAuditForm() {
this.$emit('close');
},
submitForm() {
let cMsg = this.auditForm.label;
if(cMsg == '其他') {
cMsg = this.auditForm.desc;
}
// if(!cMsg) {
// this.$message({
// type: "warning",
// message: '请填写拒绝原因或直接点击取消按钮'
// });
// return;
// }
// refuseReasonList
this.hideAuditForm();
this.$emit('checkInfo', cMsg);
}
}
};
</script>
<style scoped lang="scss">
</style>
...@@ -8,8 +8,14 @@ ...@@ -8,8 +8,14 @@
<li class="order"> <li class="order">
<div class="num" @click="toggleOrder"> <div class="num" @click="toggleOrder">
<span>学习人数</span> <span>学习人数</span>
<img v-show="!isRise" src="../../../assets/custom/icon/icon-rise.png" alt /> <span v-show="kind == 0">
<img v-show="isRise" src="../../../assets/custom/icon/icon-drop.png" alt /> <img v-show="!isRise" src="../../../assets/custom/icon/icon-rise.png" alt />
<img v-show="isRise" src="../../../assets/custom/icon/icon-drop.png" alt />
</span>
<span v-show="kind == 1">
<img v-show="!isRiseOrg" src="../../../assets/custom/icon/icon-rise.png" alt />
<img v-show="isRiseOrg" src="../../../assets/custom/icon/icon-drop.png" alt />
</span>
</div> </div>
<div class="cart-wrapper"> <div class="cart-wrapper">
<div class="cart" @click="toggleCart"> <div class="cart" @click="toggleCart">
...@@ -27,9 +33,13 @@ ...@@ -27,9 +33,13 @@
</ul> </ul>
<div v-if="courseList && courseList.list && courseList.list.length" class="list-wrapper"> <div v-if="courseList && courseList.list && courseList.list.length" class="list-wrapper">
<ul class="list"> <ul class="list">
<li v-show="kind == 1" class="course create-btn" @click="showOrgCourse(0)">
<img src="../../../assets/image/phrase3/plus-icon.png">
<span>创建机构课程</span>
</li>
<li <li
class="course" class="course"
:class="{ 'course-checked': item.checked }" :class="{ 'course-checked': item.checked, 'cursor': kind == 0 || item.checkStatus == 2}"
v-for="(item, index) in courseList.list" v-for="(item, index) in courseList.list"
:key="index" :key="index"
@click="toggleChecked(item)" @click="toggleChecked(item)"
...@@ -45,10 +55,17 @@ ...@@ -45,10 +55,17 @@
<span class="section-num">{{item.chapterSum}}{{item.lectureNum}}{{item.totalTime}}</span> <span class="section-num">{{item.chapterSum}}{{item.lectureNum}}{{item.totalTime}}</span>
<span v-if="item.testCount" class="exam-num">{{item.testCount}}场考试</span> <span v-if="item.testCount" class="exam-num">{{item.testCount}}场考试</span>
</div> </div>
<div class="cost"> <div v-if="item.checkStatus == 2 || kind == 0" class="cost">
<span class="no">免费</span> <span class="no">免费</span>
<span class="num">{{item.joinNum}}人已学</span> <span class="num">{{item.joinNum}}人已学</span>
</div> </div>
<div v-else class="cost audit">
<span class="no">{{item.checkStatus == 0 ? '审核中' : '审核失败'}}</span>
<div v-show="item.checkStatus == 1" class="edit" @click="showOrgCourse(item.courseId)">
<span>查看详情</span>
<img src="../../../assets/image/phrase3/arrow-right.png">
</div>
</div>
</div> </div>
<img <img
v-show="item.checked" v-show="item.checked"
...@@ -61,10 +78,10 @@ ...@@ -61,10 +78,10 @@
<div v-else class="no-list"> <div v-else class="no-list">
<img src="../../../assets/custom/icon/img-no-content.png" alt /> <img src="../../../assets/custom/icon/img-no-content.png" alt />
<span class="tips">没有找到相关结果,请重新查询</span> <span class="tips">没有找到相关结果,请重新查询</span>
<el-button v-show="kind == 1" type="primary" icon="el-icon-plus" @click="showOrgCourse(0)">创建机构课程</el-button>
</div> </div>
<div class="page-wrapper"> <div class="page-wrapper">
<div class="page"> <div v-show="kind == 0" class="page">
<el-pagination <el-pagination
background background
:current-page="searchParam.pageNo" :current-page="searchParam.pageNo"
...@@ -76,6 +93,18 @@ ...@@ -76,6 +93,18 @@
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
></el-pagination> ></el-pagination>
</div> </div>
<div v-show="kind == 1" class="page">
<el-pagination
background
:current-page="searchParamOrg.pageNo"
:page-sizes="[10, 30, 50, 100]"
:page-size="searchParamOrg.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="courseList.totalRows"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</div>
</div> </div>
<!-- 弹框提示 --> <!-- 弹框提示 -->
<dialog-componet :dialogObj="dialogObj"></dialog-componet> <dialog-componet :dialogObj="dialogObj"></dialog-componet>
...@@ -89,6 +118,7 @@ export default { ...@@ -89,6 +118,7 @@ export default {
data() { data() {
return { return {
isRise: true, isRise: true,
isRiseOrg: true,
isShowCart: false, isShowCart: false,
dialogObj: { dialogObj: {
title: "课程数量已达上限", title: "课程数量已达上限",
...@@ -100,19 +130,27 @@ export default { ...@@ -100,19 +130,27 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters(["cartList", "courseList", "searchParam", "courseLimitCount"]) ...mapGetters(["cartList", "courseList", "searchParam", "searchParamOrg", "courseLimitCount", "kind"])
}, },
components: { components: {
ShoppingCart, ShoppingCart,
dialogComponet: dialog dialogComponet: dialog
}, },
methods: { methods: {
...mapActions(["setCartList", "setSearchParam"]), ...mapActions(["setCartList", "setSearchParam", "setSearchParamOrg"]),
toggleOrder() { toggleOrder() {
this.isRise = !this.isRise; if(this.kind == 0) {
let dir = this.isRise ? 1 : 2; this.isRise = !this.isRise;
this.searchParam.dir = dir; let dir = this.isRise ? 1 : 2;
this.setSearchParam(this.searchParam); this.searchParam.dir = dir;
this.setSearchParam(this.searchParam);
} else {
this.isRiseOrg = !this.isRiseOrg;
let dir = this.isRiseOrg ? 1 : 2;
this.searchParamOrg.dir = dir;
this.setSearchParamOrg(this.searchParamOrg);
}
}, },
toggleCart() { toggleCart() {
this.isShowCart = !this.isShowCart; this.isShowCart = !this.isShowCart;
...@@ -120,18 +158,30 @@ export default { ...@@ -120,18 +158,30 @@ export default {
// 选择当前分页个数 // 选择当前分页个数
handleSizeChange(val) { handleSizeChange(val) {
this.searchParam.pageSize = val; if(this.kind == 0) {
this.setSearchParam(this.searchParam); this.searchParam.pageSize = val;
this.setSearchParam(this.searchParam);
} else {
this.searchParamOrg.pageSize = val;
this.setSearchParamOrg(this.searchParamOrg);
}
}, },
// 选择当前分页 // 选择当前分页
handleCurrentChange(val) { handleCurrentChange(val) {
this.searchParam.pageNo = val; console.log();
this.setSearchParam(this.searchParam); if(this.kind == 0) {
this.searchParam.pageNo = val;
this.setSearchParam(this.searchParam);
} else {
this.searchParamOrg.pageNo = val;
this.setSearchParamOrg(this.searchParamOrg);
}
}, },
// 选择课程(并要处理过滤,删除等) // 选择课程(并要处理过滤,删除等)
toggleChecked(item) { toggleChecked(item) {
if(item.checkStatus != 2 && this.kind == 1) return;
item.checked = !item.checked; item.checked = !item.checked;
if (item.checked) { if (item.checked) {
if (this.courseLimitCount != -1 && this.cartList.length >= this.courseLimitCount) { if (this.courseLimitCount != -1 && this.cartList.length >= this.courseLimitCount) {
...@@ -149,7 +199,12 @@ export default { ...@@ -149,7 +199,12 @@ export default {
} }
this.setCartList(this.cartList); this.setCartList(this.cartList);
this.$forceUpdate(); this.$forceUpdate();
} },
// 通知父组件,打开创建资源(课程)弹框
showOrgCourse(courseId) {
this.$emit('showOrgCourse', courseId ? courseId : 0);
},
} }
}; };
</script> </script>
...@@ -244,8 +299,6 @@ export default { ...@@ -244,8 +299,6 @@ export default {
flex-wrap: wrap; flex-wrap: wrap;
overflow-y: auto; overflow-y: auto;
.course { .course {
user-select: none;
cursor: pointer;
position: relative; position: relative;
top: 0; top: 0;
left: 0; left: 0;
...@@ -259,6 +312,11 @@ export default { ...@@ -259,6 +312,11 @@ export default {
margin-right: 10px; margin-right: 10px;
border-radius: 4px; border-radius: 4px;
border: 1px solid rgba(228, 231, 237, 1); border: 1px solid rgba(228, 231, 237, 1);
user-select: none;
// cursor: pointer;
&.cursor {
cursor: pointer;
}
&.course-checked { &.course-checked {
&::before { &::before {
content: ""; content: "";
...@@ -344,6 +402,24 @@ export default { ...@@ -344,6 +402,24 @@ export default {
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
} }
&.audit {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.edit {
cursor: pointer;
span {
font-size: 14px;
color: #449284;
}
img {
width: 10px;
height: 10px;
}
}
}
} }
} }
.course-selected { .course-selected {
...@@ -353,6 +429,25 @@ export default { ...@@ -353,6 +429,25 @@ export default {
width: 44px; width: 44px;
height: 44px; height: 44px;
} }
&.create-btn {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background:rgba(248,249,250,1);
border-radius:4px;
border: 1px dashed rgba(228,231,237,1);
cursor: pointer;
img {
width: 16px;
height: 16px;
}
span {
margin-top: 4px;
font-size: 12px;
color: #979899;
}
}
} }
} }
} }
...@@ -372,7 +467,7 @@ export default { ...@@ -372,7 +467,7 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// padding: 30px 200px; // padding: 30px 200px;
width: 1000px; width: 100%;
text-align: center; text-align: center;
margin-bottom: 100px; margin-bottom: 100px;
align-items: center; align-items: center;
......
<template>
<div class="custom-over">
<div class="custom-select-wrapper">
<!-- 学科分类 -->
<div class="subject-level">
<span class="title">学科分类</span>
<span
v-for="(item, index) in allLabelList"
:key="index"
class="item"
:class="{active: item.checked}"
@click="selectLabel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<!-- 课程分类 -->
<div class="course-class">
<div class="title">课程分类</div>
<div v-if="subLabelList.length" class="item" @click="selectSubLabel(subLabelList[0], 1)">
<span class="name" :class="{'active': subLabelList[0].checked}">全部</span>
</div>
<ul class="check-list">
<li
class="sub-item"
:class="{'active': item.checked}"
v-for="(item, index) in subLabelList.slice(1)"
:key="index"
@click="selectSubLabel(item, 2)"
>
<img v-show="item.checked" src="../../../assets/custom/icon/label-sel.png" alt />
<img v-show="!item.checked" src="../../../assets/custom/icon/label-sel-no.png" alt />
{{item.name}}
</li>
</ul>
<div class="right"></div>
</div>
<!-- 课程等级 -->
<div class="course-level">
<span class="title">课程等级</span>
<span
class="item"
v-for="(item, index) in courseLevel"
:key="index"
@click="selectLevel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<div class="button-wrapper">
<el-button class="add-button" plain size="small" @click="resetCond">重 置</el-button>
<el-button class="add-button" size="small" type="primary" @click="search">查 询</el-button>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
courseLevel: [
{ name: "全部", value: 0, checked: true },
{ name: "初级", value: 1, checked: false },
{ name: "中级", value: 2, checked: false },
{ name: "高级", value: 3, checked: false }
],
checkList: [431, 441]
};
},
props: {
dataList: {
type: Array,
default: () => {
return [
{
name: "全部",
checked: true
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
}
];
}
}
},
computed: {
...mapGetters(['searchParam', 'allLabelList', 'subLabelList'])
},
components: {},
methods: {
...mapActions(['setSubLabelList', 'setSearchParam']),
// 选择一级
selectLabel(index) {
this.allLabelList.forEach(element => {
element.checked = false;
});
this.allLabelList[index].checked = true;
let subLabelList = this.allLabelList[index].subList;
this.setSubLabelList(subLabelList);
},
// 选择二级
selectSubLabel(item, type) {
item.checked = !item.checked;
console.log('selectSubLabel', item);
// 如果被选中
if(item.checked) {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelList[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
// 将其它所有全部置为选中
this.allLabelList.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = true);
})
} else {
this.allLabelList[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
}
}
// 末被选中
} else {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelList[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
// 将其它所有全部置为选中
this.allLabelList.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = false);
})
} else {
this.allLabelList[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
}
}
}
// 无论哪种操作,都要重置各个“全部”按钮
this.allLabelList.forEach( (parent, index) => {
let needhecked = true, subList = parent.subList;
for(let i = 1; i < subList.length; i ++) {
if(!subList[i].checked) {
needhecked = false;
break;
}
}
this.allLabelList[index].subList[0].checked = needhecked;
})
this.$forceUpdate();
},
// 选中等级
selectLevel(index) {
this.courseLevel.forEach(element => {
element.checked = false;
});
this.courseLevel[index].checked = true;
},
// 重置按钮
resetCond() {
this.allLabelList.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.checked = true;
});
});
this.setSubLabelList(this.allLabelList[0].subList);
this.allLabelList[0].checked = true;
this.selectLevel(0);
},
search() {
let allSelectedLabel = [];
this.allLabelList[0].subList.forEach( (item, index) => {
index && item.checked && allSelectedLabel.push(item.id);
})
this.searchParam.labelIdList = allSelectedLabel;
this.courseLevel.forEach( item => {
if(item.checked) {
this.searchParam.grade = item.value;
}
})
this.searchParam.pageNo = 1;
this.setSearchParam(this.searchParam);
console.log(allSelectedLabel);
}
}
};
</script>
<style lang="less" scoped>
.custom-select-wrapper {
// width: 1090px;
user-select: none;
.department-label {
display: flex;
flex-direction: row;
height: 48px;
line-height: 48px;
border-bottom: 2px solid #449284;
border-radius: 6px 6px 0px 0px;
.item {
cursor: pointer;
position: relative;
z-index: 1;
display: inline-block;
padding: 0 22px;
font-size: 16px;
color: #666666;
// &::after {
// position: absolute;
// content: "";
// top: 14px;
// left: 0px;
// height: 20px;
// border-left: 1px solid #c7c8c9;
// }
&.checked {
color: #fff;
z-index: 3;
background: #449284;
}
&:first-child {
border-radius: 6px 0px 0px 0px;
}
}
.split {
flex-shrink: 0;
position: absolute;
top: 14px;
left: 0px;
z-index: 2;
display: inline-block;
height: 20px;
// width: 1px;
// background: #c7c8c9;
border-left: 1px solid #c7c8c9;
}
.item:nth-child(1) > .split,
.item.checked + .item > .split,
.split.acitve {
display: none;
}
}
}
.subject-level {
min-width: 1300px;
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
margin-bottom: -1px;
&.active {
border-bottom: 2px solid #449284;
}
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
color: #449284;
font-weight: 700;
// background: #449284;
}
}
}
}
.course-level {
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
color: #fff;
background: #449284;
}
}
}
}
.course-class {
display: flex;
flex-direction: row;
box-sizing: content-box;
padding: 10px 20px;
// padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dashed #e4e7ed;
.title {
height: 56px;
line-height: 56px;
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
height: 56px;
line-height: 56px;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
margin-right: 16px;
&.active {
color: #fff;
background: #449284;
}
}
}
.check-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 14px;
margin-right: 40px;
flex: 1;
.sub-item {
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
height: 30px;
line-height: 30px;
font-size: 14px;
color: #333333;
margin-right: 30px;
img {
width: 16px;
height: 16px;
margin-right: 5px;
}
&.active {
color: #449284;
}
}
}
.el-checkbox {
height: 30px;
line-height: 30px;
}
}
.button-wrapper {
display: flex;
flex-direction: row;
justify-content: flex-end;
margin-top: 20px;
// margin-right: 30px;
padding-right: 30px;
min-width: 1125px;
}
</style>
<template>
<div class="custom-over">
<div class="custom-select-wrapper">
<!-- 学科分类 -->
<div class="subject-level">
<span class="title">学科分类</span>
<span
v-for="(item, index) in allLabelListOrg"
:key="index"
class="item"
:class="{active: item.checked}"
@click="selectLabel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<!-- 课程分类 -->
<div class="course-class">
<div class="title">课程分类</div>
<div v-if="subLabelListOrg.length" class="item" @click="selectSubLabel(subLabelListOrg[0], 1)">
<span class="name" :class="{'active': subLabelListOrg[0].checked}">全部</span>
</div>
<ul class="check-list">
<li
class="sub-item"
:class="{'active': item.checked}"
v-for="(item, index) in subLabelListOrg.slice(1)"
:key="index"
@click="selectSubLabel(item, 2)"
>
<img v-show="item.checked" src="../../../assets/custom/icon/label-sel.png" alt />
<img v-show="!item.checked" src="../../../assets/custom/icon/label-sel-no.png" alt />
{{item.name}}
</li>
</ul>
<div class="right"></div>
</div>
<!-- 课程等级 -->
<div class="course-level">
<span class="title">课程等级</span>
<span
class="item"
v-for="(item, index) in courseLevel"
:key="index"
@click="selectLevel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<div class="button-wrapper">
<el-button class="add-button" plain size="small" @click="resetCond">重 置</el-button>
<el-button class="add-button" size="small" type="primary" @click="search">查 询</el-button>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
courseLevel: [
{ name: "全部", value: 0, checked: true },
{ name: "初级", value: 1, checked: false },
{ name: "中级", value: 2, checked: false },
{ name: "高级", value: 3, checked: false }
],
checkList: [431, 441]
};
},
props: {
dataList: {
type: Array,
default: () => {
return [
{
name: "全部",
checked: true
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
}
];
}
}
},
computed: {
...mapGetters(['searchParamOrg', 'allLabelListOrg', 'subLabelListOrg'])
},
components: {},
methods: {
...mapActions(['setSubLabelListOrg', 'setSearchParamOrg']),
// 选择一级
selectLabel(index) {
this.allLabelListOrg.forEach(element => {
element.checked = false;
});
this.allLabelListOrg[index].checked = true;
let subLabelListOrg = this.allLabelListOrg[index].subList;
this.setSubLabelListOrg(subLabelListOrg);
this.$forceUpdate();
},
// 选择二级
selectSubLabel(item, type) {
item.checked = !item.checked;
console.log('selectSubLabel', item);
// 如果被选中
if(item.checked) {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelListOrg[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
// 将其它所有全部置为选中
this.allLabelListOrg.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = true);
})
} else {
this.allLabelListOrg[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
}
}
// 末被选中
} else {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelListOrg[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
// 将其它所有全部置为选中
this.allLabelListOrg.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = false);
})
} else {
this.allLabelListOrg[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
}
}
}
// 无论哪种操作,都要重置各个“全部”按钮
this.allLabelListOrg.forEach( (parent, index) => {
let needhecked = true, subList = parent.subList;
for(let i = 1; i < subList.length; i ++) {
if(!subList[i].checked) {
needhecked = false;
break;
}
}
this.allLabelListOrg[index].subList[0].checked = needhecked;
})
this.$forceUpdate();
},
// 选中等级
selectLevel(index) {
this.courseLevel.forEach(element => {
element.checked = false;
});
this.courseLevel[index].checked = true;
},
// 重置按钮
resetCond() {
this.allLabelListOrg.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.checked = true;
});
});
this.setSubLabelListOrg(this.allLabelListOrg[0].subList);
this.allLabelListOrg[0].checked = true;
this.selectLevel(0);
},
search() {
let allSelectedLabelOrg = [];
this.allLabelListOrg[0].subList.forEach( (item, index) => {
index && item.checked && allSelectedLabelOrg.push(item.id);
})
this.searchParamOrg.labelIdList = allSelectedLabelOrg;
this.courseLevel.forEach( item => {
if(item.checked) {
this.searchParamOrg.grade = item.value;
}
})
this.searchParamOrg.pageNo = 1;
this.setSearchParamOrg(this.searchParamOrg);
console.log(allSelectedLabelOrg);
}
}
};
</script>
<style lang="less" scoped>
.custom-select-wrapper {
// width: 1090px;
user-select: none;
.department-label {
display: flex;
flex-direction: row;
height: 48px;
line-height: 48px;
border-bottom: 2px solid #449284;
border-radius: 6px 6px 0px 0px;
.item {
cursor: pointer;
position: relative;
z-index: 1;
display: inline-block;
padding: 0 22px;
font-size: 16px;
color: #666666;
// &::after {
// position: absolute;
// content: "";
// top: 14px;
// left: 0px;
// height: 20px;
// border-left: 1px solid #c7c8c9;
// }
&.checked {
color: #fff;
z-index: 3;
background: #449284;
}
&:first-child {
border-radius: 6px 0px 0px 0px;
}
}
.split {
flex-shrink: 0;
position: absolute;
top: 14px;
left: 0px;
z-index: 2;
display: inline-block;
height: 20px;
// width: 1px;
// background: #c7c8c9;
border-left: 1px solid #c7c8c9;
}
.item:nth-child(1) > .split,
.item.checked + .item > .split,
.split.acitve {
display: none;
}
}
}
.subject-level {
min-width: 1300px;
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
margin-bottom: -1px;
&.active {
border-bottom: 2px solid #449284;
}
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
color: #449284;
font-weight: 700;
// background: #449284;
}
}
}
}
.course-level {
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
color: #fff;
background: #449284;
}
}
}
}
.course-class {
display: flex;
flex-direction: row;
box-sizing: content-box;
padding: 10px 20px;
// padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dashed #e4e7ed;
.title {
height: 56px;
line-height: 56px;
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
height: 56px;
line-height: 56px;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
margin-right: 16px;
&.active {
color: #fff;
background: #449284;
}
}
}
.check-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 14px;
margin-right: 40px;
flex: 1;
.sub-item {
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
height: 30px;
line-height: 30px;
font-size: 14px;
color: #333333;
margin-right: 30px;
img {
width: 16px;
height: 16px;
margin-right: 5px;
}
&.active {
color: #449284;
}
}
}
.el-checkbox {
height: 30px;
line-height: 30px;
}
}
.button-wrapper {
display: flex;
flex-direction: row;
justify-content: flex-end;
margin-top: 20px;
// margin-right: 30px;
padding-right: 30px;
min-width: 1125px;
}
</style>
<template>
<div class="custom-over">
<div class="custom-select-wrapper">
<!-- 学科分类 -->
<div class="subject-level">
<span class="title">学科分类</span>
<span
v-for="(item, index) in allLabelListOrg"
:key="index"
class="item"
:class="{active: item.checked}"
@click="selectLabel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<!-- 课程分类 -->
<div class="course-class">
<div class="title">课程分类</div>
<div v-if="subLabelListOrg.length" class="item" @click="selectSubLabel(subLabelListOrg[0], 1)">
<span class="name" :class="{'active': subLabelListOrg[0].checked}">全部</span>
</div>
<ul class="check-list">
<li
class="sub-item"
:class="{'active': item.checked}"
v-for="(item, index) in subLabelListOrg.slice(1)"
:key="index"
@click="selectSubLabel(item, 2)"
>
<img v-show="item.checked" src="../../../assets/custom/icon/label-sel.png" alt />
<img v-show="!item.checked" src="../../../assets/custom/icon/label-sel-no.png" alt />
{{item.name}}
</li>
</ul>
<div class="right"></div>
</div>
<!-- 课程等级 -->
<div class="course-level">
<span class="title">课程等级</span>
<span
class="item"
v-for="(item, index) in courseLevel"
:key="index"
@click="selectLevel(index)"
>
<span class="name" :class="{active: item.checked}">{{item.name}}</span>
</span>
</div>
<div class="button-wrapper">
<el-button class="add-button" plain size="small" @click="resetCond">重 置</el-button>
<el-button class="add-button" size="small" type="primary" @click="search">查 询</el-button>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
courseLevel: [
{ name: "全部", value: 0, checked: true },
{ name: "初级", value: 1, checked: false },
{ name: "中级", value: 2, checked: false },
{ name: "高级", value: 3, checked: false }
],
checkList: [431, 441]
};
},
props: {
dataList: {
type: Array,
default: () => {
return [
{
name: "全部",
checked: true
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
},
{
name: "内科",
checked: false
},
{
name: "神经科",
checked: false
},
{
name: "肿瘤科",
checked: false
},
{
name: "妇产科",
checked: false
}
];
}
}
},
computed: {
...mapGetters(['searchParamOrg', 'allLabelListOrg', 'subLabelListOrg'])
},
components: {},
methods: {
...mapActions(['setSubLabelListOrg', 'setSearchParamOrg']),
// 选择一级
selectLabel(index) {
this.allLabelListOrg.forEach(element => {
element.checked = false;
});
this.allLabelListOrg[index].checked = true;
let subLabelListOrg = this.allLabelListOrg[index].subList;
this.setSubLabelListOrg(subLabelListOrg);
this.$forceUpdate();
},
// 选择二级
selectSubLabel(item, type) {
item.checked = !item.checked;
console.log('selectSubLabel', item);
// 如果被选中
if(item.checked) {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelListOrg[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
// 将其它所有全部置为选中
this.allLabelListOrg.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = true);
})
} else {
this.allLabelListOrg[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = true;
}
})
}
}
// 末被选中
} else {
// 是全部按钮 第一个全部:parentid-0
if(type == 1) {
let labelArr = item.id.split('-'), labelType = labelArr[0], labelIndex = labelArr[1] - 0;
labelArr = item.id.split('-');
if(labelType == 'parentid') {
// 将所有子项目选中
this.allLabelListOrg[0].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
// 将其它所有全部置为选中
this.allLabelListOrg.forEach( (item, index) => {
index != 0 && (item.subList[0].checked = false);
})
} else {
this.allLabelListOrg[labelIndex + 1].subList.forEach( (item, index) => {
if(index != 0) { // 第一个不用
item.checked = false;
}
})
}
}
}
// 无论哪种操作,都要重置各个“全部”按钮
this.allLabelListOrg.forEach( (parent, index) => {
let needhecked = true, subList = parent.subList;
for(let i = 1; i < subList.length; i ++) {
if(!subList[i].checked) {
needhecked = false;
break;
}
}
this.allLabelListOrg[index].subList[0].checked = needhecked;
})
this.$forceUpdate();
},
// 选中等级
selectLevel(index) {
this.courseLevel.forEach(element => {
element.checked = false;
});
this.courseLevel[index].checked = true;
},
// 重置按钮
resetCond() {
this.allLabelListOrg.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.checked = true;
});
});
this.setSubLabelListOrg(this.allLabelListOrg[0].subList);
this.allLabelListOrg[0].checked = true;
this.selectLevel(0);
},
search() {
let allSelectedLabelOrg = [];
this.allLabelListOrg[0].subList.forEach( (item, index) => {
index && item.checked && allSelectedLabelOrg.push(item.id);
})
this.searchParamOrg.labelIdList = allSelectedLabelOrg;
this.courseLevel.forEach( item => {
if(item.checked) {
this.searchParamOrg.grade = item.value;
}
})
this.searchParamOrg.pageNo = 1;
this.setSearchParamOrg(this.searchParamOrg);
console.log(allSelectedLabelOrg);
}
}
};
</script>
<style lang="less" scoped>
.custom-select-wrapper {
font-size: 14px;
// width: 1090px;
user-select: none;
.department-label {
display: flex;
flex-direction: row;
height: 48px;
line-height: 48px;
border-bottom: 2px solid #449284;
border-radius: 6px 6px 0px 0px;
.item {
cursor: pointer;
position: relative;
z-index: 1;
display: inline-block;
padding: 0 22px;
font-size: 16px;
color: #666666;
// &::after {
// position: absolute;
// content: "";
// top: 14px;
// left: 0px;
// height: 20px;
// border-left: 1px solid #c7c8c9;
// }
&.checked {
color: #fff;
z-index: 3;
background: #449284;
}
&:first-child {
border-radius: 6px 0px 0px 0px;
}
}
.split {
flex-shrink: 0;
position: absolute;
top: 14px;
left: 0px;
z-index: 2;
display: inline-block;
height: 20px;
// width: 1px;
// background: #c7c8c9;
border-left: 1px solid #c7c8c9;
}
.item:nth-child(1) > .split,
.item.checked + .item > .split,
.split.acitve {
display: none;
}
}
}
.subject-level {
width: 1300px;
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
border-bottom: 1px dashed #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
margin-bottom: -1px;
// &.active {
// border-bottom: 2px solid #449284;
// }
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
padding: 0 10px;
background: #449284;
color: #fff;
}
}
}
}
.course-level {
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
color: #fff;
background: #449284;
}
}
}
}
.course-class {
display: flex;
flex-direction: row;
box-sizing: content-box;
padding: 10px 20px;
// padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dashed #e4e7ed;
.title {
height: 56px;
line-height: 56px;
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
height: 56px;
line-height: 56px;
display: inline-block;
margin: 0 5px;
color: #333333;
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
margin-right: 16px;
&.active {
color: #fff;
background: #449284;
}
}
}
.check-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 14px;
margin-right: 40px;
flex: 1;
.sub-item {
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
height: 30px;
line-height: 30px;
font-size: 14px;
color: #333333;
margin-right: 30px;
img {
width: 16px;
height: 16px;
margin-right: 5px;
}
&.active {
color: #449284;
}
}
}
.el-checkbox {
height: 30px;
line-height: 30px;
}
}
.button-wrapper {
display: flex;
flex-direction: row;
justify-content: flex-end;
margin-top: 20px;
// margin-right: 30px;
padding-right: 30px;
min-width: 1125px;
}
</style>
<template> <template>
<div class="custom-over"> <div class="custom-over">
<!-- <div class="custom-select-wrapper" style="overflow:auto;">
<div class="department-label" style="width: 1200px;"> -->
<div class="custom-select-wrapper"> <div class="custom-select-wrapper">
<div class="department-label" style="min-width:1420px;"> <!-- 学科分类 -->
<div class="subject-level">
<span class="title">学科分类</span>
<span <span
v-for="(item, index) in allLabelList" v-for="(item, index) in allLabelList"
:key="index" :key="index"
class="item" class="item"
:class="{checked: item.checked}" :class="{active: item.checked}"
@click="selectLabel(index)" @click="selectLabel(index)"
> >
<span class="split" :class="{acitve: item.checked}"></span> <span class="name" :class="{active: item.checked}">{{item.name}}</span>
{{item.name}}
</span> </span>
</div> </div>
</div>
<div class="custom-select-wrapper">
<!-- 课程分类 --> <!-- 课程分类 -->
<div class="course-class"> <div class="course-class">
<div class="title">课程分类</div> <div class="title">课程分类</div>
...@@ -261,6 +258,7 @@ export default { ...@@ -261,6 +258,7 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.custom-select-wrapper { .custom-select-wrapper {
font-size: 14px;
// width: 1090px; // width: 1090px;
user-select: none; user-select: none;
.department-label { .department-label {
...@@ -276,7 +274,7 @@ export default { ...@@ -276,7 +274,7 @@ export default {
z-index: 1; z-index: 1;
display: inline-block; display: inline-block;
padding: 0 22px; padding: 0 22px;
font-size: 16px; font-size: 14px;
color: #666666; color: #666666;
// &::after { // &::after {
// position: absolute; // position: absolute;
...@@ -314,6 +312,47 @@ export default { ...@@ -314,6 +312,47 @@ export default {
} }
} }
} }
.subject-level {
min-width: 1300px;
display: flex;
flex-direction: row;
box-sizing: content-box;
height: 56px;
line-height: 56px;
padding-left: 20px;
border-bottom: 1px dashed #e4e7ed;
.title {
display: inline-block;
padding: 0 10px;
color: #999999;
}
.item {
cursor: pointer;
display: inline-block;
margin: 0 5px;
color: #333333;
margin-bottom: -1px;
// &.active {
// border-bottom: 2px solid #449284;
// }
.name {
height: 26px;
line-height: 26px;
display: inline-block;
padding: 0px 10px;
border-radius: 2px;
&.active {
padding: 0 10px;
background: #449284;
color: #fff;
// font-weight: 700;
// background: #449284;
}
}
}
}
.course-level { .course-level {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
...@@ -321,7 +360,6 @@ export default { ...@@ -321,7 +360,6 @@ export default {
height: 56px; height: 56px;
line-height: 56px; line-height: 56px;
padding-left: 20px; padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dotted #e4e7ed; border-bottom: 1px dotted #e4e7ed;
.title { .title {
display: inline-block; display: inline-block;
...@@ -353,7 +391,6 @@ export default { ...@@ -353,7 +391,6 @@ export default {
box-sizing: content-box; box-sizing: content-box;
padding: 10px 20px; padding: 10px 20px;
// padding-left: 20px; // padding-left: 20px;
// margin: 16px 0 16px 20px;
border-bottom: 1px dashed #e4e7ed; border-bottom: 1px dashed #e4e7ed;
.title { .title {
height: 56px; height: 56px;
......
<template> <template>
<div class="select-course-wrapper"> <div class="select-course-wrapper">
<div class="top-line"></div> <div class="top-line"></div>
<CourseSelect></CourseSelect> <el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公共课程" name="0">
<CourseSelect></CourseSelect>
</el-tab-pane>
<el-tab-pane label="机构课程" name="1">
<CourseSelectOrg></CourseSelectOrg>
</el-tab-pane>
</el-tabs>
<div class="top-line" style="margin-top: 20px;"></div> <div class="top-line" style="margin-top: 20px;"></div>
<CourseList></CourseList> <CourseList @showOrgCourse="showOrgCourse"></CourseList>
</div> </div>
</template> </template>
<script> <script>
import CourseSelect from '@/components/education/custom/course-select' import CourseSelect from '@/components/education/custom/course-select';
import CourseList from '@/components/education/custom/course-list' import CourseSelectOrg from '@/components/education/custom/course-select-org';
import CourseList from '@/components/education/custom/course-list';
import { mapActions, mapGetters } from 'vuex';
export default { export default {
data() { data() {
return { return {
activeName: '0'
} }
}, },
computed: {
...mapGetters(['kind'])
},
components: { components: {
CourseSelect, CourseSelect,
CourseSelectOrg,
CourseList, CourseList,
} },
methods: {
...mapActions(['setKind']),
handleClick() {
this.setKind(this.activeName);
},
showOrgCourse(courseId) {
this.$emit('showOrgCourse', courseId);
},
},
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.select-course-wrapper { .select-course-wrapper {
min-width: 1125px; // min-width: 1125px;
min-width: 1300px;
.top-line { .top-line {
// width: 120%; // width: 120%;
height: 10px; height: 10px;
background: rgb(240, 242, 245); background: rgb(240, 242, 245);
} }
} }
</style> </style>
...@@ -12,7 +12,14 @@ import ElementUI from 'element-ui'; ...@@ -12,7 +12,14 @@ import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'; import 'element-ui/lib/theme-chalk/index.css';
//引入滚动加载分页 //引入滚动加载分页
import infiniteScroll from 'vue-infinite-scroll' import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll) import VueVideoPlayer from 'vue-video-player';
import 'video.js/dist/video-js.css';
// import pdf from 'vue-pdf'
Vue.use(infiniteScroll);
Vue.use(VueVideoPlayer);
// Vue.use(pdf);
// 可调试 // 可调试
// Vue.config.devtools = true; // Vue.config.devtools = true;
// Vue.use(Logger, { prefix: new Date(), isDev: process.env.NODE_ENV === 'development', cLevel: 'debug' }) // Vue.use(Logger, { prefix: new Date(), isDev: process.env.NODE_ENV === 'development', cLevel: 'debug' })
......
...@@ -45,6 +45,9 @@ const templateEditor = r => require.ensure([], () => r(require('../views/educati ...@@ -45,6 +45,9 @@ const templateEditor = r => require.ensure([], () => r(require('../views/educati
const templateOpen = r => require.ensure([], () => r(require('../views/education/template-open.vue')), 'templateOpen') const templateOpen = r => require.ensure([], () => r(require('../views/education/template-open.vue')), 'templateOpen')
const eduRole = r => require.ensure([], () => r(require('../views/education/edu-role.vue')), 'edu-role') const eduRole = r => require.ensure([], () => r(require('../views/education/edu-role.vue')), 'edu-role')
const editCustom = r => require.ensure([], () => r(require('../views/education/edit-custom.vue')), 'templateOpen') const editCustom = r => require.ensure([], () => r(require('../views/education/edit-custom.vue')), 'templateOpen')
const externalResourceManage = r => require.ensure([], () => r(require('../views/education/external-resource-manage.vue')), 'external-resource-manage')
const auditCustomCourse = r => require.ensure([], () => r(require('../views/education/audit-custom-course.vue')), 'audit-custom-course')
const noticeEditor = r => require.ensure([], () => r(require('../views/education/notice-editor.vue')), 'notice-editor') const noticeEditor = r => require.ensure([], () => r(require('../views/education/notice-editor.vue')), 'notice-editor')
...@@ -222,7 +225,14 @@ export default [{ ...@@ -222,7 +225,14 @@ export default [{
{ {
path:'/edit-range', path:'/edit-range',
component: editRange component: editRange
},
{
path: '/external-resource-manage',
component: externalResourceManage,
},
{
path: '/audit-custom-course',
component: auditCustomCourse,
}, },
// { // {
// path: '/followup', // path: '/followup',
......
const customStore = { const customStore = {
// namespaced: true, // namespaced: true,
state: { state: {
kind: 0,
searchParam: { searchParam: {
kind: 0,
orderBy: 2,
dir: 1,
grade: 0,
pageNo: 1,
pageSize: 10,
labelIdList: []
},
searchParamOrg: {
kind: 1,
orderBy: 2, orderBy: 2,
dir: 1, dir: 1,
grade: 0, grade: 0,
...@@ -13,12 +24,20 @@ const customStore = { ...@@ -13,12 +24,20 @@ const customStore = {
courseList: [], courseList: [],
allLabelList: [], allLabelList: [],
subLabelList: [], subLabelList: [],
allLabelListOrg: [],
subLabelListOrg: [],
courseLimitCount: -1 // -1: 不限制; 其它值: 限制的个数 courseLimitCount: -1 // -1: 不限制; 其它值: 限制的个数
}, },
mutations: { mutations: {
SET_KIND: (state, kind) => {
state.kind = kind;
},
SET_SEARCH_PARAM: (state, searchParam) => { SET_SEARCH_PARAM: (state, searchParam) => {
state.searchParam = searchParam; state.searchParam = searchParam;
}, },
SET_SEARCH_PARAM_ORG: (state, searchParamOrg) => {
state.searchParamOrg = searchParamOrg;
},
SET_CART_LIST: (state, cartList) => { SET_CART_LIST: (state, cartList) => {
state.cartList = cartList; state.cartList = cartList;
}, },
...@@ -31,14 +50,26 @@ const customStore = { ...@@ -31,14 +50,26 @@ const customStore = {
SET_SUB_LABEL_LIST: (state, subLabelList) => { SET_SUB_LABEL_LIST: (state, subLabelList) => {
state.subLabelList = subLabelList; state.subLabelList = subLabelList;
}, },
SET_ALL_LABEL_LIST_ORG: (state, allLabelListOrg) => {
state.allLabelListOrg = allLabelListOrg;
},
SET_SUB_LABEL_LIST_ORG: (state, subLabelListOrg) => {
state.subLabelListOrg = subLabelListOrg;
},
SET_COURSE_LIMIT_COUNT: (state, courseLimitCount) => { SET_COURSE_LIMIT_COUNT: (state, courseLimitCount) => {
state.courseLimitCount = courseLimitCount; state.courseLimitCount = courseLimitCount;
}, },
}, },
actions: { actions: {
setKind({ commit }, kind) {
commit('SET_KIND', kind);
},
setSearchParam({ commit }, searchParam) { setSearchParam({ commit }, searchParam) {
commit('SET_SEARCH_PARAM', searchParam); commit('SET_SEARCH_PARAM', searchParam);
}, },
setSearchParamOrg({ commit }, searchParamOrg) {
commit('SET_SEARCH_PARAM_ORG', searchParamOrg);
},
setCartList({ commit }, cartList) { setCartList({ commit }, cartList) {
commit('SET_CART_LIST', cartList); commit('SET_CART_LIST', cartList);
}, },
...@@ -51,6 +82,12 @@ const customStore = { ...@@ -51,6 +82,12 @@ const customStore = {
setSubLabelList({ commit }, subLabelList) { setSubLabelList({ commit }, subLabelList) {
commit('SET_SUB_LABEL_LIST', subLabelList); commit('SET_SUB_LABEL_LIST', subLabelList);
}, },
setAllLabelListOrg({ commit }, allLabelListOrg) {
commit('SET_ALL_LABEL_LIST_ORG', allLabelListOrg);
},
setSubLabelListOrg({ commit }, subLabelListOrg) {
commit('SET_SUB_LABEL_LIST_ORG', subLabelListOrg);
},
setCourseLimitCount({ commit }, courseLimitCount) { setCourseLimitCount({ commit }, courseLimitCount) {
commit('SET_COURSE_LIMIT_COUNT', courseLimitCount); commit('SET_COURSE_LIMIT_COUNT', courseLimitCount);
}, },
......
const getters = { const getters = {
kind: state => state.customStore.kind,
searchParam: state => state.customStore.searchParam, searchParam: state => state.customStore.searchParam,
searchParamOrg: state => state.customStore.searchParamOrg,
cartList: state => state.customStore.cartList, cartList: state => state.customStore.cartList,
courseList: state => state.customStore.courseList, courseList: state => state.customStore.courseList,
allLabelList: state => state.customStore.allLabelList, allLabelList: state => state.customStore.allLabelList,
subLabelList: state => state.customStore.subLabelList, subLabelList: state => state.customStore.subLabelList,
allLabelListOrg: state => state.customStore.allLabelListOrg,
subLabelListOrg: state => state.customStore.subLabelListOrg,
courseLimitCount: state => state.customStore.courseLimitCount, courseLimitCount: state => state.customStore.courseLimitCount,
} }
......
...@@ -160,5 +160,80 @@ ...@@ -160,5 +160,80 @@
border-radius: 3px; border-radius: 3px;
} }
} }
.select-course-wrapper {
.el-tabs__item {
font-size: 16px;
}
.el-tabs__nav {
margin-left: 30px;
}
.el-tabs__item:hover {
color: #449284 !important;
}
.el-tabs__item.is-active {
color: #449284 !important;
}
.el-tabs__active-bar {
background: #449284 !important;
height: 3px !important;
border-radius: 2px !important;
}
}
.dialog-title-border {
.el-dialog__header {
margin: 0 20px;
padding: 20px 0px;
border-bottom: 1px solid #E4E7ED;
}
.el-dialog--center .el-dialog__body {
margin: 0;
padding: 0;
margin-right: 10px;
}
.el-dialog__body {
text-align: left; // 兼容360的布局
max-height: 380px;
margin: 0;
padding: 0;
overflow-y: auto;
overflow-x: hidden;
}
.dialog {
.el-dialog__body {
margin: 0;
padding: 25px 5px 30px;
border-top: 0px solid #E4E7ED;
}
}
.el-dialog__footer {
padding-top: 20px;
}
}
.dialog-title-border-old {
.el-dialog__header {
margin: 0 20px;
padding: 15px 0px;
border-bottom: 1px solid #E4E7ED;
}
.el-dialog__body {
margin: 0 20px;
padding: 25px 5px 30px;
// border-top: 1px solid #E4E7ED;
}
.dialog {
.el-dialog__body {
margin: 0;
padding: 25px 5px 30px;
border-top: 1px solid #E4E7ED;
}
}
}
.el-cascader .el-input .el-input__inner:focus, .el-cascader .el-input.is-focus .el-input__inner {
border-color: #449284 !important;
}
.el-input__inner:focus, .el-textarea__inner:focus {
border-color: #449284 !important;
}
...@@ -37,6 +37,11 @@ export const envConfig = { ...@@ -37,6 +37,11 @@ export const envConfig = {
excelUrl: 'https://dev-file.yunqueyi.com/File/template/portal/', excelUrl: 'https://dev-file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://dev-cms.yunqueyi.com/', cmsUrl: ' https://dev-cms.yunqueyi.com/',
// resource_url: "https://test-file.yunqueyi.com",
ossImgUrl: 'https://test-file.yunqueyi.com',
stsUrl: "https://dev-api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-test-huabei2",
endpoint: "oss-cn-beijing.aliyuncs.com",
}, },
dev: { dev: {
baseUrl: 'https://dev-sc.yunqueyi.com/', baseUrl: 'https://dev-sc.yunqueyi.com/',
...@@ -55,6 +60,10 @@ export const envConfig = { ...@@ -55,6 +60,10 @@ export const envConfig = {
excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/', excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://dev-cms.yunqueyi.com/', cmsUrl: ' https://dev-cms.yunqueyi.com/',
ossImgUrl: 'https://test-file.yunqueyi.com',
stsUrl: "https://dev-api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-test-huabei2",
endpoint: "oss-cn-beijing.aliyuncs.com",
}, },
test: { test: {
baseUrl: 'https://test1-sc.yunqueyi.com/', baseUrl: 'https://test1-sc.yunqueyi.com/',
...@@ -73,6 +82,10 @@ export const envConfig = { ...@@ -73,6 +82,10 @@ export const envConfig = {
excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/', excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://test1-cms.yunqueyi.com/', cmsUrl: ' https://test1-cms.yunqueyi.com/',
ossImgUrl: 'https://test-file.yunqueyi.com',
stsUrl: "https://test1-api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-test-huabei2",
endpoint: "oss-cn-beijing.aliyuncs.com",
}, },
test2: { test2: {
baseUrl: 'https://test2-work.yunqueyi.com/sc/', baseUrl: 'https://test2-work.yunqueyi.com/sc/',
...@@ -90,6 +103,10 @@ export const envConfig = { ...@@ -90,6 +103,10 @@ export const envConfig = {
excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/', excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://test2-cms.yunqueyi.com/', cmsUrl: ' https://test2-cms.yunqueyi.com/',
ossImgUrl: 'https://test-file.yunqueyi.com',
stsUrl: "https://test2-api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-test-huabei2",
endpoint: "oss-cn-beijing.aliyuncs.com",
}, },
uat: { uat: {
baseUrl: 'https://uat-sc.yunqueyi.com/', baseUrl: 'https://uat-sc.yunqueyi.com/',
...@@ -108,7 +125,11 @@ export const envConfig = { ...@@ -108,7 +125,11 @@ export const envConfig = {
excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/', excelUrl: 'https://test-file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://uat-cms.yunqueyi.com/', cmsUrl: ' https://uat-cms.yunqueyi.com/',
}, ossImgUrl: 'https://file.yunqueyi.com',
stsUrl: "https://uat-api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-pro",
endpoint: "oss-cn-shanghai.aliyuncs.com",
},
pro: { pro: {
baseUrl: 'https://sc.yunqueyi.com/', baseUrl: 'https://sc.yunqueyi.com/',
apiUrl: 'https://api.yunqueyi.com/', apiUrl: 'https://api.yunqueyi.com/',
...@@ -126,5 +147,9 @@ export const envConfig = { ...@@ -126,5 +147,9 @@ export const envConfig = {
excelUrl: 'https://file.yunqueyi.com/File/template/portal/', excelUrl: 'https://file.yunqueyi.com/File/template/portal/',
itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/', itemFileUrl: 'http://pica-test-huabei2.oss-cn-beijing.aliyuncs.com/File/template/portal/',
cmsUrl: ' https://cms.yunqueyi.com/', cmsUrl: ' https://cms.yunqueyi.com/',
} ossImgUrl: 'https://file.yunqueyi.com',
stsUrl: "https://api.yunqueyi.com/middle/oss/token/", //sts服务器
bucketName: "pica-pro",
endpoint: "oss-cn-shanghai.aliyuncs.com"
}
} }
...@@ -54,22 +54,14 @@ service.interceptors.request.use(config => { ...@@ -54,22 +54,14 @@ service.interceptors.request.use(config => {
} }
if( process.env.BUILD_ENV == "development" ){ // 本地开发环境qgit if( process.env.BUILD_ENV == "development" ){ // 本地开发环境qgit
// console.log('环境变量>>>> ', process.env.BUILD_ENV); // console.log('环境变量>>>> ', process.env.BUILD_ENV);
// config.headers['token'] = 'C503E1399DCD408992D8482B06747FD3'; config.headers['token'] = 'CD58A075AE324CB4944D7A41CE43D687';
config.headers['token'] = 'B27DC440F5A04807AEA8E31B2B58EDF8';
// config.headers['token'] = localStorage.getItem('storageToken') // config.headers['token'] = localStorage.getItem('storageToken')
}else{ }else{
config.headers['token'] = localStorage.getItem('storageToken') config.headers['token'] = localStorage.getItem('storageToken')
} }
config.headers['deviceInfo'] = JSON.stringify({ "app_channel": "", "app_mac": "", "app_uuid": "", "app_version": "", "device_brand": "", "device_ip": "", "device_model": "", "device_net": "", "device_ops": "", "resolution_wh": "", "system_level": "", "device_type": '10' }) config.headers['deviceInfo'] = JSON.stringify({ "app_channel": "", "app_mac": "", "app_uuid": "", "app_version": "", "device_brand": "", "device_ip": "", "device_model": "", "device_net": "", "device_ops": "", "resolution_wh": "", "system_level": "", "device_type": '10' })
} }
// if (config.data && config.data.setEntry) {
// config.headers['sysCode'] = config.data.sysCode || 10
// if(config.data.token){
// config.headers['token'] = config.data.token || '63C3FA92AF8A45A48B31EB7FD97B95EB'
// }
// config.headers['deviceInfo'] = JSON.stringify({ "app_channel": "", "app_mac": "", "app_uuid": "", "app_version": "", "device_brand": "", "device_ip": "", "device_model": "", "device_net": "", "device_ops": "", "resolution_wh": "", "system_level": "", "device_type": '10' })
// }
return config return config
}, error => { }, error => {
// logger.debug('service.interceptors.request: ', error) // logger.debug('service.interceptors.request: ', error)
......
...@@ -201,12 +201,36 @@ export function getWorkDomain(url) { ...@@ -201,12 +201,36 @@ export function getWorkDomain(url) {
return getConfigByEnvType('workApiSrc') + url return getConfigByEnvType('workApiSrc') + url
} }
/*
* OSS相关参数
*/
// 获取OSS域名
export function getOSSImgUrl(url = '') {
return getConfigByEnvType('ossImgUrl') + url
}
// 获取stsUrl域名
export function getSTSUrl() {
return getConfigByEnvType('stsUrl')
}
// 获取bucketName
export function getBucketName() {
return getConfigByEnvType('bucketName')
}
// 获取endpoint
export function getEndpoint() {
return getConfigByEnvType('endpoint')
}
// 根据不同环境,生成URL // 根据不同环境,生成URL
function getConfigByEnvType(urlType) { function getConfigByEnvType(urlType) {
return envConfig[process.env.BUILD_ENV][urlType] return envConfig[process.env.BUILD_ENV][urlType]
} }
// 获取report服务器域名地址 // 获取report服务器域名地址
export function getReportUrl(url) { export function getReportUrl(url) {
return getConfigByEnvType('reportUrl') + url return getConfigByEnvType('reportUrl') + url
...@@ -227,6 +251,8 @@ export function getCmsUrl(url) { ...@@ -227,6 +251,8 @@ export function getCmsUrl(url) {
return getConfigByEnvType('cmsUrl') + url return getConfigByEnvType('cmsUrl') + url
} }
// 转换时间格式 // 转换时间格式
export function convertTime(time, isToSlash = true) { export function convertTime(time, isToSlash = true) {
console.log('#########time', time); console.log('#########time', time);
...@@ -250,4 +276,36 @@ export function convertTime(time, isToSlash = true) { ...@@ -250,4 +276,36 @@ export function convertTime(time, isToSlash = true) {
} }
} }
} }
} }
\ No newline at end of file
//截位
export function subString(obj, int) {
if (isEmptyUtils(obj) || isEmptyUtils(int)) {
return "";
}
if (obj.length <= int) {
return obj;
} else {
obj = obj.substring(0, int);
}
return obj;
};
/**
* 校验对象是否为空
* */
export function isNotEmptyUtils(obj) {
if ("" == obj || null == obj || undefined == obj || "null" == obj) {
return false;
}
return true;
};
/**
* 校验对象是否为空
* */
export function isEmptyUtils (obj) {
return !isNotEmptyUtils(obj);
};
//api路径
import { isNotEmptyUtils } from "@/utils/index";
export default async(url = '', data = {}, type = 'POST', method = 'fetch',server='CONTENT') => {
type = type.toUpperCase();
// url = (server==='WECHAT'?wechatUrl:baseUrl) + url;
if (url.match("^http") == null){
url = localStorage.getItem("Url") + url;
}
console.log("完整url:",url)
if (type == 'GET' && data) {
let dataStr = ''; //数据拼接字符串
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&';
})
if (dataStr !== '') {
dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
url = url + '?' + dataStr;
// url = encodeURI(url + '?' + dataStr, true);
}
}
if (window.fetch && method == 'fetch') {
let requestConfig = {
credentials: 'include',
method: type,
// mode: "cors",
headers: {
// 'Access-Control-Allow-Origin': '*',
'Accept': '*',
'Content-Type': 'application/json',
// 'token': localStorage.getItem('token') || null, //固定传header:
// 'system_code': 'todo' //固定传header:系统编号
},
}
if (type == 'POST' || type === 'PUT' || type === 'PATCH' || type === 'DELETE' && data) {
Object.defineProperty(requestConfig, 'body', {
value: JSON.stringify(data)
})
}
try {
const response = await fetch(url, requestConfig);
const responseJson = await response.json();
return responseJson
} catch (error) {
throw new Error(error)
}
} else {
return new Promise((resolve, reject) => {
let requestObj;
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest();
} else {
requestObj = new ActiveXObject;
}
let sendData = '';
if (type == 'POST' || type == 'DELETE' || type == 'PUT') {
sendData = JSON.stringify(data);
}
requestObj.open(type, url, true);
requestObj.setRequestHeader("Content-Type", "application/json");
requestObj.send(sendData);
requestObj.onreadystatechange = () => {
if (requestObj.readyState == 4) {
if (requestObj.status == 200) {
let obj = requestObj.response
if (typeof obj !== 'object' && isNotEmptyUtils(obj)) {
obj = JSON.parse(obj);
}
resolve(obj)
} else {
reject(requestObj)
}
}
}
})
}
}
import {isEmptyUtils, isNotEmptyUtils, subString, getBucketName, getEndpoint, getSTSUrl} from "@/utils/index";
import fetch from './fetch.js';
/**
* OSS工具类
*/
// let OSS = require('ali-oss');
// 文件扩展名(图片以外的文件如果需要下载,需要在此处添加文件扩展名)
let contentTypeMap = new Map();
contentTypeMap.set("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel");
// PICA_DEV_APP.service('ossUtil', function ($rootScope, $q) {
//获取OSS客户端
// let bucketName = localStorage.getItem("bucketName");
// let endpoint = localStorage.getItem("endpoint");
// let bucketName = 'pica-test-huabei2';
// let endpoint = 'oss-cn-beijing.aliyuncs.com';
let bucketName = getBucketName();
let endpoint = getEndpoint();
console.log(bucketName, endpoint);
// //上传状态
// let status = false;
//
// /**
// * 文件上传状态
// * */
// export const isUpload = () => {
// return status;
// };
/**
* 获取OSS客户端对象
*
* @return {Object} client OSS客户端对象
* */
const doOSSAction = () => {
//sts服务器
// let stsUrl = localStorage.getItem("stsUrl") + "/" + localStorage.getItem("token");
// let stsUrl = 'https://dev-api.yunqueyi.com/middle/oss/token/' + localStorage.getItem("token");
// let stsUrl = 'https://dev-api.yunqueyi.com/middle/oss/token/D1AA498C1C1C4298B712B3678EF9BD07'
// let stsUrl = 'https://dev-api.yunqueyi.com/middle/oss/token/' + localStorage.getItem("token");
let stsUrl = getSTSUrl() + localStorage.getItem("token");
return new Promise(function (resolve, reject) {
fetch(stsUrl, {}, 'GET').then(function (result) {
let client = null;
if (isNotEmptyUtils(result) && result.StatusCode == "200") {
//获取client对象
client = new OSS.Wrapper({
accessKeyId: result.AccessKeyId,
accessKeySecret: result.AccessKeySecret,
stsToken: result.SecurityToken,
endpoint: endpoint,
bucket: bucketName
});
resolve(client);
console.log('STS临时授权成功');
} else {
reject(result);
console.error('STS临时授权失败222:', result);
}
}).catch(function (error) {
reject();
console.error('STS临时授权失败111:', error);
});
});
};
/**
* 获取OSS上的文件路径
*
* @param {String} [filePath] 文件路径
* @return {String} address 网络路径(默认有效时间半个小时)
* */
export const downloadOSSFile = (filePath) => {
let deferred = $q.defer();
if (isEmptyUtils(filePath)) {
return null;
}
let suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
// return client.signatureUrl(filePath);
//默认下载图片
let content_type = "image/png";
if (isNotEmptyUtils(suffix) && contentTypeMap.has(suffix)) {
content_type = contentTypeMap.get(suffix);
}
doOSSAction().then(function (client) {
let address = client.signatureUrl(filePath, {
expires: 1800,
response: {
'content-type': content_type,
'content-disposition': 'attachment'
}
});
deferred.resolve(address);
}
);
return deferred.promise;
};
/**
* 文件重命名
* @param {File} [file] 上传文件对象
* @param {String} [fileName] 指定文件名
* @param {String} [folder] 指定文件夹
* @return {String} fileName
* modified by Anndy Yang
*/
export const getFilePathForOSS = (file, fileName, folder) => {
if (isEmptyUtils(file)) {
return null;
}
//文件类型
let ext = file.type || 'image/jpeg';
//后缀名
let suffix = file.name.substring(file.name.lastIndexOf(".") + 1);
//若为空则从name中获取---对wps格式的文件获取不到file.type
if (isEmptyUtils(ext)) {
ext = suffix;
}
//获取当前日期对象
let date = new Date();
if (isEmptyUtils(fileName)) {
//重命名后的文件名
fileName = timeStamp(date) + "-" + subString(guid(), 8) + "." + suffix;
}
//文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
let filePath = ext + "/" + date.format('yyyy/MM/dd') + "/" + (isEmptyUtils(folder) ? "" : (folder + "/")) + fileName;
console.log(filePath);
return filePath;
};
/**
* oss上传
*
* @param {Vue} [self] vue实例
* @param {File} [file] 上传文件对象
* @param {String} [filePath] 文件全路径(文件路径 + 文件名)
* @param {String} [previewId] 显示图片的元素Id
* @param {String} [progressId] 显示上传进度的进度条id
* @param {Object} [imageAction] 图片操作
* @return {Promise} [dbFilePath] 存到数据库的文件路径
* */
export const ossUpload = (self, file, filePath, previewId, progressId, imageAction) => {
return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('OSS上传失败:非法参数');
reject();
}
//修改状态为上传
self.uploadStatus = true;
doOSSAction().then(function (client) {
//分片上传
client.multipartUpload(filePath, file, {
progress: function* (p) {
//获取百分比进度
self.uploadProgress = getPercentage(p, 2);
if (p == 1) {
//修改状态为非上传
self.uploadStatus = false;
}
console.log('uploadProgress: ' + self.uploadProgress);
},
headers: {
'Access-Control-Allow-Origin': '*'
}
}).then(function (r1) {
resolve('/' + filePath);
//修改状态为非上传
self.uploadStatus = false;
console.log('上传成功', r1);
// let address = getOSSFilePath(filePath, imageAction);
// //显示图片
// if (isNotEmptyUtils(previewId) && isNotEmptyUtils(address)) {
// console.log('图片路径: ' + address);
//
// let $img = $('<img>').attr("src", address);
// let obj = $("#" + previewId);
// obj.empty().append($img);
// obj.css('max-width', '100%');
// }
}).catch(function (err) {
reject(err);
//修改状态为非上传
self.uploadStatus = false;
console.error('OSS上传失败:', err);
// modalClick("提示", "上传失败!", "确定", function () {
// $('#model-modify').modal('hide');
// }, "", null);
});
}
);
});
};
/**
* OSS获取图片的参数模型
*
* @return {Object} [imageAction] 图片的参数模型
* */
export const getImageAction = () => {
return {
'resize': {
'width': null,
'height': null
},
'rotate': {
'angle': null //角度
}
};
};
//OSS获取图片的参数模型,转换为url路径参数
let imageActionParam = function (action) {
//有参数为true
let haveParamFlag = false;
let param = [];
if (isNotEmptyUtils(action)) {
// 缩放
if (isNotEmptyUtils(action.resize)) {
let width = isNotEmptyUtils(action.resize.width) ? ("w_" + action.resize.width) : null;
let height = isNotEmptyUtils(action.resize.height) ? ("h_" + action.resize.height) : null;
if (isNotEmptyUtils(width) || isNotEmptyUtils(height)) {
let resize = [];
if (isNotEmptyUtils(width)) {
resize.push(width);
}
if (isNotEmptyUtils(height)) {
resize.push(height);
}
param.push(['resize', resize]);
haveParamFlag = true;
}
}
//旋转
if (isNotEmptyUtils(action.rotate)) {
if (isNotEmptyUtils(action.rotate.angle)) {
param.push(['rotate', [action.rotate.angle]]);
haveParamFlag = true;
}
}
}
//如果有参数
if (haveParamFlag) {
let ParamStr = "?x-oss-process=image";
let paramMap = new Map(param);
//Map的回调函数参数依次为value、key和map本身:
paramMap.forEach(function (value, key, map) {
ParamStr = ParamStr + '/' + key;
for (let i = 0; i < value.length; i++) {
ParamStr = ParamStr + ',' + value[i];
}
});
return ParamStr;
}
return null;
};
/**
* 获取OSS上的文件路径
*
* @param {String} [filePath] 文件路径
* @param {String} [param] 参数字符串
* @return {String} address 网络路径
* */
export const getOSSFilePath = (filePath, param) => {
if (isEmptyUtils(filePath)) {
return null;
}
let paramStr = imageActionParam(param);
// http://bucket.<endpoint>/object?x-oss-process=image/action,parame_value
let str = "http://" + bucketName + "." + endpoint + "/" + filePath;
return isNotEmptyUtils(paramStr) ? (str + paramStr) : str;
};
// });
/**
* 获取全局唯一标识符(GUID,Globally Unique Identifier)
* @return {String} guid
*/
const guid = () => {
/**
* @return {String}
*/
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
};
/**
* 获取时间戳
* @param {Date} [date]日期对象,为空时,返回当前时间戳
* @return {String} timeStamp时间戳 格式:yyyyMMddhhmmssS
*/
const timeStamp = (date) => {
if (isEmptyUtils(date)) {
return new Date().format('yyyyMMddhhmmssS');
}
return date.format('yyyyMMddhhmmssS');
}
/**
* 保留precision位小数(四舍五入)后百分比显示
* @param {Number} [input] 要四舍五入的对象
* @param {Number} [precision] 要保留的小数位(默认2位)
* @return {Number} 例如:98.22
*/
const getPercentage = (input, precision) => {
if (isEmptyUtils(input)) {
return 0;
}
return Number((input * 100).toFixed(isEmptyUtils(precision) ? 2 : precision));
};
/**
* 从dataURL获取文件对象
*
* @param {String} [dataurl] 文件路径
* @param {String} [filename] 参数字符串
* @return {File} file 文件
* */
const dataURLtoFile = (dataurl, filename) => {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
};
import {isEmptyUtils, isNotEmptyUtils, subString} from "./utils";
import fetchQiniu from './fetch-qiniu.js';
import { getQiniuToken1, uploadVideo, uploadImg } from './index'
let fileApiUrl = getQiniuToken1()
//该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
let subscription = null;
//上传返回结果
let result = {
key: null,//文件保存在空间中的资源名
path: null,//保存到db的路径(不带域名)
fullPath: null,//文件网络路径(文件url)
size: null,//资源尺寸,单位为字节
name: null,//原始文件名
ext: null//上传资源的后缀名,通过自动检测的mimeType 或者原文件的后缀来获取
};
//上传状态
// var status = false;
//FIXME 请注意vue里面不要使用全局变量
let domain = uploadVideo() // 视频
let domain1 = uploadImg() // 图片
let errorCode = new Map([
[298,'部分操作执行成功'],
[400,'请求报文格式错误'],
[401,'认证授权失败'],
[403,'权限不足,拒绝访问。'],
[404,'资源不存在'],
[405,'请求方式错误'],
[406,'上传的数据 CRC32 校验错误'],
[413,'请求资源大小大于指定的最大值'],
[419,'用户账号被冻结'],
[478,'镜像回源失败'],
[502,'错误网关'],
[503,'服务端不可用'],
[504,'服务端操作超时'],
[573,'单个资源访问频率过高'],
[579,'上传成功但是回调失败'],
[599,'服务端操作失败'],
[608,'资源内容被修改'],
[612,'指定资源不存在或已被删除'],
[614,'目标资源已存在'],
[630,'已创建的空间数量达到上限,无法创建新空间。'],
[631,'指定空间不存在'],
[640,'调用列举资源(list)接口时,指定非法的marker参数。'],
[701,'在断点续上传过程中,后续上传接收地址不正确或ctx信息已过期。']
]);
let qiniuErrorCheck = function (code) {
errorCode.forEach(function (value, key, map) {
if (code === key){
console.error(key+':'+value)
}
})
}
//用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
let mimeTypeArray = null;
export const createFilePath = (file, fileName) => {
if (isEmptyUtils(file)) {
return null;
}
let arr = fileName.split('_');
if(arr.length != 4){
alert('上传视频文件名格式不正确');
return null;
}
let arr4 = arr[3].split('.');
//文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
let filePath = arr[0] + "/" + arr[1] + "/" + arr[2] + "_" + arr4[0] + '.'+arr4[1];
console.log(filePath);
return filePath;
};
/**
* 获取七牛上传凭证
*
* @return {Promise} token 七牛上传凭证
* */
const doQiniuAction1 = (fileType) => {
console.log('send---'+fileApiUrl);
return new Promise(function (resolve, reject) {
// if(isEmptyUtils(localStorage.getItem('qiniuToken'))){
fetchQiniu(fileApiUrl, {"fileType": fileType}, 'GET').then(function (result) {
let token = null;
if (isNotEmptyUtils(result) && result.code == "000000") {
token = result.data.qiniuToken;
resolve(token);
console.log('七牛临时授权成功');
localStorage.setItem('qiniuToken',token);
} else {
reject(result);
console.error('七牛临时授权失败:', result);
}
}).catch(function (error) {
reject();
console.error('七牛临时授权失败:', error);
});
// }else{
// console.log('从localStorage获取token:'+localStorage.getItem('qiniuToken'))
// resolve(localStorage.getItem('qiniuToken'));
// }
});
};
/**
*
* @param self
* @param file
* @param filePath
* @param previewId
* @param progressId
* @returns {Promise}
*/
export const qiniuUpload = (self, file, filePath, previewId, progressId) => {
// var deferred = $q.defer();
return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('七牛上传失败:非法参数');
reject();
}
let key = filePath ? filePath : getFilePath(file);
//修改状态为上传
self.qiniuUploadStatus = true;
// let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
doQiniuAction().then(function (token) {
let putExtra = {
fname: file.name, //原文件名
params: {}, //用来放置自定义变量
mimeType: mimeTypeArray || null //null || array,用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
};
let config = {
useCdnDomain: true, //表示是否使用 cdn 加速域名,为布尔值,true 表示使用,默认为 false。
region: null //选择上传域名区域;当为 null 或 undefined 时,自动分析上传域名区域
};
/*
* qiniu.upload 返回一个 observable 对象用来控制上传行为,observable 对像通过 subscribe 方法可以被 observer 所订阅,
* 订阅同时会开始触发上传,同时返回一个 subscription 对象,该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
* */
let observable = qiniu.upload(file, key, token, putExtra, config);
/**
* 接收上传进度信息,res 参数是一个带有 total 字段的 object,包含loaded、total、percent三个属性,提供上传进
* total.loaded: number,已上传大小,单位为字节。
* total.total: number,本次上传的总量控制信息,单位为字节,注意这里的 total 跟文件大小并不一致。
* total.percent: number,当前上传进度,范围:0~100
* */
let next = function (res) {
//res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}
//获取百分比进度
let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress);
console.log('Progress1: ' + progress);
//如果有进度条
/*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId);
//开始上传时,显示进度条
if (isNotEmptyUtils(obj.parent())) {
//修改状态为上传
// status = true;
self.qiniuUploadStatus = true;
obj.parent().removeClass("hidden");
obj.fadeIn("fast");
}
obj.css("width", progress + '%');
obj.text(progress + '%');
//上传完成,2秒后淡出进度条
if (progress === "100.00") {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = true;
obj.fadeOut(2000);
}
}*/
};
/**
* 接收上传完成后的后端返回信息,res 参数为一个 object, 为上传成功后后端返回的信息
* ,具体返回结构取决于后端sdk的配置,可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
* */
let complete = function (res) {
console.log("七牛上传完成");
setTimeout(function(){
result.key = res.key;
result.path = '/' + res.key;
result.fullPath = domain + '/' + res.key + '?v=' + new Date().getTime();
result.size = res.fsize;
result.name = res.fname ;
result.ext = res.ext;
// deferred.resolve(result);
resolve(result);
// self.model.qCloudUrl = result.fullPath;
// $("#introVideoLecture").attr("src", self.model.qCloudUrl);
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false;
if (isNotEmptyUtils(previewId)) {
let address = domain + result.path;
console.log('文件路径: ' + address);
//显示图片
let $img = $('<img>').attr("src", address);
let obj = $("#" + previewId);
obj.empty().append($img);
obj.css('max-width', '100%');
}
},2000);
};
/**
* 上传错误后触发,当不是 xhr 请求错误时,会把当前错误产生原因直接抛出,诸如 JSON 解析异常等;当产生 xhr 请求错误时,参数 err 为一个包含 code、message、isRequestError 三个属性的 object:
* err.isRequestError: 用于区分是否 xhr 请求错误;当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时,该参数为 true;否则为 undefined 。
* err.reqId: string,xhr请求错误的 X-Reqid。
* err.code: number,请求错误状态码,只有在 err.isRequestError 为 true 的时候才有效,可查阅码值对应说明。
* err.message: string,错误信息,包含错误码,当后端返回提示信息时也会有相应的错误信息。
* */
let error = function (err) {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false
localStorage.removeItem('qiniuToken');
console.log("七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses");
//输出简略错误信息
if (err.isRequestError){
qiniuErrorCheck(err.code)
}else {
console.error(err);
}
/*modalClick("提示", "上传失败!", "确定", function () {
$('#model-modify').modal('hide');
}, "", null);*/
// deferred.reject(new Error('七牛上传失败'));
// return deferred.promise;
return reject(new Error('七牛上传失败'));
};
// 上传开始
subscription = observable.subscribe(next, error, complete);
});
console.log(22222);
window.QNSubscription = subscription;
// return deferred.promise;
});
};
/**
* 获取时间戳
* @param {Date} [date]日期对象,为空时,返回当前时间戳
* @return {String} timeStamp时间戳 格式:yyyyMMddhhmmssS
*/
const timeStamp = (date) => {
if (isEmptyUtils(date)) {
return new Date().format('yyyyMMddhhmmssS');
}
return date.format('yyyyMMddhhmmssS');
}
/**
* 获取全局唯一标识符(GUID,Globally Unique Identifier)
* @return {String} guid
*/
const guid = () => {
/**
* @return {String}
*/
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
};
/**
* 文件重命名--七牛图片 2018 11
* @param {File} [file] 上传文件对象
* @param {String} [fileName] 指定文件名
* @param {String} [folder] 指定文件夹
* @return {String} fileName
*/
export const getFilePath = (file,fileName,folder) => {
if (isEmptyUtils(file)) {
return null;
}
//文件类型
var ext = file.type;
//后缀名
var suffix = file.name.substring(file.name.lastIndexOf(".") + 1);
//若为空则从name中获取---对wps格式的文件获取不到file.type
if (isEmptyUtils(ext)) {
ext = suffix;
}
//获取当前日期对象
var date = new Date();
if (isEmptyUtils(fileName)) {
//重命名后的文件名
fileName = timeStamp(date) + "-" + subString(guid(), 8) + "." + suffix;
}
//文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
// var filePath = ext + "/" + date.format('yyyy/MM/dd') + "/" + (isEmptyUtils(folder) ? "" : (folder + "/")) + fileName;
//var filePath = ext + "/" + "common/" + file.name.split('.')[0] + '-' + timeStamp(date) + "." + suffix;
var filePath = ext + "/" + "protal/project/" + timeStamp(date) + "." + suffix;
console.log('filePath==============',filePath);
return filePath;
}
/**
*七牛上传图片、视频、文件 2018 11 hws
* @param self
* @param file
* @param filePath
* @param previewId
* @param progressId
* @param fileType 1--图片和文件 空为视频
* @returns {Promise}
*/
export const doUpload = (self, file, filePath, previewId, progressId, fileType) => {
// var deferred = $q.defer();
return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('七牛上传失败:非法参数');
reject();
}
let key = filePath ? filePath : getFilePath(file);
//修改状态为上传
self.qiniuUploadStatus = true;
// let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
doQiniuAction1(fileType).then(function (token) {
let putExtra = {
fname: file.name, //原文件名
params: {}, //用来放置自定义变量
mimeType: mimeTypeArray || null //null || array,用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
};
let config = {
useCdnDomain: true, //表示是否使用 cdn 加速域名,为布尔值,true 表示使用,默认为 false。
region: null //选择上传域名区域;当为 null 或 undefined 时,自动分析上传域名区域
};
/*
* qiniu.upload 返回一个 observable 对象用来控制上传行为,observable 对像通过 subscribe 方法可以被 observer 所订阅,
* 订阅同时会开始触发上传,同时返回一个 subscription 对象,该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
* */
let observable = qiniu.upload(file, key, token, putExtra, config);
/**
* 接收上传进度信息,res 参数是一个带有 total 字段的 object,包含loaded、total、percent三个属性,提供上传进
* total.loaded: number,已上传大小,单位为字节。
* total.total: number,本次上传的总量控制信息,单位为字节,注意这里的 total 跟文件大小并不一致。
* total.percent: number,当前上传进度,范围:0~100
* */
let next = function (res) {
//res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}
//获取百分比进度
let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress);
if(progressId == 'uploadProgress1') {
self.uploadProgress1 = Number(progress);
}
if(progressId == 'uploadProgress2') {
self.uploadProgress2 = Number(progress);
}
console.log('Progress2: ' + progress);
//如果有进度条
/*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId);
//开始上传时,显示进度条
if (isNotEmptyUtils(obj.parent())) {
//修改状态为上传
// status = true;
self.qiniuUploadStatus = true;
obj.parent().removeClass("hidden");
obj.fadeIn("fast");
}
obj.css("width", progress + '%');
obj.text(progress + '%');
//上传完成,2秒后淡出进度条
if (progress === "100.00") {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = true;
obj.fadeOut(2000);
}
}*/
};
/**
* 接收上传完成后的后端返回信息,res 参数为一个 object, 为上传成功后后端返回的信息
* ,具体返回结构取决于后端sdk的配置,可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
* */
let complete = function (res) {
console.log("七牛上传完成");
setTimeout(function(){
result.key = res.key;
result.path = '/' + res.key;
// result.fullPath = domain + '/' + res.key + '_' + new Date().getTime();
if(!fileType) { // 图片 文件
console.log('---domain-------',domain)
result.fullPath = domain + '/' + res.key;
}else{ // 视频
console.log('----domain1------',domain1)
result.fullPath = domain1 + '/' + res.key;
}
result.size = res.fsize;
result.name = res.fname ;
result.ext = res.ext;
// deferred.resolve(result);
resolve(result);
// self.model.qCloudUrl = result.fullPath;
// $("#introVideoLecture").attr("src", self.model.qCloudUrl);
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false;
},500);
};
/**
* 上传错误后触发,当不是 xhr 请求错误时,会把当前错误产生原因直接抛出,诸如 JSON 解析异常等;当产生 xhr 请求错误时,参数 err 为一个包含 code、message、isRequestError 三个属性的 object:
* err.isRequestError: 用于区分是否 xhr 请求错误;当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时,该参数为 true;否则为 undefined 。
* err.reqId: string,xhr请求错误的 X-Reqid。
* err.code: number,请求错误状态码,只有在 err.isRequestError 为 true 的时候才有效,可查阅码值对应说明。
* err.message: string,错误信息,包含错误码,当后端返回提示信息时也会有相应的错误信息。
* */
let error = function (err) {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false
localStorage.removeItem('qiniuToken');
console.log("七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses");
//输出简略错误信息
if (err.isRequestError){
qiniuErrorCheck(err.code)
}else {
console.error(err);
}
return reject(new Error('七牛上传失败'));
};
// 上传开始
subscription = observable.subscribe(next, error, complete);
});
// 保存到全局对象
window.QNSubscription = subscription;
// return deferred.promise;
});
};
import {isEmptyUtils, isNotEmptyUtils, subString} from "./utils";
import fetchQiniu from './fetch-qiniu.js';
import { getQiniuToken1, uploadVideo, uploadImg } from './index'
let fileApiUrl = getQiniuToken1()
//该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
let subscription = null;
//上传返回结果
let result = {
key: null,//文件保存在空间中的资源名
path: null,//保存到db的路径(不带域名)
fullPath: null,//文件网络路径(文件url)
size: null,//资源尺寸,单位为字节
name: null,//原始文件名
ext: null//上传资源的后缀名,通过自动检测的mimeType 或者原文件的后缀来获取
};
//上传状态
// var status = false;
//FIXME 请注意vue里面不要使用全局变量
let domain = uploadVideo() // 视频
let domain1 = uploadImg() // 图片
let errorCode = new Map([
[298,'部分操作执行成功'],
[400,'请求报文格式错误'],
[401,'认证授权失败'],
[403,'权限不足,拒绝访问。'],
[404,'资源不存在'],
[405,'请求方式错误'],
[406,'上传的数据 CRC32 校验错误'],
[413,'请求资源大小大于指定的最大值'],
[419,'用户账号被冻结'],
[478,'镜像回源失败'],
[502,'错误网关'],
[503,'服务端不可用'],
[504,'服务端操作超时'],
[573,'单个资源访问频率过高'],
[579,'上传成功但是回调失败'],
[599,'服务端操作失败'],
[608,'资源内容被修改'],
[612,'指定资源不存在或已被删除'],
[614,'目标资源已存在'],
[630,'已创建的空间数量达到上限,无法创建新空间。'],
[631,'指定空间不存在'],
[640,'调用列举资源(list)接口时,指定非法的marker参数。'],
[701,'在断点续上传过程中,后续上传接收地址不正确或ctx信息已过期。']
]);
let qiniuErrorCheck = function (code) {
errorCode.forEach(function (value, key, map) {
if (code === key){
console.error(key+':'+value)
}
})
}
//用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
let mimeTypeArray = null;
export const createFilePath = (file, fileName) => {
if (isEmptyUtils(file)) {
return null;
}
let arr = fileName.split('_');
if(arr.length != 4){
alert('上传视频文件名格式不正确');
return null;
}
let arr4 = arr[3].split('.');
//文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
let filePath = arr[0] + "/" + arr[1] + "/" + arr[2] + "_" + arr4[0] + '.'+arr4[1];
console.log(filePath);
return filePath;
};
/**
* 获取七牛上传凭证
*
* @return {Promise} token 七牛上传凭证
* */
const doQiniuAction1 = (fileType) => {
console.log('send---'+fileApiUrl);
return new Promise(function (resolve, reject) {
// if(isEmptyUtils(localStorage.getItem('qiniuToken'))){
fetchQiniu(fileApiUrl, {"fileType": fileType}, 'GET').then(function (result) {
let token = null;
if (isNotEmptyUtils(result) && result.code == "000000") {
token = result.data.qiniuToken;
resolve(token);
console.log('七牛临时授权成功');
localStorage.setItem('qiniuToken',token);
} else {
reject(result);
console.error('七牛临时授权失败:', result);
}
}).catch(function (error) {
reject();
console.error('七牛临时授权失败:', error);
});
// }else{
// console.log('从localStorage获取token:'+localStorage.getItem('qiniuToken'))
// resolve(localStorage.getItem('qiniuToken'));
// }
});
};
/**
*
* @param self
* @param file
* @param filePath
* @param previewId
* @param progressId
* @returns {Promise}
*/
export const qiniuUpload = (self, file, filePath, previewId, progressId) => {
// var deferred = $q.defer();
return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('七牛上传失败:非法参数');
reject();
}
let key = filePath ? filePath : getFilePath(file);
//修改状态为上传
self.qiniuUploadStatus = true;
// let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
doQiniuAction().then(function (token) {
let putExtra = {
fname: file.name, //原文件名
params: {}, //用来放置自定义变量
mimeType: mimeTypeArray || null //null || array,用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
};
let config = {
useCdnDomain: true, //表示是否使用 cdn 加速域名,为布尔值,true 表示使用,默认为 false。
region: null //选择上传域名区域;当为 null 或 undefined 时,自动分析上传域名区域
};
/*
* qiniu.upload 返回一个 observable 对象用来控制上传行为,observable 对像通过 subscribe 方法可以被 observer 所订阅,
* 订阅同时会开始触发上传,同时返回一个 subscription 对象,该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
* */
let observable = qiniu.upload(file, key, token, putExtra, config);
/**
* 接收上传进度信息,res 参数是一个带有 total 字段的 object,包含loaded、total、percent三个属性,提供上传进
* total.loaded: number,已上传大小,单位为字节。
* total.total: number,本次上传的总量控制信息,单位为字节,注意这里的 total 跟文件大小并不一致。
* total.percent: number,当前上传进度,范围:0~100
* */
let next = function (res) {
//res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}
//获取百分比进度
let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress);
console.log('Progress: ' + progress);
//如果有进度条
/*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId);
//开始上传时,显示进度条
if (isNotEmptyUtils(obj.parent())) {
//修改状态为上传
// status = true;
self.qiniuUploadStatus = true;
obj.parent().removeClass("hidden");
obj.fadeIn("fast");
}
obj.css("width", progress + '%');
obj.text(progress + '%');
//上传完成,2秒后淡出进度条
if (progress === "100.00") {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = true;
obj.fadeOut(2000);
}
}*/
};
/**
* 接收上传完成后的后端返回信息,res 参数为一个 object, 为上传成功后后端返回的信息
* ,具体返回结构取决于后端sdk的配置,可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
* */
let complete = function (res) {
console.log("七牛上传完成");
setTimeout(function(){
result.key = res.key;
result.path = '/' + res.key;
result.fullPath = domain + '/' + res.key + '?v=' + new Date().getTime();
result.size = res.fsize;
result.name = res.fname ;
result.ext = res.ext;
// deferred.resolve(result);
resolve(result);
// self.model.qCloudUrl = result.fullPath;
// $("#introVideoLecture").attr("src", self.model.qCloudUrl);
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false;
if (isNotEmptyUtils(previewId)) {
let address = domain + result.path;
console.log('文件路径: ' + address);
//显示图片
let $img = $('<img>').attr("src", address);
let obj = $("#" + previewId);
obj.empty().append($img);
obj.css('max-width', '100%');
}
},2000);
};
/**
* 上传错误后触发,当不是 xhr 请求错误时,会把当前错误产生原因直接抛出,诸如 JSON 解析异常等;当产生 xhr 请求错误时,参数 err 为一个包含 code、message、isRequestError 三个属性的 object:
* err.isRequestError: 用于区分是否 xhr 请求错误;当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时,该参数为 true;否则为 undefined 。
* err.reqId: string,xhr请求错误的 X-Reqid。
* err.code: number,请求错误状态码,只有在 err.isRequestError 为 true 的时候才有效,可查阅码值对应说明。
* err.message: string,错误信息,包含错误码,当后端返回提示信息时也会有相应的错误信息。
* */
let error = function (err) {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false
localStorage.removeItem('qiniuToken');
console.log("七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses");
//输出简略错误信息
if (err.isRequestError){
qiniuErrorCheck(err.code)
}else {
console.error(err);
}
/*modalClick("提示", "上传失败!", "确定", function () {
$('#model-modify').modal('hide');
}, "", null);*/
// deferred.reject(new Error('七牛上传失败'));
// return deferred.promise;
return reject(new Error('七牛上传失败'));
};
// 上传开始
subscription = observable.subscribe(next, error, complete);
});
// return deferred.promise;
});
};
/**
* 获取时间戳
* @param {Date} [date]日期对象,为空时,返回当前时间戳
* @return {String} timeStamp时间戳 格式:yyyyMMddhhmmssS
*/
const timeStamp = (date) => {
if (isEmptyUtils(date)) {
return new Date().format('yyyyMMddhhmmssS');
}
return date.format('yyyyMMddhhmmssS');
}
/**
* 获取全局唯一标识符(GUID,Globally Unique Identifier)
* @return {String} guid
*/
const guid = () => {
/**
* @return {String}
*/
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
};
/**
* 文件重命名--七牛图片 2018 11
* @param {File} [file] 上传文件对象
* @param {String} [fileName] 指定文件名
* @param {String} [folder] 指定文件夹
* @return {String} fileName
*/
export const getFilePath = (file,fileName,folder) => {
if (isEmptyUtils(file)) {
return null;
}
//文件类型
var ext = file.type;
//后缀名
var suffix = file.name.substring(file.name.lastIndexOf(".") + 1);
//若为空则从name中获取---对wps格式的文件获取不到file.type
if (isEmptyUtils(ext)) {
ext = suffix;
}
//获取当前日期对象
var date = new Date();
if (isEmptyUtils(fileName)) {
//重命名后的文件名
fileName = timeStamp(date) + "-" + subString(guid(), 8) + "." + suffix;
}
//文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
// var filePath = ext + "/" + date.format('yyyy/MM/dd') + "/" + (isEmptyUtils(folder) ? "" : (folder + "/")) + fileName;
//var filePath = ext + "/" + "common/" + file.name.split('.')[0] + '-' + timeStamp(date) + "." + suffix;
var filePath = ext + "/" + "protal/project/" + timeStamp(date) + "." + suffix;
console.log('filePath==============',filePath);
return filePath;
}
/**
*七牛上传图片、视频、文件 2018 11 hws
* @param self
* @param file
* @param filePath
* @param previewId
* @param progressId
* @param fileType 1--图片和文件 空为视频
* @returns {Promise}
*/
export const doUpload = (self,file, filePath, previewId,progressId, fileType) => {
// var deferred = $q.defer();
return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('七牛上传失败:非法参数');
reject();
}
let key = filePath ? filePath : getFilePath(file);
//修改状态为上传
self.qiniuUploadStatus = true;
// let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
doQiniuAction1(fileType).then(function (token) {
let putExtra = {
fname: file.name, //原文件名
params: {}, //用来放置自定义变量
mimeType: mimeTypeArray || null //null || array,用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
};
let config = {
useCdnDomain: true, //表示是否使用 cdn 加速域名,为布尔值,true 表示使用,默认为 false。
region: null //选择上传域名区域;当为 null 或 undefined 时,自动分析上传域名区域
};
/*
* qiniu.upload 返回一个 observable 对象用来控制上传行为,observable 对像通过 subscribe 方法可以被 observer 所订阅,
* 订阅同时会开始触发上传,同时返回一个 subscription 对象,该对象有一个 unsubscribe 方法取消订阅,同时终止上传行为。
* */
let observable = qiniu.upload(file, key, token, putExtra, config);
/**
* 接收上传进度信息,res 参数是一个带有 total 字段的 object,包含loaded、total、percent三个属性,提供上传进
* total.loaded: number,已上传大小,单位为字节。
* total.total: number,本次上传的总量控制信息,单位为字节,注意这里的 total 跟文件大小并不一致。
* total.percent: number,当前上传进度,范围:0~100
* */
let next = function (res) {
//res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}
//获取百分比进度
let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress);
if(progressId == 'uploadProgress1') {
self.uploadProgress1 = Number(progress);
}
if(progressId == 'uploadProgress2') {
self.uploadProgress2 = Number(progress);
}
console.log('Progress: ' + progress);
//如果有进度条
/*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId);
//开始上传时,显示进度条
if (isNotEmptyUtils(obj.parent())) {
//修改状态为上传
// status = true;
self.qiniuUploadStatus = true;
obj.parent().removeClass("hidden");
obj.fadeIn("fast");
}
obj.css("width", progress + '%');
obj.text(progress + '%');
//上传完成,2秒后淡出进度条
if (progress === "100.00") {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = true;
obj.fadeOut(2000);
}
}*/
};
/**
* 接收上传完成后的后端返回信息,res 参数为一个 object, 为上传成功后后端返回的信息
* ,具体返回结构取决于后端sdk的配置,可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
* */
let complete = function (res) {
console.log("七牛上传完成");
setTimeout(function(){
result.key = res.key;
result.path = '/' + res.key;
// result.fullPath = domain + '/' + res.key + '_' + new Date().getTime();
if(!fileType) { // 图片 文件
console.log('---domain-------',domain)
result.fullPath = domain + '/' + res.key;
}else{ // 视频
console.log('----domain1------',domain1)
result.fullPath = domain1 + '/' + res.key;
}
result.size = res.fsize;
result.name = res.fname ;
result.ext = res.ext;
// deferred.resolve(result);
resolve(result);
// self.model.qCloudUrl = result.fullPath;
// $("#introVideoLecture").attr("src", self.model.qCloudUrl);
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false;
// if (isNotEmptyUtils(previewId)) {
// let address = domain + result.path;
// console.log('文件路径: ' + address);
// //显示图片
// let uplodImg = $('<img>').attr("src", address);
// let obj = $("#" + previewId);
// obj.empty().append(uplodImg);
// obj.css('max-width', '100%');
// }
},500);
};
/**
* 上传错误后触发,当不是 xhr 请求错误时,会把当前错误产生原因直接抛出,诸如 JSON 解析异常等;当产生 xhr 请求错误时,参数 err 为一个包含 code、message、isRequestError 三个属性的 object:
* err.isRequestError: 用于区分是否 xhr 请求错误;当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时,该参数为 true;否则为 undefined 。
* err.reqId: string,xhr请求错误的 X-Reqid。
* err.code: number,请求错误状态码,只有在 err.isRequestError 为 true 的时候才有效,可查阅码值对应说明。
* err.message: string,错误信息,包含错误码,当后端返回提示信息时也会有相应的错误信息。
* */
let error = function (err) {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false
localStorage.removeItem('qiniuToken');
console.log("七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses");
//输出简略错误信息
if (err.isRequestError){
qiniuErrorCheck(err.code)
}else {
console.error(err);
}
/*modalClick("提示", "上传失败!", "确定", function () {
$('#model-modify').modal('hide');
}, "", null);*/
// deferred.reject(new Error('七牛上传失败'));
// return deferred.promise;
return reject(new Error('七牛上传失败'));
};
// 上传开始
subscription = observable.subscribe(next, error, complete);
});
// return deferred.promise;
});
};
...@@ -166,7 +166,7 @@ export const qiniuUpload = (self, file, filePath, previewId, progressId) => { ...@@ -166,7 +166,7 @@ export const qiniuUpload = (self, file, filePath, previewId, progressId) => {
//获取百分比进度 //获取百分比进度
let progress = res.total.percent.toFixed(2); let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress); self.uploadProgress = Number(progress);
console.log('Progress: ' + progress); console.log('Progress1: ' + progress);
//如果有进度条 //如果有进度条
/*if (isNotEmptyUtils(progressId)) { /*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId); let obj = $("#" + progressId);
...@@ -338,24 +338,16 @@ export const getFilePath = (file,fileName,folder) => { ...@@ -338,24 +338,16 @@ export const getFilePath = (file,fileName,folder) => {
* @param fileType 1--图片和文件 空为视频 * @param fileType 1--图片和文件 空为视频
* @returns {Promise} * @returns {Promise}
*/ */
export const doUpload = (self,file, filePath, previewId,progressId, fileType) => { export const doUpload = (self, file, filePath, previewId, progressId, fileType) => {
// var deferred = $q.defer();
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
if (isEmptyUtils(file) || isEmptyUtils(filePath)) { if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
console.error('七牛上传失败:非法参数'); console.error('七牛上传失败:非法参数');
reject(); reject();
} }
let key = filePath ? filePath : getFilePath(file); let key = filePath ? filePath : getFilePath(file);
//修改状态为上传 //修改状态为上传
self.qiniuUploadStatus = true; self.qiniuUploadStatus = true;
// let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
doQiniuAction1(fileType).then(function (token) { doQiniuAction1(fileType).then(function (token) {
let putExtra = { let putExtra = {
fname: file.name, //原文件名 fname: file.name, //原文件名
...@@ -386,34 +378,14 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) => ...@@ -386,34 +378,14 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) =>
//获取百分比进度 //获取百分比进度
let progress = res.total.percent.toFixed(2); let progress = res.total.percent.toFixed(2);
self.uploadProgress = Number(progress); self.uploadProgress = Number(progress);
if(progressId == 'uploadProgress1') { if(progressId == 'uploadProgress1') {
self.uploadProgress1 = Number(progress); self.uploadProgress1 = Number(progress);
} }
if(progressId == 'uploadProgress2') { if(progressId == 'uploadProgress2') {
self.uploadProgress2 = Number(progress); self.uploadProgress2 = Number(progress);
} }
console.log('Progress: ' + progress); console.log('Progress2: ' + progress);
//如果有进度条
/*if (isNotEmptyUtils(progressId)) {
let obj = $("#" + progressId);
//开始上传时,显示进度条
if (isNotEmptyUtils(obj.parent())) {
//修改状态为上传
// status = true;
self.qiniuUploadStatus = true;
obj.parent().removeClass("hidden");
obj.fadeIn("fast");
}
obj.css("width", progress + '%');
obj.text(progress + '%');
//上传完成,2秒后淡出进度条
if (progress === "100.00") {
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = true;
obj.fadeOut(2000);
}
}*/
}; };
/** /**
...@@ -425,7 +397,6 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) => ...@@ -425,7 +397,6 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) =>
setTimeout(function(){ setTimeout(function(){
result.key = res.key; result.key = res.key;
result.path = '/' + res.key; result.path = '/' + res.key;
// result.fullPath = domain + '/' + res.key + '_' + new Date().getTime();
if(!fileType) { // 图片 文件 if(!fileType) { // 图片 文件
console.log('---domain-------',domain) console.log('---domain-------',domain)
result.fullPath = domain + '/' + res.key; result.fullPath = domain + '/' + res.key;
...@@ -433,32 +404,12 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) => ...@@ -433,32 +404,12 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) =>
console.log('----domain1------',domain1) console.log('----domain1------',domain1)
result.fullPath = domain1 + '/' + res.key; result.fullPath = domain1 + '/' + res.key;
} }
result.size = res.fsize; result.size = res.fsize;
result.name = res.fname ; result.name = res.fname ;
result.ext = res.ext; result.ext = res.ext;
// deferred.resolve(result);
resolve(result); resolve(result);
// self.model.qCloudUrl = result.fullPath;
// $("#introVideoLecture").attr("src", self.model.qCloudUrl);
//修改状态为非上传
// status = false;
self.qiniuUploadStatus = false; self.qiniuUploadStatus = false;
// if (isNotEmptyUtils(previewId)) {
// let address = domain + result.path;
// console.log('文件路径: ' + address);
// //显示图片
// let uplodImg = $('<img>').attr("src", address);
// let obj = $("#" + previewId);
// obj.empty().append(uplodImg);
// obj.css('max-width', '100%');
// }
},500); },500);
}; };
/** /**
...@@ -480,12 +431,6 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) => ...@@ -480,12 +431,6 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) =>
}else { }else {
console.error(err); console.error(err);
} }
/*modalClick("提示", "上传失败!", "确定", function () {
$('#model-modify').modal('hide');
}, "", null);*/
// deferred.reject(new Error('七牛上传失败'));
// return deferred.promise;
return reject(new Error('七牛上传失败')); return reject(new Error('七牛上传失败'));
}; };
...@@ -494,9 +439,7 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) => ...@@ -494,9 +439,7 @@ export const doUpload = (self,file, filePath, previewId,progressId, fileType) =>
}); });
// 保存到全局对象
// return deferred.promise; window.QNSubscription = subscription;
}); });
}; };
<template>
<div class="review-access-wrap">
<bread-crumb :curmbFirst="curmbFirst" :curmbSecond="curmbSecond"></bread-crumb>
<div class="edit-course-wrapper review-access screenSet" id="screenSet">
<div class="course-content">
<el-form
ref="formDataRef"
:model="formData"
:rules="rules"
label-width="120px"
class="basic-form"
>
<el-form-item label="课程名称:" prop="courseName" class="valid-msg">
<el-col :span="20">
<el-input
size="small"
v-model="formData.courseName"
placeholder="请输入课程名称"
style="width: 360px"
maxlength="25"
:disabled="disabled"
></el-input>
<span class="word-num">
{{(formData.courseName || '').replace(/\s+/g,"").length}}/25
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData, 'courseNameCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseNameCheck && formData.checkStatus != 2" class="error">
<span>{{formData.courseNameCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData, 'courseNameCheck')">X</span>
</div>
</el-col>
</el-form-item>
<el-form-item label="学科分类:" prop="subjectIdList" class="valid-msg">
<el-col :span="18">
<el-cascader
style="width: 360px"
v-model="formData.subjectIdList"
:options="labelOptions"
:props="{ value: 'id', label: 'name', children: 'subList'}"
:disabled="disabled"
>
</el-cascader>
</el-col>
</el-form-item>
<el-form-item label="开放范围:" prop="shareType" class="valid-msg">
<el-radio-group v-model="formData.shareType">
<el-radio :label="1">机构共享</el-radio>
</el-radio-group>
</el-form-item>
<div class="basic-item-icon" style="margin-top: -18px; padding-top: 0;">
<ul v-show="formData.courseCustomChapterModels[0].courseCustomLectureModelList.length" class="custom-list">
<li v-for="(lecture, index) in formData.courseCustomChapterModels[0].courseCustomLectureModelList" :key="index" class="valid-msg">
<ul class="video">
<li class="video-wapper">
<span class="title">视频{{index + 1}}</span>
<img src="../../assets/image/phrase3/icon-pin.png" />
<span class="name" @click="previewVideoAction(lecture)">{{lecture.resourceModel && lecture.resourceModel.name}}</span>
<span v-show="formData.checkStatus == 0" class="edit-wrapper" style="margin-left: 100px;" @click="auditField(formData.courseCustomChapterModels[0].courseCustomLectureModelList[index], 'contentCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</li>
<div style="top: 29px;" v-show="needShowAuditMsg && formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].contentCheck && formData.checkStatus != 2" class="error-video">
<span>{{formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].contentCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomChapterModels[0].courseCustomLectureModelList[index], 'contentCheck')">X</span>
</div>
</ul>
<div class="video-name">
<span class="title">
<span style="color: red;">*</span>
<span class="video-title">视频名称{{index + 1}}</span>
</span>
<el-input
size="small"
v-model="lecture.name"
placeholder="请输入课程名称"
style="width: 380px"
maxlength="25"
:disabled="disabled"
></el-input>
<span class="word-num">
{{(lecture.name || '').replace(/\s+/g,"").length}}/25
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData.courseCustomChapterModels[0].courseCustomLectureModelList[index], 'nameCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div style="top: 86px;" v-show="needShowAuditMsg && formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].nameCheck && formData.checkStatus != 2" class="error-video">
<span>{{formData.courseCustomChapterModels[0].courseCustomLectureModelList[index].nameCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomChapterModels[0].courseCustomLectureModelList[index], 'nameCheck')">X</span>
</div>
</div>
</li>
<span v-show="needShowUploadProcess" class="upload-process" :style="{'width': (uploadProgress/100 * 340) + 'px'}"></span>
</ul>
</div>
<div class="other-content valid-msg">
<div class="tips">注:以下信息为非必填项,您也可以根据实际情况修改</div>
<div class="basic-item-icon">
<!-- <span class="require">*</span> -->
<el-form-item label="课程封面:">
<el-upload
v-model="formData.courseIntroImage"
class="bg-uploader"
action="#"
:show-file-list="false"
:disabled="disabled"
>
<div class="bg-img-wrapper">
<img
v-if="formData.courseIntroImage"
@mouseover.stop="imgMouseOver=true"
:src="getOSSDomain(formData.courseIntroImage)"
class="bg-img"
/>
<img
v-if="!formData.courseIntroImage"
class="bg-img"
src="../../assets/image/small.png"
/>
</div>
</el-upload>
<div class="limit-text">尺寸:750*420,只支持jpg、jpeg格式</div>
<span class="word-num">
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData, 'courseIntroImageCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseIntroImageCheck" class="error" :class="{'top-124': formData.checkStatus == 0}" style="position:absolute;top:103px;">
<span>{{formData.courseIntroImageCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData, 'courseIntroImageCheck')">X</span>
</div>
</el-form-item>
<p class="upload-message" v-if="uploadImgMessage">请选择列表图片</p>
</div>
<el-form-item label="课程难度:">
<el-radio-group v-model="formData.difficultyLevel" :disabled="disabled">
<el-radio :label="1">初级</el-radio>
<el-radio :label="2">中级</el-radio>
<el-radio :label="3">高级</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="formData.courseCustomDoctorModels[0]">
<el-form-item label="讲师名称:" class="valid-msg">
<el-col :span="18">
<el-input
size="small"
v-model="formData.courseCustomDoctorModels[0].courseDoctorName"
placeholder="请输入讲师名称"
style="width: 360px"
maxlength="25"
@focus="isShowDoctorList=true"
@input="filterDoctorName"
@blur="doctorNameInputBlur"
:disabled="disabled"
></el-input>
<ul v-show="isShowDoctorList" class="doctor-select-list">
<li
v-for="(item, index) in doctorNameList"
:key="index"
@click="selectDoctor(item.courseDoctorName, index)"
:class="{'doctor-selected': item.seleted}"
>
<span v-show="item.show">{{item.courseDoctorName || '测试名'}}</span>
</li>
</ul>
<span class="word-num">
{{(formData.courseCustomDoctorModels[0] && formData.courseCustomDoctorModels[0].courseDoctorName || '').replace(/\s+/g,"").length}}/25
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData.courseCustomDoctorModels[0], 'courseDoctorNameCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorNameCheck && formData.checkStatus != 2" class="error">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorNameCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomDoctorModels[0], 'courseDoctorNameCheck')">X</span>
</div>
</el-col>
</el-form-item>
<div class="basic-item-icon">
<el-form-item label="讲师头像:" class="valid-msg">
<el-upload
v-model="formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl"
class="bg-uploader"
action="#"
:show-file-list="false"
:disabled="disabled"
>
<div class="bg-img-wrapper">
<img
v-if="formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl || ''"
@mouseover.stop="imgMouseOver=true"
:src="getOSSDomain(formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl)"
class="bg-img-doctor"
/>
<img
v-if="!(formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl || '')"
class="bg-img-doctor"
src="../../assets/image/small.png"
/>
</div>
</el-upload>
<div class="limit-text">尺寸:88*88,只支持jpg、jpeg格式</div>
<span class="word-num">
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData.courseCustomDoctorModels[0], 'courseDoctorAvatarUrlCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorAvatarUrlCheck" class="error" :class="{'top-124': formData.checkStatus == 0}" style="position:absolute;top: 102px;">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorAvatarUrlCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomDoctorModels[0], 'courseDoctorAvatarUrlCheck')">X</span>
</div>
</el-form-item>
<p class="upload-message" v-if="uploadImgMessage">请选择列表图片</p>
</div>
<el-form-item label="所属机构:" class="valid-msg">
<el-col :span="18">
<el-input
size="small"
v-model="formData.courseCustomDoctorModels[0].courseDoctorHospital"
placeholder="请输入所属机构"
style="width: 360px"
maxlength="25"
:disabled="disabled"
></el-input>
<span class="word-num">
{{(formData.courseCustomDoctorModels && formData.courseCustomDoctorModels[0].courseDoctorHospital || '').replace(/\s+/g,"").length}}/25
<!-- <span class="edit-wrapper"> -->
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData.courseCustomDoctorModels[0], 'courseDoctorHospitalCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseCustomDoctorModels[0].courseDoctorHospitalCheck && formData.checkStatus != 2" class="error">
<span>{{formData.courseCustomDoctorModels[0].courseDoctorHospitalCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData.courseCustomDoctorModels[0], 'courseDoctorHospitalCheck')">X</span>
</div>
</el-col>
</el-form-item>
</div>
<div v-if="formData.courseIntro">
<el-form-item label="课程简介:" class="valid-msg">
<el-col :span="14">
<el-input
style="width:420px"
size="small"
type="textarea"
maxlength="200"
:autosize="{ minRows: 5}"
placeholder="请输入课程简介"
v-model="formData.courseIntro"
:disabled="disabled"
/>
<span class="word-num">
{{(formData.courseIntro || '').replace(/\s+/g,"").length}}/200
<span v-show="formData.checkStatus == 0" class="edit-wrapper" @click="auditField(formData, 'courseIntroCheck')">
<img class="edit-img" src="../../assets/image/phrase3/icon-pz.png" />拒绝原因
</span>
</span>
<div v-show="needShowAuditMsg && formData.courseIntroCheck && formData.checkStatus != 2" class="error-area">
<span>{{formData.courseIntroCheck}}</span>
<span v-show="formData.checkStatus == 0" class="cancle" @click="cancleAudit(formData, 'courseIntroCheck')">X</span>
</div>
</el-col>
</el-form-item>
</div>
</div>
</el-form>
</div>
<footer style="padding: 30px;padding-bottom: 50px;">
<el-button style="margin-left: 20px" @click="backToListPage">返回列表</el-button>
<el-button v-if="formData.checkStatus == 0" style="margin-left: 100px" type="primary" @click="passOrRefuse(2)">通 过</el-button>
<el-button v-if="formData.checkStatus == 0" type="primary" @click="passOrRefuse(1)">拒 绝</el-button>
</footer>
</div>
<DialogComponet :dialogObj="dialogObj" @hide="passOrRefuseAction" @confirm="dialogObj.visible=false"></DialogComponet>
<PreviewVideo :dialogVisible="isPreviewVideo" :videoUrl="videoUrl" @close="isPreviewVideo=false"></PreviewVideo>
<RejectReasonDialog :refuseReasonList="refuseReasonList" :dialogVisible="auditVisible" @close="auditVisible=false" @checkInfo="checkInfo"></RejectReasonDialog>
</div>
</template>
<script>
import PreviewVideo from "@/components/education/custom-resource/preview-video";
import PreviewProtocol from "@/components/education/custom-resource/preview-protocol";
import DialogComponet from "@/components/education/template/dialog";
import RejectReasonDialog from "@/components/education/custom-resource/reject-reason-dialog";
import { openLoading, closeLoading } from "@/utils/utils";
import BreadCrumb from "../../components/breadcrumb.vue";
import { getOSSImgUrl } from "@/utils/index";
import * as commonUtil from "../../utils/utils";
let vm = null;
export default {
data() {
return {
curmbFirst: "CME",
curmbSecond: "外部资源管理",
auditVisible: false,
needCheckField: false,
needShowAuditMsg: false,
needShowUploadProcess: false,
disabled: true,
formData: {
checkStatus: 0,
courseCustomChapterModels: [
{
courseCustomLectureModelList: [],
id: null,
name: "视频课程"
}
],
courseCustomDoctorModels: [
{
courseDoctorAvatarUrl:
"/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
}
],
courseId: null,
courseIntro: "",
courseIntroCheck: "",
courseIntroImage: "/h5/images/cme/project-banner.png",
courseIntroImageCheck: "",
courseName: "",
courseNameCheck: "",
deleteCustomLectureIds: [],
difficultyLevel: 1,
shareType: 1,
subjectIdList: []
},
uploadImgMessage: false,
imgMouseOver: false,
rules: {
courseName: [
{ required: true, message: " " },
],
subjectIdList: [
{ required: true, message: "请输入课程名称" }
],
shareType: [
{ required: true, message: "请选择开放范围" }
]
},
labelOptions: [],
fileList: [
],
projectBanner: "/h5/images/cme/project-banner.png",
doctorHeader: "/h5/images/cme/doctor-header.png",
doctorNameList: [
{ courseDoctorName: "333", show: true, seleted: false },
{ courseDoctorName: "334", show: true, seleted: false },
{ courseDoctorName: "335", show: true, seleted: false },
{ courseDoctorName: "336", show: true, seleted: false }
],
isShowDoctorList: false,
isPreviewVideo: false,
videoUrl: "",
orgCourseInfo: {
defaultDoctor: {
courseDoctorAvatarUrl :"/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
},
doctorModelList: [
{
courseDoctorAvatarUrl: "/h5/images/cme/doctor-header.png",
courseDoctorAvatarUrlCheck: "",
courseDoctorHospital: "",
courseDoctorHospitalCheck: "",
courseDoctorName: "",
courseDoctorNameCheck: "",
id: null
}
],
limitModel: {
maxLimitOneVideoSize: 0,
maxLimitVideoCount: 0,
maxStorageSpace: 0,
usedStorageSpace: 0
}
},
uploadProgress: 0,
dialogObj: {
visible: false,
title: "确定取消吗?",
message: "确定课程已完成检测并通过审核?",
tip: "",
// confirmMsg: "取 消",
// hideMsg: "确 定"
},
statusObj: {
pass: {
title: "确认通过",
message: "确定课程已完成检测并通过审核?",
// message: "确定“云小鹊”提交的「高血压治疗规范」课程已完成检测并通过审核?",
tip: "",
confirmMsg: "取 消",
hideMsg: "确 定"
},
refuse: {
title: "",
message: "您已添加过「拒绝原因」,不能通过该课程",
tip: "",
confirmMsg: "我知道了",
hideMsg: ""
},
refuseReasen: {
title: "",
message: "请填写拒绝原因",
tip: "",
confirmMsg: "我知道了",
hideMsg: ""
},
confirmRefuse: {
title: "确认拒绝",
message: "确定课程审核为拒绝",
tip: "",
confirmMsg: "取 消",
hideMsg: "确 定"
},
},
courseId: 0,
currentModifiedOrg: {},
currentFieldName: '',
refuseReasonList: [],
createdDoctorName: ''
};
},
computed: {},
components: {
BreadCrumb,
PreviewVideo,
DialogComponet,
RejectReasonDialog
},
created() {
vm = this;
this.courseId = this.$route && this.$route.query && this.$route.query.courseId || 0;
this.createdDoctorName = this.$route && this.$route.query && this.$route.query.createdDoctorName || '';
vm.initModify();
},
mounted() {
this.getLabelList();
this.getRefuseList();
commonUtil.resizeHeight();
},
methods: {
// 获取OSS域名,用于显示图片
getOSSDomain(url) {
return getOSSImgUrl(url);
},
// 返回到列表页面
backToListPage() {
this.$router.back(-1)
},
// 创建课程页面的初始信息
initOrgCourseInfo() {
vm.GET("contents/course/custom/info/init", { setEntry: true }).then(
res => {
if (res.code == "000000") {
this.orgCourseInfo = res.data;
this.formData.courseCustomDoctorModels[0] = this.orgCourseInfo.defaultDoctor;
this.formData.courseCustomDoctorModels[0].courseDoctorAvatarUrl =
this.orgCourseInfo.defaultDoctor.courseDoctorAvatarUrl ||
"/h5/images/cme/doctor-header.png";
this.doctorNameList = this.convertDNameToSelectOpt(
this.orgCourseInfo.doctorModelList
);
+this.courseId && this.getCourseInfoById(this.courseId);
}
}
);
},
// 将医生名称进行处理
convertDNameToSelectOpt(doctorModelList) {
doctorModelList.forEach(item => {
item.show = true;
item.seleted = false;
});
return doctorModelList;
},
// 初始化课程信息
initModify() {
this.needShowAuditMsg = true;
this.initOrgCourseInfo();
},
// 创建课程页面的初始信息
getCourseInfoById(courseId) {
vm.GET(`contents/course/custom/info/${courseId}`)
.then( res => {
if ( res.code == "000000") {
this.formData = res.data;
}
}
);
},
// 过滤医生信息
filterDoctorName(value) {
this.doctorNameList.forEach(item => {
if (value) {
if ((item.value + "").indexOf(value) == -1) {
item.show = false;
} else {
item.show = true;
}
if (item.value == value) {
item.seleted = true;
} else {
item.seleted = false;
}
} else {
item.show = true;
}
});
},
// 当选择医生的焦点失去时,要反选医生信息
doctorNameInputBlur() {
setTimeout(() => {
this.isShowDoctorList = false;
this.selectDoctorByName(
this.formData.courseCustomDoctorModels[0].courseDoctorName
);
}, 200);
},
// 根据姓名反选医生信息
// TODO 尝试找到完全匹配的医生
selectDoctorByName(name) {
},
// 选择其中一个
selectDoctor(name) {
console.log(name);
this.formData.courseCustomDoctorModels[0].courseDoctorName = name;
this.selectDoctorByName(name);
},
// 获取学科列表
getLabelList() {
let req = {};
this.GET("aggregate/content/labelList", req).then(res => {
if (res.code == "000000") {
this.convertLabelList(res.data);
}
});
},
// 将所有子分类中的“全部”去掉
convertLabelList(labelList) {
let newLabelList = [];
labelList.forEach(item => {
item.subList = item.subList.slice(1);
});
this.labelOptions = labelList;
},
// 查找是否有拒绝原因
hasAuditMsg(cData) {
let flag = false;
if(cData.courseCustomDoctorModels[0]) {
if(cData.courseNameCheck
|| cData.courseIntroCheck
|| cData.courseIntroImageCheck
|| cData.courseCustomDoctorModels[0].courseDoctorNameCheck
|| cData.courseCustomDoctorModels[0].courseDoctorAvatarUrlCheck
|| cData.courseCustomDoctorModels[0].courseDoctorHospitalCheck
) {
flag = true;
}
} else {
if(cData.courseNameCheck
|| cData.courseIntroCheck
|| cData.courseIntroImageCheck
) {
flag = true;
}
}
if(!flag) {
let lectureList = cData.courseCustomChapterModels[0].courseCustomLectureModelList;
for(let i = 0; i < lectureList.length; i ++) {
if(lectureList[i].nameCheck || lectureList[i].contentCheck) {
flag = true;
break;
}
}
}
return flag;
},
// 添加或修改课程(kind = 3)
passOrRefuse(checkStatus) {
// checkStatus 1:拒绝的话,要有理由;2:通过的话,没有拒绝理由
// TODO 判断
this.currentCheckStatus = checkStatus;
let flag = this.hasAuditMsg(this.formData);
console.log('passOrRefuse', flag);
// 点击拒绝按钮
if(checkStatus == 1) {
if(flag) { // 有拒绝原因
vm.statusObj.confirmRefuse.message = `确定“${this.createdDoctorName}”提交的「${this.formData.courseName}」课程审核为拒绝`,
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj.confirmRefuse
);
} else {
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj.refuseReasen
);
}
// 点击通过按钮
} else {
if(flag) { // 有拒绝原因
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj.refuse
);
} else {
vm.statusObj.pass.message = `确定“${this.createdDoctorName}”提交的「${this.formData.courseName}」课程已完成检测并通过审核`,
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj.pass
);
}
}
vm.dialogObj.visible = true;
},
passOrRefuseAction(){
this.formData.checkStatus = this.currentCheckStatus;
this.POST("contents/course/custom/check/v1/check", this.formData).then(res => {
if (res.code == "000000") {
this.backToListPage();
}
this.dialogObj.visible = false;
});
},
// 关闭(“取消”按钮弹出来的)弹框
hideCancleTips() {
this.dialogObj.visible = false;
},
// 预览视频
previewVideoAction(lecture) {
this.videoUrl = lecture.resourceModel.filePath;
this.isPreviewVideo = true;
},
// 对特定字段进行修改
auditField(modifiedOrg, fieldName) {
this.currentModifiedOrg = modifiedOrg;
this.currentFieldName = fieldName;
this.auditVisible = true;
},
// 对特定字段进行重置
cancleAudit(modifiedOrg, fieldName) {
modifiedOrg[fieldName] = '';
},
// 获取到审核结果
checkInfo(info) {
this.currentModifiedOrg[this.currentFieldName] = info;
console.log(info);
},
// 获取默认的拒绝原因列表
getRefuseList() {
this.GET("contents/course/custom/check/v1/refuse/list", {}).then(res => {
if (res.code == "000000") {
this.refuseReasonList = res.data || [];
}
});
},
}
};
</script>
<style scoped lang="scss">
.edit-course-wrapper {
.course-content {
// color: red;
padding-top: 30px;
.basic-item-icon {
position: relative;
margin-top: 20px;
.require {
position: absolute;
left: 40px;
top: 11px;
color: #f56c6c;
}
.upload-message {
position: absolute;
left: 160px;
top: 105px;
font-size: 12px;
color: #f56c6c;
}
.img-delete {
position: absolute;
left: 0px;
top: 0px;
width: 84px;
height: 100px;
background: #000;
opacity: 0.7;
z-index: 999;
i {
color: #fff;
margin-top: 39px;
margin-left: 0px;
}
}
.upload-tips {
width: 100%;
position: relative;
top: -10px;
font-size: 12px;
color: #979899;
// display: inline-block;
}
.custom-list {
// width: 100%;
width: 800px;
display: flex;
flex-direction: column;
// border-radius: 3px;
// border: 1px solid rgba(228,231,237,1);
padding: 20px;
padding-top: 0px;
font-size: 12px;
color: #606266;
& > li {
margin: 10px 0;
}
.video {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.video-wapper {
height: 40px;
line-height: 40px;
margin-bottom: 10px;
.title {
display: inline-block;
width: 80px;
text-align: right;
margin-right: 10px;
}
.name {
cursor: pointer;
color: #5890DD;
}
img {
width: 12px;
height: 12px;
}
}
// .delete {
// position: relative;
// top: 4px;
// cursor: pointer;
// width: 16px;
// height: 16px;
// }
}
.video-name {
.title {
display: inline-block;
width: 80px;
text-align: right;
margin-right: 10px;
}
}
}
}
.word-num {
font-size: 12px;
color: #999;
padding-top: 5px;
}
.bg-uploader {
img {
float: left;
}
.bg-img-wrapper {
.bg-img {
display: block;
width: 160px;
height: 90px;
}
.bg-img-doctor {
display: block;
width: 88px;
height: 88px;
}
}
.bg-video {
float: left;
width: 84px;
height: 100px;
}
}
.limit-text {
position: absolute;
top: 86px;
left: 0px;
font-size: 12px;
color: #979899;
}
.separator-line {
width: 100%;
display: flex;
flex-direction: row;
align-content: center;
align-items: center;
justify-content: space-between;
.center {
cursor: pointer;
width: 130px;
color: #666666;
img {
width: 12px;
}
}
.line-left,
.line-right {
// display: inline-block;
// width: 100%;
flex: 1;
border-bottom: 1px dashed #e4e7ed;
}
}
.tips {
width: 500px;
height: 32px;
line-height: 32px;
margin-left: 38px;
padding-left: 12px;
background: rgba(254, 250, 245, 1);
border-radius: 3px;
color: #e6a23c;
}
.valid-msg {
position: relative;
.error {
width: 370px;
position: absolute;
display: flex;
justify-content: space-between;
top: 29px;
font-size: 13px;
color: #ed3131;
.text {
flex: 1;
}
.cancle {
width: 20px;
margin-left: 20px;
cursor: pointer;
}
}
.error-area {
position: absolute;
bottom: -32px;
font-size: 13px;
color: #ed3131;
.cancle {
width: 20px;
margin-left: 20px;
cursor: pointer;
}
}
.error-video {
position: absolute;
top: 64px;
left: 82px;
font-size: 13px;
color: #ed3131;
.cancle {
width: 20px;
margin-left: 20px;
cursor: pointer;
}
}
.edit-wrapper {
cursor: pointer;
color: #449284;
.edit-img {
position: relative;
top: 2px;
width: 12px;
margin: 0 2px 0 4px;
}
}
.doctor-select-list {
width: 200px;
// max-height: 100px;
position: absolute;
z-index: 100;
background: #fff;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
// margin: 10px;
li {
padding-left: 20px;
cursor: pointer;
&:hover {
background: #f4f7fd;
}
&.doctor-selected {
background: #f4f7fd;
}
}
}
}
.upload-process {
margin: 10px 0 10px 10px;
display: block;
// width: 310px;
height: 4px;
background: #449284;
border-radius: 2px;
}
}
}
</style>
<style scoped lang="scss">
.review-access-wrap {
.review-access {
padding: 10px;
background: #fff;
}
.top-124 {
top: 124px !important;
}
}
</style>
\ No newline at end of file
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<!-- 选择课程 --> <!-- 选择课程 -->
<div v-if="active == 0" class="tpl-main"> <div v-if="active == 0" class="tpl-main">
<SelectCourseComp></SelectCourseComp> <SelectCourseComp @showOrgCourse="showOrgCourse" :activeName="kind"></SelectCourseComp>
</div> </div>
<!-- 填写项目信息--> <!-- 填写项目信息-->
...@@ -70,6 +70,17 @@ ...@@ -70,6 +70,17 @@
<dialog-componet :dialogObj="dialogObj" @hide="hide"></dialog-componet> <dialog-componet :dialogObj="dialogObj" @hide="hide"></dialog-componet>
<dialog-componet :dialogObj="sendObj" @hide="hidefn" @confirm="confirmFn"></dialog-componet> <dialog-componet :dialogObj="sendObj" @hide="hidefn" @confirm="confirmFn"></dialog-componet>
<PreviewEditCourse
:dialogVisible="isPreviewEditCourse"
:courseId="courseId"
@close="closeEditCourse"
/>
<PreviewProtocol
:dialogVisible="isPreviewProtocol"
:protocolId="protocolId"
:protocolContent="protocolContent"
@close="closeProtocol"
/>
</div> </div>
</template> </template>
...@@ -82,6 +93,8 @@ import selectRegion from "@/components/education/template/selectRegion"; ...@@ -82,6 +93,8 @@ import selectRegion from "@/components/education/template/selectRegion";
import setOrganization from "@/components/education/template/setOrganization"; import setOrganization from "@/components/education/template/setOrganization";
import SelectCourseComp from "@/components/education/custom/select-course-comp"; import SelectCourseComp from "@/components/education/custom/select-course-comp";
import dialog from "@/components/education/template/dialog"; import dialog from "@/components/education/template/dialog";
import PreviewEditCourse from "@/components/education/custom-resource/edit-course-dialog";
import PreviewProtocol from "@/components/education/custom-resource/preview-protocol";
import { openLoading, closeLoading, resizeHeight } from "@/utils/utils"; import { openLoading, closeLoading, resizeHeight } from "@/utils/utils";
import { mapGetters, mapActions } from "vuex"; import { mapGetters, mapActions } from "vuex";
...@@ -157,18 +170,52 @@ export default { ...@@ -157,18 +170,52 @@ export default {
isPreview: 0, // 1表示是查看信息 isPreview: 0, // 1表示是查看信息
maxLimitCreatedCustomProjectCountInYear: 20, // 同一个用户每年能够创建的项目数 maxLimitCreatedCustomProjectCountInYear: 20, // 同一个用户每年能够创建的项目数
allSubList: [], allSubList: [],
isPreviewEditCourse: false,
courseId: '0',
isPreviewProtocol: false,
protocolId: 22,
protocolContent: '',
isFirst: true, // 是否是第一次(不做更新)
}; };
}, },
computed: { computed: {
...mapGetters(["searchParam", "cartList"]) ...mapGetters(["searchParam", "searchParamOrg", "cartList", "kind"])
}, },
watch: { watch: {
kind(newKind) {
console.log(newKind);
let searchParam = newKind == 0 ? this.searchParam : this.searchParamOrg;
searchParam.pageNo = 1;
if(newKind <= 1) {
this.getCourseList(searchParam);
} else {
newKind = newKind == 0 ? 0 : 1; // 将大于1的情况也置为1
this.setKind(newKind);
}
},
searchParam: { searchParam: {
handler(val) { handler(val) {
console.log('searchParam', val);
this.getCourseList(val); this.getCourseList(val);
}, },
deep: true deep: true
}, },
searchParamOrg: {
handler(val) {
console.log('searchParamOrg', val, this.isFirst);
// 第一次不执行
if(!this.isFirst) {
this.getCourseList(val);
}
// 也只执行一次
if(this.isFirst) {
this.isFirst = false;
}
},
deep: true
},
cartList(val) { cartList(val) {
this.canNext = val.length > 0; this.canNext = val.length > 0;
} }
...@@ -180,7 +227,9 @@ export default { ...@@ -180,7 +227,9 @@ export default {
selectRegion, selectRegion,
setOrganization, setOrganization,
dialogComponet: dialog, dialogComponet: dialog,
SelectCourseComp SelectCourseComp,
PreviewEditCourse,
PreviewProtocol
}, },
created() { created() {
vm = this; vm = this;
...@@ -189,36 +238,31 @@ export default { ...@@ -189,36 +238,31 @@ export default {
}, },
mounted() { mounted() {
resizeHeight(); resizeHeight();
this.getLabelList();
this.initPageParams(); this.initPageParams();
// this.initPageParams(); this.getLabelList();
}, },
methods: { methods: {
...mapActions([ ...mapActions([
"setSearchParam", "setSearchParam",
"setSearchParamOrg",
"setCartList", "setCartList",
"setCourseList", "setCourseList",
"setAllLabelList", "setAllLabelList",
"setSubLabelList", "setSubLabelList",
"setAllLabelListOrg",
"setSubLabelListOrg",
"setCourseLimitCount", "setCourseLimitCount",
"setKind"
]), ]),
initPageParams(labelIdList) { initPageParams(labelIdList) {
let searchParam = {
orderBy: 2,
dir: 1,
grade: 0,
pageNo: 1,
pageSize: 10,
labelIdList: labelIdList || []
};
this.setCartList([]); this.setCartList([]);
this.setCourseList([]); this.setCourseList([]);
this.setAllLabelList([]); this.setAllLabelList([]);
this.setSubLabelList([]); this.setSubLabelList([]);
this.setAllLabelListOrg([]);
this.setSubLabelListOrg([]);
this.courseLimitCount(); this.courseLimitCount();
// this.getLabelList();
// this.getCourseList(searchParam);
}, },
// 自定义项目--选择课程个数限制(-1表示不限制) // 自定义项目--选择课程个数限制(-1表示不限制)
...@@ -231,55 +275,106 @@ export default { ...@@ -231,55 +275,106 @@ export default {
}, },
// 获取所有标签(一级及二级),交做相应处理 // 获取所有标签(一级及二级),交做相应处理
// 先将所有的标签添加checked字段
getLabelList() { getLabelList() {
vm.GET("contents/diseases/labelList", {}).then(res => { vm.GET("contents/diseases/labelList", {}).then(res => {
if (res.code == "000000") { if (res.code == "000000") {
// 先将所有的标签添加checked字段 this.storeLables(JSON.parse(JSON.stringify(res.data)));
let labelList = res.data; this.storeLablesOrg(JSON.parse(JSON.stringify(res.data)));
let allSubList = [];
let labelIdList = [];
labelList.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.parentIndex = index;
sub.checked = true;
if (subIndex == 0) {
sub.id = `subid-${index}`; // 将二级中的“全部”id改为可以识别的
} else {
allSubList.push(sub);
labelIdList.push(sub.id);
}
});
});
// 构建其子标签
allSubList.unshift({
name: "全部",
checked: true,
id: 'parentid-0'
});
// 添加一级的“全部”标签,并构建其子标签
labelList.unshift({
name: "全部",
checked: true,
subList: allSubList
});
// this.initPageParams(labelIdList);
this.setAllLabelList(labelList);
this.setSubLabelList(allSubList);
let searchParam = {
orderBy: 2,
dir: 1,
grade: 0,
pageNo: 1,
pageSize: 10,
labelIdList: labelIdList || []
};
this.setSearchParam(searchParam);
} }
}); });
}, },
// 设置公共课程的相关查询
storeLables(labelList) {
let allSubList = [];
let labelIdList = [];
labelList.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.parentIndex = index;
sub.checked = true;
if (subIndex == 0) {
sub.id = `subid-${index}`; // 将二级中的“全部”id改为可以识别的
} else {
allSubList.push(sub);
labelIdList.push(sub.id);
}
});
});
// 构建其子标签
allSubList.unshift({
name: "全部",
checked: true,
id: 'parentid-0'
});
// 添加一级的“全部”标签,并构建其子标签
labelList.unshift({
name: "全部",
checked: true,
subList: allSubList
});
this.setAllLabelList(labelList);
this.setSubLabelList(allSubList);
let searchParam = {
kind: 0,
orderBy: 2,
dir: 1,
grade: 0,
pageNo: 1,
pageSize: 10,
labelIdList: labelIdList || []
};
this.setSearchParam(searchParam);
},
// 设置机构的相关查询
storeLablesOrg(labelList) {
let allSubList = [];
let labelIdList = [];
labelList.forEach((item, index) => {
item.checked = false;
item.subList.forEach((sub, subIndex) => {
sub.parentIndex = index;
sub.checked = true;
if (subIndex == 0) {
sub.id = `subid-${index}`; // 将二级中的“全部”id改为可以识别的
} else {
allSubList.push(sub);
labelIdList.push(sub.id);
}
});
});
// 构建其子标签
allSubList.unshift({
name: "全部",
checked: true,
id: 'parentid-0'
});
// 添加一级的“全部”标签,并构建其子标签
labelList.unshift({
name: "全部",
checked: true,
subList: allSubList
});
this.setAllLabelListOrg(labelList);
this.setSubLabelListOrg(allSubList);
let searchParam = {
kind: 1,
orderBy: 2,
dir: 1,
grade: 0,
pageNo: 1,
pageSize: 10,
labelIdList: labelIdList || []
};
this.setSearchParamOrg(searchParam);
},
// (根据条件)查询课程 // (根据条件)查询课程
getCourseList(searchParam) { getCourseList(searchParam) {
vm.GET("contents/diseases/courseListForPortal", searchParam).then(res => { vm.GET("contents/diseases/courseListForPortal", searchParam).then(res => {
...@@ -324,7 +419,6 @@ export default { ...@@ -324,7 +419,6 @@ export default {
nextStep() { nextStep() {
if (vm.active == 0) { if (vm.active == 0) {
vm.checkSelectCustomCourse(); vm.checkSelectCustomCourse();
// vm.checkSelectTemplate()
return; return;
} }
if (vm.active == 1) { if (vm.active == 1) {
...@@ -376,6 +470,7 @@ export default { ...@@ -376,6 +470,7 @@ export default {
hidefn() { hidefn() {
vm.regionComplete(vm.changeStatus); vm.regionComplete(vm.changeStatus);
}, },
// 选择学元范围暂存 // 选择学元范围暂存
regionComplete(fishFn) { regionComplete(fishFn) {
let req = { let req = {
...@@ -477,70 +572,142 @@ export default { ...@@ -477,70 +572,142 @@ export default {
}); });
}, },
//选中模板后点击下一步时检测(机构和进行中的项目)
checkSelectTemplate() {
openLoading(vm);
vm.GET(
`portal/openTemplateProject/checkAfterSelectOneOpenTemplate/${vm.openTemplateId}`
)
.then(res => {
closeLoading(vm);
if (res.code == "000000") {
if (res.data.status == 0) {
vm.active = 1;
return;
} else {
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj[`status_${res.data.status}`]
);
vm.dialogObj.visible = true;
return;
}
} else {
vm.$message.info(res.message);
}
})
.catch(err => {
closeLoading(vm);
vm.$message.warning("请稍后重试");
});
},
// 隐藏弹框 // 隐藏弹框
hide() { hide() {
vm.dialogObj.visible = false; vm.dialogObj.visible = false;
}, },
// 获取行政范围 // 获取行政范围
setRegion() { setRegion() {
vm.getOrganizationList(vm.$refs.selectRegion.getScope()); vm.getOrganizationList(vm.$refs.selectRegion.getScope());
}, },
// 查询行政范围的设定机构列表 // 查询行政范围的设定机构列表
getOrganizationList(r) { getOrganizationList(r) {
vm.$refs.setOrganization.init(); vm.$refs.setOrganization.init();
vm.$refs.setOrganization.getOrganization(r); vm.$refs.setOrganization.getOrganization(r);
}, },
// 返回选择模板页 // 返回选择模板页
backSelectVue() { backSelectVue() {
vm.active = 0; vm.active = 0;
}, },
// 是否隐藏暂存按钮 // 是否隐藏暂存按钮
hideSave(num) { hideSave(num) {
this.projectStatus = num; this.projectStatus = num;
}, },
// 从子组件(项目信息)获取项目状态是否为上架 // 从子组件(项目信息)获取项目状态是否为上架
setStatus4Flag(s) { setStatus4Flag(s) {
vm.status4Flag = s; vm.status4Flag = s;
} },
/*
展示添加机构课程弹框
如果已经加入机构,1:没有同意过协议,则打开协议弹框;2:已经加入,时直接打开添加弹框
如果没有加入机构,则直接弹出提示(我知道了)
*/
showOrgCourse(courseId) {
this.checkHospital();
this.courseId = courseId
},
// 创建机构课程前校验机构
checkHospital() {
openLoading(vm);
let req = {
setEntry: true
}
vm.GET(`portal/portalCustom/checkHospital`, req)
.then(res => {
closeLoading(vm);
if (res.code == "000000") {
console.log(res);
if (res.data == 0) {
this.checkProtocol();
} else {
vm.dialogObj = Object.assign(
vm.dialogObj,
vm.statusObj[`status_${res.data}`]
);
vm.dialogObj.visible = true;
}
} else {
vm.$message.info(res.message);
}
})
.catch(err => {
closeLoading(vm);
vm.$message.warning("请稍后重试");
});
},
// 判断用户是否签署了最新版协议
// 如果没有签署,则打开协议签署弹框
checkProtocol() {
let req = {
setEntry: true,
type: this.protocolId
}
vm.GET(`smartcontract/protocol/sign/check`, req)
.then(res => {
if (res.code == "000000") {
if(!res.data) { // 没有签署,打开协议签署弹框
this.getProtocolInfoById();
} else {
this.isPreviewEditCourse = true;
}
} else {
vm.$message.info(res.message);
}
})
.catch(err => {
vm.$message.warning("请稍后重试");
});
},
// 根据协议获取内容
getProtocolInfoById() {
let req = {
type: this.protocolId
};
this.GET("smartcontract/protocol/content", req).then(res => {
if (res.code == "000000") {
this.protocolContent = res.data;
this.isPreviewProtocol = true;
} else {
vm.$message.info(res.message);
}
}).catch(err => {
vm.$message.warning("请稍后重试");
});
},
// 关闭编辑课程弹框
closeEditCourse() {
this.isPreviewEditCourse = false;
},
// 关闭预览协议弹框
closeProtocol(needShowAdd) {
if( needShowAdd ) {
this.isPreviewEditCourse = true;
}
this.isPreviewProtocol = false;
},
} }
}; }
</script> </script>
<style lang="scss"> <style lang="scss">
.edit-custom-wrap { .edit-custom-wrap {
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 10px; // width: 10px;
height: 10px; // height: 10px;
width: 5px;
height: 5px;
background-color: #fff; background-color: #fff;
} }
......
<template>
<div class="review-access-wrap">
<bread-crumb :curmbFirst="curmbFirst" :curmbSecond="curmbSecond"></bread-crumb>
<div class="review-access screenSet" id="screenSet">
<div class="header-title">外部资源管理</div>
<el-form ref="form" :model="searchForm" label-width="100px" class="search-form-wrap">
<el-row>
<el-form-item label="课程名称:" class="search-item" >
<el-input v-model="searchForm.courseName" size="small" class="form-width" placeholder="请输入课程名称"></el-input>
</el-form-item>
<el-form-item label="状态:" class="search-item">
<el-select v-model="searchForm.checkStatus" placeholder="请选择" size="small" class="form-width">
<el-option v-for="(item, index) in checkStatusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-row>
<el-row>
<el-form-item label="创建人:" class="search-item" >
<el-input v-model="searchForm.createdDoctorName" size="small" class="form-width" placeholder="请输入创建人"></el-input>
</el-form-item>
<el-form-item label="创建日期:" class="search-item">
<el-date-picker
v-model="searchForm.createdTime"
type="date"
size="small"
class="form-width"
value-format="yyyy-MM-dd"
placeholder="请选择创建日期">
</el-date-picker>
<!-- <span style="color: #DCDFE6;"></span>
<el-date-picker
v-model="searchForm.endTime"
type="datetime"
size="small"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择结束时间">
</el-date-picker> -->
</el-form-item>
<el-form-item class="btn-list">
<el-button @click="search()" type="primary" size="small">查询</el-button>
<el-button @click="reset" size="small">重置</el-button>
</el-form-item>
</el-row>
</el-form>
<el-table :data="tableList" border style="width: 100%">
<el-table-column align="center" prop="courseName" label="课程名称"></el-table-column>
<el-table-column align="center" prop="subjectName" label="课程分类" ></el-table-column>
<el-table-column align="center" prop="createdDoctorName" label="创建人" ></el-table-column>
<el-table-column align="center" prop="createdHospitalName" label="所属机构" ></el-table-column>
<el-table-column align="center" prop="createdTime" label="创建日期" >
<template slot-scope="scope">
{{scope.row.createdTime && new Date(scope.row.createdTime).format('yyyy-MM-dd hh:mm:ss')}}
</template>
</el-table-column>
<el-table-column align="center" prop="checkStatus" label="审核状态" >
<template slot-scope="scope">
<span v-html="getHtmlCheckStatus(scope.row.checkStatus)"></span>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button @click="viewOrAudit(scope.row)" type="text" size="small"><span style="color: #449284;">查看</span></el-button>
</template>
</el-table-column>
<div slot="empty">
<div class="table-empty">
<img src="../../assets/image/no-content1.png">
<p>没有查询到外部资源</p>
</div>
</div>
</el-table>
<div class="pagination">
<el-pagination
class="pagination-style"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:total="totalRows"
:current-page="searchForm.pageNo"
:page-sizes="[15, 30, 50, 100]"
:page-size="searchForm.pageSize"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
</div>
</div>
<!-- 拒绝原因 -->
<el-dialog
title="拒绝原因"
@close="hideAuditForm"
:visible.sync="addEditVisible"
:close-on-click-modal="false"
width="600px"
center>
<el-form ref="auditForm" :model="auditForm" label-width="120px">
<el-form-item label="拒绝原因:">
<el-radio-group v-model="auditForm.auditRadio">
<div style="padding-top: 12px;">
<el-radio label="含有政治类、医疗健康、社会事件类不实信息" value="1"></el-radio>
</div>
<div style="padding-top: 16px;">
<el-radio label="含有欺诈,色情,诱导、违法犯罪非法字符" value="2"></el-radio>
</div>
<div style="padding-top: 16px;">
<el-radio label="其他" value="3"></el-radio>
</div>
</el-radio-group>
<el-input type="textarea" v-model="auditForm.desc" maxlength="25" style="width: 310px;margin-top: 10px;"></el-input>
<span class="word-num">{{(auditForm.desc).replace(/\s+/g,"").length}}/25</span>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="hideAuditForm">取 消</el-button>
<el-button type="primary" @click="auditAction()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { openLoading, closeLoading } from "../../utils/utils";
import BreadCrumb from "../../components/breadcrumb.vue";
import * as commonUtil from "../../utils/utils";
import {
handleDeleteReq,
} from '@/utils/cme/cmeApi'
export default {
data() {
return {
curmbFirst: "CME",
curmbSecond: "外部资源管理",
totalRows: 0,
addEditVisible: false,
isAdd: true, // 新增或编辑状态:新增 true; 编辑 false
deleteVisible: false,
currentRow: null, // 当前行数据
searchForm: {
courseName: '',
checkStatus: -1,
createdDoctorName: '',
createdTime: '',
// createdHospitalName: '',
// subjectName: '',
pageNo: 1,
pageSize: 15,
},
auditForm: {
auditRadio: '',
desc: '',
},
checkStatusList: [
{
name: '全部状态',
value: -1
},{
name: '待审核',
value: 0
},{
name: '拒绝',
value: 1
},{
name: '通过',
value: 2
}
],
tableList: [],
}
},
components: {
BreadCrumb,
},
created() {
this.search();
},
mounted() {
commonUtil.resizeHeight();
},
methods: {
getHtmlCheckStatus(checkStatus) {
if(checkStatus == 0) {
return `<span style="color:#666666;">待审核</span>`;
} else if(checkStatus == 1) {
return `<span style="color:#D0021B;">拒绝</span>`;
} else if(checkStatus == 2) {
return `<span style="color:#417505;">通过</span>`;
} else {
return ''
}
},
// 查询列表
search() {
let searchForm = Object.assign({}, this.searchForm);
let createdTime = searchForm.createdTime;
if(createdTime) {
searchForm.createdTime = new Date(searchForm.createdTime + ' 00:00:00').getTime();
} else {
searchForm.createdTime = '';
}
this.GET("contents/course/custom/check/v1/list", searchForm).then(res => {
if (res.code == "000000") {
this.tableList = res.data && res.data.courseList || [];
this.totalRows = res.data.totalSize || 0;
// this.protocolInfo = res.data;
}
});
},
// 重置
reset() {
this.searchForm = {
courseName: '',
checkStatus: -1,
createdDoctorName: '',
createdTime: '',
// createdHospitalName: '',
// subjectName: '',
pageNo: 1,
pageSize: 15,
};
},
// 查看 每种查看的方式不一样
viewOrAudit(row) {
console.log(row);
this.$router.push({
path: 'audit-custom-course',
query: {
courseId: row.courseId,
createdDoctorName: row.createdDoctorName,
}
})
},
auditAction() {
console.log(row);
},
// 重置
resetForm(formName) {
this.$refs[formName].resetFields();
},
hideAuditForm() {
this.addEditVisible = false;
this.resetForm('auditForm');
this.auditForm = {
auditRadio: '',
desc: '',
};
},
handleSizeChange(val){
this.searchForm.pageSize = val;
this.search();
},
// 切换当前页
handleCurrentChange(val){
this.searchForm.pageNo = val;
this.search();
},
},
}
</script>
<style lang="scss">
.review-access-wrap{
.review-access{
padding: 10px;
background: #fff;
.el-button--small{
font-size: 14px;
}
.header-title {
padding: 10px 12px 20px;
font-size: 14px;
color: #606266;
border-bottom: 1px solid #efefef;
}
.search-form-wrap{
padding: 25px 0 20px;
overflow: hidden;
// border-bottom: 1px dashed #efefef;
}
.search-item{
float: left;
}
.btn-list{
float: right;
.el-form-item__content{
margin-left: 0 !important;
}
}
.new-add{
float: right;
margin: 10px 0 20px;
}
.table-empty {
img {
width: 100px;
}
p {
margin-top: -50px;
}
}
}
}
</style>
\ No newline at end of file
...@@ -433,7 +433,7 @@ export default { ...@@ -433,7 +433,7 @@ export default {
commonUtil.resizeHeight(); commonUtil.resizeHeight();
}, },
methods: { methods: {
...mapActions(["updateItemManager"]), ...mapActions(["updateItemManager", "setKind"]),
//跳转到报告详情页 //跳转到报告详情页
reviewReport(row) { reviewReport(row) {
...@@ -466,6 +466,7 @@ export default { ...@@ -466,6 +466,7 @@ export default {
this.$router.push("template-open?projectType=3&isPreview=" + isPreview); this.$router.push("template-open?projectType=3&isPreview=" + isPreview);
}, },
toEditCustomPage(isPreview = 0) { toEditCustomPage(isPreview = 0) {
this.setKind(0);
this.$router.push("edit-custom?projectType=4&isPreview=" + isPreview); this.$router.push("edit-custom?projectType=4&isPreview=" + isPreview);
}, },
toShield(row) { toShield(row) {
......
...@@ -22,6 +22,7 @@ export default { ...@@ -22,6 +22,7 @@ export default {
} }
img { img {
width: 12px; width: 12px;
height: 12px;
padding-right: 5px; padding-right: 5px;
} }
} }
......
...@@ -379,14 +379,34 @@ ...@@ -379,14 +379,34 @@
title: '学分发放管理', title: '学分发放管理',
icon: 'el-icon-document', icon: 'el-icon-document',
index: 'credit-send-manage' index: 'credit-send-manage'
}, },
// {
// title: '外部资源管理',
// icon: 'el-icon-document',
// index: 'external-resource-manage'
// },
] ]
} }
const yqRange = {
title: '云鹊小圈', const yqRange = {
icon: 'el-icon-setting', title: '云鹊小圈',
index: 'yq-range' icon: 'el-icon-setting',
}; index: 'yq-range'
};
const outResourceManage = {
title: '外部资源管理',
icon: 'el-icon-reading',
index: 'external-resource-manage',
subs: [
{
title: '外部资源列表',
icon: 'el-icon-document',
index: 'external-resource-manage'
},
]
};
vm.items[1].subs.push(itemComponent); vm.items[1].subs.push(itemComponent);
vm.items[1].subs.push(templateManager); vm.items[1].subs.push(templateManager);
...@@ -394,6 +414,7 @@ ...@@ -394,6 +414,7 @@
vm.items.push(eduRole); vm.items.push(eduRole);
vm.items.push(cme); vm.items.push(cme);
vm.items.push(yqRange); vm.items.push(yqRange);
vm.items.push(outResourceManage);
}, },
goToMessageSendPage(checkAuth) { goToMessageSendPage(checkAuth) {
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册