| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <script setup lang="ts">
- import {onMounted, ref, type Ref, watch} from "vue";
- import * as echarts from 'echarts';
- import {inject} from "vue-demi";
- import type {EChartsType} from "echarts";
- import useApis from "@/apis";
- const props = defineProps<{
- assignmentId:number,
- splitNumber:number,
- }>()
- const currentEngagement = inject('currentEngagement') as Ref<any>;
- let productData = [];
- let cursorData = [];
- let processData = [];
- watch(currentEngagement,()=>{
- noData.value = false
- setTimeout(()=>{
- let chartDom = document.getElementById('process-canvas');
- if (!chartDom)return;
- let myChart = echarts.getInstanceByDom(chartDom);
- if (!myChart){
- myChart = echarts.init(chartDom);
- }
- getCanvasData(myChart);
- },0)
- });
- const loadingStatus = inject('loadingStatus') as Ref<{
- edit:boolean,
- pause:boolean,
- process:boolean,
- total:boolean
- }>;
- function formatTimeWithMilliseconds(stamp:number,flag = false ){
- const date = new Date(stamp);
- const hours = date.getHours().toString().padStart(2, '0');
- const minutes = date.getMinutes().toString().padStart(2, '0');
- const seconds = date.getSeconds().toString().padStart(2, '0');
- if (flag){
- return `${hours}:${minutes}:${seconds}`
- }
- const milliseconds = date.getMilliseconds().toString().padStart(3, '0');
- return `${hours}:${minutes}:${seconds}.${milliseconds}`;
- }
- const apis = useApis();
- //停顿数据
- const pauseData:any[] = [];
- let chartData:any[] = [];
- //visualMap 上下限
- const limit = {
- max:0,
- min:0
- }
- let versionIndex = inject('currentVersionIndex') satisfies Ref<number>
- watch(versionIndex,()=>{
- setTimeout(()=>{
- let chartDom = document.getElementById('process-canvas');
- if (!chartDom)return;
- let myChart = echarts.getInstanceByDom(chartDom);
- if (!myChart){
- myChart = echarts.init(chartDom);
- }
- getCanvasData(myChart);
- },0)
- })
- function getCanvasData(chart:EChartsType){
- //TODO
- if (!currentEngagement.value){
- return;
- }
- chart.showLoading({text:'加载中'});
- loadingStatus.value.process = true;
- let studentId = currentEngagement.value.studentId;
- let assignmentId = currentEngagement.value.assignmentId;
- apis.selectBehaviorRecordVersions(studentId,assignmentId)
- .then((res:any) => {
- if (res.data && res.data.code == 200 && res.data.data && res.data.data.versions
- && Array.isArray(res.data.data.versions[versionIndex.value]?.events)){
- let rowData = res.data.data.versions[versionIndex.value].events as any[];
- console.log("行为数据",rowData);
- //数组初始化
- let clock = new Date(0);
- clock.setHours(clock.getHours() + 16);
- // clock.setFullYear(2025)
- // clock.setMonth(6)
- // clock.setDate(26);
- cursorData = [[clock,0]]
- productData = [[clock,0]]
- processData = [[clock,0]]
- pauseData.length = 0;
- chartData.length = 0;
- let processCount = 0;
- let zeroCount =0;
- if (!rowData){
- chart.hideLoading();
- loadingStatus.value.process = false;
- noData.value = true
- return
- }
- else{
- loadingStatus.value.process = false;
- noData.value = false
- }
- rowData.forEach((item:any) => {
- // console.log("item",item)
- let startStamp = 0;
- if (item.startStamp){
- startStamp = item.startStamp;
- }
- else{
- return;
- }
- if (item.pauseTime < 0){
- return;
- }
- if (startStamp == 0){
- zeroCount++;
- }
- if (zeroCount>1){
- zeroCount = 0;
- return;
- }
- let clock = new Date(startStamp);
- clock.setHours(clock.getHours() + 16);
- // clock.setFullYear(2025)
- // clock.setMonth(6)
- // clock.setDate(26);
- cursorData.push([clock,item.retain+1])
- productData.push([clock,item.docLength])
- pauseData.push([clock,item.pauseTime])
- chartData.push([clock,item.pauseTime])
- limit.max = Math.max(limit.max,item.pauseTime);
- let temp = 0;
- if (productData.length == 1){
- temp = productData[0][1];
- }
- else{
- let pre = productData[productData.length-2][1];
- if (item.docLength > pre){
- temp += item.docLength - pre;
- }
- }
- processCount+=temp;
- processData.push([clock,processCount])
- })
- let option = {
- xAxis: {
- type: 'time',
- axisPointer: {
- label: {
- show: true,
- formatter: function(params) {
- return formatTimeWithMilliseconds(params.value);
- }
- },
- show: true,
- type: "line"
- },
- splitNumber: props.splitNumber,
- axisLabel:{
- formatter: function(value) {
- return formatTimeWithMilliseconds(value,true);
- }
- }
- },
- yAxis: [{
- type: 'value',
- name:'characters',
- position:'left',
- alignTicks:true
- },{
- type: 'value',
- name:'停顿时间(s)',
- position: 'right',
- axisLabel:{
- formatter: function (value:number) {
- return (value/1000).toFixed(2) + 's';
- }
- }
- }],
- tooltip:{
- },
- dataZoom: [
- {
- type: 'inside',
- },
- {
- type: 'slider',
- labelFormatter: function (value) {
- return formatTimeWithMilliseconds(value,true);
- },
- left:60,
- right:60
- }
- ],
- legend:{
- left:0
- },
- visualMap: {
- type: 'continuous', // 连续型映射
- calculable: true,
- min: 0, // 数据最小值
- max: limit.max, // 数据最大值
- dimension: 1, // 根据第2个维度(y值)映射颜色
- inRange: {
- color: ['orange', 'red'] // 渐变范围:小值→蓝色,大值→红色
- },
- seriesIndex: [3],
- itemWidth: 10,
- top:0,
- right:0,
- orient:'horizontal',
- align: 'right',
- formatter: function (value:number) {
- return (value/1000).toFixed(3)+'s'; // 范围标签显示内容。
- }
- },
- series: [
- {
- itemStyle: {
- color:'#37ff00',
- opacity: 0
- },
- name:'product',
- data: productData,
- type: 'line',
- yAxisIndex: 0
- },
- {
- itemStyle: {
- color:'#37ff00',
- opacity: 0
- },
- lineStyle: {
- type: "dotted"
- },
- name:'cursor',
- data: cursorData,
- type: 'line',
- yAxisIndex: 0
- },
- {
- itemStyle: {
- color:'#1d86dc',
- opacity: 0
- },
- name:'process',
- data: processData,
- type: 'line',
- yAxisIndex: 0
- },
- {
- symbolSize: 10,
- data: chartData,
- type: 'scatter',
- yAxisIndex: 1
- }
- ]
- };
- chart.setOption( option);
- chart.hideLoading();
- loadingStatus.value.process = false;
- chart.on('datarangeselected', (params:any) => {
- let range = params.selected as [number,number];
- chartData = pauseData.filter((item:any) => {
- return item[1] >= range[0] && item[1] <= range[1];
- })
- option.series[3].data = chartData;
- chart.setOption(option)
- });
- }
- else{
- loadingStatus.value.process = false
- chart.hideLoading()
- noData.value = true
- }
- })
- //测试用数据
- }
- let noData = ref(false)
- onMounted(()=>{
- let chartDom = document.getElementById('process-canvas');
- let myChart = echarts.init(chartDom);
- getCanvasData(myChart)
- window.addEventListener('resize', ()=>{
- myChart.resize()
- })
- })
- </script>
- <template>
- <div id="process-canvas" class="canvas-container" v-if="!noData">
- </div>
- <div class="canvas-container" v-else>
- <el-empty description="暂无数据"/>
- </div>
- </template>
- <style scoped>
- .canvas-container{
- width: 100%;
- height: 100%;
- }
- </style>
|