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

Commit 11caf63e authored by 姜秀龙's avatar 姜秀龙

admin-购票、观演须知管理

parent cbfb255b
-- 给 kylin_buy_notice 表增加 notice_type 字段
ALTER TABLE `kylin_buy_notice`
ADD COLUMN `notice_type` tinyint(2) NOT NULL DEFAULT '1' COMMENT '须知类型 1购票须知 2观演须知' AFTER `sort`;
-- 给现有数据设置默认类型为购票须知
UPDATE `kylin_buy_notice` SET `notice_type` = 1 WHERE `notice_type` IS NULL OR `notice_type` = 0;
-- 添加索引
ALTER TABLE `kylin_buy_notice` ADD INDEX `idx_notice_type` (`notice_type`);
\ No newline at end of file
package com.liquidnet.service.kylin.dto.param;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
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-01-19
*/
@Data
@ApiModel("购票须知参数")
public class BuyNoticeParam {
@ApiModelProperty(value = "须知ID")
private String buyNoticeId;
@ApiModelProperty(value = "须知图片")
private String imgUrl;
@ApiModelProperty(value = "须知标题")
private String title;
@ApiModelProperty(value = "须知内容")
private String message;
@ApiModelProperty(value = "排序权重")
private Integer sort;
@ApiModelProperty(value = "须知类型 1购票须知 2观演须知")
private Integer noticeType;
@ApiModelProperty(value = "状态 0禁用 1启用")
private Integer status;
@ApiModelProperty(value = "批量操作的ID列表")
private List<String> ids;
public KylinBuyNotice getFields(String buyNoticeId, LocalDateTime createdAt) {
KylinBuyNotice kylinBuyNotice = new KylinBuyNotice();
BeanUtils.copyProperties(this, kylinBuyNotice);
if (buyNoticeId != null) {
kylinBuyNotice.setBuyNoticeId(buyNoticeId);
}
if (createdAt != null) {
kylinBuyNotice.setCreatedAt(createdAt);
}
kylinBuyNotice.setUpdatedAt(LocalDateTime.now());
return kylinBuyNotice;
}
}
\ No newline at end of file
package com.liquidnet.service.kylin.dto.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 购票须知搜索参数
*
* @author system
* @since 2026-01-19
*/
@Data
@ApiModel("购票须知搜索参数")
public class BuyNoticeSearchParam {
@ApiModelProperty(value = "须知标题")
private String title;
@ApiModelProperty(value = "须知类型 1购票须知 2观演须知")
private Integer noticeType;
@ApiModelProperty(value = "状态 0禁用 1启用")
private Integer status;
@ApiModelProperty(value = "页码")
private Integer pageNum = 1;
@ApiModelProperty(value = "每页数量")
private Integer pageSize = 10;
}
\ No newline at end of file
package com.liquidnet.service.kylin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 购票须知VO
*
* @author system
* @since 2026-01-19
*/
@Data
@ApiModel("购票须知VO")
public class BuyNoticeVo implements Serializable {
@ApiModelProperty(value = "须知ID")
private String buyNoticeId;
@ApiModelProperty(value = "须知图片")
private String imgUrl;
@ApiModelProperty(value = "须知标题")
private String title;
@ApiModelProperty(value = "须知内容")
private String message;
@ApiModelProperty(value = "排序权重")
private Integer sort;
@ApiModelProperty(value = "须知类型 1购票须知 2观演须知")
private Integer noticeType;
@ApiModelProperty(value = "须知类型名称")
private String noticeTypeName;
@ApiModelProperty(value = "状态 0禁用 1启用")
private Integer status;
@ApiModelProperty(value = "状态名称")
private String statusName;
@ApiModelProperty(value = "创建时间")
private String createdAt;
@ApiModelProperty(value = "修改时间")
private String updatedAt;
}
\ No newline at end of file
package com.liquidnet.service.kylin.service.admin;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.kylin.dto.param.BuyNoticeParam;
import com.liquidnet.service.kylin.dto.param.BuyNoticeSearchParam;
import com.liquidnet.service.kylin.dto.vo.BuyNoticeVo;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
import java.util.List;
/**
* 购票须知服务接口
*
* @author system
* @since 2026-01-19
*/
public interface IBuyNoticeService {
/**
* 创建购票须知
*/
Boolean create(BuyNoticeParam param);
/**
* 更新购票须知
*/
Boolean update(BuyNoticeParam param);
/**
* 获取购票须知详情
*/
BuyNoticeVo detail(String buyNoticeId);
/**
* 删除购票须知
*/
Boolean delete(List<String> buyNoticeIds);
/**
* 购票须知列表
*/
PageInfo<KylinBuyNotice> noticeList(BuyNoticeSearchParam param);
}
\ No newline at end of file
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.KylinBuyNoticeServiceImpl;
import com.liquidnet.service.kylin.dto.param.BuyNoticeParam;
import com.liquidnet.service.kylin.dto.param.BuyNoticeSearchParam;
import com.liquidnet.service.kylin.dto.vo.BuyNoticeVo;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
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 jiangxiulong
* @since 2026-01-16
*/
@Controller
@RequestMapping("/kylin/notices")
public class KylinNoticesAdminController extends BaseController {
private String prefix = "zhengzai/kylin/notices";
@Value("${liquidnet.client.admin.platformUrl}")
private String platformUrl;
@Autowired
private KylinBuyNoticeServiceImpl kylinNoticesServiceImpl;
@GetMapping("/create")
public String create(ModelMap mmap) {
mmap.put("platformUrl", platformUrl);
return prefix + "/create";
}
@Log(title = "创建须知", businessType = BusinessType.INSERT)
@RequiresPermissions("kylin:notices:create")
@PostMapping("create")
@ResponseBody
public AjaxResult createSave(BuyNoticeParam param) {
Boolean res = kylinNoticesServiceImpl.create(param);
if (res) {
return success();
} else {
return error("添加须知失败");
}
}
@GetMapping("/update/{buyNoticeId}")
public String update(@PathVariable("buyNoticeId") String buyNoticeId, ModelMap mmap) {
BuyNoticeVo result = kylinNoticesServiceImpl.detail(buyNoticeId);
mmap.put("BuyNoticeVo", result);
mmap.put("platformUrl", platformUrl);
return prefix + "/update";
}
@Log(title = "修改须知", businessType = BusinessType.UPDATE)
@RequiresPermissions("kylin:notices:update")
@PostMapping("update")
@ResponseBody
public AjaxResult updateSave(BuyNoticeParam param) {
Boolean res = kylinNoticesServiceImpl.update(param);
if (res) {
return success();
} else {
return error("修改须知失败");
}
}
@RequiresPermissions("kylin:notices:detail")
@GetMapping("/detail/{buyNoticeId}")
public String detail(@PathVariable("buyNoticeId") String buyNoticeId, ModelMap mmap) {
BuyNoticeVo result = kylinNoticesServiceImpl.detail(buyNoticeId);
mmap.put("BuyNoticeVo", result);
return prefix + "/detail";
}
@RequiresPermissions("kylin:notices:list")
@GetMapping()
public String notices() {
return prefix + "/notices";
}
// @Log(title = "须知列表", businessType = BusinessType.LIST)
@RequiresPermissions("kylin:notices:list")
@PostMapping("list")
@ResponseBody
public TableDataInfo noticeList(BuyNoticeSearchParam param) {
PageInfo<KylinBuyNotice> result = kylinNoticesServiceImpl.noticeList(param);
return getDataTable(result.getList());
}
@Log(title = "删除须知", businessType = BusinessType.DELETE)
@RequiresPermissions("kylin:notices:delete")
@PostMapping("delete")
@ResponseBody
public AjaxResult delete(BuyNoticeParam param) {
List<String> buyNoticeIds = param.getIds();
Boolean result = kylinNoticesServiceImpl.delete(buyNoticeIds);
if (result) {
return success("删除成功");
} else {
return error("删除失败");
}
}
}
<!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-notice-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="title" id="title"
maxlength="50" placeholder="最多输入50个字" required>
<span class="help-block m-b-none text-muted">
<span id="titleCount">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">
<div class="radio check-box">
<label>
<input type="radio" value="1" name="noticeType" checked=""> 购票须知
</label>
</div>
<div class="radio check-box">
<label>
<input type="radio" value="2" name="noticeType"> 观演须知
</label>
</div>
</div>
</div>
<!--<div class="form-group">
<label class="col-sm-2 control-label">排序(越大越靠前):</label>
<div class="col-sm-10">
<input class="form-control" type="number" name="sort" id="sort" value="0">
</div>
</div>-->
<div class="form-group">
<label class="col-sm-2 control-label is-required">内容:</label>
<div class="col-sm-10">
<textarea id="message" name="message" class="form-control"
rows="8" maxlength="300" placeholder="最多输入300个字" required></textarea>
<span class="help-block m-b-none text-muted">
<span id="contentCount">0</span>/300 字
</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-notice-image" 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> 支持上传png格式文件,最大支持上传5M;如不上传,前端展示默认"!"图标</span>
</div>
</div>
<input hidden id="imgUrl" name="imgUrl">
</form>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: bootstrap-fileinput-js"/>
<script type="text/javascript">
var prefix = ctx + "kylin/notices";
var platformUrl = "[[${platformUrl}]]";
function submitHandler() {
var title = $('#title').val().trim();
if (!title) {
$.modal.alertWarning("请填写须知标题");
$('#title').focus();
return false;
}
if (title.length > 50) {
$.modal.alertWarning("须知标题最多输入50个字");
$('#title').focus();
return false;
}
var message = $('#message').val().trim();
if (!message) {
$.modal.alertWarning("请填写须知内容");
$('#message').focus();
return false;
}
if (message.length > 300) {
$.modal.alertWarning("须知内容最多输入300个字");
$('#message').focus();
return false;
}
if ($.validate.form()) {
var data = $('#form-notice-add').serializeArray();
$.operate.save(prefix + "/create", data);
}
}
$(function () {
// 标题字数统计和实时校验
$('#title').on('input', function() {
var length = $(this).val().length;
$('#titleCount').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();
}
});
// 标题失去焦点校验
$('#title').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');
}
});
// 内容字数统计和实时校验
$('#message').on('input', function() {
var length = $(this).val().length;
$('#contentCount').text(length);
if (length > 300) {
$(this).addClass('is-invalid');
$(this).parent().find('.error-msg').remove();
$(this).parent().append('<span class="error-msg text-danger">内容不能超过300个字</span>');
} else {
$(this).removeClass('is-invalid');
$(this).parent().find('.error-msg').remove();
}
});
// 内容失去焦点校验
$('#message').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 > 300) {
$(this).addClass('is-invalid');
$(this).parent().append('<span class="error-msg text-danger">内容不能超过300个字</span>');
} else {
$(this).removeClass('is-invalid');
}
});
// 初始化文件上传
$("#fileinput-notice-image").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "notice",
"buckType": 1
},
autoReplace: true,
dropZoneTitle: "请上传图标",
maxFileCount: 1,
maxFileSize: 5120, // 5MB = 5120KB
allowedFileExtensions: ['png'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件'
});
$("#fileinput-notice-image").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
// 保存完整的URL地址
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
$("#imgUrl").val(fullUrl);
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('须知详情')"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m">
<div class="form-group">
<label class="col-sm-2 control-label">ID:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.buyNoticeId}"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">标题:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.title}"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">类型:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.noticeTypeName}"></p>
</div>
</div>
<!--<div class="form-group">
<label class="col-sm-2 control-label">排序:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.sort}"></p>
</div>
</div>-->
<div class="form-group">
<label class="col-sm-2 control-label">内容:</label>
<div class="col-sm-10">
<div class="form-control-static" th:utext="${BuyNoticeVo.message}"
style="border: 1px solid #e5e6e7; padding: 15px; min-height: 100px; background-color: #fff;"></div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">图标:</label>
<div class="col-sm-10">
<img th:if="${BuyNoticeVo.imgUrl != null and BuyNoticeVo.imgUrl != ''}"
th:src="${BuyNoticeVo.imgUrl}"
style="max-width: 500px; max-height: 400px;" />
<p th:if="${BuyNoticeVo.imgUrl == null or BuyNoticeVo.imgUrl == ''}"
class="form-control-static">暂无图标</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">创建时间:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.createdAt}"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">修改时间:</label>
<div class="col-sm-10">
<p class="form-control-static" th:text="${BuyNoticeVo.updatedAt}"></p>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer"/>
</body>
</html>
<!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="title"/>
</li>
<li>
<label>须知类型:</label>
<select name="noticeType">
<option value="">全部</option>
<option value="1">购票须知</option>
<option value="2">观演须知</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:notices:create">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger multiple disabled" onclick="removeAllNotices()" shiro:hasPermission="kylin:notices:delete">
删除
</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:notices:update')}]];
var removeFlag = [[${@permission.hasPermi('kylin:notices:delete')}]];
var detailFlag = [[${@permission.hasPermi('kylin:notices:detail')}]];
var prefix = ctx + "kylin/notices";
$(function () {
var options = {
url: prefix + "/list",
updateUrl: prefix + "/update/{id}",
createUrl: prefix + "/create",
removeUrl: prefix + "/delete",
detailUrl: prefix + "/detail/{id}",
modalName: "须知",
columns: [{
checkbox: true
},
{
field: 'buyNoticeId',
title: 'ID'
},
{
field: 'imgUrl',
title: '图标',
formatter: function(value, row, index) {
return $.table.imageView(value, "300", "600");
}
},
{
field: 'title',
title: '标题'
},
{
field: 'noticeTypeName',
title: '须知类型'
},
{
field: 'message',
title: '须知内容'
},
{
field: 'createdAt',
title: '创建时间'
},
{
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.buyNoticeId + '\')"><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.buyNoticeId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="removeNotice(\'' + row.buyNoticeId + '\')"><i class="fa fa-remove"></i>删除</a> ');
return actions.join('');
}
}]
};
$.table.init(options);
});
// 单条删除
function removeNotice(id) {
$.operate.remove(id, "删除后该信息将无法被引用,也无法找回,确认要将该条须知内容删除吗?");
}
// 批量删除
function removeAllNotices() {
$.operate.removeAll("删除后该信息将无法被引用,也无法找回,确认要将选中的须知内容删除吗?");
}
</script>
</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"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-notice-edit">
<input type="hidden" name="buyNoticeId" th:value="${BuyNoticeVo.buyNoticeId}">
<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="title" id="title"
maxlength="50" placeholder="最多输入50个字"
th:value="${BuyNoticeVo.title}" required>
<span class="help-block m-b-none text-muted">
<span id="titleCount">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">
<div class="radio check-box">
<label>
<input type="radio" value="1" name="noticeType"
th:checked="${BuyNoticeVo.noticeType == 1}"> 购票须知
</label>
</div>
<div class="radio check-box">
<label>
<input type="radio" value="2" name="noticeType"
th:checked="${BuyNoticeVo.noticeType == 2}"> 观演须知
</label>
</div>
</div>
</div>
<!--<div class="form-group">
<label class="col-sm-2 control-label">排序(越大越靠前):</label>
<div class="col-sm-10">
<input class="form-control" type="number" name="sort" id="sort"
th:value="${BuyNoticeVo.sort}">
</div>
</div>-->
<div class="form-group">
<label class="col-sm-2 control-label is-required">内容:</label>
<div class="col-sm-10">
<textarea id="message" name="message" class="form-control"
rows="8" maxlength="300" placeholder="最多输入300个字"
required th:text="${BuyNoticeVo.message}"></textarea>
<span class="help-block m-b-none text-muted">
<span id="contentCount">0</span>/300 字
</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-notice-image" 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> 支持上传png格式文件,最大支持上传5M;如不上传,前端展示默认"!"图标</span>
</div>
</div>
<input hidden id="imgUrl" name="imgUrl" th:value="${BuyNoticeVo.imgUrl}">
</form>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: bootstrap-fileinput-js"/>
<script type="text/javascript">
var prefix = ctx + "kylin/notices";
var platformUrl = "[[${platformUrl}]]";
var currentImage = "[[${BuyNoticeVo.imgUrl}]]";
function submitHandler() {
var title = $('#title').val().trim();
if (!title) {
$.modal.alertWarning("请填写须知标题");
$('#title').focus();
return false;
}
if (title.length > 50) {
$.modal.alertWarning("须知标题最多输入50个字");
$('#title').focus();
return false;
}
var message = $('#message').val().trim();
if (!message) {
$.modal.alertWarning("请填写须知内容");
$('#message').focus();
return false;
}
if (message.length > 300) {
$.modal.alertWarning("须知内容最多输入300个字");
$('#message').focus();
return false;
}
if ($.validate.form()) {
var data = $('#form-notice-edit').serializeArray();
$.operate.save(prefix + "/update", data);
}
}
$(function () {
// 初始化字数统计
$('#titleCount').text($('#title').val().length);
$('#contentCount').text($('#message').val().length);
// 标题字数统计和实时校验
$('#title').on('input', function() {
var length = $(this).val().length;
$('#titleCount').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();
}
});
// 标题失去焦点校验
$('#title').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');
}
});
// 内容字数统计和实时校验
$('#message').on('input', function() {
var length = $(this).val().length;
$('#contentCount').text(length);
if (length > 300) {
$(this).addClass('is-invalid');
$(this).parent().find('.error-msg').remove();
$(this).parent().append('<span class="error-msg text-danger">内容不能超过300个字</span>');
} else {
$(this).removeClass('is-invalid');
$(this).parent().find('.error-msg').remove();
}
});
// 内容失去焦点校验
$('#message').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 > 300) {
$(this).addClass('is-invalid');
$(this).parent().append('<span class="error-msg text-danger">内容不能超过300个字</span>');
} else {
$(this).removeClass('is-invalid');
}
});
// 初始化文件上传
$("#fileinput-notice-image").fileinput({
'theme': 'explorer-fas',
'uploadUrl': platformUrl + "/platform/basicServices/alOss/upload/unsm",
"uploadExtraData": {
"pathName": "notice",
"buckType": 1
},
autoReplace: true,
dropZoneTitle: "请上传图标",
maxFileCount: 1,
maxFileSize: 5120,
allowedFileExtensions: ['png'],
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB,最大支持上传5M文件',
overwriteInitial: false,
initialPreviewAsData: true,
initialPreview: currentImage ? [currentImage] : []
});
$("#fileinput-notice-image").on("fileuploaded", function (event, data, previewId, index) {
var imgPath = data.response.data.ossPath;
// 保存完整的URL地址
var fullUrl = "https://img.zhengzai.tv/" + imgPath;
$("#imgUrl").val(fullUrl);
});
});
</script>
</body>
</html>
\ No newline at end of file
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.dto.param.BuyNoticeParam;
import com.liquidnet.service.kylin.dto.param.BuyNoticeSearchParam;
import com.liquidnet.service.kylin.dto.vo.BuyNoticeVo;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
import com.liquidnet.service.kylin.mapper.KylinBuyNoticeMapper;
import com.liquidnet.service.kylin.service.admin.IBuyNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 须知管理 服务实现类
* </p>
*
* @author jiangxiulong
* @since 2026-01-16
*/
@Slf4j
@Service
public class KylinBuyNoticeServiceImpl extends ServiceImpl<KylinBuyNoticeMapper, KylinBuyNotice> implements IBuyNoticeService {
@Autowired
private KylinBuyNoticeMapper noticesMapper;
/**
* 创建须知
*/
public Boolean create(BuyNoticeParam param) {
try {
String buyNoticeId = IDGenerator.nextSnowId();
LocalDateTime createdAt = LocalDateTime.now();
KylinBuyNotice kylinBuyNotice = param.getFields(buyNoticeId, createdAt);
noticesMapper.insert(kylinBuyNotice);
return true;
} catch (Exception e) {
log.error("创建须知失败", e);
return false;
}
}
/**
* 修改须知
*/
public Boolean update(BuyNoticeParam param) {
try {
String buyNoticeId = param.getBuyNoticeId();
LocalDateTime updatedAt = LocalDateTime.now();
KylinBuyNotice params = param.getFields(null, null);
params.setUpdatedAt(updatedAt);
noticesMapper.update(params, new UpdateWrapper<KylinBuyNotice>().eq("buy_notice_id", buyNoticeId));
return true;
} catch (Exception e) {
log.error("修改须知失败", e);
return false;
}
}
/**
* 须知详情
*/
public BuyNoticeVo detail(String buyNoticeId) {
KylinBuyNotice data = noticesMapper.selectOne(
new UpdateWrapper<KylinBuyNotice>().eq("buy_notice_id", buyNoticeId).eq("status", 1)
);
BuyNoticeVo BuyNoticeVo = new BuyNoticeVo();
if (data != null) {
BeanUtils.copyProperties(data, BuyNoticeVo);
// 设置须知类型名称
if (data.getNoticeType() != null) {
BuyNoticeVo.setNoticeTypeName(data.getNoticeType() == 1 ? "购票须知" : "观演须知");
}
// 格式化时间显示
if (data.getCreatedAt() != null) {
BuyNoticeVo.setCreatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getCreatedAt()));
}
if (data.getUpdatedAt() != null) {
BuyNoticeVo.setUpdatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getUpdatedAt()));
}
} else {
return null;
}
return BuyNoticeVo;
}
/**
* 须知列表
*/
public PageInfo<KylinBuyNotice> noticeList(BuyNoticeSearchParam param) {
PageInfo<KylinBuyNotice> pageInfoTmp = null;
try {
PageHelper.startPage(param.getPageNum(), param.getPageSize());
Map<String, Object> paramMap = BeanUtil.convertBeanToMap(param);
log.info("原始参数对象: title={}, noticeType={}, status={}", param.getTitle(), param.getNoticeType(), param.getStatus());
log.info("转换后的Map参数: {}", paramMap);
List<KylinBuyNotice> list = noticesMapper.searchNoticesList(paramMap);
// 设置须知类型名称
if (list != null) {
for (KylinBuyNotice item : list) {
if (item.getNoticeType() != null) {
item.setNoticeTypeName(item.getNoticeType() == 1 ? "购票须知" : "观演须知");
}
}
}
pageInfoTmp = new PageInfo<>(list);
} catch (Exception e) {
log.error("获取须知列表失败", e);
return new PageInfo<>();
}
return pageInfoTmp;
}
/**
* 删除须知(逻辑删除)
*/
public Boolean delete(List<String> buyNoticeIds) {
try {
LocalDateTime updatedAt = LocalDateTime.now();
KylinBuyNotice KylinBuyNotice = new KylinBuyNotice();
KylinBuyNotice.setUpdatedAt(updatedAt);
KylinBuyNotice.setStatus(0);
noticesMapper.update(
KylinBuyNotice,
new UpdateWrapper<KylinBuyNotice>().in("buy_notice_id", buyNoticeIds)
);
return true;
} catch (Exception e) {
log.error("删除须知失败", e);
return false;
}
}
}
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 java.time.LocalDateTime;
import java.io.Serializable;
......@@ -54,6 +55,17 @@ public class KylinBuyNotice implements Serializable ,Cloneable {
*/
private Integer sort;
/**
* 须知类型 1购票须知 2观演须知
*/
private Integer noticeType;
/**
* 须知类型名称(非数据库字段)
*/
@TableField(exist = false)
private String noticeTypeName;
/**
* 创建时间
*/
......
......@@ -3,6 +3,9 @@ package com.liquidnet.service.kylin.mapper;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
import java.util.Map;
/**
* <p>
* 购票须知表 Mapper 接口
......@@ -13,4 +16,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface KylinBuyNoticeMapper extends BaseMapper<KylinBuyNotice> {
/**
* 搜索须知列表
*/
List<KylinBuyNotice> searchNoticesList(Map<String, Object> params);
}
......@@ -2,4 +2,30 @@
<!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.KylinBuyNoticeMapper">
</mapper>
<!-- 搜索须知列表 -->
<select id="searchNoticesList" parameterType="java.util.Map" resultType="com.liquidnet.service.kylin.entity.KylinBuyNotice">
SELECT
mid,
buy_notice_id,
title,
img_url,
message,
status,
sort,
notice_type,
created_at,
updated_at
FROM kylin_buy_notice
<where>
status = 1
<if test="title != null and title != ''">
AND title LIKE CONCAT('%', #{title}, '%')
</if>
<if test="noticeType != null and noticeType != ''">
AND notice_type = #{noticeType}
</if>
</where>
ORDER BY sort DESC, mid DESC
</select>
</mapper>
\ No newline at end of file
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