作者 雷海东

Merge branch 'dev' of http://39.105.222.208:1024/compliance_management/ruoyi-ui into dev

# Conflicts:
#	src/views/system/orginfo/index.vue
@@ -53,12 +53,14 @@ @@ -53,12 +53,14 @@
53 "quill": "1.3.7", 53 "quill": "1.3.7",
54 "screenfull": "5.0.2", 54 "screenfull": "5.0.2",
55 "sortablejs": "1.10.2", 55 "sortablejs": "1.10.2",
  56 + "video.js": "^8.16.1",
56 "vue": "2.6.12", 57 "vue": "2.6.12",
57 "vue-count-to": "1.0.13", 58 "vue-count-to": "1.0.13",
58 "vue-cropper": "0.5.5", 59 "vue-cropper": "0.5.5",
59 "vue-meta": "2.4.0", 60 "vue-meta": "2.4.0",
60 "vue-pdf": "^4.3.0", 61 "vue-pdf": "^4.3.0",
61 "vue-router": "3.4.9", 62 "vue-router": "3.4.9",
  63 + "vue-video-player": "^5.0.2",
62 "vuedraggable": "2.24.3", 64 "vuedraggable": "2.24.3",
63 "vuex": "3.6.0", 65 "vuex": "3.6.0",
64 "xml-js": "1.6.11" 66 "xml-js": "1.6.11"
@@ -38,6 +38,10 @@ import VueMeta from 'vue-meta' @@ -38,6 +38,10 @@ import VueMeta from 'vue-meta'
38 // 字典数据组件 38 // 字典数据组件
39 import DictData from '@/components/DictData' 39 import DictData from '@/components/DictData'
40 40
  41 +// import VideoPlayer from 'vue-video-player'
  42 +// // import 'vue-video-player/src/custom-theme.css'
  43 +// import 'video.js/dist/video-js.css'
  44 +
41 // 全局方法挂载 45 // 全局方法挂载
42 Vue.prototype.getDicts = getDicts 46 Vue.prototype.getDicts = getDicts
43 Vue.prototype.getConfigKey = getConfigKey 47 Vue.prototype.getConfigKey = getConfigKey
@@ -62,6 +66,7 @@ Vue.component('ImagePreview', ImagePreview) @@ -62,6 +66,7 @@ Vue.component('ImagePreview', ImagePreview)
62 Vue.use(directive) 66 Vue.use(directive)
63 Vue.use(plugins) 67 Vue.use(plugins)
64 Vue.use(VueMeta) 68 Vue.use(VueMeta)
  69 +// Vue.use(VideoPlayer)
65 DictData.install() 70 DictData.install()
66 71
67 /** 72 /**
@@ -113,8 +113,20 @@ export const constantRoutes = [ @@ -113,8 +113,20 @@ export const constantRoutes = [
113 meta: { title: '证照管理', icon: '' } 113 meta: { title: '证照管理', icon: '' }
114 } 114 }
115 ] 115 ]
  116 + },
  117 + {
  118 + path: '/compliance/compliancemanagement/compliancetraining',
  119 + component: Layout,
  120 + hidden: true,
  121 + children: [
  122 + {
  123 + path: 'trainingcourse/play',
  124 + component: () => import('@/views/compliancemanagement/compliancetraining/trainingcourse/play'),
  125 + name: 'orginfoCertificate',
  126 + meta: { title: '培训课程', icon: '' }
  127 + }
  128 + ]
116 } 129 }
117 - // /contract/compliancemanagement/orginfoCertificate  
118 ] 130 ]
119 131
120 // 动态路由,基于用户权限动态去加载 132 // 动态路由,基于用户权限动态去加载
@@ -107,6 +107,11 @@ @@ -107,6 +107,11 @@
107 @click="handleDelete(scope.row)" 107 @click="handleDelete(scope.row)"
108 v-hasPermi="['system:trainingcourse:remove']" 108 v-hasPermi="['system:trainingcourse:remove']"
109 >删除</el-button> 109 >删除</el-button>
  110 + <el-button
  111 + size="mini"
  112 + type="text"
  113 + @click="handlePlayer(scope.row)"
  114 + >播放视频</el-button>
110 </template> 115 </template>
111 </el-table-column> 116 </el-table-column>
112 </el-table> 117 </el-table>
@@ -229,13 +234,17 @@ export default { @@ -229,13 +234,17 @@ export default {
229 id: [ 234 id: [
230 { required: true, message: "不能为空", trigger: "blur" } 235 { required: true, message: "不能为空", trigger: "blur" }
231 ] 236 ]
232 - } 237 + },
233 }; 238 };
234 }, 239 },
235 created() { 240 created() {
236 this.getList(); 241 this.getList();
237 }, 242 },
238 methods: { 243 methods: {
  244 +//视频播放
  245 + handlePlayer(){
  246 + this.$router.push({ path: '/compliance/compliancemanagement/compliancetraining/trainingcourse/play'});
  247 + },
239 /** 查询【请填写功能名称】列表 */ 248 /** 查询【请填写功能名称】列表 */
240 getList() { 249 getList() {
241 this.loading = true; 250 this.loading = true;
  1 +<template>
  2 + <div class="info">
  3 + <div class="container">
  4 + <div class="play">
  5 + <el-row>
  6 + <el-col :span="24">
  7 + <video-player
  8 + id="video"
  9 + class="video-player vjs-custom-skin"
  10 + ref="videoPlayer"
  11 + @ended="videoEnded"
  12 + @timeupdate="videoTimeUp"
  13 + @loadeddata="videoLoaded"
  14 + @seeking="videoSeeking"
  15 + @seeked="videoSeeked"
  16 + :events="['seeking', 'seeked']"
  17 + :playsinline="true"
  18 + :options="playerOptions"
  19 + ></video-player>
  20 + <!-- <h3 id="text-progress">{{ this.progress }}</h3> -->
  21 + </el-col>
  22 + <!-- <el-col :span="6" class="text"> -->
  23 + <!-- </el-col> -->
  24 + </el-row>
  25 + </div>
  26 + </div>
  27 + </div>
  28 + </template>
  29 +
  30 + <script>
  31 + import Vue from 'vue'
  32 + import VideoPlayer from 'vue-video-player'
  33 +import 'video.js/dist/video-js.css'
  34 +import 'vue-video-player/src/custom-theme.css'
  35 +Vue.use(VideoPlayer)
  36 + export default {
  37 + data() {
  38 + return {
  39 + classHour : [],
  40 + data : [],
  41 + userId :'',
  42 + videoInformation : [],
  43 + progress : '0.00%',
  44 + durationTime : '' ,// 视频总时常
  45 + currentTime : '' ,// 当前播放进度时长
  46 + saveDurationTime : '', // 视频总时常
  47 + saveCurrentTime:'', // 当前播放进度时长
  48 + isShowSubs: false,
  49 + recodrTime :null,
  50 + playerOptions:{
  51 + playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
  52 + autoplay: false, //如果true,浏览器准备好时开始回放。
  53 + muted: false, // 默认情况下将会消除任何音频。
  54 + loop: false, // 导致视频一结束就重新开始。
  55 + preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
  56 + language: 'zh-CN',
  57 + aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
  58 + fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
  59 + sources: [
  60 + {
  61 + type: 'video/mp4', //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
  62 + src: 'http://vjs.zencdn.net/v/oceans.mp4' //url地址
  63 + }
  64 + ],
  65 + poster: '', //你的封面地址
  66 + // width: document.documentElement.clientWidth, //播放器宽度
  67 + notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息。
  68 + controlBar: {
  69 + timeDivider: true,
  70 + durationDisplay: true,
  71 + remainingTimeDisplay: false,
  72 + fullscreenToggle: true //全屏按钮
  73 + }
  74 + }
  75 + }
  76 + },
  77 + created() {
  78 + },
  79 + methods: {
  80 + // 视频信息加载完成,获取总时长,若接口返回进度,断点播放
  81 + videoLoaded(item) {
  82 + this.durationTime = item.cache_.duration
  83 + this.videoInformation = item
  84 + // console.log('progress', this.progress)
  85 + if (this.progress > '0.00%') {
  86 + item.currentTime(Number(this.currentTime))
  87 + }
  88 + // console.log('视频信息videoLoaded:', this.videoInformation)
  89 + },
  90 + // 当前播放进度
  91 + videoTimeUp(item) {
  92 + this.currentTime = item.cache_.currentTime
  93 + this.progress = ((this.currentTime.toFixed(2) / item.cache_.duration.toFixed(2)) * 100).toFixed(2) + '%'
  94 + // console.log('当前播放进度', item)
  95 + },
  96 + // 正在拖动
  97 + videoSeeking(item) {
  98 + // console.log('正在拖动',item)
  99 + this.isSeeking = true
  100 + },
  101 + // 拖动结束
  102 + videoSeeked(item) {
  103 + // console.log('拖动结束',item)
  104 + this.isSeeking = false
  105 + },
  106 +
  107 + // 点击播放
  108 + videoPlay() {
  109 + //清除定时器
  110 + if (this.pauseTimer) {
  111 + clearTimeout(this.pauseTimer)
  112 + }
  113 + },
  114 + // 触发暂停
  115 + videoPause(item) {
  116 + //利用定时器延迟
  117 + this.pauseTimer = setTimeout(() => {
  118 + if (this.isVideoEnd) return
  119 + if (this.isSeeking) return
  120 + // 展示蒙层
  121 + this.isShowSubs = true
  122 + }, 100)
  123 + },
  124 + // 播放结束
  125 + videoEnded() {
  126 + this.isVideoEnd = true
  127 + }
  128 + }
  129 + }
  130 + </script>
  131 + <style lang="scss" scoped>
  132 + $width: 1140px;
  133 + .info {
  134 + width: 100%;
  135 + }
  136 + .container {
  137 + width: $width;
  138 + margin: auto;
  139 + .breadcrumb {
  140 + padding-top: 20px;
  141 + padding-bottom: 20px;
  142 + }
  143 + .play {
  144 + box-shadow: 0 4px 8px 0 rgba(28, 31, 33, 0.1);
  145 + background-color: #26262b;
  146 + .text {
  147 + font-size: 15px;
  148 + color: #fff;
  149 + text-align: left;
  150 + .title {
  151 + padding: 12px 15px;
  152 + }
  153 + .teacher {
  154 + padding: 12px 0 12px 10px;
  155 + background: #2d2d2d;
  156 + }
  157 + .list {
  158 + height: 393px;
  159 + width: 283px;
  160 + .name1 {
  161 + cursor: pointer;
  162 + background: #2d2d2d;
  163 + font-size: 15px;
  164 + padding: 10px 0 10px 47px;
  165 + margin-top: 2px;
  166 + }
  167 + .name2 {
  168 + cursor: pointer;
  169 + color: rgb(61, 231, 112);
  170 + background: #2d2d2d;
  171 + font-size: 15px;
  172 + padding: 10px 0 10px 47px;
  173 + margin-top: 2px;
  174 + }
  175 + }
  176 + }
  177 + }
  178 + // .biref {
  179 + // box-shadow: 0 4px 8px 0 rgba(28, 31, 33, 0.1);
  180 + // background-color: #ffffff;
  181 + // font-size: 15px;
  182 + // text-align: left;
  183 + // color: #5e5e5e;
  184 + // padding: 25px 20px;
  185 + // margin: 30px 0;
  186 + // img {
  187 + // vertical-align: middle;
  188 + // margin-right: 5px;
  189 + // }
  190 + // }
  191 + }
  192 + </style>
  193 + <style>
  194 + body {
  195 + background-color: #f7f9fc !important;
  196 + /* background-color: #d7e4f7 !important; */
  197 + }
  198 + .vjs-custom-skin > .video-js .vjs-big-play-button {
  199 + width: 70px;
  200 + border-radius: 50%;
  201 + }
  202 + .el-breadcrumb__inner {
  203 + color: #2c3e50 !important;
  204 + }
  205 + .el-scrollbar__wrap {
  206 + overflow: hidden;
  207 + position: relative;
  208 + }
  209 + </style>
1 <template> 1 <template>
2 <div class="app-container home"> 2 <div class="app-container home">
3 <el-row :gutter="20"> 3 <el-row :gutter="20">
4 - <el-col :sm="24" :lg="12" style="padding-left: 20px"> 4 + <!-- <el-col :sm="24" :lg="12" style="padding-left: 20px">
5 <h2>合规管理系统</h2> 5 <h2>合规管理系统</h2>
6 - </el-col> 6 + </el-col> -->
  7 + <img src="@/assets/images/home.png" style="width: 100%;"/>
7 </el-row> 8 </el-row>
8 </div> 9 </div>
9 </template> 10 </template>
@@ -198,9 +198,8 @@ export default { @@ -198,9 +198,8 @@ export default {
198 }, 198 },
199 methods: { 199 methods: {
200 toOrginfoCertificateList(row){ 200 toOrginfoCertificateList(row){
201 - console.log('row=====',row)  
202 - this.$router.push({ path: '/system/orginfo/orginfoCertificate/orginfoCertificate/index', query: {orgcode: row.orgcode }});  
203 - }, 201 + this.$router.push({ path: '/system/orginfo/orginfoCertificate/orginfoCertificate/index', query: {orgcode: row.orgcode }});
  202 + },
204 /** 查询【请填写功能名称】列表 */ 203 /** 查询【请填写功能名称】列表 */
205 getList() { 204 getList() {
206 this.loading = true; 205 this.loading = true;
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 @keyup.enter.native="handleQuery" 17 @keyup.enter.native="handleQuery"
18 /> 18 />
19 </el-form-item> 19 </el-form-item>
20 - <el-form-item label="认证机构名称" prop="certificationName"> 20 + <el-form-item label="认证机构名称" prop="certificationName" label-width="150">
21 <el-input 21 <el-input
22 v-model="queryParams.certificationName" 22 v-model="queryParams.certificationName"
23 placeholder="请输入认证机构名称" 23 placeholder="请输入认证机构名称"
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 placeholder="请选择发证时间"> 33 placeholder="请选择发证时间">
34 </el-date-picker> 34 </el-date-picker>
35 </el-form-item> 35 </el-form-item>
36 - <el-form-item label="证书有效期" prop="certificateValidityPeriod"> 36 + <el-form-item label="证书有效期" prop="certificateValidityPeriod" label-width="100px">
37 <el-date-picker clearable 37 <el-date-picker clearable
38 v-model="queryParams.certificateValidityPeriod" 38 v-model="queryParams.certificateValidityPeriod"
39 type="date" 39 type="date"
@@ -41,14 +41,14 @@ @@ -41,14 +41,14 @@
41 placeholder="请选择证书有效期"> 41 placeholder="请选择证书有效期">
42 </el-date-picker> 42 </el-date-picker>
43 </el-form-item> 43 </el-form-item>
44 - <el-form-item label="证书附件" prop="certificateAttachment"> 44 + <!-- <el-form-item label="证书附件" prop="certificateAttachment">
45 <el-input 45 <el-input
46 v-model="queryParams.certificateAttachment" 46 v-model="queryParams.certificateAttachment"
47 placeholder="请输入证书附件" 47 placeholder="请输入证书附件"
48 clearable 48 clearable
49 @keyup.enter.native="handleQuery" 49 @keyup.enter.native="handleQuery"
50 /> 50 />
51 - </el-form-item> 51 + </el-form-item> -->
52 <el-form-item> 52 <el-form-item>
53 <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> 53 <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
54 <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> 54 <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -118,8 +118,7 @@ @@ -118,8 +118,7 @@
118 </template> 118 </template>
119 </el-table-column> 119 </el-table-column>
120 <el-table-column label="证书附件" align="center" prop="certificateAttachment" > 120 <el-table-column label="证书附件" align="center" prop="certificateAttachment" >
121 - <template slot-scope="scope">  
122 - 121 + <template slot-scope="scope">
123 <img src="@/assets/images/PDF.png" @click="openFile(scope.row.certificateAttachment)" width="40px" height="auto" style="cursor: pointer"/> 122 <img src="@/assets/images/PDF.png" @click="openFile(scope.row.certificateAttachment)" width="40px" height="auto" style="cursor: pointer"/>
124 </template> 123 </template>
125 </el-table-column> 124 </el-table-column>
@@ -151,9 +150,12 @@ @@ -151,9 +150,12 @@
151 @pagination="getList" 150 @pagination="getList"
152 /> 151 />
153 152
  153 + <el-dialog title="预览" :visible.sync="dialogVisible" width="50%" center :before-close="handleClose">
  154 + <vue-pdf :src="currentFile" type="application/pdf" width="100%" height="800px" />
  155 + </el-dialog>
154 <!-- 添加或修改单位证照表对话框 --> 156 <!-- 添加或修改单位证照表对话框 -->
155 - <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>  
156 - <el-form ref="form" :model="form" :rules="rules" label-width="80px"> 157 + <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
  158 + <el-form ref="form" :model="form" :rules="rules" label-width="110px">
157 <el-form-item label="单位编号" prop="orgcode"> 159 <el-form-item label="单位编号" prop="orgcode">
158 <el-input v-model="this.orgcode" placeholder="请输入单位编号" :disabled="true"/> 160 <el-input v-model="this.orgcode" placeholder="请输入单位编号" :disabled="true"/>
159 </el-form-item> 161 </el-form-item>
@@ -225,6 +227,9 @@ import { getToken } from "@/utils/auth"; @@ -225,6 +227,9 @@ import { getToken } from "@/utils/auth";
225 import VuePdf from 'vue-pdf'; 227 import VuePdf from 'vue-pdf';
226 export default { 228 export default {
227 name: "OrginfoCertificate", 229 name: "OrginfoCertificate",
  230 + components: {
  231 + VuePdf
  232 + },
228 data() { 233 data() {
229 return { 234 return {
230 // 设置上传的请求头部 235 // 设置上传的请求头部
@@ -233,6 +238,9 @@ export default { @@ -233,6 +238,9 @@ export default {
233 url: process.env.VUE_APP_BASE_API + "/common/uploads", 238 url: process.env.VUE_APP_BASE_API + "/common/uploads",
234 // urlhead: "http://joycart.zgftlm.com", 239 // urlhead: "http://joycart.zgftlm.com",
235 urlhead:process.env.VUE_APP_BASE_API, 240 urlhead:process.env.VUE_APP_BASE_API,
  241 + baseUrl:process.env.VUE_APP_BASE_API,
  242 + dialogVisible:false,
  243 + currentFile:'',
236 fileList: [], 244 fileList: [],
237 file:[], 245 file:[],
238 // 按钮loading 246 // 按钮loading
@@ -304,7 +312,7 @@ export default { @@ -304,7 +312,7 @@ export default {
304 methods: { 312 methods: {
305 //根据单位编号查询列表 313 //根据单位编号查询列表
306 getorgcode(orgcode){ 314 getorgcode(orgcode){
307 - console.log(orgcode) 315 + // console.log(orgcode)
308 selectByOrgnCode(orgcode).then(response =>{ 316 selectByOrgnCode(orgcode).then(response =>{
309 console.log(response.data) 317 console.log(response.data)
310 this.orginfoCertificateList = response.data 318 this.orginfoCertificateList = response.data
@@ -429,12 +437,15 @@ export default { @@ -429,12 +437,15 @@ export default {
429 }, 437 },
430 438
431 openFile(filePath) { 439 openFile(filePath) {
432 -  
433 - this.currentFile = this.urlhead+filePath; 440 + this.currentFile = this.baseUrl+filePath;
434 console.log(this.currentFile) 441 console.log(this.currentFile)
435 this.dialogVisible = true; 442 this.dialogVisible = true;
436 443
437 }, 444 },
  445 + handleClose() {
  446 + this.currentFile = ''
  447 + this.dialogVisible = false
  448 + },
438 beforeUpload(file) { 449 beforeUpload(file) {
439 const isPDF = file.type === 'application/pdf'; 450 const isPDF = file.type === 'application/pdf';
440 const isLt5M = file.size / 1024 / 1024 < 5; 451 const isLt5M = file.size / 1024 / 1024 < 5;