1.设置设备查看权限(每个公司只能查看自己购买的设备,未完善)

2.添加设备信息模块,可以选择设备查看详情(未添加实时数据部分)
3.添加教学视频模块,拉取b站系列中的视频
4.初步调整ui
This commit is contained in:
2026-03-31 17:46:40 +08:00
parent 0e2d75c23c
commit 2b8d5cc126
334 changed files with 2303 additions and 28691 deletions

View File

@@ -0,0 +1,240 @@
package com.ruoyi.system.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 设备基本信息对象 device_info
*
* @author ruoyi
* @date 2026-03-31
*/
public class DeviceInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 设备ID */
private Long deviceId;
/** 部门/公司ID */
private Long deptId;
/** 设备名称 */
@Excel(name = "设备名称")
private String deviceName;
/** 设备编号 */
@Excel(name = "设备编号")
private String deviceCode;
/** 运行状态0正常 1故障 2停机 3维护 */
@Excel(name = "运行状态", readConverterExp = "0=正常,1=故障,2=停机,3=维护")
private String deviceStatus;
/** 设备示例图片 */
@Excel(name = "设备示例图片")
private String deviceImage;
/** 型号规格 */
@Excel(name = "型号规格")
private String modelSpec;
/** 购买日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "购买日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date purchaseDate;
/** 设备序列号 */
@Excel(name = "设备序列号")
private String serialNumber;
/** 安装地址 */
@Excel(name = "安装地址")
private String installAddress;
/** 负责人 */
@Excel(name = "负责人")
private String responsiblePerson;
/** 质保开始日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "质保开始日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date warrantyStartDate;
/** 质保结束日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "质保结束日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date warrantyEndDate;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public Long getDeviceId()
{
return deviceId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public Long getDeptId()
{
return deptId;
}
public void setDeviceName(String deviceName)
{
this.deviceName = deviceName;
}
public String getDeviceName()
{
return deviceName;
}
public void setDeviceCode(String deviceCode)
{
this.deviceCode = deviceCode;
}
public String getDeviceCode()
{
return deviceCode;
}
public void setDeviceStatus(String deviceStatus)
{
this.deviceStatus = deviceStatus;
}
public String getDeviceStatus()
{
return deviceStatus;
}
public void setDeviceImage(String deviceImage)
{
this.deviceImage = deviceImage;
}
public String getDeviceImage()
{
return deviceImage;
}
public void setModelSpec(String modelSpec)
{
this.modelSpec = modelSpec;
}
public String getModelSpec()
{
return modelSpec;
}
public void setPurchaseDate(Date purchaseDate)
{
this.purchaseDate = purchaseDate;
}
public Date getPurchaseDate()
{
return purchaseDate;
}
public void setSerialNumber(String serialNumber)
{
this.serialNumber = serialNumber;
}
public String getSerialNumber()
{
return serialNumber;
}
public void setInstallAddress(String installAddress)
{
this.installAddress = installAddress;
}
public String getInstallAddress()
{
return installAddress;
}
public void setResponsiblePerson(String responsiblePerson)
{
this.responsiblePerson = responsiblePerson;
}
public String getResponsiblePerson()
{
return responsiblePerson;
}
public void setWarrantyStartDate(Date warrantyStartDate)
{
this.warrantyStartDate = warrantyStartDate;
}
public Date getWarrantyStartDate()
{
return warrantyStartDate;
}
public void setWarrantyEndDate(Date warrantyEndDate)
{
this.warrantyEndDate = warrantyEndDate;
}
public Date getWarrantyEndDate()
{
return warrantyEndDate;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("deviceId", getDeviceId())
.append("deptId", getDeptId())
.append("deviceName", getDeviceName())
.append("deviceCode", getDeviceCode())
.append("deviceStatus", getDeviceStatus())
.append("deviceImage", getDeviceImage())
.append("modelSpec", getModelSpec())
.append("purchaseDate", getPurchaseDate())
.append("serialNumber", getSerialNumber())
.append("installAddress", getInstallAddress())
.append("responsiblePerson", getResponsiblePerson())
.append("warrantyStartDate", getWarrantyStartDate())
.append("warrantyEndDate", getWarrantyEndDate())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,294 @@
package com.ruoyi.system.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 教学视频对象 teaching_video
*
* @author ruoyi
* @date 2026-03-31
*/
public class TeachingVideo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 视频ID */
private Long videoId;
/** 视频来源类型(BILIBILI等) */
private String sourceType;
/** 来源唯一键(B站bvid等) */
private String sourceKey;
/** 来源原始链接 */
private String sourceUrl;
/** 分类编码(ALL/BASIC/FAQ/TROUBLE) */
@Excel(name = "分类编码(ALL/BASIC/FAQ/TROUBLE)")
private String categoryCode;
/** 视频标题 */
@Excel(name = "视频标题")
private String title;
/** 视频简介(列表摘要) */
@Excel(name = "视频简介(列表摘要)")
private String summary;
/** 封面URL */
@Excel(name = "封面URL")
private String coverUrl;
/** 视频URL */
@Excel(name = "视频URL")
private String videoUrl;
/** 时长(秒) */
@Excel(name = "时长(秒)")
private Long durationSeconds;
/** 播放量 */
@Excel(name = "播放量")
private Long viewCount;
/** 发布日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "发布日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date publishDate;
/** 排序(越大越靠前) */
@Excel(name = "排序(越大越靠前)")
private Long sortNum;
/** 状态(0上架 1下架) */
@Excel(name = "状态(0上架 1下架)")
private String status;
/** 删除标志(0存在 2删除) */
private String delFlag;
/** 同步状态(0正常 1失败) */
private String syncStatus;
/** 最近同步时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date syncTime;
/** 最近同步错误 */
private String syncError;
public void setVideoId(Long videoId)
{
this.videoId = videoId;
}
public Long getVideoId()
{
return videoId;
}
public void setSourceType(String sourceType)
{
this.sourceType = sourceType;
}
public String getSourceType()
{
return sourceType;
}
public void setSourceKey(String sourceKey)
{
this.sourceKey = sourceKey;
}
public String getSourceKey()
{
return sourceKey;
}
public void setSourceUrl(String sourceUrl)
{
this.sourceUrl = sourceUrl;
}
public String getSourceUrl()
{
return sourceUrl;
}
public void setCategoryCode(String categoryCode)
{
this.categoryCode = categoryCode;
}
public String getCategoryCode()
{
return categoryCode;
}
public void setTitle(String title)
{
this.title = title;
}
public String getTitle()
{
return title;
}
public void setSummary(String summary)
{
this.summary = summary;
}
public String getSummary()
{
return summary;
}
public void setCoverUrl(String coverUrl)
{
this.coverUrl = coverUrl;
}
public String getCoverUrl()
{
return coverUrl;
}
public void setVideoUrl(String videoUrl)
{
this.videoUrl = videoUrl;
}
public String getVideoUrl()
{
return videoUrl;
}
public void setDurationSeconds(Long durationSeconds)
{
this.durationSeconds = durationSeconds;
}
public Long getDurationSeconds()
{
return durationSeconds;
}
public void setViewCount(Long viewCount)
{
this.viewCount = viewCount;
}
public Long getViewCount()
{
return viewCount;
}
public void setPublishDate(Date publishDate)
{
this.publishDate = publishDate;
}
public Date getPublishDate()
{
return publishDate;
}
public void setSortNum(Long sortNum)
{
this.sortNum = sortNum;
}
public Long getSortNum()
{
return sortNum;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
public void setSyncStatus(String syncStatus)
{
this.syncStatus = syncStatus;
}
public String getSyncStatus()
{
return syncStatus;
}
public void setSyncTime(Date syncTime)
{
this.syncTime = syncTime;
}
public Date getSyncTime()
{
return syncTime;
}
public void setSyncError(String syncError)
{
this.syncError = syncError;
}
public String getSyncError()
{
return syncError;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("videoId", getVideoId())
.append("sourceType", getSourceType())
.append("sourceKey", getSourceKey())
.append("sourceUrl", getSourceUrl())
.append("categoryCode", getCategoryCode())
.append("title", getTitle())
.append("summary", getSummary())
.append("coverUrl", getCoverUrl())
.append("videoUrl", getVideoUrl())
.append("durationSeconds", getDurationSeconds())
.append("viewCount", getViewCount())
.append("publishDate", getPublishDate())
.append("sortNum", getSortNum())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("syncStatus", getSyncStatus())
.append("syncTime", getSyncTime())
.append("syncError", getSyncError())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,144 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 教学视频外部源配置对象 teaching_video_source
*
* @author ruoyi
*/
public class TeachingVideoSource extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 源ID */
private Long sourceId;
/** 来源类型(BILIBILI) */
private String sourceType;
/** UP主mid */
private Long mid;
/** 合集/系列season_id */
private Long seasonId;
/** 落库分类 */
private String categoryCode;
/** 启用(0启用 1停用) */
private String enabled;
/** 排序 */
private Integer sortNum;
/** 最近同步时间 */
private java.util.Date lastSyncTime;
/** 最近同步状态(0正常 1失败) */
private String lastSyncStatus;
/** 最近同步错误 */
private String lastSyncError;
public Long getSourceId()
{
return sourceId;
}
public void setSourceId(Long sourceId)
{
this.sourceId = sourceId;
}
public String getSourceType()
{
return sourceType;
}
public void setSourceType(String sourceType)
{
this.sourceType = sourceType;
}
public Long getMid()
{
return mid;
}
public void setMid(Long mid)
{
this.mid = mid;
}
public Long getSeasonId()
{
return seasonId;
}
public void setSeasonId(Long seasonId)
{
this.seasonId = seasonId;
}
public String getCategoryCode()
{
return categoryCode;
}
public void setCategoryCode(String categoryCode)
{
this.categoryCode = categoryCode;
}
public String getEnabled()
{
return enabled;
}
public void setEnabled(String enabled)
{
this.enabled = enabled;
}
public Integer getSortNum()
{
return sortNum;
}
public void setSortNum(Integer sortNum)
{
this.sortNum = sortNum;
}
public java.util.Date getLastSyncTime()
{
return lastSyncTime;
}
public void setLastSyncTime(java.util.Date lastSyncTime)
{
this.lastSyncTime = lastSyncTime;
}
public String getLastSyncStatus()
{
return lastSyncStatus;
}
public void setLastSyncStatus(String lastSyncStatus)
{
this.lastSyncStatus = lastSyncStatus;
}
public String getLastSyncError()
{
return lastSyncError;
}
public void setLastSyncError(String lastSyncError)
{
this.lastSyncError = lastSyncError;
}
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.DeviceInfo;
/**
* 设备基本信息Mapper接口
*
* @author ruoyi
* @date 2026-03-31
*/
public interface DeviceInfoMapper
{
/**
* 查询设备基本信息
*
* @param deviceId 设备基本信息主键
* @return 设备基本信息
*/
public DeviceInfo selectDeviceInfoByDeviceId(Long deviceId);
/**
* 查询设备基本信息列表
*
* @param deviceInfo 设备基本信息
* @return 设备基本信息集合
*/
public List<DeviceInfo> selectDeviceInfoList(DeviceInfo deviceInfo);
/**
* 新增设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
public int insertDeviceInfo(DeviceInfo deviceInfo);
/**
* 修改设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
public int updateDeviceInfo(DeviceInfo deviceInfo);
/**
* 删除设备基本信息
*
* @param deviceId 设备基本信息主键
* @return 结果
*/
public int deleteDeviceInfoByDeviceId(Long deviceId);
/**
* 批量删除设备基本信息
*
* @param deviceIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDeviceInfoByDeviceIds(Long[] deviceIds);
}

View File

@@ -0,0 +1,69 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.TeachingVideo;
/**
* 教学视频Mapper接口
*
* @author ruoyi
* @date 2026-03-31
*/
public interface TeachingVideoMapper
{
/**
* 查询教学视频
*
* @param videoId 教学视频主键
* @return 教学视频
*/
public TeachingVideo selectTeachingVideoByVideoId(Long videoId);
/**
* 查询教学视频列表
*
* @param teachingVideo 教学视频
* @return 教学视频集合
*/
public List<TeachingVideo> selectTeachingVideoList(TeachingVideo teachingVideo);
/**
* 按来源唯一键 upsert
*
* @param teachingVideo 教学视频
* @return 结果
*/
public int upsertTeachingVideoBySource(TeachingVideo teachingVideo);
/**
* 新增教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
public int insertTeachingVideo(TeachingVideo teachingVideo);
/**
* 修改教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
public int updateTeachingVideo(TeachingVideo teachingVideo);
/**
* 删除教学视频
*
* @param videoId 教学视频主键
* @return 结果
*/
public int deleteTeachingVideoByVideoId(Long videoId);
/**
* 批量删除教学视频
*
* @param videoIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteTeachingVideoByVideoIds(Long[] videoIds);
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.TeachingVideoSource;
/**
* 教学视频外部源配置Mapper接口
*
* @author ruoyi
*/
public interface TeachingVideoSourceMapper
{
/**
* 查询启用的同步源列表
*
* @return 源列表
*/
public List<TeachingVideoSource> selectEnabledSources();
/**
* 更新同步状态
*
* @param source 源
* @return 结果
*/
public int updateSyncStatus(TeachingVideoSource source);
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.service;
import java.util.List;
import com.ruoyi.system.domain.DeviceInfo;
/**
* 设备基本信息Service接口
*
* @author ruoyi
* @date 2026-03-31
*/
public interface IDeviceInfoService
{
/**
* 查询设备基本信息
*
* @param deviceId 设备基本信息主键
* @return 设备基本信息
*/
public DeviceInfo selectDeviceInfoByDeviceId(Long deviceId);
/**
* 查询设备基本信息列表
*
* @param deviceInfo 设备基本信息
* @return 设备基本信息集合
*/
public List<DeviceInfo> selectDeviceInfoList(DeviceInfo deviceInfo);
/**
* 新增设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
public int insertDeviceInfo(DeviceInfo deviceInfo);
/**
* 修改设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
public int updateDeviceInfo(DeviceInfo deviceInfo);
/**
* 批量删除设备基本信息
*
* @param deviceIds 需要删除的设备基本信息主键集合
* @return 结果
*/
public int deleteDeviceInfoByDeviceIds(Long[] deviceIds);
/**
* 删除设备基本信息信息
*
* @param deviceId 设备基本信息主键
* @return 结果
*/
public int deleteDeviceInfoByDeviceId(Long deviceId);
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.service;
import java.util.List;
import com.ruoyi.system.domain.TeachingVideo;
/**
* 教学视频Service接口
*
* @author ruoyi
* @date 2026-03-31
*/
public interface ITeachingVideoService
{
/**
* 查询教学视频
*
* @param videoId 教学视频主键
* @return 教学视频
*/
public TeachingVideo selectTeachingVideoByVideoId(Long videoId);
/**
* 查询教学视频列表
*
* @param teachingVideo 教学视频
* @return 教学视频集合
*/
public List<TeachingVideo> selectTeachingVideoList(TeachingVideo teachingVideo);
/**
* 新增教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
public int insertTeachingVideo(TeachingVideo teachingVideo);
/**
* 修改教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
public int updateTeachingVideo(TeachingVideo teachingVideo);
/**
* 批量删除教学视频
*
* @param videoIds 需要删除的教学视频主键集合
* @return 结果
*/
public int deleteTeachingVideoByVideoIds(Long[] videoIds);
/**
* 删除教学视频信息
*
* @param videoId 教学视频主键
* @return 结果
*/
public int deleteTeachingVideoByVideoId(Long videoId);
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.system.service;
/**
* 教学视频外部源同步Service
*/
public interface ITeachingVideoSyncService
{
/**
* 同步所有启用的外部源
*
* @return 同步条目数
*/
int syncAllEnabledSources();
}

View File

@@ -0,0 +1,98 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.DeviceInfoMapper;
import com.ruoyi.system.domain.DeviceInfo;
import com.ruoyi.system.service.IDeviceInfoService;
/**
* 设备基本信息Service业务层处理
*
* @author ruoyi
* @date 2026-03-31
*/
@Service
public class DeviceInfoServiceImpl implements IDeviceInfoService
{
@Autowired
private DeviceInfoMapper deviceInfoMapper;
/**
* 查询设备基本信息
*
* @param deviceId 设备基本信息主键
* @return 设备基本信息
*/
@Override
public DeviceInfo selectDeviceInfoByDeviceId(Long deviceId)
{
return deviceInfoMapper.selectDeviceInfoByDeviceId(deviceId);
}
/**
* 查询设备基本信息列表
*
* @param deviceInfo 设备基本信息
* @return 设备基本信息
*/
@Override
@DataScope(deptAlias = "d")
public List<DeviceInfo> selectDeviceInfoList(DeviceInfo deviceInfo)
{
return deviceInfoMapper.selectDeviceInfoList(deviceInfo);
}
/**
* 新增设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
@Override
public int insertDeviceInfo(DeviceInfo deviceInfo)
{
deviceInfo.setCreateTime(DateUtils.getNowDate());
return deviceInfoMapper.insertDeviceInfo(deviceInfo);
}
/**
* 修改设备基本信息
*
* @param deviceInfo 设备基本信息
* @return 结果
*/
@Override
public int updateDeviceInfo(DeviceInfo deviceInfo)
{
deviceInfo.setUpdateTime(DateUtils.getNowDate());
return deviceInfoMapper.updateDeviceInfo(deviceInfo);
}
/**
* 批量删除设备基本信息
*
* @param deviceIds 需要删除的设备基本信息主键
* @return 结果
*/
@Override
public int deleteDeviceInfoByDeviceIds(Long[] deviceIds)
{
return deviceInfoMapper.deleteDeviceInfoByDeviceIds(deviceIds);
}
/**
* 删除设备基本信息信息
*
* @param deviceId 设备基本信息主键
* @return 结果
*/
@Override
public int deleteDeviceInfoByDeviceId(Long deviceId)
{
return deviceInfoMapper.deleteDeviceInfoByDeviceId(deviceId);
}
}

View File

@@ -0,0 +1,96 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.TeachingVideoMapper;
import com.ruoyi.system.domain.TeachingVideo;
import com.ruoyi.system.service.ITeachingVideoService;
/**
* 教学视频Service业务层处理
*
* @author ruoyi
* @date 2026-03-31
*/
@Service
public class TeachingVideoServiceImpl implements ITeachingVideoService
{
@Autowired
private TeachingVideoMapper teachingVideoMapper;
/**
* 查询教学视频
*
* @param videoId 教学视频主键
* @return 教学视频
*/
@Override
public TeachingVideo selectTeachingVideoByVideoId(Long videoId)
{
return teachingVideoMapper.selectTeachingVideoByVideoId(videoId);
}
/**
* 查询教学视频列表
*
* @param teachingVideo 教学视频
* @return 教学视频
*/
@Override
public List<TeachingVideo> selectTeachingVideoList(TeachingVideo teachingVideo)
{
return teachingVideoMapper.selectTeachingVideoList(teachingVideo);
}
/**
* 新增教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
@Override
public int insertTeachingVideo(TeachingVideo teachingVideo)
{
teachingVideo.setCreateTime(DateUtils.getNowDate());
return teachingVideoMapper.insertTeachingVideo(teachingVideo);
}
/**
* 修改教学视频
*
* @param teachingVideo 教学视频
* @return 结果
*/
@Override
public int updateTeachingVideo(TeachingVideo teachingVideo)
{
teachingVideo.setUpdateTime(DateUtils.getNowDate());
return teachingVideoMapper.updateTeachingVideo(teachingVideo);
}
/**
* 批量删除教学视频
*
* @param videoIds 需要删除的教学视频主键
* @return 结果
*/
@Override
public int deleteTeachingVideoByVideoIds(Long[] videoIds)
{
return teachingVideoMapper.deleteTeachingVideoByVideoIds(videoIds);
}
/**
* 删除教学视频信息
*
* @param videoId 教学视频主键
* @return 结果
*/
@Override
public int deleteTeachingVideoByVideoId(Long videoId)
{
return teachingVideoMapper.deleteTeachingVideoByVideoId(videoId);
}
}

View File

@@ -0,0 +1,279 @@
package com.ruoyi.system.service.impl;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.TeachingVideo;
import com.ruoyi.system.domain.TeachingVideoSource;
import com.ruoyi.system.mapper.TeachingVideoMapper;
import com.ruoyi.system.mapper.TeachingVideoSourceMapper;
import com.ruoyi.system.service.ITeachingVideoSyncService;
/**
* 教学视频外部源同步B站合集/系列)
*/
@Service
public class TeachingVideoSyncServiceImpl implements ITeachingVideoSyncService
{
private static final String SOURCE_TYPE_BILIBILI = "BILIBILI";
// B站合集/系列列表公开接口字段会随B站调整
// 参考x/polymer/web-space/seasons_archives_list?mid=xxx&season_id=xxx&page_num=1&page_size=30
private static final String BILI_SEASON_API = "https://api.bilibili.com/x/polymer/web-space/seasons_archives_list";
// B站“视频列表/系列”(type=series) 列表接口
// 参考x/series/archives?mid=xxx&series_id=xxx&only_normal=true&pn=1&ps=30
private static final String BILI_SERIES_API = "https://api.bilibili.com/x/series/archives";
private final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private TeachingVideoSourceMapper sourceMapper;
@Autowired
private TeachingVideoMapper teachingVideoMapper;
@Override
public int syncAllEnabledSources()
{
int count = 0;
List<TeachingVideoSource> sources = sourceMapper.selectEnabledSources();
for (TeachingVideoSource src : sources)
{
if (!SOURCE_TYPE_BILIBILI.equalsIgnoreCase(src.getSourceType()))
{
continue;
}
try
{
count += syncBiliSeason(src);
src.setLastSyncTime(new Date());
src.setLastSyncStatus("0");
src.setLastSyncError(null);
}
catch (Exception ex)
{
src.setLastSyncTime(new Date());
src.setLastSyncStatus("1");
src.setLastSyncError(StringUtils.substring(ex.getMessage(), 0, 500));
}
sourceMapper.updateSyncStatus(src);
}
return count;
}
private int syncBiliSeason(TeachingVideoSource src) throws Exception
{
if (src.getMid() == null || src.getSeasonId() == null || src.getMid() <= 0 || src.getSeasonId() <= 0)
{
throw new IllegalArgumentException("B站同步源配置不完整mid/season_id 不能为空且需为正数");
}
int pageNum = 1;
int pageSize = 30;
int upserted = 0;
while (true)
{
// 先尝试 season 接口B站“合集/系列season”
FetchResult r = fetchBiliSeason(src.getMid(), src.getSeasonId(), pageNum, pageSize);
// 若失败或为空,再尝试 series 接口space里 type=series 的列表)
if (r.code == -404 || r.code == -352 || r.archives == null || r.archives.isEmpty())
{
r = fetchBiliSeries(src.getMid(), src.getSeasonId(), pageNum, pageSize);
}
if (r.code != 0)
{
throw new IllegalStateException("B站接口返回异常code=" + r.code + ", message=" + r.message);
}
if (r.archives == null || r.archives.isEmpty())
{
break;
}
for (Map<String, Object> a : r.archives)
{
String bvid = asString(a.get("bvid"));
if (StringUtils.isBlank(bvid))
{
continue;
}
TeachingVideo tv = new TeachingVideo();
tv.setSourceType(SOURCE_TYPE_BILIBILI);
tv.setSourceKey(bvid);
tv.setSourceUrl("https://www.bilibili.com/video/" + bvid);
tv.setCategoryCode(StringUtils.defaultIfBlank(src.getCategoryCode(), "BASIC"));
tv.setTitle(asString(a.get("title")));
// season接口字段cover/descseries接口字段pic(封面)/无desc
String desc = asString(a.get("desc"));
tv.setSummary(StringUtils.defaultString(desc));
String cover = StringUtils.defaultIfBlank(asString(a.get("cover")), asString(a.get("pic")));
tv.setCoverUrl(StringUtils.defaultString(cover));
tv.setVideoUrl(buildBiliEmbedUrl(bvid));
tv.setDurationSeconds(asLongObj(a.get("duration")));
Map<String, Object> stat = castMap(a.get("stat"));
tv.setViewCount(asLongObj(stat != null ? stat.get("view") : null));
tv.setPublishDate(pubDateFromTs(a.get("pubdate")));
tv.setSortNum(0L);
tv.setStatus("0");
tv.setDelFlag("0");
tv.setUpdateBy("system");
tv.setUpdateTime(new Date());
tv.setSyncStatus("0");
tv.setSyncTime(new Date());
tv.setSyncError(null);
teachingVideoMapper.upsertTeachingVideoBySource(tv);
upserted++;
}
if (r.archives.size() < pageSize)
{
break;
}
pageNum++;
}
return upserted;
}
private FetchResult fetchBiliSeason(Long mid, Long seasonId, int pageNum, int pageSize) throws Exception
{
String query = "mid=" + mid + "&season_id=" + seasonId + "&page_num=" + pageNum + "&page_size=" + pageSize;
return fetchJson(BILI_SEASON_API, query, "archives");
}
private FetchResult fetchBiliSeries(Long mid, Long seriesId, int pn, int ps) throws Exception
{
String query = "mid=" + mid + "&series_id=" + seriesId + "&only_normal=true&pn=" + pn + "&ps=" + ps;
return fetchJson(BILI_SERIES_API, query, "archives");
}
private FetchResult fetchJson(String baseUrl, String query, String archivesKey) throws Exception
{
String json = biliGet(baseUrl, query);
if (StringUtils.isBlank(json))
{
throw new IllegalStateException("B站接口返回为空");
}
Map<String, Object> root = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
Object codeObj = root.get("code");
int code = codeObj instanceof Number ? ((Number) codeObj).intValue() : 0;
String message = asString(root.get("message"));
Map<String, Object> data = castMap(root.get("data"));
List<Map<String, Object>> archives = data == null ? null : castListMap(data.get(archivesKey));
return new FetchResult(code, message, archives);
}
private static String biliGet(String baseUrl, String query) throws Exception
{
String url = StringUtils.isNotBlank(query) ? baseUrl + "?" + query : baseUrl;
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(8000);
conn.setReadTimeout(15000);
conn.setRequestProperty("accept", "application/json, text/plain, */*");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
// B站部分接口需要Referer否则可能返回-352/-400
conn.setRequestProperty("referer", "https://www.bilibili.com/");
conn.connect();
try (InputStream in = conn.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream())
{
byte[] buf = new byte[4096];
int n;
while ((n = in.read(buf)) > 0)
{
out.write(buf, 0, n);
}
return out.toString(StandardCharsets.UTF_8);
}
}
private static class FetchResult
{
final int code;
final String message;
final List<Map<String, Object>> archives;
FetchResult(int code, String message, List<Map<String, Object>> archives)
{
this.code = code;
this.message = message;
this.archives = archives;
}
}
private static String buildBiliEmbedUrl(String bvid)
{
return "https://player.bilibili.com/player.html?bvid=" + bvid + "&page=1&high_quality=1&danmaku=0";
}
private static Date pubDateFromTs(Object ts)
{
Long v = asLongObj(ts);
if (v == null || v <= 0)
{
return null;
}
// B站pubdate通常是秒级时间戳
return new Date(v * 1000L);
}
@SuppressWarnings("unchecked")
private static Map<String, Object> castMap(Object o)
{
if (o instanceof Map)
{
return (Map<String, Object>) o;
}
return null;
}
@SuppressWarnings("unchecked")
private static List<Map<String, Object>> castListMap(Object o)
{
if (o instanceof List)
{
return (List<Map<String, Object>>) o;
}
return null;
}
private static String asString(Object o)
{
return o == null ? null : String.valueOf(o);
}
private static Long asLongObj(Object o)
{
if (o == null)
{
return null;
}
if (o instanceof Number)
{
return ((Number) o).longValue();
}
try
{
return Long.parseLong(String.valueOf(o));
}
catch (Exception ex)
{
return null;
}
}
}

View File

@@ -0,0 +1,136 @@
<?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.ruoyi.system.mapper.DeviceInfoMapper">
<resultMap type="DeviceInfo" id="DeviceInfoResult">
<result property="deviceId" column="device_id" />
<result property="deptId" column="dept_id" />
<result property="deviceName" column="device_name" />
<result property="deviceCode" column="device_code" />
<result property="deviceStatus" column="device_status" />
<result property="deviceImage" column="device_image" />
<result property="modelSpec" column="model_spec" />
<result property="purchaseDate" column="purchase_date" />
<result property="serialNumber" column="serial_number" />
<result property="installAddress" column="install_address" />
<result property="responsiblePerson" column="responsible_person" />
<result property="warrantyStartDate" column="warranty_start_date" />
<result property="warrantyEndDate" column="warranty_end_date" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectDeviceInfoVo">
select d.device_id, d.dept_id, d.device_name, d.device_code, d.device_status, d.device_image, d.model_spec, d.purchase_date, d.serial_number, d.install_address, d.responsible_person, d.warranty_start_date, d.warranty_end_date, d.del_flag, d.create_by, d.create_time, d.update_by, d.update_time, d.remark from device_info d
</sql>
<select id="selectDeviceInfoList" parameterType="DeviceInfo" resultMap="DeviceInfoResult">
<include refid="selectDeviceInfoVo"/>
<where>
<if test="deptId != null "> and d.dept_id = #{deptId}</if>
<if test="deviceName != null and deviceName != ''"> and d.device_name like concat('%', #{deviceName}, '%')</if>
<if test="deviceCode != null and deviceCode != ''"> and d.device_code = #{deviceCode}</if>
<if test="deviceStatus != null and deviceStatus != ''"> and d.device_status = #{deviceStatus}</if>
<if test="deviceImage != null and deviceImage != ''"> and d.device_image = #{deviceImage}</if>
<if test="modelSpec != null and modelSpec != ''"> and d.model_spec = #{modelSpec}</if>
<if test="purchaseDate != null "> and d.purchase_date = #{purchaseDate}</if>
<if test="serialNumber != null and serialNumber != ''"> and d.serial_number = #{serialNumber}</if>
<if test="installAddress != null and installAddress != ''"> and d.install_address = #{installAddress}</if>
<if test="responsiblePerson != null and responsiblePerson != ''"> and d.responsible_person = #{responsiblePerson}</if>
<if test="warrantyStartDate != null "> and d.warranty_start_date = #{warrantyStartDate}</if>
<if test="warrantyEndDate != null "> and d.warranty_end_date = #{warrantyEndDate}</if>
${params.dataScope}
</where>
</select>
<select id="selectDeviceInfoByDeviceId" parameterType="Long" resultMap="DeviceInfoResult">
<include refid="selectDeviceInfoVo"/>
where d.device_id = #{deviceId}
</select>
<insert id="insertDeviceInfo" parameterType="DeviceInfo" useGeneratedKeys="true" keyProperty="deviceId">
insert into device_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deptId != null">dept_id,</if>
<if test="deviceName != null and deviceName != ''">device_name,</if>
<if test="deviceCode != null and deviceCode != ''">device_code,</if>
<if test="deviceStatus != null">device_status,</if>
<if test="deviceImage != null">device_image,</if>
<if test="modelSpec != null">model_spec,</if>
<if test="purchaseDate != null">purchase_date,</if>
<if test="serialNumber != null">serial_number,</if>
<if test="installAddress != null">install_address,</if>
<if test="responsiblePerson != null">responsible_person,</if>
<if test="warrantyStartDate != null">warranty_start_date,</if>
<if test="warrantyEndDate != null">warranty_end_date,</if>
<if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deptId != null">#{deptId},</if>
<if test="deviceName != null and deviceName != ''">#{deviceName},</if>
<if test="deviceCode != null and deviceCode != ''">#{deviceCode},</if>
<if test="deviceStatus != null">#{deviceStatus},</if>
<if test="deviceImage != null">#{deviceImage},</if>
<if test="modelSpec != null">#{modelSpec},</if>
<if test="purchaseDate != null">#{purchaseDate},</if>
<if test="serialNumber != null">#{serialNumber},</if>
<if test="installAddress != null">#{installAddress},</if>
<if test="responsiblePerson != null">#{responsiblePerson},</if>
<if test="warrantyStartDate != null">#{warrantyStartDate},</if>
<if test="warrantyEndDate != null">#{warrantyEndDate},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
</trim>
</insert>
<update id="updateDeviceInfo" parameterType="DeviceInfo">
update device_info
<trim prefix="SET" suffixOverrides=",">
<if test="deptId != null">dept_id = #{deptId},</if>
<if test="deviceName != null and deviceName != ''">device_name = #{deviceName},</if>
<if test="deviceCode != null and deviceCode != ''">device_code = #{deviceCode},</if>
<if test="deviceStatus != null">device_status = #{deviceStatus},</if>
<if test="deviceImage != null">device_image = #{deviceImage},</if>
<if test="modelSpec != null">model_spec = #{modelSpec},</if>
<if test="purchaseDate != null">purchase_date = #{purchaseDate},</if>
<if test="serialNumber != null">serial_number = #{serialNumber},</if>
<if test="installAddress != null">install_address = #{installAddress},</if>
<if test="responsiblePerson != null">responsible_person = #{responsiblePerson},</if>
<if test="warrantyStartDate != null">warranty_start_date = #{warrantyStartDate},</if>
<if test="warrantyEndDate != null">warranty_end_date = #{warrantyEndDate},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
</trim>
where device_id = #{deviceId}
</update>
<delete id="deleteDeviceInfoByDeviceId" parameterType="Long">
delete from device_info where device_id = #{deviceId}
</delete>
<delete id="deleteDeviceInfoByDeviceIds" parameterType="String">
delete from device_info where device_id in
<foreach item="deviceId" collection="array" open="(" separator="," close=")">
#{deviceId}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,174 @@
<?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.ruoyi.system.mapper.TeachingVideoMapper">
<resultMap type="TeachingVideo" id="TeachingVideoResult">
<result property="videoId" column="video_id" />
<result property="sourceType" column="source_type" />
<result property="sourceKey" column="source_key" />
<result property="sourceUrl" column="source_url" />
<result property="categoryCode" column="category_code" />
<result property="title" column="title" />
<result property="summary" column="summary" />
<result property="coverUrl" column="cover_url" />
<result property="videoUrl" column="video_url" />
<result property="durationSeconds" column="duration_seconds" />
<result property="viewCount" column="view_count" />
<result property="publishDate" column="publish_date" />
<result property="sortNum" column="sort_num" />
<result property="status" column="status" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<result property="syncStatus" column="sync_status" />
<result property="syncTime" column="sync_time" />
<result property="syncError" column="sync_error" />
</resultMap>
<sql id="selectTeachingVideoVo">
select video_id, source_type, source_key, source_url, category_code, title, summary, cover_url, video_url, duration_seconds, view_count, publish_date, sort_num, status, del_flag, create_by, create_time, update_by, update_time, remark, sync_status, sync_time, sync_error from teaching_video
</sql>
<select id="selectTeachingVideoList" parameterType="TeachingVideo" resultMap="TeachingVideoResult">
<include refid="selectTeachingVideoVo"/>
<where>
<if test="categoryCode != null and categoryCode != ''"> and category_code = #{categoryCode}</if>
<if test="title != null and title != ''"> and title = #{title}</if>
<if test="summary != null and summary != ''"> and summary = #{summary}</if>
<if test="coverUrl != null and coverUrl != ''"> and cover_url = #{coverUrl}</if>
<if test="videoUrl != null and videoUrl != ''"> and video_url = #{videoUrl}</if>
<if test="durationSeconds != null "> and duration_seconds = #{durationSeconds}</if>
<if test="viewCount != null "> and view_count = #{viewCount}</if>
<if test="publishDate != null "> and publish_date = #{publishDate}</if>
<if test="sortNum != null "> and sort_num = #{sortNum}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
</where>
</select>
<select id="selectTeachingVideoByVideoId" parameterType="Long" resultMap="TeachingVideoResult">
<include refid="selectTeachingVideoVo"/>
where video_id = #{videoId}
</select>
<insert id="upsertTeachingVideoBySource" parameterType="TeachingVideo" useGeneratedKeys="true" keyProperty="videoId">
insert into teaching_video
(source_type, source_key, source_url, category_code, title, summary, cover_url, video_url, duration_seconds, view_count, publish_date, sort_num, status, del_flag, create_by, create_time, update_by, update_time, remark, sync_status, sync_time, sync_error)
values
(#{sourceType}, #{sourceKey}, #{sourceUrl}, #{categoryCode}, #{title}, #{summary}, #{coverUrl}, #{videoUrl}, #{durationSeconds}, #{viewCount}, #{publishDate}, #{sortNum}, #{status}, #{delFlag}, #{createBy}, #{createTime}, #{updateBy}, #{updateTime}, #{remark}, #{syncStatus}, #{syncTime}, #{syncError})
on duplicate key update
source_url = values(source_url),
category_code = values(category_code),
title = values(title),
summary = values(summary),
cover_url = values(cover_url),
video_url = values(video_url),
duration_seconds = values(duration_seconds),
view_count = values(view_count),
publish_date = values(publish_date),
sort_num = values(sort_num),
status = values(status),
del_flag = values(del_flag),
update_by = values(update_by),
update_time = values(update_time),
sync_status = values(sync_status),
sync_time = values(sync_time),
sync_error = values(sync_error);
</insert>
<insert id="insertTeachingVideo" parameterType="TeachingVideo" useGeneratedKeys="true" keyProperty="videoId">
insert into teaching_video
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="sourceType != null and sourceType != ''">source_type,</if>
<if test="sourceKey != null and sourceKey != ''">source_key,</if>
<if test="sourceUrl != null and sourceUrl != ''">source_url,</if>
<if test="categoryCode != null and categoryCode != ''">category_code,</if>
<if test="title != null and title != ''">title,</if>
<if test="summary != null">summary,</if>
<if test="coverUrl != null">cover_url,</if>
<if test="videoUrl != null">video_url,</if>
<if test="durationSeconds != null">duration_seconds,</if>
<if test="viewCount != null">view_count,</if>
<if test="publishDate != null">publish_date,</if>
<if test="sortNum != null">sort_num,</if>
<if test="status != null">status,</if>
<if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
<if test="syncStatus != null">sync_status,</if>
<if test="syncTime != null">sync_time,</if>
<if test="syncError != null">sync_error,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="sourceType != null and sourceType != ''">#{sourceType},</if>
<if test="sourceKey != null and sourceKey != ''">#{sourceKey},</if>
<if test="sourceUrl != null and sourceUrl != ''">#{sourceUrl},</if>
<if test="categoryCode != null and categoryCode != ''">#{categoryCode},</if>
<if test="title != null and title != ''">#{title},</if>
<if test="summary != null">#{summary},</if>
<if test="coverUrl != null">#{coverUrl},</if>
<if test="videoUrl != null">#{videoUrl},</if>
<if test="durationSeconds != null">#{durationSeconds},</if>
<if test="viewCount != null">#{viewCount},</if>
<if test="publishDate != null">#{publishDate},</if>
<if test="sortNum != null">#{sortNum},</if>
<if test="status != null">#{status},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
<if test="syncStatus != null">#{syncStatus},</if>
<if test="syncTime != null">#{syncTime},</if>
<if test="syncError != null">#{syncError},</if>
</trim>
</insert>
<update id="updateTeachingVideo" parameterType="TeachingVideo">
update teaching_video
<trim prefix="SET" suffixOverrides=",">
<if test="sourceType != null and sourceType != ''">source_type = #{sourceType},</if>
<if test="sourceKey != null and sourceKey != ''">source_key = #{sourceKey},</if>
<if test="sourceUrl != null and sourceUrl != ''">source_url = #{sourceUrl},</if>
<if test="categoryCode != null and categoryCode != ''">category_code = #{categoryCode},</if>
<if test="title != null and title != ''">title = #{title},</if>
<if test="summary != null">summary = #{summary},</if>
<if test="coverUrl != null">cover_url = #{coverUrl},</if>
<if test="videoUrl != null">video_url = #{videoUrl},</if>
<if test="durationSeconds != null">duration_seconds = #{durationSeconds},</if>
<if test="viewCount != null">view_count = #{viewCount},</if>
<if test="publishDate != null">publish_date = #{publishDate},</if>
<if test="sortNum != null">sort_num = #{sortNum},</if>
<if test="status != null">status = #{status},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="syncStatus != null">sync_status = #{syncStatus},</if>
<if test="syncTime != null">sync_time = #{syncTime},</if>
<if test="syncError != null">sync_error = #{syncError},</if>
</trim>
where video_id = #{videoId}
</update>
<delete id="deleteTeachingVideoByVideoId" parameterType="Long">
delete from teaching_video where video_id = #{videoId}
</delete>
<delete id="deleteTeachingVideoByVideoIds" parameterType="String">
delete from teaching_video where video_id in
<foreach item="videoId" collection="array" open="(" separator="," close=")">
#{videoId}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,42 @@
<?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.ruoyi.system.mapper.TeachingVideoSourceMapper">
<resultMap type="TeachingVideoSource" id="TeachingVideoSourceResult">
<result property="sourceId" column="source_id" />
<result property="sourceType" column="source_type" />
<result property="mid" column="mid" />
<result property="seasonId" column="season_id" />
<result property="categoryCode" column="category_code" />
<result property="enabled" column="enabled" />
<result property="sortNum" column="sort_num" />
<result property="lastSyncTime" column="last_sync_time" />
<result property="lastSyncStatus" column="last_sync_status" />
<result property="lastSyncError" column="last_sync_error" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<select id="selectEnabledSources" resultMap="TeachingVideoSourceResult">
select source_id, source_type, mid, season_id, category_code, enabled, sort_num, last_sync_time, last_sync_status, last_sync_error, create_by, create_time, update_by, update_time, remark
from teaching_video_source
where enabled = '0'
order by sort_num desc, source_id desc
</select>
<update id="updateSyncStatus" parameterType="TeachingVideoSource">
update teaching_video_source
set last_sync_time = #{lastSyncTime},
last_sync_status = #{lastSyncStatus},
last_sync_error = #{lastSyncError},
update_time = sysdate()
where source_id = #{sourceId}
</update>
</mapper>