zoukankan      html  css  js  c++  java
  • 「小程序JAVA实战」小程序首页视频(49)

    转自:https://idig8.com/2018/09/21/xiaochengxujavashizhanxiaochengxushouyeshipin48/

    视频显示的内容是视频的截图,用户的头像,用户的昵称,都需要一个结合。所以涉及到关联查询.源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15

    获取系统信息

    • 官网介绍

      https://developers.weixin.qq.com/miniprogram/dev/dev/api/system/system-info/wx.getSystemInfo.html

    • 获取系统信息

      因为现在手机的屏幕大小不一致,显示适配是个很大的问题,如何适配首选要拿到对应手机的像素值,通过像素值获取响应的信息,动态的控制适配。

    后台程序

    自定义关联查询,通过分页组件查询出来对应的组合数据,controller提供分页接口。

    • java分页工具
    package com.idig8.utils;
    
    import java.util.List;
    
    /**
     * @Description: 封装分页后的数据格式
     */
    public class PagedResult {
    
        private int page;           // 当前页数
        private int total;          // 总页数  
        private long records;       // 总记录数
        private List<?> rows;       // 每行显示的内容
    
        public int getPage() {
            return page;
        }
        public void setPage(int page) {
            this.page = page;
        }
        public int getTotal() {
            return total;
        }
        public void setTotal(int total) {
            this.total = total;
        }
        public long getRecords() {
            return records;
        }
        public void setRecords(long records) {
            this.records = records;
        }
        public List<?> getRows() {
            return rows;
        }
        public void setRows(List<?> rows) {
            this.rows = rows;
        }
    
    }
    
    
    • java组件原理

      通过拦截的方式,当在执行某条sql语句的时候在根据不同数据库的方言,在sql语句查询的时候添加查询limit。PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件,其实我并不想加上好用两个字,但是为了表扬插件作者开源免费的崇高精神,我毫不犹豫的加上了好用一词作为赞美。原本以为分页插件,应该是很简单的,然而PageHelper比我想象的要复杂许多,它做的很强大,也很彻底,强大到使用者可能并不需要这么多功能,彻底到一参可以两用。但是,我认为,作为分页插件,完成物理分页任务是根本,其它的很多智能并不是必要的,保持它够傻够憨,专业术语叫stupid,简单就是美。

    • 增加Vo返回参数实体
    package com.idig8.pojo.vo;
    
    import java.util.Date;
    import javax.persistence.*;
    
    public class VideosVO {
        private String id;
        private String userId;
        private String audioId;
        private String videoDesc;
        private String videoPath;
        private Float videoSeconds;
        private Integer videoWidth;
        private Integer videoHeight;
        private String coverPath;
        private Long likeCounts;
        private Integer status;
        private Date createTime;
        private String username;
        private String faceImage;
        private String nickname;
    
        public String getId() {
            return id;
        }
    
        /**
         * @param id
         */
        public void setId(String id) {
            this.id = id;
        }
    
        /**
         * 获取发布者id
         *
         * @return user_id - 发布者id
         */
        public String getUserId() {
            return userId;
        }
    
        /**
         * 设置发布者id
         *
         * @param userId 发布者id
         */
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        /**
         * 获取用户使用音频的信息
         *
         * @return audio_id - 用户使用音频的信息
         */
        public String getAudioId() {
            return audioId;
        }
    
        /**
         * 设置用户使用音频的信息
         *
         * @param audioId 用户使用音频的信息
         */
        public void setAudioId(String audioId) {
            this.audioId = audioId;
        }
    
        /**
         * 获取视频描述
         *
         * @return video_desc - 视频描述
         */
        public String getVideoDesc() {
            return videoDesc;
        }
    
        /**
         * 设置视频描述
         *
         * @param videoDesc 视频描述
         */
        public void setVideoDesc(String videoDesc) {
            this.videoDesc = videoDesc;
        }
    
        /**
         * 获取视频存放的路径
         *
         * @return video_path - 视频存放的路径
         */
        public String getVideoPath() {
            return videoPath;
        }
    
        /**
         * 设置视频存放的路径
         *
         * @param videoPath 视频存放的路径
         */
        public void setVideoPath(String videoPath) {
            this.videoPath = videoPath;
        }
    
        /**
         * 获取视频秒数
         *
         * @return video_seconds - 视频秒数
         */
        public Float getVideoSeconds() {
            return videoSeconds;
        }
    
        /**
         * 设置视频秒数
         *
         * @param videoSeconds 视频秒数
         */
        public void setVideoSeconds(Float videoSeconds) {
            this.videoSeconds = videoSeconds;
        }
    
        /**
         * 获取视频宽度
         *
         * @return video_width - 视频宽度
         */
        public Integer getVideoWidth() {
            return videoWidth;
        }
    
        /**
         * 设置视频宽度
         *
         * @param videoWidth 视频宽度
         */
        public void setVideoWidth(Integer videoWidth) {
            this.videoWidth = videoWidth;
        }
    
        /**
         * 获取视频高度
         *
         * @return video_height - 视频高度
         */
        public Integer getVideoHeight() {
            return videoHeight;
        }
    
        /**
         * 设置视频高度
         *
         * @param videoHeight 视频高度
         */
        public void setVideoHeight(Integer videoHeight) {
            this.videoHeight = videoHeight;
        }
    
        /**
         * 获取视频封面图
         *
         * @return cover_path - 视频封面图
         */
        public String getCoverPath() {
            return coverPath;
        }
    
        /**
         * 设置视频封面图
         *
         * @param coverPath 视频封面图
         */
        public void setCoverPath(String coverPath) {
            this.coverPath = coverPath;
        }
    
        /**
         * 获取喜欢/赞美的数量
         *
         * @return like_counts - 喜欢/赞美的数量
         */
        public Long getLikeCounts() {
            return likeCounts;
        }
    
        /**
         * 设置喜欢/赞美的数量
         *
         * @param likeCounts 喜欢/赞美的数量
         */
        public void setLikeCounts(Long likeCounts) {
            this.likeCounts = likeCounts;
        }
    
        /**
         * 获取视频状态:
    1、发布成功
    2、禁止播放,管理员操作
         *
         * @return status - 视频状态:
    1、发布成功
    2、禁止播放,管理员操作
         */
        public Integer getStatus() {
            return status;
        }
    
        /**
         * 设置视频状态:
    1、发布成功
    2、禁止播放,管理员操作
         *
         * @param status 视频状态:
    1、发布成功
    2、禁止播放,管理员操作
         */
        public void setStatus(Integer status) {
            this.status = status;
        }
    
        /**
         * 获取创建时间
         *
         * @return create_time - 创建时间
         */
        public Date getCreateTime() {
            return createTime;
        }
    
        /**
         * 设置创建时间
         *
         * @param createTime 创建时间
         */
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getFaceImage() {
            return faceImage;
        }
    
        public void setFaceImage(String faceImage) {
            this.faceImage = faceImage;
        }
    
        public String getNickname() {
            return nickname;
        }
    
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
    
    
    }
    
    • 数据库查询java的mapper
    package com.idig8.mapper;
    
    import java.util.List;
    
    import com.idig8.pojo.Videos;
    import com.idig8.pojo.vo.VideosVO;
    import com.idig8.utils.MyMapper;
    
    public interface VideosUsersMapper extends MyMapper<VideosVO> {
    
        public List<VideosVO> queryAllVideos();
    }
    
    • 数据库Mybatis的xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.idig8.mapper.VideosUsersMapper" >
      <resultMap id="BaseResultMap" type="com.idig8.pojo.vo.VideosVO" >
        <!--
          WARNING - @mbg.generated
        -->
        <id column="id" property="id" jdbcType="VARCHAR" />
        <result column="user_id" property="userId" jdbcType="VARCHAR" />
        <result column="audio_id" property="audioId" jdbcType="VARCHAR" />
        <result column="video_desc" property="videoDesc" jdbcType="VARCHAR" />
        <result column="video_path" property="videoPath" jdbcType="VARCHAR" />
        <result column="video_seconds" property="videoSeconds" jdbcType="REAL" />
        <result column="video_width" property="videoWidth" jdbcType="INTEGER" />
        <result column="video_height" property="videoHeight" jdbcType="INTEGER" />
        <result column="cover_path" property="coverPath" jdbcType="VARCHAR" />
        <result column="like_counts" property="likeCounts" jdbcType="BIGINT" />
        <result column="status" property="status" jdbcType="INTEGER" />
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
        <result column="username" property="username" jdbcType="VARCHAR" />
        <result column="face_image" property="faceImage" jdbcType="VARCHAR" />
        <result column="nickname" property="nickname" jdbcType="VARCHAR" />
      </resultMap>
    
      <select id="queryAllVideos" resultMap="BaseResultMap">
        select v.*,u.face_image,u.username,u.nickname from videos v
        left join users u on v.user_id = u.id
        where 
            1 = 1
            and v.status = 1
        order by v.create_time
    
      </select>
    
    </mapper>
    
    
    • service的接口和实现
    package com.idig8.service;
    
    import com.idig8.pojo.Videos;
    import com.idig8.utils.PagedResult;
    
    public interface VideoService {
    
    
        /**
         * 保存视频信息
         * @param Id
         * @return
         */
        public String saveVideo(Videos video);
    
        /**
         * 分析查询视频列表
         * @param page
         * @param pageSize
         * @return
         */
        public PagedResult getAllVideos(Integer page,Integer pageSize);
    }
    
    
    
    
    package com.idig8.service.Impl;
    
    import java.util.List;
    
    import org.n3r.idworker.Sid;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration;
    import com.idig8.mapper.VideosMapper;
    import com.idig8.mapper.VideosUsersMapper;
    import com.idig8.pojo.Videos;
    import com.idig8.pojo.vo.VideosVO;
    import com.idig8.service.VideoService;
    import com.idig8.utils.PagedResult;
    
    @Service
    public class VideoServiceImpl implements  VideoService {
    
        @Autowired
        private VideosMapper videosMapper;
    
        @Autowired
        private VideosUsersMapper videosUsersMapper;
    
        @Autowired
        private Sid sid;
    
        @Transactional(propagation =Propagation.REQUIRED)
        public String  saveVideo(Videos video){
            String id = sid.nextShort();
            video.setId(id);
    
            videosMapper.insertSelective(video);
            return id;
    
    
        }
    
        @Override
        @Transactional(propagation =Propagation.SUPPORTS)
        public PagedResult getAllVideos(Integer page, Integer pageSize) {
    
            PageHelper.startPage(page,pageSize);
    
            List<VideosVO> list = videosUsersMapper.queryAllVideos();
            PageInfo<VideosVO> pageList =new PageInfo<>(list);
    
            PagedResult result = new PagedResult();
            result.setPage(page);
            result.setTotal(pageList.getPages());
            result.setRows(list);
            result.setRecords(pageList.getTotal());
    
            return result;
        }
    }
    
    
    • controller的开发
    package com.idig8.controller;
    
    import java.io.File;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.idig8.pojo.Bgm;
    import com.idig8.pojo.Videos;
    import com.idig8.service.BgmService;
    import com.idig8.service.VideoService;
    import com.idig8.utils.FetchVideoCover;
    import com.idig8.utils.JSONResult;
    import com.idig8.utils.MergeVideoMp3;
    import com.idig8.utils.PagedResult;
    import com.idig8.utils.enums.VideoStatusEnum;
    import com.idig8.utils.file.FileUtil;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiParam;
    
    
    @RestController
    @Api(value="视频相关业务的接口", tags= {"视频相关业务的controller"})
    @RequestMapping("/video")
    public class VideoController extends BasicController {
    
        @Autowired
        private BgmService bgmService;
    
        @Autowired
        private VideoService videosService;
    
        @Value("${server.file.path}")
        private String fileSpace;
    
        @Value("${server.ffmpeg.path}")
        private String ffmpegexe;
    
    
        @ApiOperation(value="上传视频", notes="上传视频的接口")
        @ApiImplicitParams({
            @ApiImplicitParam(name="userId", value="用户id", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="bgmId", value="背景音乐id", required=false, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoSeconds", value="背景音乐播放长度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoWidth", value="视频宽度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoHeight", value="视频高度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="desc", value="视频描述", required=false, 
                    dataType="String", paramType="form")
        })
        @PostMapping(value="/upload", headers="content-type=multipart/form-data")
        public JSONResult upload(String userId, 
                    String bgmId, double videoSeconds, 
                    int videoWidth, int videoHeight,
                    String desc,
                    @ApiParam(value="短视频", required=true)
                    MultipartFile file) throws Exception {
    
            if (StringUtils.isBlank(userId)) {
                return JSONResult.errorMsg("用户id不能为空...");
            }
            // 文件保存的命名空间
            String fileName = file.getOriginalFilename();
            // 保存到数据库中的相对路径
            String path = "";
            String videOutPath = "";
            String ImagePath = "";
            try {
                 path = FileUtil.uploadFile(file.getBytes(), fileSpace, fileName);
                } catch (Exception e) {
                    e.getStackTrace();
                       return JSONResult.errorMsg(e.getMessage());
                }                
    
    
            if(StringUtils.isNotBlank(bgmId)){
                Bgm bgm = bgmService.queryBgmById(bgmId);
                String mp3BgmPath = fileSpace + bgm.getPath();
                MergeVideoMp3 mergeVideoMp3 = new MergeVideoMp3(ffmpegexe);
                String videOutPathName = UUID.randomUUID().toString()+".mp4";
                File targetFile = new File(fileSpace + userId);
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }
                videOutPath = "/"+userId+"/"+videOutPathName;
                String videoInput = fileSpace +path;
                mergeVideoMp3.convertor(videoInput, mp3BgmPath, videoSeconds, fileSpace +videOutPath);
    
            }else{
                videOutPath = path;
    
            }
    
            ImagePath =  "/"+userId+"/"+UUID.randomUUID().toString()+".jpg";;
            FetchVideoCover fetchVideoCover = new FetchVideoCover(ffmpegexe);
            fetchVideoCover.getCover(fileSpace +videOutPath, fileSpace +ImagePath);
    
    
            Videos videos = new Videos();
            videos.setAudioId(bgmId);
            videos.setCreateTime(new Date());
            videos.setVideoDesc(desc);
            videos.setId(UUID.randomUUID().toString());
            videos.setUserId(userId);
            videos.setVideoHeight(videoHeight);
            videos.setVideoWidth(videoWidth);
            videos.setVideoPath(videOutPath);
            videos.setCoverPath(ImagePath);
            videos.setStatus(VideoStatusEnum.SUCCESS.value);
            videosService.saveVideo(videos);
    
            return JSONResult.ok(path);
    
        }
    
        @PostMapping(value="/showAll")
        @ApiOperation(value="视频列表", notes="分页的视频列表")
        @ApiImplicitParam(name="page", value="页码", 
        dataType="String", paramType="query")
        public JSONResult upload(
                    Integer page) throws Exception {
            if(page == null){
                page = 1;
            }
    
            PagedResult result = videosService.getAllVideos(page, PAGE_SIZE);
    
            return JSONResult.ok(result);
    
        }
    }
    

    小程序的页面开发

      <view wx:for="{{videoList}}" class="item-container">  
    
    
    
         <view style='{{screenWidth}}px;height:210px;' class='back-img'> 
            <image src="{{serverUrl}}{{item.coverPath}}" style='{{screenWidth}}px;height:210px;' mode="aspectFit" bindtap='showVideoInfo' data-arrindex='{{index}}'></image>
         </view> 
    
    
        <view class="desc">
            <view class="faceName">
                <image class='myface' src="{{serverUrl}}{{item.faceImage}}"></image>
                <view class="nickname">{{item.nickname}}</view>
            </view>
        </view>
    
    
      </view>  
    
    .item-container {
        position: relative;
    }
    
    .cover {
         100%;
        height: 400rpx;
        display: block; 
    }
    
    .back-img{
        display: block; 
        background-color: black;
    }
    
    .desc {
        margin-top: -40rpx;
        margin-bottom: 10rpx;
        display: flex;
        align-items: center;
    }
    
    .desc .right {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    
    .desc .faceName {
        display: flex;
        flex-direction: column;
        align-items: center;
    
        margin-left: 10px;
    }
    
    .title {
        font-size: 30rpx;
        margin-top: 10rpx;
        margin-left: 20rpx;
         600rpx;
    }
    
    .myface {
        display: block;
         60rpx;
        height: 60rpx;
        border-radius: 30rpx;
        margin-top: 10rpx;
        margin-right: 20rpx;
    }
    
    .nickname {
        font-size: 20rpx;
        margin-top: 6rpx;
        margin-right: 20rpx;
        color: darkgray;
    }
    
    
    const app = getApp()
    
    Page({
      data: {
        // 用于分页的属性
        totalPage: 1,
        page: 1,
        videoList: [],
        screenWidth: 350,
        serverUrl: "",
        searchContent: ""
      },
    
      onLoad: function (params) {
        var me = this;
        var screenWidth = wx.getSystemInfoSync().screenWidth;
        me.setData({
          screenWidth: screenWidth,
        });
    
        var searchContent = params.search;
        var isSaveRecord = params.isSaveRecord;
        if (isSaveRecord == null || isSaveRecord == '' || isSaveRecord == undefined) {
          isSaveRecord = 0;
        }
    
        me.setData({
          searchContent: searchContent
        });
    
        // 获取当前的分页数
        var page = me.data.page;
        var me = this;
        var serverUrl = app.serverUrl;
        wx.showLoading({
          title: '请等待,加载中...',
        });
    
        var searchContent = me.data.searchContent;
    
        wx.request({
          url: serverUrl + '/video/showAll?page=' + page + "&isSaveRecord=" + isSaveRecord,
          method: "POST",
          data: {
            videoDesc: searchContent
          },
          success: function (res) {
            wx.hideLoading();
            wx.hideNavigationBarLoading();
            wx.stopPullDownRefresh();
    
            console.log(res.data);
    
            // 判断当前页page是否是第一页,如果是第一页,那么设置videoList为空
            if (page === 1) {
              me.setData({
                videoList: []
              });
            }
    
            var videoList = res.data.data.rows;
            var newVideoList = me.data.videoList;
    
            me.setData({
              videoList: newVideoList.concat(videoList),
              page: page,
              totalPage: res.data.data.total,
              serverUrl: serverUrl
            });
    
          }
        })
      }
    
    
    })
    
    

    PS:主要说了关联查询的步骤,首选建立一个VO类,然后mapper关联VO类,增加对应xml文件返回VO类,service内添加分页插件,查询VO类,通过分页插件设置。
    页面通过微信组件获取手机的宽度,通过宽度动态的进行适配,调用接口返回内容通过block方法迭代循环展示数据。下次说下上拉和下拉刷新。

  • 相关阅读:
    CRUD工程师——嵌入式Web容器
    CRUD工程师——SpringBoot启动原理
    CRUD工程师——日志
    CRUD工程师——慢SQL
    CRUD工程师——索引
    前端专业术语: shim 和 Polyfill,了解下
    H5之postMessage 。实现跨域
    摘抄详细的VUE生命周期
    如何在不使用三大地图的KEY和相关组件的情况下,直接传参数到相关的H5地图
    Mac下通过brew安装指定版本的nodejs
  • 原文地址:https://www.cnblogs.com/sharpest/p/10312215.html
Copyright © 2011-2022 走看看