记得上下班打卡 | git大法好,push需谨慎

Commit 1fb824d3 authored by wangyifan's avatar wangyifan

艺人操作记录功能

parent e58516fd
package com.liquidnet.service.kylin.service.admin;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.kylin.dao.KylinArtistOperationLogDao;
import com.liquidnet.service.kylin.entity.KylinArtistOperationLog;
/**
* <p>
* 艺人操作日志 服务类
* </p>
*
* @author liquidnet
* @since 2026-03-04
*/
public interface IKylinArtistOperationLogService extends IService<KylinArtistOperationLog> {
/**
* 记录操作日志(自动获取当前用户)
*
* @param artistId 艺人ID
* @param operationType 操作类型 1新增 2编辑 3删除
* @param operationContent 操作内容描述
*/
void recordLog(String artistId, Integer operationType, String operationContent);
/**
* 记录操作日志(指定操作人)
*
* @param artistId 艺人ID
* @param operationType 操作类型 1新增 2编辑 3删除
* @param operationContent 操作内容描述
* @param operatorId 操作人ID
* @param operatorName 操作人名称
*/
void recordLog(String artistId, Integer operationType, String operationContent, String operatorId, String operatorName);
/**
* 获取艺人操作记录列表
*
* @param artistId 艺人ID
* @param pageNum 页码
* @param pageSize 每页数量
* @return 操作记录分页列表
*/
PageInfo<KylinArtistOperationLogDao> getOperationLogs(String artistId, Integer pageNum, Integer pageSize);
}
...@@ -7,10 +7,12 @@ import com.liquidnet.client.admin.common.core.domain.AjaxResult; ...@@ -7,10 +7,12 @@ import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo; import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.enums.BusinessType; import com.liquidnet.client.admin.common.enums.BusinessType;
import com.liquidnet.service.kylin.dao.KylinArtistDao; import com.liquidnet.service.kylin.dao.KylinArtistDao;
import com.liquidnet.service.kylin.dao.KylinArtistOperationLogDao;
import com.liquidnet.service.kylin.dto.param.ArtistParam; import com.liquidnet.service.kylin.dto.param.ArtistParam;
import com.liquidnet.service.kylin.dto.param.ArtistSearchParam; import com.liquidnet.service.kylin.dto.param.ArtistSearchParam;
import com.liquidnet.service.kylin.dto.vo.ArtistVo; import com.liquidnet.service.kylin.dto.vo.ArtistVo;
import com.liquidnet.service.kylin.service.admin.IKylinArtistService; import com.liquidnet.service.kylin.service.admin.IKylinArtistService;
import com.liquidnet.service.kylin.service.admin.IKylinArtistOperationLogService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -42,6 +44,9 @@ public class KylinArtistController extends BaseController { ...@@ -42,6 +44,9 @@ public class KylinArtistController extends BaseController {
@Autowired @Autowired
private IKylinArtistService kylinArtistService; private IKylinArtistService kylinArtistService;
@Autowired
private IKylinArtistOperationLogService operationLogService;
@GetMapping("/create") @GetMapping("/create")
@RequiresPermissions("kylin:artist:create") @RequiresPermissions("kylin:artist:create")
public String create(ModelMap mmap) { public String create(ModelMap mmap) {
...@@ -170,4 +175,29 @@ public class KylinArtistController extends BaseController { ...@@ -170,4 +175,29 @@ public class KylinArtistController extends BaseController {
} }
return success(); return success();
} }
/**
* 艺人操作记录页面
*/
@RequiresPermissions("kylin:artist:detail")
@GetMapping("/operationLog/{artistId}")
public String operationLog(@PathVariable("artistId") String artistId, ModelMap mmap) {
// 获取艺人基本信息
ArtistVo artistVo = kylinArtistService.detail(artistId);
mmap.put("artistId", artistId);
mmap.put("artistName", artistVo != null ? artistVo.getArtistName() : "");
return prefix + "/operationLog";
}
/**
* 获取艺人操作记录列表
*/
@RequiresPermissions("kylin:artist:detail")
@PostMapping("/operationLogList")
@ResponseBody
public TableDataInfo operationLogList(String artistId, Integer pageNum, Integer pageSize) {
PageInfo<KylinArtistOperationLogDao> result =
operationLogService.getOperationLogs(artistId, pageNum, pageSize);
return getDataTable(result.getList());
}
} }
...@@ -127,6 +127,7 @@ ...@@ -127,6 +127,7 @@
var actions = []; var actions = [];
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.artistId + '\')"><i class="fa fa-eye"></i>详情</a> '); actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.artistId + '\')"><i class="fa fa-eye"></i>详情</a> ');
actions.push('<a class="btn btn-success btn-xs ' + updateFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.artistId + '\')"><i class="fa fa-edit"></i>编辑</a> '); actions.push('<a class="btn btn-success btn-xs ' + updateFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.artistId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="showOperationLog(\'' + row.artistId + '\')"><i class="fa fa-history"></i>操作日志</a> ');
return actions.join(''); return actions.join('');
} }
}] }]
...@@ -164,6 +165,12 @@ ...@@ -164,6 +165,12 @@
function removeArtist(id) { function removeArtist(id) {
$.operate.remove(id, "删除后该艺人信息将无法被引用,也无法找回,确认要将该艺人删除吗?"); $.operate.remove(id, "删除后该艺人信息将无法被引用,也无法找回,确认要将该艺人删除吗?");
} }
// 显示操作日志
function showOperationLog(artistId) {
var url = prefix + '/operationLog/' + artistId;
$.modal.openTab("艺人操作记录", url);
}
</script> </script>
</body> </body>
</html> </html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('艺人操作记录')"/>
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<!-- 头部信息 -->
<div class="col-sm-12" style="margin-bottom: 15px;">
<div class="alert alert-info" style="margin-bottom: 0;">
<strong>艺人ID:</strong><span th:text="${artistId}">10001</span>
<strong style="margin-left: 30px;">艺人名称:</strong><span th:text="${artistName}">摩登天空</span>
</div>
</div>
<div class="col-sm-12 select-table table-bordered">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer"/>
<script th:inline="javascript">
var artistId = [[${artistId}]];
var prefix = ctx + "kylin/artist";
$(function () {
var options = {
url: prefix + "/operationLogList",
queryParams: function(params) {
return {
pageNum: params.offset / params.limit + 1,
pageSize: params.limit,
artistId: artistId
};
},
columns: [
{
field: 'operationType',
title: '操作类型',
width: '10%',
formatter: function(value, row, index) {
var typeClass = '';
var typeName = row.operationTypeName || '未知';
if (value == 1) {
typeClass = 'label-success';
} else if (value == 2) {
typeClass = 'label-warning';
} else if (value == 3) {
typeClass = 'label-danger';
}
return '<span class="label ' + typeClass + '">' + typeName + '</span>';
}
},
{
field: 'createdAt',
title: '操作时间',
width: '20%'
},
{
field: 'operationContent',
title: '修改内容',
width: '50%'
},
{
field: 'operatorName',
title: '操作人',
width: '20%',
formatter: function(value, row, index) {
return value || '系统';
}
}
]
};
$.table.init(options);
});
</script>
</body>
</html>
package com.liquidnet.client.admin.zhengzai.kylin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.core.domain.entity.SysUser;
import com.liquidnet.client.admin.common.utils.ShiroUtils;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.kylin.dao.KylinArtistOperationLogDao;
import com.liquidnet.service.kylin.entity.KylinArtistOperationLog;
import com.liquidnet.service.kylin.mapper.KylinArtistOperationLogMapper;
import com.liquidnet.service.kylin.service.admin.IKylinArtistOperationLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 艺人操作日志 服务实现类
* </p>
*
* @author liquidnet
* @since 2026-03-04
*/
@Slf4j
@Service
public class KylinArtistOperationLogServiceImpl extends ServiceImpl<KylinArtistOperationLogMapper, KylinArtistOperationLog>
implements IKylinArtistOperationLogService {
@Override
public void recordLog(String artistId, Integer operationType, String operationContent) {
// 获取当前用户
String operatorId = "SYSTEM";
String operatorName = "系统";
try {
SysUser currentUser = ShiroUtils.getSysUser();
if (currentUser != null) {
operatorId = currentUser.getUserId().toString();
operatorName = currentUser.getUserName();
}
} catch (Exception e) {
log.warn("获取当前用户失败,使用系统默认值", e);
}
// 调用重载方法
recordLog(artistId, operationType, operationContent, operatorId, operatorName);
}
@Override
public void recordLog(String artistId, Integer operationType, String operationContent, String operatorId, String operatorName) {
try {
// 保存操作日志
KylinArtistOperationLog operLog = new KylinArtistOperationLog();
operLog.setLogId(IDGenerator.nextSnowId());
operLog.setArtistId(artistId);
operLog.setOperationType(operationType);
operLog.setOperationContent(operationContent);
operLog.setOperatorId(operatorId);
operLog.setOperatorName(operatorName);
operLog.setCreatedAt(LocalDateTime.now());
baseMapper.insert(operLog);
log.info("艺人操作日志记录成功: artistId={}, operationType={}, operator={}", artistId, operationType, operatorName);
} catch (Exception e) {
// 日志记录失败不影响主业务
log.error("保存艺人操作日志失败", e);
}
}
@Override
public PageInfo<KylinArtistOperationLogDao> getOperationLogs(String artistId, Integer pageNum, Integer pageSize) {
try {
PageHelper.startPage(pageNum != null ? pageNum : 1, pageSize != null ? pageSize : 10);
List<KylinArtistOperationLogDao> list = baseMapper.selectLogsByArtistId(artistId);
return new PageInfo<>(list);
} catch (Exception e) {
log.error("获取艺人操作记录失败, artistId: {}", artistId, e);
return new PageInfo<>();
}
}
}
...@@ -18,6 +18,7 @@ import com.liquidnet.service.kylin.mapper.KylinArtistAlbumMapper; ...@@ -18,6 +18,7 @@ import com.liquidnet.service.kylin.mapper.KylinArtistAlbumMapper;
import com.liquidnet.service.kylin.mapper.KylinArtistMapper; import com.liquidnet.service.kylin.mapper.KylinArtistMapper;
import com.liquidnet.service.kylin.mapper.KylinArtistPerformanceMapper; import com.liquidnet.service.kylin.mapper.KylinArtistPerformanceMapper;
import com.liquidnet.service.kylin.service.admin.IKylinArtistService; import com.liquidnet.service.kylin.service.admin.IKylinArtistService;
import com.liquidnet.service.kylin.service.admin.IKylinArtistOperationLogService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -52,6 +53,9 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -52,6 +53,9 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
@Autowired @Autowired
private KylinArtistPerformanceMapper artistPerformanceMapper; private KylinArtistPerformanceMapper artistPerformanceMapper;
@Autowired
private IKylinArtistOperationLogService operationLogService;
/** /**
* 创建艺人 * 创建艺人
*/ */
...@@ -77,6 +81,9 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -77,6 +81,9 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
saveAlbumImages(artistId, param.getAlbumImages()); saveAlbumImages(artistId, param.getAlbumImages());
} }
// 记录操作日志
operationLogService.recordLog(artistId, 1, buildCreateLogContent(param));
return true; return true;
} catch (Exception e) { } catch (Exception e) {
log.error("创建艺人失败", e); log.error("创建艺人失败", e);
...@@ -92,6 +99,16 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -92,6 +99,16 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
try { try {
String artistId = param.getArtistId(); String artistId = param.getArtistId();
// 获取原始数据用于对比
KylinArtist oldArtist = artistMapper.selectOne(
new UpdateWrapper<KylinArtist>().eq("artist_id", artistId).eq("status", 1)
);
if (oldArtist == null) {
log.warn("艺人不存在: {}", artistId);
return false;
}
// 校验艺人名称是否已被其他艺人使用 // 校验艺人名称是否已被其他艺人使用
KylinArtist existArtist = artistMapper.selectByArtistName(param.getArtistName()); KylinArtist existArtist = artistMapper.selectByArtistName(param.getArtistName());
if (existArtist != null && !existArtist.getArtistId().equals(artistId)) { if (existArtist != null && !existArtist.getArtistId().equals(artistId)) {
...@@ -114,6 +131,12 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -114,6 +131,12 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
saveAlbumImages(artistId, param.getAlbumImages()); saveAlbumImages(artistId, param.getAlbumImages());
} }
// 记录操作日志(对比变更)
String logContent = buildUpdateLogContent(oldArtist, param);
if (logContent != null && !logContent.isEmpty()) {
operationLogService.recordLog(artistId, 2, logContent);
}
return true; return true;
} catch (Exception e) { } catch (Exception e) {
log.error("修改艺人失败", e); log.error("修改艺人失败", e);
...@@ -229,9 +252,18 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -229,9 +252,18 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
new UpdateWrapper<KylinArtist>().in("artist_id", artistIds) new UpdateWrapper<KylinArtist>().in("artist_id", artistIds)
); );
// 删除相册图片 // 删除相册图片并记录日志
for (String artistId : artistIds) { for (String artistId : artistIds) {
// 获取艺人信息用于日志
KylinArtist artist = artistMapper.selectOne(
new UpdateWrapper<KylinArtist>().eq("artist_id", artistId)
);
artistAlbumMapper.deleteByArtistId(artistId); artistAlbumMapper.deleteByArtistId(artistId);
// 记录删除日志
String logContent = "删除艺人:" + (artist != null ? artist.getArtistName() + "(ID:" + artistId + ")" : artistId);
operationLogService.recordLog(artistId, 3, logContent);
} }
return true; return true;
...@@ -276,4 +308,94 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin ...@@ -276,4 +308,94 @@ public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, Kylin
artistAlbumMapper.insert(album); artistAlbumMapper.insert(album);
} }
} }
/**
* 构建新增操作的日志内容
*/
private String buildCreateLogContent(ArtistParam param) {
StringBuilder content = new StringBuilder();
content.append("新增艺人: [").append(param.getArtistName()).append("];");
content.append("类型: [").append(getArtistTypeName(param.getArtistType())).append("];");
if (param.getIntroduction() != null && !param.getIntroduction().isEmpty()) {
String intro = param.getIntroduction();
content.append("介绍: ").append(intro.length() > 50 ? intro.substring(0, 50) + "..." : intro);
}
return content.toString();
}
/**
* 构建修改操作的日志内容(逐字段对比)
*/
private String buildUpdateLogContent(KylinArtist oldArtist, ArtistParam newParam) {
StringBuilder content = new StringBuilder();
boolean hasChange = false;
// 对比艺人名称
if (!oldArtist.getArtistName().equals(newParam.getArtistName())) {
content.append("名称从[").append(oldArtist.getArtistName()).append("]")
.append("改为[").append(newParam.getArtistName()).append("];");
hasChange = true;
}
// 对比艺人类型
if (!oldArtist.getArtistType().equals(newParam.getArtistType())) {
content.append("类型从[").append(getArtistTypeName(oldArtist.getArtistType()))
.append("]改为[").append(getArtistTypeName(newParam.getArtistType())).append("];");
hasChange = true;
}
// 对比艺人头像
String oldAvatar = oldArtist.getAvatarUrl() != null ? oldArtist.getAvatarUrl() : "";
String newAvatar = newParam.getAvatarUrl() != null ? newParam.getAvatarUrl() : "";
if (!oldAvatar.equals(newAvatar)) {
content.append("更新了艺人头像;");
hasChange = true;
}
// 对比艺人简介
String oldIntro = oldArtist.getIntroduction() != null ? oldArtist.getIntroduction() : "";
String newIntro = newParam.getIntroduction() != null ? newParam.getIntroduction() : "";
if (!oldIntro.equals(newIntro)) {
content.append("更新了艺人简介;");
hasChange = true;
}
// 对比排序权重
Integer oldSort = oldArtist.getSort() != null ? oldArtist.getSort() : 0;
Integer newSort = newParam.getSort() != null ? newParam.getSort() : 0;
if (!oldSort.equals(newSort)) {
content.append("排序权重从").append(oldSort).append("改为").append(newSort).append(";");
hasChange = true;
}
// 注意:相册图片每次都会删除重建,所以不对比相册
// 如果其他字段都没变化,说明只是更新了相册
if (!hasChange && newParam.getAlbumImages() != null && !newParam.getAlbumImages().isEmpty()) {
content.append("更新了艺人相册图片");
hasChange = true;
}
return hasChange ? content.toString() : null;
}
/**
* 获取艺人类型名称
*/
private String getArtistTypeName(Integer artistType) {
if (artistType == null) return "未知";
switch (artistType) {
case 1:
return "音乐人";
case 2:
return "艺术家";
case 3:
return "厂牌";
case 4:
return "品牌方";
default:
return "未知";
}
}
} }
package com.liquidnet.service.kylin.dao;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* <p>
* 艺人操作记录DAO
* </p>
*
* @author liquidnet
* @since 2026-03-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistOperationLogDao implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 操作类型 1新增 2编辑 3删除
*/
private Integer operationType;
/**
* 操作类型名称
*/
private String operationTypeName;
/**
* 操作时间
*/
private String createdAt;
/**
* 修改内容
*/
private String operationContent;
/**
* 操作人
*/
private String operatorName;
}
package com.liquidnet.service.kylin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 艺人操作记录表
* </p>
*
* @author liquidnet
* @since 2026-03-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistOperationLog implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO)
private Long mid;
/**
* 日志ID
*/
private String logId;
/**
* 关联艺人ID
*/
private String artistId;
/**
* 操作类型 1新增 2编辑 3删除
*/
private Integer operationType;
/**
* 修改内容描述
*/
private String operationContent;
/**
* 操作人ID
*/
private String operatorId;
/**
* 操作人名称
*/
private String operatorName;
/**
* 操作时间
*/
private LocalDateTime createdAt;
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.dao.KylinArtistOperationLogDao;
import com.liquidnet.service.kylin.entity.KylinArtistOperationLog;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 艺人操作记录 Mapper 接口
* </p>
*
* @author liquidnet
* @since 2026-03-04
*/
public interface KylinArtistOperationLogMapper extends BaseMapper<KylinArtistOperationLog> {
/**
* 根据艺人ID查询操作记录列表
*
* @param artistId 艺人ID
* @return 操作记录列表
*/
List<KylinArtistOperationLogDao> selectLogsByArtistId(@Param("artistId") String artistId);
}
<?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.liquidnet.service.kylin.mapper.KylinArtistOperationLogMapper">
<!-- 根据艺人ID查询操作记录列表 -->
<select id="selectLogsByArtistId" parameterType="java.lang.String" resultType="com.liquidnet.service.kylin.dao.KylinArtistOperationLogDao">
SELECT
operation_type as operationType,
CASE operation_type
WHEN 1 THEN '新增'
WHEN 2 THEN '编辑'
WHEN 3 THEN '删除'
ELSE '未知'
END as operationTypeName,
DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as createdAt,
operation_content as operationContent,
operator_name as operatorName
FROM kylin_artist_operation_log
WHERE artist_id = #{artistId}
ORDER BY created_at DESC
</select>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment