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

Commit 4575268b authored by wangyifan's avatar wangyifan

1.5 需求

parent 46a09ccb
package com.liquidnet.service.kylin.dto.param;
import com.liquidnet.service.kylin.entity.KylinArtist;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.time.LocalDateTime;
import java.util.List;
/**
* 艺人管理参数
*
* @author system
* @since 2026-02-04
*/
@Data
@ApiModel("艺人管理参数")
public class ArtistParam {
@ApiModelProperty(value = "艺人ID")
private String artistId;
@ApiModelProperty(value = "艺人名称")
private String artistName;
@ApiModelProperty(value = "艺人类型 1音乐人 2艺术家 3厂牌 4品牌方")
private Integer artistType;
@ApiModelProperty(value = "艺人头像")
private String avatarUrl;
@ApiModelProperty(value = "艺人简介")
private String introduction;
@ApiModelProperty(value = "艺人相册图片列表")
private List<String> albumImages;
@ApiModelProperty(value = "排序权重")
private Integer sort;
@ApiModelProperty(value = "状态 0禁用 1启用")
private Integer status;
@ApiModelProperty(value = "批量操作的ID列表")
private List<String> ids;
public KylinArtist getFields(String artistId, LocalDateTime createdAt) {
KylinArtist kylinArtist = new KylinArtist();
BeanUtils.copyProperties(this, kylinArtist);
if (artistId != null) {
kylinArtist.setArtistId(artistId);
}
if (createdAt != null) {
kylinArtist.setCreatedAt(createdAt);
}
kylinArtist.setUpdatedAt(LocalDateTime.now());
// 设置默认值
if (kylinArtist.getStatus() == null) {
kylinArtist.setStatus(1);
}
if (kylinArtist.getSort() == null) {
kylinArtist.setSort(0);
}
return kylinArtist;
}
}
package com.liquidnet.service.kylin.dto.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 艺人搜索参数
*
* @author system
* @since 2026-02-04
*/
@Data
@ApiModel("艺人搜索参数")
public class ArtistSearchParam {
@ApiModelProperty(value = "艺人名称")
private String artistName;
@ApiModelProperty(value = "艺人ID")
private String artistId;
@ApiModelProperty(value = "艺人类型 1音乐人 2艺术家 3厂牌 4品牌方")
private Integer artistType;
@ApiModelProperty(value = "开始日期")
private String beginDate;
@ApiModelProperty(value = "结束日期")
private String endDate;
@ApiModelProperty(value = "当前页码")
private Integer pageNum = 1;
@ApiModelProperty(value = "每页数量")
private Integer pageSize = 10;
}
package com.liquidnet.service.kylin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 艺人详情VO
*
* @author system
* @since 2026-02-04
*/
@Data
@ApiModel("艺人详情VO")
public class ArtistVo {
@ApiModelProperty(value = "艺人ID")
private String artistId;
@ApiModelProperty(value = "艺人名称")
private String artistName;
@ApiModelProperty(value = "艺人类型 1音乐人 2艺术家 3厂牌 4品牌方")
private Integer artistType;
@ApiModelProperty(value = "艺人类型名称")
private String artistTypeName;
@ApiModelProperty(value = "艺人头像")
private String avatarUrl;
@ApiModelProperty(value = "艺人简介")
private String introduction;
@ApiModelProperty(value = "艺人相册图片列表")
private List<String> albumImages;
@ApiModelProperty(value = "关联演出")
private List<PerformanceVo> performanceVoList;
@ApiModelProperty(value = "关联商品")
private List<ProductVo> productVoList;
@ApiModelProperty(value = "排序权重")
private Integer sort;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "创建时间")
private String createdAt;
@ApiModelProperty(value = "更新时间")
private String updatedAt;
@Data
@ApiModel("演出VO")
public static class PerformanceVo{
@ApiModelProperty("演出ID")
private String performanceId;
@ApiModelProperty("演出名称")
private String title;
@ApiModelProperty("演出开始时间")
private String timeStart;
}
@Data
@ApiModel("商品VO")
private static class ProductVo {
}
}
package com.liquidnet.service.kylin.service.admin;
import com.baomidou.mybatisplus.extension.service.IService;
import com.liquidnet.service.kylin.entity.KylinArtist;
/**
* <p>
* 艺人管理 服务类
* </p>
*
* @author liquidnet
* @since 2026-02-04
*/
public interface IKylinArtistService extends IService<KylinArtist> {
}
package com.liquidnet.client.admin.web.controller.zhengzai.kylin;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.annotation.Log;
import com.liquidnet.client.admin.common.core.controller.BaseController;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.enums.BusinessType;
import com.liquidnet.client.admin.zhengzai.kylin.service.impl.KylinArtistServiceImpl;
import com.liquidnet.service.kylin.dao.KylinArtistDao;
import com.liquidnet.service.kylin.dto.param.ArtistParam;
import com.liquidnet.service.kylin.dto.param.ArtistSearchParam;
import com.liquidnet.service.kylin.dto.vo.ArtistVo;
import io.swagger.annotations.Api;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 艺人管理 后端管理控制器
* </p>
*
* @author liquidnet
* @since 2026-02-04
*/
@Api(tags = "艺人管理")
@Controller
@RequestMapping("/kylin/artist")
public class KylinArtistController extends BaseController {
private final String prefix = "zhengzai/kylin/artist";
@Value("${liquidnet.client.admin.platformUrl}")
private String platformUrl;
@Autowired
private KylinArtistServiceImpl kylinArtistService;
@GetMapping("/create")
@RequiresPermissions("kylin:artist:create")
public String create(ModelMap mmap) {
mmap.put("platformUrl", platformUrl);
return prefix + "/create";
}
@GetMapping("/update/{artistId}")
@RequiresPermissions("kylin:artist:update")
public String update(@PathVariable("artistId") String artistId, ModelMap mmap) {
ArtistVo result = kylinArtistService.detail(artistId);
mmap.put("ArtistVo", result);
mmap.put("platformUrl", platformUrl);
return prefix + "/update";
}
@RequiresPermissions("kylin:artist:list")
@GetMapping()
public String artists() {
return prefix + "/artists";
}
@RequiresPermissions("kylin:artist:detail")
@GetMapping("/detail/{artistId}")
public String detail(@PathVariable("artistId") String artistId, ModelMap mmap) {
ArtistVo result = kylinArtistService.detail(artistId);
mmap.put("ArtistVo", result);
return prefix + "/detail";
}
@RequiresPermissions("kylin:artist:list")
@PostMapping("list")
@ResponseBody
public TableDataInfo artistList(ArtistSearchParam param) {
PageInfo<KylinArtistDao> result = kylinArtistService.artistList(param);
return getDataTable(result.getList());
}
@Log(title = "创建艺人", businessType = BusinessType.INSERT)
@RequiresPermissions("kylin:artist:create")
@PostMapping("create")
@ResponseBody
public AjaxResult createSave(ArtistParam param, String albumImagesJson) {
// 校验艺人名称是否已存在
Boolean exists = kylinArtistService.checkArtistNameExists(param.getArtistName(), null);
if (exists) {
return error("艺人名称已存在,不可重复创建");
}
// 解析相册图片JSON数组
if (albumImagesJson != null && !albumImagesJson.isEmpty() && !albumImagesJson.equals("[]")) {
try {
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
List<String> albumImages = mapper.readValue(albumImagesJson,
mapper.getTypeFactory().constructCollectionType(List.class, String.class));
param.setAlbumImages(albumImages);
} catch (Exception e) {
return error("相册图片数据格式错误");
}
}
Boolean res = kylinArtistService.create(param);
if (res) {
return success();
} else {
return error("添加艺人失败");
}
}
@Log(title = "修改艺人", businessType = BusinessType.UPDATE)
@RequiresPermissions("kylin:artist:update")
@PostMapping("update")
@ResponseBody
public AjaxResult updateSave(ArtistParam param, String albumImagesJson) {
// 校验艺人名称是否已被其他艺人使用
Boolean exists = kylinArtistService.checkArtistNameExists(param.getArtistName(), param.getArtistId());
if (exists) {
return error("艺人名称已被其他艺人使用");
}
// 解析相册图片JSON数组
if (albumImagesJson != null && !albumImagesJson.isEmpty() && !albumImagesJson.equals("[]")) {
try {
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
List<String> albumImages = mapper.readValue(albumImagesJson,
mapper.getTypeFactory().constructCollectionType(List.class, String.class));
param.setAlbumImages(albumImages);
} catch (Exception e) {
return error("相册图片数据格式错误");
}
}
Boolean res = kylinArtistService.update(param);
if (res) {
return success();
} else {
return error("修改艺人失败");
}
}
@Log(title = "删除艺人", businessType = BusinessType.DELETE)
@RequiresPermissions("kylin:artist:delete")
@PostMapping("delete")
@ResponseBody
public AjaxResult delete(ArtistParam param) {
List<String> artistIds = param.getIds();
Boolean result = kylinArtistService.delete(artistIds);
if (result) {
return success("删除成功");
} else {
return error("删除失败");
}
}
/**
* 检查艺人名称是否存在
*/
@PostMapping("checkName")
@ResponseBody
public AjaxResult checkArtistName(String artistName, String artistId) {
Boolean exists = kylinArtistService.checkArtistNameExists(artistName, artistId);
if (exists) {
return error("艺人名称已存在");
}
return success();
}
}
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('艺人列表')"/>
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>艺人名称:</label>
<input type="text" name="artistName" placeholder="请输入艺人名称"/>
</li>
<li>
<label>艺人类型:</label>
<select name="artistType">
<option value="">全部</option>
<option value="1">音乐人</option>
<option value="2">艺术家</option>
<option value="3">厂牌</option>
<option value="4">品牌方</option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i
class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="kylin:artist:create">
<i class="fa fa-plus"></i> 添加
</a>
</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 updateFlag = [[${@permission.hasPermi('kylin:artist:update')}]];
var removeFlag = [[${@permission.hasPermi('kylin:artist:delete')}]];
var detailFlag = [[${@permission.hasPermi('kylin:artist:detail')}]];
var prefix = ctx + "kylin/artist";
$(function () {
var options = {
url: prefix + "/list",
updateUrl: prefix + "/update/{id}",
createUrl: prefix + "/create",
removeUrl: prefix + "/delete",
detailUrl: prefix + "/detail/{id}",
modalName: "艺人",
columns: [
{
field: 'artistId',
title: '艺人ID'
},
{
field: 'avatarUrl',
title: '艺人头像',
formatter: function(value, row, index) {
return $.table.imageView(value, "80", "80");
}
},
{
field: 'artistName',
title: '艺人名称'
},
{
field: 'artistTypeName',
title: '艺人类型',
},
{
field: 'createdAt',
title: '艺人入驻时间',
formatter: function(value, row, index) {
if (value) {
var date = new Date(value);
return date.getFullYear() + '-' +
String(date.getMonth() + 1).padStart(2, '0') + '-' +
String(date.getDate()).padStart(2, '0') + ' ' +
String(date.getHours()).padStart(2, '0') + ':' +
String(date.getMinutes()).padStart(2, '0') + ':' +
String(date.getSeconds()).padStart(2, '0');
}
return '';
}
},
{
field: 'performanceCount',
title: '关联演出',
formatter: function(value, row, index) {
return value || 0;
}
},
{
field: 'productCount',
title: '关联商品',
formatter: function(value, row, index) {
return value || 0;
}
},
{
title: '操作',
align: 'center',
formatter: function (value, row, index) {
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-success btn-xs ' + updateFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.artistId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
return actions.join('');
}
}]
};
$.table.init(options);
});
// 单条删除
function removeArtist(id) {
$.operate.remove(id, "删除后该艺人信息将无法被引用,也无法找回,确认要将该艺人删除吗?");
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('添加艺人')"/>
<th:block th:include="include :: bootstrap-fileinput-css"/>
<th:block th:include="include :: summernote-css"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-artist-add">
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人名称:</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="artistName" id="artistName"
maxlength="50" placeholder="最多输入50个字" required>
<span class="help-block m-b-none text-muted">
<span id="nameCount">0</span>/50 字
</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人类型:</label>
<div class="col-sm-10">
<select class="form-control" name="artistType" id="artistType" required>
<option value="">请选择艺人类型</option>
<option value="1">音乐人</option>
<option value="2">艺术家</option>
<option value="3">厂牌</option>
<option value="4">品牌方</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人头像:</label>
<div class="col-sm-10">
<div class="file-loading">
<input id="fileinput-avatar" type="file" name="file" data-browse-on-zone-click="true">
</div>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 支持上传jpg、png格式图片,最大支持5M,上传后按照1:1格式进行裁剪</span>
</div>
</div>
<input hidden id="avatarUrl" name="avatarUrl">
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人简介:</label>
<div class="col-sm-10">
<div id="introduction" name="introduction"></div>
<span class="help-block m-b-none text-muted">
<span id="introCount">0</span>/2000 字
</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">艺人相册:</label>
<div class="col-sm-10">
<div class="file-loading">
<input id="fileinput-album" type="file" name="file" multiple data-browse-on-zone-click="true">
</div>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 支持上传jpg、png格式图片,单次最多上传20张,每张最大支持5M</span>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: bootstrap-fileinput-js"/>
<th:block th:include="include :: summernote-js"/>
<script type="text/javascript">
var prefix = ctx + "kylin/artist";
var platformUrl = "[[${platformUrl}]]";
var albumImagesList = [];
function submitHandler() {
var artistName = $('#artistName').val().trim();
if (!artistName) {
$.modal.alertWarning("请填写艺人名称");
$('#artistName').focus();
return false;
}
if (artistName.length > 50) {
$.modal.alertWarning("艺人名称最多输入50个字");
$('#artistName').focus();
return false;
}
// 检查艺人名称是否已存在
var nameExists = false;
$.ajax({
url: prefix + "/checkName",
type: "post",
data: { artistName: artistName },
async: false,
success: function(result) {
if (result.code != 0) {
$.modal.alertWarning("艺人名称已存在,不可重复创建");
$('#artistName').focus();
nameExists = true;
}
}
});
if (nameExists) {
return false;
}
var artistType = $('#artistType').val();
if (!artistType) {
$.modal.alertWarning("请选择艺人类型");
$('#artistType').focus();
return false;
}
var avatarUrl = $('#avatarUrl').val();
if (!avatarUrl) {
$.modal.alertWarning("请上传艺人头像");
return false;
}
var introduction = $('#introduction').summernote('code');
if (!introduction || introduction.trim() === '' || introduction === '<p><br></p>') {
$.modal.alertWarning("请填写艺人简介");
return false;
}
// 计算富文本内容的文字长度
var introText = $('<div>').html(introduction).text();
if (introText.length > 2000) {
$.modal.alertWarning("艺人简介最多输入2000个字");
return false;
}
// 将相册图片列表转换为JSON数组
var albumImagesJson = JSON.stringify(albumImagesList);
if ($.validate.form()) {
var data = $('#form-artist-add').serializeArray();
// 添加富文本内容
data.push({name: 'introduction', value: introduction});
// 添加相册图片(作为JSON数组字符串)
data.push({name: 'albumImagesJson', value: albumImagesJson});
$.operate.save(prefix + "/create", data);
}
}
$(function () {
// 艺人名称字数统计和实时校验
$('#artistName').on('input', function() {
var length = $(this).val().length;
$('#nameCount').text(length);
if (length > 50) {
$(this).addClass('is-invalid');
$(this).parent().find('.error-msg').remove();
$(this).parent().append('<span class="error-msg text-danger">艺人名称不能超过50个字</span>');
} else {
$(this).removeClass('is-invalid');
$(this).parent().find('.error-msg').remove();
}
});
// 艺人名称失去焦点校验
$('#artistName').on('blur', function() {
var value = $(this).val().trim();
$(this).parent().find('.error-msg').remove();
if (!value) {
$(this).addClass('is-invalid');
$(this).parent().append('<span class="error-msg text-danger">请填写艺人名称</span>');
} else if (value.length > 50) {
$(this).addClass('is-invalid');
$(this).parent().append('<span class="error-msg text-danger">艺人名称不能超过50个字</span>');
} else {
$(this).removeClass('is-invalid');
}
});
// 初始化富文本编辑器
$('#introduction').summernote({
height: 200,
lang: 'zh-CN',
placeholder: '请输入艺人简介,最多输入2000个字',
callbacks: {
onChange: function(contents, $editable) {
var text = $('<div>').html(contents).text();
var length = text.length;
$('#introCount').text(length);
if (length > 2000) {
$('#introCount').addClass('text-danger');
} else {
$('#introCount').removeClass('text-danger');
}
}
}
});
// 初始化头像上传
$("#fileinput-avatar").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "artist/avatar",
"buckType": 1
},
autoReplace: true,
dropZoneTitle: "请上传艺人头像(1:1比例)",
maxFileCount: 1,
maxFileSize: 5120,
allowedFileExtensions: ['jpg', 'png', 'jpeg'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件'
});
$("#fileinput-avatar").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
$("#avatarUrl").val(fullUrl);
});
// 初始化相册上传
$("#fileinput-album").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "artist/album",
"buckType": 1
},
dropZoneTitle: "请上传艺人相册图片",
maxFileCount: 20,
maxFileSize: 5120,
allowedFileExtensions: ['jpg', 'png', 'jpeg'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件'
});
$("#fileinput-album").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
albumImagesList.push(fullUrl);
});
$("#fileinput-album").on("fileremoved", function(event, id, index) {
// 从列表中移除对应的图片
if (index < albumImagesList.length) {
albumImagesList.splice(index, 1);
}
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('艺人详情')"/>
<style>
.artist-detail-container {
padding: 20px;
}
.artist-basic-info {
margin-bottom: 30px;
}
.artist-basic-info h3 {
margin-bottom: 15px;
color: #333;
font-size: 18px;
}
.info-row {
display: flex;
margin-bottom: 12px;
}
.info-label {
width: 120px;
font-weight: bold;
color: #666;
}
.info-value {
flex: 1;
color: #333;
}
.artist-intro {
margin-top: 20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 4px;
}
.section-title {
font-size: 18px;
font-weight: bold;
color: #333;
margin: 30px 0 15px 0;
padding-bottom: 10px;
border-bottom: 2px solid #e9ecef;
}
.album-gallery {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.album-item {
width: 100px;
height: 100px;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background-color: #f8f9fa;
}
.album-item img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.table-container {
margin-top: 15px;
border: 1px solid #e9ecef;
border-radius: 4px;
overflow: hidden;
}
.custom-table {
width: 100%;
border-collapse: collapse;
}
.custom-table thead {
background-color: #f8f9fa;
}
.custom-table th,
.custom-table td {
padding: 12px 15px;
border-bottom: 1px solid #e9ecef;
text-align: left;
}
.custom-table th {
font-weight: bold;
color: #333;
}
.custom-table tbody tr:hover {
background-color: #f8f9fa;
}
.product-image {
width: 60px;
height: 60px;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.product-image img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.status-badge {
display: inline-block;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
}
.status-on {
background-color: #d4edda;
color: #155724;
}
.status-off {
background-color: #f8d7da;
color: #721c24;
}
.empty-data {
text-align: center;
padding: 40px;
color: #999;
font-style: italic;
}
.action-buttons {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #e9ecef;
}
.btn-custom {
min-width: 100px;
}
.btn-back {
background-color: #6c757d;
border-color: #6c757d;
color: white;
}
.btn-back:hover {
background-color: #5a6268;
border-color: #545b62;
color: white;
}
</style>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight">
<div class="ibox">
<div class="ibox-title">
<h5>艺人详情</h5>
</div>
<div class="ibox-content" th:object="${ArtistVo}">
<div class="artist-detail-container">
<!-- 基本信息 -->
<div class="artist-basic-info">
<h3>基本信息</h3>
<div class="info-row">
<div class="info-label">艺人ID:</div>
<div class="info-value" th:text="*{artistId}">10001</div>
</div>
<div class="info-row">
<div class="info-label">艺人名称:</div>
<div class="info-value" th:text="*{artistName}">摩登天空</div>
</div>
<div class="info-row">
<div class="info-label">艺人类型:</div>
<div class="info-value" th:text="*{artistTypeName}">品牌方</div>
</div>
<!-- 艺人头像 -->
<div class="info-row" th:if="*{avatarUrl}">
<div class="info-label">艺人头像:</div>
<div class="info-value">
<div style="width: 100px; height: 100px; border: 1px solid #ddd; border-radius: 4px; overflow: hidden; display: flex; align-items: center; justify-content: center;">
<img th:src="*{avatarUrl}" alt="艺人头像" style="max-width: 100%; max-height: 100%;">
</div>
</div>
</div>
<!-- 艺人简介 -->
<div class="artist-intro">
<div class="info-label" style="margin-bottom: 8px;">艺人介绍:</div>
<div class="info-value" th:utext="*{introduction} ?: '暂无介绍'">
摩登天空是中国知名音乐厂牌,致力于推广独立音乐。
</div>
</div>
</div>
<!-- 艺人相册 -->
<div th:if="*{albumImages != null and !albumImages.isEmpty()}">
<div class="section-title">艺人相册</div>
<div class="album-gallery">
<th:block th:each="img, iterStat : ${ArtistVo.albumImages}">
<div class="album-item">
<img th:src="${img}" th:alt="'相册图片' + ${iterStat.index + 1}">
</div>
</th:block>
</div>
</div>
<!-- 演出信息 -->
<div>
<div class="section-title">
艺人演出信息
<span th:if="*{performanceVoList != null}" style="font-size: 14px; color: #666; margin-left: 10px;">
(共<span th:text="*{performanceVoList.size()}">2</span>条)
</span>
</div>
<div class="table-container" th:if="*{performanceVoList != null and !performanceVoList.isEmpty()}">
<table class="custom-table">
<thead>
<tr>
<th width="40%">演出名称</th>
<th width="30%">演出ID</th>
<th width="30%">演出时间</th>
</tr>
</thead>
<tbody>
<tr th:each="performance : ${ArtistVo.performanceVoList}">
<td th:text="${performance.title}">摩登天空音乐节</td>
<td th:text="${performance.performanceId}">show001</td>
<td th:text="${performance.timeStart}">2023-05-01</td>
</tr>
</tbody>
</table>
</div>
<div th:if="*{performanceVoList == null or performanceVoList.isEmpty()}" class="empty-data">
暂无演出信息
</div>
</div>
<!-- 关联商品信息 -->
<div>
<div class="section-title">
艺人关联商品信息
<span th:if="*{productVoList != null}" style="font-size: 14px; color: #666; margin-left: 10px;">
(共<span th:text="*{productVoList.size()}">2</span>条)
</span>
</div>
<div class="table-container" th:if="*{productVoList != null and !productVoList.isEmpty()}">
<table class="custom-table">
<thead>
<tr>
<th width="15%">商品编码</th>
<th width="20%">商品名称</th>
<th width="15%">商品头图</th>
<th width="15%">商品分类</th>
<th width="15%">商品售价</th>
<th width="15%">上架状态</th>
</tr>
</thead>
<tbody>
<tr th:each="product : ${ArtistVo.productVoList}">
<td th:text="${product.productCode} ?: '--'">goods001</td>
<td th:text="${product.productName} ?: '--'">摩登天空T恤</td>
<td>
<div class="product-image" th:if="${product.imageUrl}">
<img th:src="${product.imageUrl}" alt="商品图片">
</div>
<span th:unless="${product.imageUrl}">--</span>
</td>
<td th:text="${product.category} ?: '--'">服饰</td>
<td th:text="${product.price} ?: '--'">99.00元</td>
<td>
<span th:if="${product.status == 1}" class="status-badge status-on">已上架</span>
<span th:if="${product.status == 0}" class="status-badge status-off">未上架</span>
<span th:if="${product.status != 1 and product.status != 0}" th:text="${product.status}">--</span>
</td>
</tr>
</tbody>
</table>
</div>
<div th:if="*{productVoList == null or productVoList.isEmpty()}" class="empty-data">
暂无关联商品信息
</div>
</div>
<!-- 操作按钮 -->
<div class="action-buttons">
<button type="button" class="btn btn-custom btn-back" onclick="$.modal.close()">
<i class="fa fa-arrow-left"></i> 返回
</button>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer"/>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('编辑艺人')"/>
<th:block th:include="include :: bootstrap-fileinput-css"/>
<th:block th:include="include :: summernote-css"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-artist-edit" th:object="${ArtistVo}">
<input type="hidden" name="artistId" th:field="*{artistId}">
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人名称:</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="artistName" id="artistName"
th:field="*{artistName}" maxlength="50" placeholder="最多输入50个字" required>
<span class="help-block m-b-none text-muted">
<span id="nameCount">0</span>/50 字
</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人类型:</label>
<div class="col-sm-10">
<select class="form-control" name="artistType" id="artistType" th:field="*{artistType}" required>
<option value="">请选择艺人类型</option>
<option value="1">音乐人</option>
<option value="2">艺术家</option>
<option value="3">厂牌</option>
<option value="4">品牌方</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人头像:</label>
<div class="col-sm-10">
<div class="file-loading">
<input id="fileinput-avatar" type="file" name="file" data-browse-on-zone-click="true">
</div>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 支持上传jpg、png格式图片,最大支持5M,上传后按照1:1格式进行裁剪</span>
</div>
</div>
<input hidden id="avatarUrl" name="avatarUrl" th:field="*{avatarUrl}">
<div class="form-group">
<label class="col-sm-2 control-label is-required">艺人简介:</label>
<div class="col-sm-10">
<div id="introduction" name="introduction"></div>
<span class="help-block m-b-none text-muted">
<span id="introCount">0</span>/2000 字
</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">艺人相册:</label>
<div class="col-sm-10">
<div class="file-loading">
<input id="fileinput-album" type="file" name="files" multiple data-browse-on-zone-click="true">
</div>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 支持上传jpg、png格式图片,单次最多上传20张,每张最大支持5M</span>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: bootstrap-fileinput-js"/>
<th:block th:include="include :: summernote-js"/>
<script th:inline="javascript">
var prefix = ctx + "kylin/artist";
var platformUrl = "[[${platformUrl}]]";
var artistData = [[${ArtistVo}]];
var albumImagesList = [];
var originalArtistName = artistData.artistName;
function submitHandler() {
var artistName = $('#artistName').val().trim();
if (!artistName) {
$.modal.alertWarning("请填写艺人名称");
$('#artistName').focus();
return false;
}
if (artistName.length > 50) {
$.modal.alertWarning("艺人名称最多输入50个字");
$('#artistName').focus();
return false;
}
// 如果艺人名称有修改,检查是否已存在
if (artistName !== originalArtistName) {
var nameExists = false;
$.ajax({
url: prefix + "/checkName",
type: "post",
data: {
artistName: artistName,
artistId: artistData.artistId
},
async: false,
success: function(result) {
if (result.code != 0) {
$.modal.alertWarning("艺人名称已被其他艺人使用");
$('#artistName').focus();
nameExists = true;
}
}
});
if (nameExists) {
return false;
}
}
var artistType = $('#artistType').val();
if (!artistType) {
$.modal.alertWarning("请选择艺人类型");
$('#artistType').focus();
return false;
}
var avatarUrl = $('#avatarUrl').val();
if (!avatarUrl) {
$.modal.alertWarning("请上传艺人头像");
return false;
}
var introduction = $('#introduction').summernote('code');
if (!introduction || introduction.trim() === '' || introduction === '<p><br></p>') {
$.modal.alertWarning("请填写艺人简介");
return false;
}
var introText = $('<div>').html(introduction).text();
if (introText.length > 2000) {
$.modal.alertWarning("艺人简介最多输入2000个字");
return false;
}
var albumImagesJson = JSON.stringify(albumImagesList);
if ($.validate.form()) {
var data = $('#form-artist-edit').serializeArray();
data.push({name: 'introduction', value: introduction});
data.push({name: 'albumImagesJson', value: albumImagesJson});
$.operate.save(prefix + "/update", data);
}
}
$(function () {
// 初始化字数统计
var nameLength = $('#artistName').val().length;
$('#nameCount').text(nameLength);
// 艺人名称字数统计和实时校验
$('#artistName').on('input', function() {
var length = $(this).val().length;
$('#nameCount').text(length);
if (length > 50) {
$(this).addClass('is-invalid');
$(this).parent().find('.error-msg').remove();
$(this).parent().append('<span class="error-msg text-danger">艺人名称不能超过50个字</span>');
} else {
$(this).removeClass('is-invalid');
$(this).parent().find('.error-msg').remove();
}
});
// 初始化富文本编辑器
$('#introduction').summernote({
height: 200,
lang: 'zh-CN',
placeholder: '请输入艺人简介,最多输入2000个字',
callbacks: {
onChange: function(contents, $editable) {
var text = $('<div>').html(contents).text();
var length = text.length;
$('#introCount').text(length);
if (length > 2000) {
$('#introCount').addClass('text-danger');
} else {
$('#introCount').removeClass('text-danger');
}
}
}
});
// 设置富文本内容
if (artistData.introduction) {
$('#introduction').summernote('code', artistData.introduction);
}
// 初始化相册图片列表
if (artistData.albumImages && artistData.albumImages.length > 0) {
albumImagesList = artistData.albumImages;
}
// 初始化头像上传
var avatarInitialPreview = [];
var avatarInitialPreviewConfig = [];
if (artistData.avatarUrl) {
avatarInitialPreview.push(artistData.avatarUrl);
avatarInitialPreviewConfig.push({
caption: "当前头像",
url: "#",
key: 1
});
}
$("#fileinput-avatar").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "artist/avatar",
"buckType": 1
},
autoReplace: true,
initialPreview: avatarInitialPreview,
initialPreviewAsData: true,
initialPreviewConfig: avatarInitialPreviewConfig,
dropZoneTitle: "请上传艺人头像(1:1比例)",
maxFileCount: 1,
maxFileSize: 5120,
allowedFileExtensions: ['jpg', 'png', 'jpeg'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件'
});
$("#fileinput-avatar").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
$("#avatarUrl").val(fullUrl);
});
// 初始化相册上传
var albumInitialPreview = [];
var albumInitialPreviewConfig = [];
if (albumImagesList.length > 0) {
albumImagesList.forEach(function(img, index) {
albumInitialPreview.push(img);
albumInitialPreviewConfig.push({
caption: "相册图片" + (index + 1),
url: "#",
key: index + 1
});
});
}
$("#fileinput-album").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "artist/album",
"buckType": 1
},
initialPreview: albumInitialPreview,
initialPreviewAsData: true,
initialPreviewConfig: albumInitialPreviewConfig,
dropZoneTitle: "请上传艺人相册图片",
maxFileCount: 20,
maxFileSize: 5120,
allowedFileExtensions: ['jpg', 'png', 'jpeg'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件'
});
$("#fileinput-album").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
albumImagesList.push(fullUrl);
});
$("#fileinput-album").on("fileremoved", function(event, id, index) {
if (index < albumImagesList.length) {
albumImagesList.splice(index, 1);
}
});
});
</script>
</body>
</html>
package com.liquidnet.client.admin.zhengzai.kylin.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.kylin.dao.KylinArtistDao;
import com.liquidnet.service.kylin.dto.param.ArtistParam;
import com.liquidnet.service.kylin.dto.param.ArtistSearchParam;
import com.liquidnet.service.kylin.dto.vo.ArtistVo;
import com.liquidnet.service.kylin.entity.KylinArtist;
import com.liquidnet.service.kylin.entity.KylinArtistAlbum;
import com.liquidnet.service.kylin.mapper.KylinArtistAlbumMapper;
import com.liquidnet.service.kylin.mapper.KylinArtistMapper;
import com.liquidnet.service.kylin.mapper.KylinArtistPerformanceMapper;
import com.liquidnet.service.kylin.service.admin.IKylinArtistService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 艺人管理 服务实现类
* </p>
*
* @author liquidnet
* @since 2026-02-04
*/
@Slf4j
@Service
public class KylinArtistServiceImpl extends ServiceImpl<KylinArtistMapper, KylinArtist> implements IKylinArtistService {
@Autowired
private KylinArtistMapper artistMapper;
@Autowired
private KylinArtistAlbumMapper artistAlbumMapper;
@Autowired
private KylinArtistPerformanceMapper artistPerformanceMapper;
/**
* 创建艺人
*/
@Transactional(rollbackFor = Exception.class)
public Boolean create(ArtistParam param) {
try {
// 校验艺人名称是否已存在
KylinArtist existArtist = artistMapper.selectByArtistName(param.getArtistName());
if (existArtist != null) {
log.warn("艺人名称已存在: {}", param.getArtistName());
return false;
}
String artistId = IDGenerator.nextSnowId();
LocalDateTime createdAt = LocalDateTime.now();
// 保存艺人基本信息
KylinArtist kylinArtist = param.getFields(artistId, createdAt);
artistMapper.insert(kylinArtist);
// 保存相册图片
if (param.getAlbumImages() != null && !param.getAlbumImages().isEmpty()) {
saveAlbumImages(artistId, param.getAlbumImages());
}
return true;
} catch (Exception e) {
log.error("创建艺人失败", e);
throw new RuntimeException("创建艺人失败", e);
}
}
/**
* 修改艺人
*/
@Transactional(rollbackFor = Exception.class)
public Boolean update(ArtistParam param) {
try {
String artistId = param.getArtistId();
// 校验艺人名称是否已被其他艺人使用
KylinArtist existArtist = artistMapper.selectByArtistName(param.getArtistName());
if (existArtist != null && !existArtist.getArtistId().equals(artistId)) {
log.warn("艺人名称已被其他艺人使用: {}", param.getArtistName());
return false;
}
LocalDateTime updatedAt = LocalDateTime.now();
// 更新艺人基本信息
KylinArtist params = param.getFields(null, null);
params.setUpdatedAt(updatedAt);
artistMapper.update(params, new UpdateWrapper<KylinArtist>().eq("artist_id", artistId));
// 删除旧的相册图片(逻辑删除)
artistAlbumMapper.deleteByArtistId(artistId);
// 保存新的相册图片
if (param.getAlbumImages() != null && !param.getAlbumImages().isEmpty()) {
saveAlbumImages(artistId, param.getAlbumImages());
}
return true;
} catch (Exception e) {
log.error("修改艺人失败", e);
throw new RuntimeException("修改艺人失败", e);
}
}
/**
* 艺人详情
*/
public ArtistVo detail(String artistId) {
KylinArtist data = artistMapper.selectOne(
new UpdateWrapper<KylinArtist>().eq("artist_id", artistId).eq("status", 1)
);
ArtistVo artistVo = new ArtistVo();
if (data != null) {
BeanUtils.copyProperties(data, artistVo);
// 设置艺人类型名称
if (data.getArtistType() != null) {
String typeName = "";
switch (data.getArtistType()) {
case 1: typeName = "音乐人"; break;
case 2: typeName = "艺术家"; break;
case 3: typeName = "厂牌"; break;
case 4: typeName = "品牌方"; break;
default: typeName = "未知"; break;
}
artistVo.setArtistTypeName(typeName);
}
// 查询相册图片
List<KylinArtistAlbum> albumList = artistAlbumMapper.selectByArtistId(artistId);
if (albumList != null && !albumList.isEmpty()) {
List<String> imageUrls = albumList.stream()
.map(KylinArtistAlbum::getImageUrl)
.collect(Collectors.toList());
artistVo.setAlbumImages(imageUrls);
}
// 格式化时间显示
if (data.getCreatedAt() != null) {
artistVo.setCreatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getCreatedAt()));
}
if (data.getUpdatedAt() != null) {
artistVo.setUpdatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getUpdatedAt()));
}
// TODO 设置关联演出
artistVo.setPerformanceVoList(Collections.EMPTY_LIST);
} else {
log.error("[detail] query artist is null, artistId: {}", artistId);
return null;
}
return artistVo;
}
/**
* 艺人列表
*/
public PageInfo<KylinArtistDao> artistList(ArtistSearchParam param) {
PageInfo<KylinArtistDao> pageInfoTmp = null;
try {
PageHelper.startPage(param.getPageNum(), param.getPageSize());
Map<String, Object> paramMap = BeanUtil.convertBeanToMap(param);
log.info("艺人列表查询参数: {}", paramMap);
List<KylinArtistDao> list = artistMapper.searchArtistList(paramMap);
pageInfoTmp = new PageInfo<>(list);
} catch (Exception e) {
log.error("获取艺人列表失败", e);
return new PageInfo<>();
}
return pageInfoTmp;
}
/**
* 删除艺人(逻辑删除)
*/
@Transactional(rollbackFor = Exception.class)
public Boolean delete(List<String> artistIds) {
try {
LocalDateTime updatedAt = LocalDateTime.now();
// 删除艺人基本信息
KylinArtist kylinArtist = new KylinArtist();
kylinArtist.setUpdatedAt(updatedAt);
kylinArtist.setStatus(0);
artistMapper.update(
kylinArtist,
new UpdateWrapper<KylinArtist>().in("artist_id", artistIds)
);
// 删除相册图片
for (String artistId : artistIds) {
artistAlbumMapper.deleteByArtistId(artistId);
}
return true;
} catch (Exception e) {
log.error("删除艺人失败", e);
throw new RuntimeException("删除艺人失败", e);
}
}
/**
* 检查艺人名称是否存在
*/
public Boolean checkArtistNameExists(String artistName, String artistId) {
KylinArtist existArtist = artistMapper.selectByArtistName(artistName);
if (existArtist == null) {
return false;
}
// 如果是编辑操作,排除自己
if (artistId != null && existArtist.getArtistId().equals(artistId)) {
return false;
}
return true;
}
/**
* 保存相册图片
*/
private void saveAlbumImages(String artistId, List<String> imageUrls) {
LocalDateTime now = LocalDateTime.now();
int sort = imageUrls.size();
for (String imageUrl : imageUrls) {
KylinArtistAlbum album = new KylinArtistAlbum();
album.setAlbumId(IDGenerator.nextSnowId());
album.setArtistId(artistId);
album.setImageUrl(imageUrl);
album.setSort(sort--);
album.setStatus(1);
album.setCreatedAt(now);
album.setUpdatedAt(now);
artistAlbumMapper.insert(album);
}
}
}
package com.liquidnet.service.kylin.dao;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 艺人管理DAO - 用于列表展示
* </p>
*
* @author liquidnet
* @since 2026-02-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistDao implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 艺人ID
*/
private String artistId;
/**
* 艺人名称
*/
private String artistName;
/**
* 艺人类型 1音乐人 2艺术家 3厂牌 4品牌方
*/
private Integer artistType;
/**
* 艺人类型名称
*/
private String artistTypeName;
/**
* 艺人头像
*/
private String avatarUrl;
/**
* 艺人简介
*/
private String introduction;
/**
* 关联演出数量
*/
private Integer performanceCount;
/**
* 关联商品数量
*/
private Integer productCount;
/**
* 创建时间
*/
private LocalDateTime createdAt;
}
package com.liquidnet.service.kylin.dao;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistPerformanceDao implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 艺人ID
*/
private String artistId;
/**
* 艺人名称
*/
private String artistName;
/**
* 艺人头像
*/
private String artistUrl;
/**
* 演出ID
*/
private String performanceId;
/**
* 艺人在演出排序 越大越靠前
*/
private Integer sort;
/**
* 演出标题
*/
private String title;
/**
* 演出开始时间
*/
private String timeStart;
}
package com.liquidnet.service.kylin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
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-02-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtist implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO)
private Integer mid;
/**
* 艺人ID
*/
private String artistId;
/**
* 艺人名称
*/
private String artistName;
/**
* 艺人类型 1音乐人 2艺术家 3厂牌 4品牌方
*/
private Integer artistType;
/**
* 艺人头像
*/
private String avatarUrl;
/**
* 艺人简介
*/
private String introduction;
/**
* 状态 1启用 0禁用
*/
private Integer status;
/**
* 排序权重
*/
private Integer sort;
/**
* 创建时间
*/
private LocalDateTime createdAt;
/**
* 修改时间
*/
private LocalDateTime updatedAt;
private static final KylinArtist obj = new KylinArtist();
public static KylinArtist getNew() {
try {
return (KylinArtist) obj.clone();
} catch (CloneNotSupportedException e) {
return new KylinArtist();
}
}
}
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-02-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistAlbum implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO)
private Integer mid;
/**
* 相册ID
*/
private String albumId;
/**
* 艺人ID
*/
private String artistId;
/**
* 图片地址
*/
private String imageUrl;
/**
* 排序权重
*/
private Integer sort;
/**
* 状态 1启用 0禁用
*/
private Integer status;
/**
* 创建时间
*/
private LocalDateTime createdAt;
/**
* 修改时间
*/
private LocalDateTime updatedAt;
private static final KylinArtistAlbum obj = new KylinArtistAlbum();
public static KylinArtistAlbum getNew() {
try {
return (KylinArtistAlbum) obj.clone();
} catch (CloneNotSupportedException e) {
return new KylinArtistAlbum();
}
}
}
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;
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinArtistPerformance implements Serializable{
private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO)
private Long mid;
/**
* 关联 kylin_artist.artist_id
*/
private String artistId;
/**
* 关联 kylin_performances.performances_id
*/
private String performancesId;
/**
* 该艺人在本演出中的排序权重,越大越靠前
*/
private Integer sort;
/**
*创建时间
*/
private LocalDateTime createdAt;
/**
*更新时间
*/
private LocalDateTime updatedAt;
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinArtistAlbum;
import java.util.List;
public interface KylinArtistAlbumMapper extends BaseMapper<KylinArtistAlbum> {
/**
* 根据艺人ID查询相册列表
*/
List<KylinArtistAlbum> selectByArtistId(String artistId);
/**
* 根据艺人ID删除相册(逻辑删除)
*/
int deleteByArtistId(String artistId);
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.dao.KylinArtistDao;
import com.liquidnet.service.kylin.entity.KylinArtist;
import java.util.List;
import java.util.Map;
public interface KylinArtistMapper extends BaseMapper<KylinArtist> {
/**
* 搜索艺人列表
*/
List<KylinArtistDao> searchArtistList(Map<String, Object> paramMap);
/**
* 根据艺人名称查询是否存在
*/
KylinArtist selectByArtistName(String artistName);
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.dao.KylinArtistPerformanceDao;
import com.liquidnet.service.kylin.entity.KylinArtistPerformance;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface KylinArtistPerformanceMapper extends BaseMapper<KylinArtistPerformance> {
/**
* 根据艺人ID查询关联的演出信息
*
* @param artistId 艺人ID
* @return 演出信息列表
*/
List<KylinArtistPerformanceDao> selectPerformancesByArtistId(@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.KylinArtistAlbumMapper">
<!-- 根据艺人ID查询相册列表 -->
<select id="selectByArtistId" parameterType="java.lang.String" resultType="com.liquidnet.service.kylin.entity.KylinArtistAlbum">
SELECT
mid,
album_id,
artist_id,
image_url,
sort,
status,
created_at,
updated_at
FROM kylin_artist_album
WHERE artist_id = #{artistId} AND status = 1
ORDER BY sort DESC, mid DESC
</select>
<!-- 根据艺人ID删除相册(逻辑删除) -->
<update id="deleteByArtistId" parameterType="java.lang.String">
UPDATE kylin_artist_album
SET status = 0, updated_at = NOW()
WHERE artist_id = #{artistId}
</update>
</mapper>
<?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.KylinArtistMapper">
<!-- 搜索艺人列表 -->
<select id="searchArtistList" parameterType="java.util.Map" resultType="com.liquidnet.service.kylin.dao.KylinArtistDao">
SELECT
a.artist_id,
a.artist_name,
a.artist_type,
CASE a.artist_type
WHEN 1 THEN '音乐人'
WHEN 2 THEN '艺术家'
WHEN 3 THEN '厂牌'
WHEN 4 THEN '品牌方'
ELSE '未知'
END as artist_type_name,
a.avatar_url,
a.introduction,
a.created_at
FROM kylin_artist a
<where>
a.status = 1
<if test="artistName != null and artistName != ''">
AND a.artist_name LIKE CONCAT('%', #{artistName}, '%')
</if>
<if test="artistType != null and artistType != ''">
AND a.artist_type = #{artistType}
</if>
</where>
ORDER BY a.sort DESC, a.mid DESC
</select>
<!-- 根据艺人名称查询是否存在 -->
<select id="selectByArtistName" parameterType="java.lang.String" resultType="com.liquidnet.service.kylin.entity.KylinArtist">
SELECT * FROM kylin_artist
WHERE artist_name = #{artistName} AND status = 1
LIMIT 1
</select>
</mapper>
<?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.KylinArtistPerformanceMapper">
<select id="selectPerformancesByArtistId" parameterType="java.lang.String" resultType="com.liquidnet.service.kylin.dao.KylinArtistPerformanceDao">
</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