Переглянути джерело

Merge branch 'master' of http://git.cc-lotus.info/sckj/okc-vue

15143018065 7 місяців тому
батько
коміт
d4ecbe351b

+ 62 - 1
okc/src/main/java/com/ruoyi/okc/service/impl/OkcVideoProServiceImpl.java

@@ -811,13 +811,74 @@ public class OkcVideoProServiceImpl implements IOkcVideoProService
                 chartsStatus.getFileName();
         String title = chartsStatus.getTitle();
         mkdirs(filePath);
-        ChartUtils.createLinePortThreeD(title, dataMap, "学生控制行为", "教师控制行为", filePath, line);
+        List<List<String>> datas = new ArrayList<>();
+        if (ObjectUtils.isNotEmpty(dataMap) && dataMap.size() <= 50) {
+            try {
+                for (Map.Entry<String, String> data: dataMap.entrySet()) {
+                    List<String> in = new ArrayList<>();
+                    in.add(data.getKey());
+                    in.add(data.getValue());
+                    datas.add(in);
+                }
+                List<List<String>> inList = new ArrayList<>();
+                for (int i = 0; i < datas.size() - 1; i++) {
+                    if ((Integer.parseInt(datas.get(i).get(0)) + 1 < Integer.parseInt(datas.get(i + 1).get(0)))
+                            && !StringUtils.equals(datas.get(i).get(1), datas.get(i + 1).get(1))) {
+                        List<String> in = new ArrayList<>();
+                        in.add(String.valueOf(Integer.parseInt(datas.get(i + 1).get(0)) - 1));
+                        in.add(datas.get(i).get(1));
+                        inList.add(in);
+                    }
+                }
+                datas.addAll(inList);
+                datas = datas.stream().sorted(Comparator.comparing(c -> Integer.parseInt(c.get(1))))
+                        .sorted(Comparator.comparing(c -> Integer.parseInt(c.get(0)))).collect(Collectors.toList());
+            } catch (Exception e) {
+                List<List<String>> newData = new ArrayList<>();
+                for (Map.Entry<String, String> data: dataMap.entrySet()) {
+                    List<String> in = new ArrayList<>();
+                    in.add(data.getKey());
+                    in.add(data.getValue());
+                    newData.add(in);
+                }
+                datas = newData;
+            }
+//            datas = dataMap.keySet().stream().collect(Collectors.toList());
+//            Map<String, String> in = new LinkedHashMap<>();
+//            List<String> inList = new ArrayList<>();
+//            for (Map.Entry<String, String> data: dataMap.entrySet()) {
+//                inList.add(data.getKey());
+//            }
+//            for (int i = 0; i < inList.size() - 1; i++) {
+//                if (Integer.parseInt(inList.get(i)) + 1 < Integer.parseInt(inList.get(i + 1))) {
+//                    in.put(String.valueOf(Integer.parseInt(inList.get(i + 1)) - 1), dataMap.get(inList.get(i)));
+//                }
+//            }
+//            dataMap.putAll(in);
+        } else {
+            for (Map.Entry<String, String> data: dataMap.entrySet()) {
+                List<String> in = new ArrayList<>();
+                in.add(data.getKey());
+                in.add(data.getValue());
+                datas.add(in);
+            }
+        }
+//        map = dataMap.entrySet().stream().collect(Collectors.toMap(e -> Integer.parseInt(e.getKey()), Map.Entry::getValue));
+//        map = sortByKey(map);
+        ChartUtils.createLinePortThreeD(title, datas, "学生控制行为", "教师控制行为", filePath, line);
         res.put("name", chartsStatus.getFileName());
         res.put("path", filePath);
         res.put("relativePath", "/profile/" + okcVideoPro.getId() + File.separator + chartsStatus.getFileName());
         return res;
     }
 
+    public Map<Integer, String> sortByKey(Map<Integer, String> map) {
+        Map<Integer, String> result = new LinkedHashMap<>();
+        map.entrySet().stream()
+                .sorted(Map.Entry.<Integer, String>comparingByKey()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
+        return result;
+    }
+
     private Map<String, Object> getBehavierLine(List<OkcVideoRec> recList, String st) {
         Map<String, Object> res = new LinkedHashMap<>();
         Map<String, String> data = new LinkedHashMap<>();

+ 3 - 0
okc/src/main/resources/mapper/okc/OkcVideoProMapper.xml

@@ -53,6 +53,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createUserId != null  and createUserId != ''"> and create_user_id = #{createUserId}</if>
             <if test="videoName != null  and videoName != ''"> and video_name like concat('%', #{videoName}, '%')</if>
         </where>
+        <if test='params.order != null and params.order == "time"'> order by create_time_str</if>
+        <if test='params.order != null and params.order == "name"'> order by class_name</if>
+        <if test="params.desc != null and params.desc != ''"> desc</if>
     </select>
 
     <select id="selectOkcVideoProById" parameterType="String" resultMap="OkcVideoProResult">

+ 4 - 2
ruoyi-common/src/main/java/com/ruoyi/common/utils/ChartUtils.java

@@ -6,6 +6,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.text.NumberFormat;
 import java.util.*;
+import java.util.List;
 import java.util.Map.Entry;
 
 import com.ruoyi.common.config.RuoYiConfig;
@@ -228,11 +229,12 @@ public class ChartUtils {
         }
     }
 
-    public static void createLinePortThreeD(String title, Map<String, String> datas, String xName, String yName, String url, double line){
+    public static void createLinePortThreeD(String title, List<List<String>> datas, String xName, String yName, String url, double line){
         try {
             // 折线图3D
             DefaultCategoryDataset dataset = new DefaultCategoryDataset();
-            datas.forEach((key, value) -> dataset.setValue(Double.parseDouble(value), title, key));
+            datas.forEach(d -> dataset.setValue(Double.parseDouble(d.get(1)), title, d.get(0)));
+//            datas.forEach((key, value) -> dataset.setValue(Double.parseDouble(value), title, key));
             JFreeChart chart = ChartFactory.createLineChart(title, "", "", dataset,//2D折线图
                     PlotOrientation.VERTICAL,
                     true, // 是否显示图例(对于简单的柱状图必须是false)

+ 9 - 0
ruoyi-ui/src/components/PageHeader/index.vue

@@ -5,18 +5,27 @@
 </template>
 
 <script>
+  import { mapGetters } from 'vuex'
 export default {
 	name: 'PageHeader',
 	data() {
 		return {}
 	},
 	computed: {
+    ...mapGetters([
+      'isAdmin',
+    ]),
 		content() {
 			return this.$route.meta.title
 		}
 	},
 	methods: {
 		goBack() {
+		  console.log(this.$router.history.current.path,'this.$router.history.current.path');
+		  if(!this.isAdmin&&this.$router.history.current.path=='/editor')
+      {
+        return
+      }
 			if(this.$router.history.current.path !== '/index'){
 				this.$router.go(-1)
 			}

+ 2 - 2
ruoyi-ui/src/layout/components/Sidebar/Logo.vue

@@ -1,11 +1,11 @@
 <template>
   <div class="sidebar-logo-container" :class="{'collapse':collapse}">
     <transition name="sidebarLogoFade">
-      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
+      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" :to=" {path: $route.fullPath}">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
         <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
       </router-link>
-      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
+      <router-link v-else key="expand" class="sidebar-logo-link" :to=" {path: $route.fullPath}">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
         <h1 class="sidebar-title">{{ title }} </h1>
       </router-link>

+ 42 - 14
ruoyi-ui/src/views/editor/courseEdit.vue

@@ -5,6 +5,14 @@
         style="color: #30D2BE;"
 				@click="handleAdd" v-hasPermi="['okc:videoPro:edit']"
       >新建课堂</el-button>
+      <el-select v-model="valueIndex" @change="getList" style="width: 150px;margin-left: 12px" placeholder="请选择">
+        <el-option
+          v-for="item in sortOpt"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value">
+        </el-option>
+      </el-select>
 			<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 		</el-row>
 
@@ -118,8 +126,8 @@
 				<table style="width: 100%">
 					<tr>
 						<td>
-							<el-form-item label="课程名称及主题" prop="className">
-								<el-input v-model="videoForm.className" placeholder="请输入课程名称及主题"></el-input>
+							<el-form-item label="课程名称及主题" prop="className" >
+								<el-input v-model="videoForm.className" auto-complete="on" name="className" placeholder="请输入课程名称及主题"></el-input>
 							</el-form-item>
 						</td>
 						<td>
@@ -161,7 +169,7 @@
 					<tr>
 						<td>
 							<el-form-item label="主讲老师" prop="teacher">
-								<el-input v-model="videoForm.teacher" placeholder="请输入主讲老师"></el-input>
+								<el-input v-model="videoForm.teacher" auto-complete="on" name="teacher" placeholder="请输入主讲老师"></el-input>
 							</el-form-item>
 						</td>
 						<td>
@@ -179,7 +187,7 @@
 					<tr>
 						<td>
 							<el-form-item label="所在学校" prop="school">
-								<el-input v-model="videoForm.school" placeholder="请输入所在学校"></el-input>
+								<el-input v-model="videoForm.school" auto-complete="on" name="school" placeholder="请输入所在学校"></el-input>
 							</el-form-item>
 						</td>
 						<td>
@@ -199,7 +207,7 @@
 					<tr>
 						<td colspan="2">
 							<el-form-item label="课程视频文件" prop="fileName">
-								<el-input class="video-ipt" type="text" v-model="videoForm.fileName"  placeholder="请导入mp4格式的视频文件" disabled />
+								<el-input class="video-ipt" type="text" v-model="videoForm.fileName"  placeholder="请导入mp4格式的视频文件" :disabled="isDisabled" />
 								<el-button
 									type="info"
 									plain
@@ -402,7 +410,15 @@ export default {
 			videoForm: {},
 			videoFile: null,
 			vLoading: false,
+      isDisabled:true,
 			videoIdForImport: null,
+      valueIndex:1,
+      sortOpt:[
+        {label:'时间正序',value:0, order:'time',desc:''},
+        {label:'时间倒序',value:1,order:'time',desc:'desc'},
+        {label:'名称正序',value:2,order:'name',desc:''},
+        {label:'名称倒序',value:3,order:'name',desc:'desc'},
+      ],
       classroomTypeOpt:[
         {value:'传统教室'},
         {value:'智慧教室'},
@@ -470,9 +486,9 @@ export default {
         {value:'香港'},
       ],
       querySearch(queryString, cb,restaurants) {
-        let results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants;
+        // let results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants;
         // 调用 callback 返回建议列表的数据
-        cb(results);
+        cb(restaurants);
       },
       createFilter(queryString) {
         return (restaurant) => {
@@ -481,7 +497,7 @@ export default {
       },
 			videoRules: {
 				region: [
-					{ required: true, message: '所在地区不能为空', trigger: 'blur' }
+					{ required: true, message: '所在地区不能为空', trigger: 'change' }
 				],
 				teacher: [
 					{ required: true, message: '主讲老师不能为空', trigger: 'blur' }
@@ -490,13 +506,13 @@ export default {
 					{ required: true, message: '所在学校不能为空', trigger: 'blur' }
 				],
 				teacherTitle: [
-					{ required: false, message: '教师职称不能为空', trigger: 'blur' }
+					{ required: false, message: '教师职称不能为空', trigger: 'change' }
 				],
 				branch: [
-					{ required: true, message: '学科不能为空', trigger: 'blur' }
+					{ required: true, message: '学科不能为空', trigger: 'change' }
 				],
 				session: [
-					{ required: true, message: '课程学年不能为空', trigger: 'blur' }
+					{ required: true, message: '课程学年不能为空', trigger: 'change' }
 				],
 				className: [
 					{ required: true, message: '课程名称及主题不能为空', trigger: 'blur' }
@@ -605,7 +621,15 @@ export default {
 		/** 查询视频项目信息列表 */
 		getList() {
 			this.tLoading = true
-			listVideoPro(this.queryParams).then(response => {
+      let formQur={
+        params:{
+          order:this.sortOpt[this.valueIndex].order,
+          desc:this.sortOpt[this.valueIndex].desc,
+        },
+        ...this.queryParams
+      };
+			console.log(formQur,'<--------formQur');
+			listVideoPro(formQur).then(response => {
 				this.videoProList = response.rows
 				this.total = response.total
 				this.tLoading = false
@@ -625,10 +649,14 @@ export default {
 		getVideo(e) {
 			let file = e.target.files[0],
 				types = ['video/mp4', 'video/ogm', 'video/wmv', 'video/mpg', 'video/webm', 'video/ogv', 'video/mov', 'video/asx', 'video/mpeg', 'video/m4v', 'video/avi']
-			if (types.indexOf(file.type) > -1) {
+      console.log(file.name,'<-------file');
+      if (types.indexOf(file.type) > -1) {
+        this.videoFile = file
+        this.isDisabled=false;
 				this.videoForm.fileName = file.name
-				this.videoFile = file
+        this.isDisabled=true;
 				this.videoForm.videoDur = file.size
+        console.log(this.videoForm,'<-------this.videoForm');
 				this.getDuration(file)
 			} else {
 				this.$modal.msgSuccess('所选文件格式不支持!')

+ 6 - 3
ruoyi-ui/src/views/editor/index.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="container">
 		<!--<h3 class="project-name">项目名称:{{}}</h3>-->
-		<el-tabs v-model="activeName" @tab-click="handleTab">
+		<el-tabs v-model="activeName" @tab-click="handleTab" :before-leave="beforeLeave">
 			<el-tab-pane label="文档编辑" name="first" v-if="isAdmin">
 				<documentEdit></documentEdit>
 			</el-tab-pane>
@@ -12,10 +12,8 @@
 				<excelEdit></excelEdit>
 			</el-tab-pane>
       <el-tab-pane label="教师发展助手" name="five">
-
       </el-tab-pane>
       <el-tab-pane label="图谱分析平台" name="six">
-
       </el-tab-pane>
 		</el-tabs>
 	</div>
@@ -56,6 +54,11 @@ export default {
       }
 
 		},
+    beforeLeave(activeName, oldActiveName){
+       if(activeName=='five'||activeName=='six'){
+         return false
+       }
+    }
 	},
 }
 </script>

+ 30 - 8
ruoyi-ui/src/views/system/user/profile/userInfo.vue

@@ -2,7 +2,7 @@
   <el-form ref="form" :model="user" :rules="rules" label-width="80px">
     <el-form-item label="用户昵称" prop="nickName">
       <el-input v-model="user.nickName" maxlength="30" />
-    </el-form-item> 
+    </el-form-item>
     <el-form-item label="手机号码" prop="phonenumber">
       <el-input v-model="user.phonenumber" maxlength="11" />
     </el-form-item>
@@ -24,13 +24,18 @@
 
 <script>
 import { updateUserProfile } from "@/api/system/user";
-
+import { mapGetters } from 'vuex'
 export default {
   props: {
     user: {
       type: Object
     }
   },
+  computed: {
+    ...mapGetters([
+      'isAdmin',
+    ]),
+  },
   data() {
     return {
       // 表单校验
@@ -48,11 +53,11 @@ export default {
         ],
         phonenumber: [
           { required: true, message: "手机号码不能为空", trigger: "blur" },
-          {
-            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
-            message: "请输入正确的手机号码",
-            trigger: "blur"
-          }
+          // {
+          //   pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+          //   message: "请输入正确的手机号码",
+          //   trigger: "blur"
+          // }
         ]
       }
     };
@@ -68,8 +73,25 @@ export default {
       });
     },
     close() {
-      this.$tab.closePage();
+      // this.$tab.closePage();
+      if(this.isAdmin)
+      {
+        this.$router.push({ path: '/index' })
+      }else{
+        this.$router.push({ path: '/editor' })
+      }
     }
   }
 };
 </script>
+<style scoped>
+  /deep/ .el-form-item__label{
+    color: black;
+  }
+  /deep/ .el-input__inner{
+    color: black;
+  }
+  /deep/ .el-radio{
+    color: black;
+  }
+</style>

+ 40 - 30
ruoyi-ui/src/views/videoAnalysis/index.vue

@@ -22,7 +22,7 @@
           </el-select>
         </el-form-item>
         <el-form-item label="备注">
-          <el-input  type="textarea" v-model="radios.comments" placeholder="请输入备注" />
+          <el-input  type="textarea" v-model="workForm.comments" placeholder="请输入备注" />
         </el-form-item>
       </el-form>
       <div class="btBox">
@@ -37,16 +37,15 @@
 
     </div>
     <div class="box_right">
-      <video class="video" id="video" ref="video"  controlslist="nodownload"  disablePictureInPicture   oncontextmenu = "return false"  :controls="showCtrl"></video>
       <!--视频上方中间时间-->
       <p class="duration">持续时间区间:{{ formatTime(startTime)}} - {{formatTime(endTime)}}</p>
-
+      <video class="video" id="video" ref="video"  controlslist="nodownload"  disablePictureInPicture   oncontextmenu = "return false"  :controls="showCtrl"></video>
       <!--视频右边工具图标-->
       <div class="v-okc tool-wrap">
         <!--v-hasPermi="['okc:videoPro:remove']"-->
-        <el-button v-if="!disabled" class="tool-btn" plain circle icon="el-icon-plus"  @click="changeProject" />
-        <el-button class="tool-btn" plain circle icon="el-icon-edit"  @click="openDrawer('draw')" />
-        <el-button class="tool-btn" plain circle icon="el-icon-upload2"  @click="openDrawer('export')" />
+        <el-button v-if="!disabled" title="导入视频"  class="tool-btn" plain circle icon="el-icon-plus"  @click="changeProject" />
+        <el-button class="tool-btn" title="绘制图表"  plain circle icon="el-icon-edit"  @click="openDrawer('draw')" />
+        <el-button class="tool-btn" title="导出图表"  plain circle icon="el-icon-upload2"  @click="openDrawer('export')" />
       </div>
 
       <!--视频左边工具图标-->
@@ -508,7 +507,19 @@ export default {
 				this.$modal.msgSuccess('所选文件格式不支持!')
 			}
 		},
-
+    changeUpdateVideoPro(){
+      updateVideoPro(this.projectForm).then((res) => {
+        this.$modal.msgSuccess('视频导入成功')
+        this.$refs.video.src = URL.createObjectURL(this.projectForm.file)
+        this.showCtrl = true
+        this.$refs.video.autoplay = true
+        yuxStorage.setItem(this.projectForm.id, this.projectForm.file).catch(err => console.log(err))
+        this.projectDialog = false
+      }).finally(() => {
+        this.pLoading = false
+        this.disabled = true
+      })
+    },
 		// 提交新建项目
 		submitProjectForm() {
 			this.$refs.projectForm.validate((valid) => {
@@ -516,20 +527,17 @@ export default {
 					this.pLoading = true
 					if (this.projectForm.id) {
 						if (this.projectForm.videoDur == this.projectTemp.videoDur || this.projectTemp.videoDur === null) {
-							updateVideoPro(this.projectForm).then((res) => {
-								this.$modal.msgSuccess('视频导入成功')
-								this.$refs.video.src = URL.createObjectURL(this.projectForm.file)
-								this.showCtrl = true
-								this.$refs.video.autoplay = true
-								yuxStorage.setItem(this.projectForm.id, this.projectForm.file).catch(err => console.log(err))
-								this.projectDialog = false
-							}).finally(() => {
-								this.pLoading = false
-								this.disabled = true
-							})
+                  this.changeUpdateVideoPro();
 						} else {
-							this.$modal.msgError('导入的视频非本项目原视频,请重试!')
-							this.pLoading = false
+              this.$confirm('导入的视频非本项目原视频,确定导入?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+              }).then(() => {
+                this.changeUpdateVideoPro();
+              }).catch(() => {});
+							// this.$modal.msgError('导入的视频非本项目原视频,请重试!')
+							// this.pLoading = false
 						}
 					} else {
 						// 生成项目ID
@@ -610,11 +618,11 @@ export default {
 		// 开始截取
 		getStartTime() {
 			let currentTime = this.$refs.video.currentTime
-			if (this.startTime === 0) {
+			// if (this.startTime === 0) {
 				this.startTime = currentTime
-			} else {
-				this.$modal.msgSuccess('开始截取时间必须为上次结束时间!')
-			}
+			// } else {
+			// 	this.$modal.msgSuccess('开始截取时间必须为上次结束时间!')
+			// }
 		},
 
 		// 结束截取
@@ -693,8 +701,8 @@ export default {
 				if (response.code === 200) {
 					response.rows.forEach((item, index) => {
 						item.orderId = index + 1
-						item.startShowTime = this.timeTranslate(item.startTime)
-						item.endShowTime = this.timeTranslate(item.endTime)
+						item.startShowTime = this.formatTime(item.startTime)
+						item.endShowTime = this.formatTime(item.endTime)
 					})
 					this.history = response.rows
 				}
@@ -721,7 +729,7 @@ export default {
 			if (this.currentRecord) {
 				this.$refs.video.currentTime = Number(this.currentRecord.startTime)
 				this.startTime = Number(this.currentRecord.startTime)
-				this.endTime = 0
+				this.endTime = Number(this.currentRecord.endTime)
 				this.workForm = {
 					id: this.currentRecord.id,
 					behavior: this.currentRecord.behavior,
@@ -836,7 +844,7 @@ export default {
 						return item
 					})
 					this.chartsData.unshift(
-						['时间', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'B11', 'B12', 'B13', 'B14', 'B15', 'B16', 'IL', 'II', 'IC', 'IP', 'IA', 'IX', 'TL', 'TI', 'TP', 'ID', 'Verbal', 'Non_media', 'CK', 'PK', 'TK', 'PCK', 'TCK', 'TPK', 'TPACK']
+						['时间', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'B11', 'B12', 'B13', 'B14', 'B15', 'B16', 'M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12', 'CK', 'PK', 'TK', 'PCK', 'TCK', 'TPK', 'TPACK']
 					)
 				} else {
 					this.$modal.msgWarning('暂无RC数据!')
@@ -1157,6 +1165,8 @@ export default {
     width: 85%;
     height: 100%;
     position: relative;
+    display: flex;
+    flex-direction: column;
     video {
       width: 100%;
       background-color: #000;
@@ -1171,8 +1181,8 @@ export default {
 
 }
 .duration {
-  position: absolute;
-  top: 1%;
+  /*position: relative;*/
+  /*top: 1%;*/
   width: 100%;
   margin: 0;
   text-align: center;