课时统计

46 篇文章 0 订阅
7 篇文章 0 订阅

项目是是应用springmvc 框架

java,类,控制层

package com.school.web.controller.nini;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.school.business.StatisticsDurationCuManager;
import com.school.domain.StatisticsDurationCourse;
import com.school.util.PageRequest;
import com.school.util.Pageable;
import com.school.util.Paginator;

@Controller
@RequestMapping("/secure/course/statistics")
public class StatisticsDurationCuController extends AbstractSecureController {

    @Autowired
    private StatisticsDurationCuManager statisticsDurationCuManager;

    /**
     * 根据一门课程学员分组去统计时长。
     */
    @RequestMapping("/{courseId}/duration")
    public ModelAndView getStuOneCourseDur(@PathVariable String courseId, HttpServletRequest request) {
        String schoolId = this.getSchoolId(request); // 网校ID
        int page = ServletRequestUtils.getIntParameter(request, "page", 1); // 第几页
        // 分页查询该课程的所有学员
        Pageable pageable = new PageRequest(page, PAGE_SIZE);
        Paginator<StatisticsDurationCourse> paginator = statisticsDurationCuManager.getDurationByCourse(schoolId,
                courseId, pageable);
        // 模版视图
        ModelAndView mav = this.createCourseModelAndView(courseId, request);
        mav.setViewName(getSecureViewDir(request) + "/courseStatistics/students");

        String queryString = null;
        mav.addObject("paginator", paginator);
        mav.addObject("paginationHtml", paginator.toPaginationHtml(queryString));

        return mav;
    }

    /**
     * 根据一门课程学员分组去统计时长的详情。(分页)
     */
    @RequestMapping("/{courseId}/duration/{userId}/detailed")
    public ModelAndView getStuOneCourseDurDetail(@PathVariable String courseId, @PathVariable String userId,
            HttpServletRequest request) {
        String schoolId = this.getSchoolId(request); // 网校ID
        String nickname = ServletRequestUtils.getStringParameter(request, "nickname", "");
        String duration = ServletRequestUtils.getStringParameter(request, "duration", "");
        String count = ServletRequestUtils.getStringParameter(request, "count", "");
        int page = ServletRequestUtils.getIntParameter(request, "page", 1); // 第几页
        // 分页查询
        Pageable pageable = new PageRequest(page, PAGE_SIZE);
        Paginator<StatisticsDurationCourse> paginator = statisticsDurationCuManager.getDurByCourseDetailPage(schoolId,
                courseId, userId, pageable);
        // 模版视图
        ModelAndView mav = this.createCourseModelAndView(courseId, request);
        mav.setViewName(getSecureViewDir(request) + "/courseStatistics/detailed");

        String url = "/secure/course/statistics/" + courseId + "/duration/" + userId + "/detailed";
        String queryString = null;
        mav.addObject("paginator", paginator);
        mav.addObject("paginationHtml", paginator.toPaginationHtml(url, queryString));

        mav.addObject("nickname", nickname);
        mav.addObject("courseId", courseId);
        mav.addObject("userId", courseId);
        mav.addObject("duration", duration);
        mav.addObject("count", count);
        return mav;
    }

    /**
     * 根据一门课程学员分组去统计时长的详情。(不分页)
     */
    @RequestMapping("/{courseId}/duration/{userId}/detailed/list")
    public ModelAndView getStuOneCoDurDetailList(@PathVariable String courseId, @PathVariable String userId,
            HttpServletRequest request) {
        String schoolId = this.getSchoolId(request); // 网校ID
        String nickname = ServletRequestUtils.getStringParameter(request, "nickname", "");

        List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurByCourseDetailed(schoolId,
                courseId, userId);
        // 模版视图
        ModelAndView mav = this.createCourseModelAndView(courseId, request);
        mav.setViewName(getSecureViewDir(request) + "/courseStatistics/detailed");

        mav.addObject("durationList", durationList);
        mav.addObject("nickname", nickname);
        return mav;
    }

    /**
     * 一门课程最近30天的时长统计
     * @throws IOException
     * @throws ParseException
     */
    @RequestMapping("/{courseId}/duration/day")
    public ModelAndView getCourseDurationDay(@PathVariable String courseId, HttpServletRequest request)
            throws IOException, ParseException {
        String schoolId = this.getSchoolId(request); // 网校ID
        String type = ServletRequestUtils.getStringParameter(request, "type", "");
        String startDate = ServletRequestUtils.getStringParameter(request, "startDate", "");
        String endDate = ServletRequestUtils.getStringParameter(request, "endDate", "");
        ModelAndView mav = this.createCourseModelAndView(courseId, request);
        
        boolean selectmark = false;// 页面传过来的不合法的自定义的查询条件

        if (StringUtils.isNotBlank(type)) {

            if ("week".equals(type.trim())) {
                // 按照时间的顺序,最近7天
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String currentTime = sdf.format(new Date());
                String sevenDay = getPassDate(currentTime, 7);
                
                List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
                        schoolId, courseId, sevenDay, currentTime);
                
                //补数据,没有记录的数据,一天没有产生数据,补一条0的数据
                List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,7);
                mav.addObject("durationList", durationListData);
                
                // 报表所需要的折线图
                List<String> dayList = new ArrayList<String>();
                List<Integer> numberList = new ArrayList<Integer>();
                List<Float> totalTimes = new ArrayList<Float>();
                
                if (durationListData.size() > 0) {
                    for (int i = durationListData.size(); i >0; i--) {
                        StatisticsDurationCourse sdc = new StatisticsDurationCourse();
                        sdc = durationListData.get(i-1);
                        String dateString=sdf.format(sdc.getDate());
                           
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(sdf.parse(dateString));
                        int month = cal.get(Calendar.MONTH) + 1;
                        int day = cal.get(Calendar.DAY_OF_MONTH);
                        String dayX = month + "月" + day + "日";
                        numberList.add(sdc.getNumber());
                        totalTimes.add(sdc.getTotalDuration()*60);
                        dayList.add(dayX);
                    }
                    
                }

                // 转为json数组
                String numberListStr = writeListToJsonArray(numberList);
                String dayListStr = writeListToJsonArray(dayList);
                String totalTimesStr = writeListToJsonArray(totalTimes);

                mav.addObject("numberList", numberListStr);// 次数
                mav.addObject("totalTimes", totalTimesStr);// 时长
                mav.addObject("dayList", dayListStr);// 时间
                mav.addObject("timeMark", "week");// 查询条件说明

            } else if ("month".equals(type.trim())) {
                // 最近30天
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String currentTime = sdf.format(new Date());
                String thirtyDay = getPassDate(currentTime, 30);
                List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
                        schoolId, courseId, thirtyDay, currentTime);
               
             //补数据,没有记录的数据,一天没有产生数据,补一条0的数据
               List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,30);
               mav.addObject("durationList", durationListData);
               
                // 报表所需要的折线图
                List<String> dayList = new ArrayList<String>();
                List<Integer> numberList = new ArrayList<Integer>();
                List<Float> totalTimes = new ArrayList<Float>();

                if (durationListData.size() > 0) {
                    for (int i = durationListData.size(); i >0; i--)  {
                        StatisticsDurationCourse sdc = new StatisticsDurationCourse();
                        sdc = durationListData.get(i-1);

                        Calendar cal = Calendar.getInstance();
                        cal.setTime(sdc.getDate());
                        int month = cal.get(Calendar.MONTH) + 1;
                        int day = cal.get(Calendar.DAY_OF_MONTH);
                        String dayX = month + "月" + day + "日";
                        numberList.add(sdc.getNumber());
                        totalTimes.add(sdc.getTotalDuration() * 60);
                        dayList.add(dayX);
                    }
                }

                // 转为json数组
                String numberListStr = writeListToJsonArray(numberList);
                String dayListStr = writeListToJsonArray(dayList);
                String totalTimesStr = writeListToJsonArray(totalTimes);

                mav.addObject("numberList", numberListStr);// 次数
                mav.addObject("totalTimes", totalTimesStr);// 时长
                mav.addObject("dayList", dayListStr);// 时间
                mav.addObject("timeMark", "month");// 查询条件说明
            } else if ("time".equals(type.trim())) {
                // 自由选择时间
                // 时间段小于30天
                // 结束时间超过当前时间
                if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    Date d1 = sdf.parse(startDate);
                    Date d2 = sdf.parse(endDate);
                    Date now = new Date();
                    long daysNows = (d2.getTime() - now.getTime() + 1000000) / (3600 * 24 * 1000);
                    if (daysNows > 0) {
                        // 结束时间超过当前时间,吧当前时间的值给结束时间
                        endDate = sdf.format(now);
                    }

                    long daysBetween = (d2.getTime() - d1.getTime() + 1000000) / (3600 * 24 * 1000);
                    //System.out.println("1987-01-01 与 2010-01-01 相隔 "+daysBetween+" 天");
                    // 两个自定义时间之间必须小于31天
                    if ((daysBetween + 1) <= 31 && (daysBetween + 1) >= 1) {
                        List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
                                schoolId, courseId, startDate, endDate);
                      //补数据,没有记录的数据,一天没有产生数据,补一条0的数据
                        int intervalDay=(int) daysBetween+1;
                        List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,intervalDay);
                        mav.addObject("durationList", durationListData);

                        // 报表所需要的折线图
                        List<String> dayList = new ArrayList<String>();
                        List<Integer> numberList = new ArrayList<Integer>();
                        List<Float> totalTimes = new ArrayList<Float>();

                        if (durationListData.size() > 0) {
                            for (int i = durationListData.size(); i >0; i--) {
                                StatisticsDurationCourse sdc = new StatisticsDurationCourse();
                                sdc = durationListData.get(i-1);

                                Calendar cal = Calendar.getInstance();
                                cal.setTime(sdc.getDate());
                                int month = cal.get(Calendar.MONTH) + 1;
                                int day = cal.get(Calendar.DAY_OF_MONTH);
                                String dayX = month + "月" + day + "日";
                                numberList.add(sdc.getNumber());
                                totalTimes.add(sdc.getTotalDuration()*60);
                                dayList.add(dayX);
                            }
                        }

                        // 转为json数组
                        String numberListStr = writeListToJsonArray(numberList);
                        String dayListStr = writeListToJsonArray(dayList);
                        String totalTimesStr = writeListToJsonArray(totalTimes);

                        mav.addObject("numberList", numberListStr);// 次数
                        mav.addObject("totalTimes", totalTimesStr);// 时长
                        mav.addObject("dayList", dayListStr);// 时间
                        mav.addObject("timeMark", "time");// 查询条件说明
                        mav.addObject("startDate", startDate);// 开始时间
                        mav.addObject("endDate", endDate);// 结束时间
                    } else {
                        //超过31天,按照7天来搜索
                        selectmark=true;
                    }

                }else {
                    //查询时间条件为空
                    selectmark = true;
                }

            }//if time
        }//type是否为空

        
        if(selectmark){
            // 两个时间之间超过31天 ,按照7天来统计
            // 按照时间的顺序,最近7天
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String currentTime = sdf.format(new Date());
            String sevenDay = getPassDate(currentTime, 7);
            
            List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
                    schoolId, courseId, sevenDay, currentTime);
            
            //补数据,没有记录的数据,一天没有产生数据,补一条0的数据
            List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,7);
            mav.addObject("durationList", durationListData);
            
            // 报表所需要的折线图
            List<String> dayList = new ArrayList<String>();
            List<Integer> numberList = new ArrayList<Integer>();
            List<Float> totalTimes = new ArrayList<Float>();
            
            if (durationListData.size() > 0) {
                for (int i = durationListData.size(); i >0; i--) {
                    StatisticsDurationCourse sdc = new StatisticsDurationCourse();
                    sdc = durationListData.get(i-1);
                    String dateString=sdf.format(sdc.getDate());
                       
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(sdf.parse(dateString));
                    int month = cal.get(Calendar.MONTH) + 1;
                    int day = cal.get(Calendar.DAY_OF_MONTH);
                    String dayX = month + "月" + day + "日";
                    numberList.add(sdc.getNumber());
                    totalTimes.add(sdc.getTotalDuration()*60);
                    dayList.add(dayX);
                }
                
            }

            // 转为json数组
            String numberListStr = writeListToJsonArray(numberList);
            String dayListStr = writeListToJsonArray(dayList);
            String totalTimesStr = writeListToJsonArray(totalTimes);

            mav.addObject("numberList", numberListStr);// 次数
            mav.addObject("totalTimes", totalTimesStr);// 时长
            mav.addObject("dayList", dayListStr);// 时间
            mav.addObject("timeMark", "week");// 查询条件说明
        }
        
        mav.setViewName(getSecureViewDir(request) + "/courseStatistics/count");
        return mav;
    }


    /**
     * 一门课程一个月的每一天的时长统计
     */
    @RequestMapping("/{courseId}/duration/month")
    public ModelAndView getCourseDurationMonth(@PathVariable String courseId, HttpServletRequest request) {
        String schoolId = this.getSchoolId(request); // 网校ID
        String time = ServletRequestUtils.getStringParameter(request, "time", "");//
        ModelAndView mav = this.createCourseModelAndView(courseId, request);

        if (StringUtils.isBlank(time)) {
            // 统计当前月份的
            Calendar cal = Calendar.getInstance();
            int month = cal.get(Calendar.MONTH) + 1;
            int year = cal.get(Calendar.YEAR);
            // int day = cal.get(Calendar.DAY_OF_MONTH);
            List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationMonth(schoolId,
                    courseId, year, month);
            mav.addObject("durationList", durationList);
        } else {
            // 统计上一个月的
            Calendar cal = Calendar.getInstance();
            int month = cal.get(Calendar.MONTH);
            int year = cal.get(Calendar.YEAR);
            // int day = cal.get(Calendar.DAY_OF_MONTH);
            List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationMonth(schoolId,
                    courseId, year, month);
            mav.addObject("durationList", durationList);
        }

        mav.setViewName(getSecureViewDir(request) + "/courseStatistics/durationByDay");
        return mav;
    }

    // list转为json数组
    public String writeListToJsonArray(List list) throws IOException {
        OutputStream out = new ByteArrayOutputStream();
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(out, list);
        byte[] data = ((ByteArrayOutputStream) out).toByteArray();
        // System.out.println(new String(data));
        String result = new String(data, "UTF-8");
        return result;
    }
    
    /**
     * 根据输入的日期字符串 和 提前天数 ,
     * 获得 指定日期提前几天的日期对象
     * @param dateString 日期对象 ,格式如 1-31-1900
     * @param lazyDays 倒推的天数
     * @return 指定日期倒推指定天数后的日期对象
     * @throws ParseException
     */
    public String getPassDate(String dateString, int beforeDays) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date inputDate = dateFormat.parse(dateString);
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDate);
        int inputDayOfYear = cal.get(Calendar.DAY_OF_YEAR);
        cal.set(Calendar.DAY_OF_YEAR, inputDayOfYear - beforeDays);
        String dateTime = dateFormat.format(cal.getTime());
        return dateTime;
    }
    
    //补数据,没有记录的数据,一天没有产生数据,补一条0的数据
    public List<StatisticsDurationCourse> addNullDayData(List<StatisticsDurationCourse> durationList,int len) throws ParseException {
        List<StatisticsDurationCourse> durationListSort = new ArrayList<StatisticsDurationCourse>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if(durationList.size()>0){
            for(int j=0;j<len;j++){
                //找出空的时间,补数据
                  String currentTime2 = sdf.format(new Date());
                  String recentlyDay = getPassDate(currentTime2, j);//最近7天的时间
                  boolean addmark=true;
                  
                  for (int i = 0; i < durationList.size(); i++) {
                      StatisticsDurationCourse sdc = new StatisticsDurationCourse();
                      sdc = durationList.get(i);
                      String dateString=sdf.format(sdc.getDate());
                      if(recentlyDay.equals(dateString)){
                          //记录里有最近7天其中一天的数据
                          durationListSort.add(sdc);
                          addmark=false;
                          break;
                      }
                  }
                  
                  if(addmark){
                      //记录里没有最近7天中任何一天的数据
                      StatisticsDurationCourse sdcNo = new StatisticsDurationCourse();
                      sdcNo.setDate(sdf.parse(recentlyDay));
                      sdcNo.setNumber(0);
                      sdcNo.setTotalDuration(0);
                      durationListSort.add(sdcNo);
                  }
            }
        }
        return durationListSort;
    }
    
}

页面是使用freemarker

<#-- 页头 -->
<#assign pageTitle="课程统计">
<#include "/default/commons/header.ftl">
  <style>
     .searchDate{
        margin:10px auto -10px;
     }
     .inputLabel{
        line-height:30px;
     }
     .form-radio{
        margin-top:-2px;
     }
     .name-font{
        font-size:18px;
        text-indent:2em;
        margin-top:20px;
     }
     .terminal{
        margin-top:10px;
     }
     #draw{
        width:95%;
        height:400px;
        margin:0 auto;
     }
     .table-th{
        background-color: #4B4B4B;
        color:#e2e2e2;
     }
     .warnning{
        padding:5px 15px;
     }
  </style>
  <div id="content-container" class="container">
  
    <#-- 课程管理相关页面的顶部模版 -->
    <#include "../course/manage/topSection.ftl">  
    
     <div class="row">
     
	  <div class="col-md-3">
	    <#-- 左侧导航 -->
	    <#assign sidebarNav="duration">
	    <#include "../course/manage/sidebar.ftl">
	  </div>
	  
	<div class="col-md-9">
	   <div class="panel panel-default panel-col">
	   <!--右侧内容-->
         
           <div class="well well-sm" style="width:90%; margin-top:20px;margin-left:auto;margin-right:auto;text-align:center;">
			    <form id="statistics-search" class="form-inline" action="/secure/course/statistics/${course.courseId}/duration/day" method="get"> 
				      <div class="form-group">
				        <input class="form-control" type="text" id="startDate" name="startDate" value="" placeholder="起始时间">
				      </div>
				
				      <span>--</span>
				      
				      <div class="form-group">
				        <input class="form-control" type="text" id="endDate" name="endDate" value="" placeholder="结束时间">
				      </div>
				      <span>--</span>
				
				      <div class="form-group">
				          <select class="form-control" name="type" id="markType">
					         <option value="week">最近7天</option>
					         <option value="month">最近30天</option>
					         <option value="time">自定义时间</option>
					      </select>
				      </div>
				
				      <button class="btn btn-primary">统计</button>
			    </form>
  		  </div>
         
           <!--统计日期选择-->
           <div class="name-font">
              « <span id="courseName">${(course.title)!''}</span>» 统计   
              <span id="markText" style="float:right;margin-right:40px;"></span>
           </div>
           <div id="draw">
           </div>
           <!--折线图-->
      
           <div class="table-view" style="width:90%;margin:auto;">
               <table class="table table-hover" id="tongji" style="text-align:center;">
                  <thead class="table-th">
                     <th style="text-align:center;">日期</th>
                     <th style="text-align:center;">观看次数(次)</th>
                     <th style="text-align:center;">观看时长(分钟)</th>
                  </thead>
                  <tbody>
                    <#if durationList?has_content>
                      	<#list durationList as item>
		                    <tr>
		                       <td>${(item.date)?string("yyyy-MM-dd")}</td>
		                       <td>${(item.number)!''}</td>
		                       <td>${((item.totalDuration)*60)?string("0.##")}</td>
		                    </tr>
	                     </#list>
	                <#else>
	                   <span> 暂时还没数据! </span>    
                    </#if>
                  </tbody>
               </table>
           </div>
           <!--数据列表-->
           <input type="hidden" id="timeMark" value="${(timeMark)!''}" />
       </div>
   </div>
   </div>


 
 <#--页脚开始 -->
<#include "/default/commons/footerBegin.ftl">
<script type="text/javascript" src="/resources/echart/esl.js"></script> 
<script type="text/javascript" src="/resources/datetimepicker/js/bootstrap-datetimepicker.min.js"></script> 


  <script type="text/javascript">  
            // 路径配置  
            require.config({  
                paths:{   
                    'echarts' : '/resources/echart/echarts',  
                    'echarts/chart/bar' : '/resources/echart/echarts'  
                }  
            });  
              
            // 使用  
            require(  
                [  
                    'echarts',  
                    'echarts/chart/bar' // 使用柱状图就加载bar模块,按需加载  
                ],  
                function (ec) {  
                    // 基于准备好的dom,初始化echarts图表  
                    var myChart = ec.init(document.getElementById('draw'));   
                      
                     var jsonNum=${numberList};
					  var jsonTime=${totalTimes};
					  var jsonDay=${dayList};
                      
                   option = {
					    tooltip : {
					        trigger: 'axis'
					    },
					    legend: {
					        data:['观看次数','观看时长']
					    },
					    toolbox: {
					        show : true,
					        feature : {
					            magicType : {show: false, type: ['line']}
					           
					            
					        }
					    },
					    calculable : true,
					    xAxis : [
					        {
					            type : 'category',
					            boundaryGap : true,
					            name: '月份',
					            data : jsonDay
					        }
					    ],
					    yAxis : [
					        {
					            type : 'value',
					            name: '分钟/次数'
					        }
					    ],
					    series : [
					        {
					            name:'观看次数',
					            type:'line',
					            stack: '次',
					            data:jsonNum
					        },
					        {
					            name:'观看时长',
					            type:'line',
					            stack: '分钟',
					            data:jsonTime
					        }
					    ]
					}; 
              
                    // 为echarts对象加载数据   
                    myChart.setOption(option);   
                }  
            );  
  </script> 
  
  
  <script>
  
      $(document).ready(function(){
          var timeMark="${timeMark}";
           $("#markType").val(timeMark);
           
           if("time"==timeMark){
              var startDate="${startDate}";
              var endDate="${endDate}";
              var textStr=startDate+"----"+endDate+"的观看情况";
              $("#markText").text(textStr);
           }
      });
  
       $("#startDate").datetimepicker({
		    weekStart: 1,
	        todayBtn:  1,
			autoclose: 1,
			todayHighlight: 1,
			startView: 2,
			minView: 2,
			forceParse: 0,
     	  format:"yyyy-mm-dd"
       });
            	   
	   $("#endDate").datetimepicker({
	        weekStart: 1,
            todayBtn:  1,
		    autoclose: 1,
		    todayHighlight: 1,
		    startView: 2,
		    minView: 2,
		    forceParse: 0,
 	        format:"yyyy-mm-dd"
       });
  </script>


  
<#--页脚页脚页脚-->
<#include "/default/commons/footerEnd.ftl">

运行效果图:






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值