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

Commit f6f4f83e authored by 姜秀龙's avatar 姜秀龙

Merge remote-tracking branch 'refs/remotes/origin/master' into jxl_20240313_prod

# Conflicts:
#	liquidnet-bus-support/liquidnet-support-eureka/src/main/resources/application-dev.yml
parents 7ac5b220 46a09ccb
-- 给 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`);
alter table kylin_buy_notice
modify message varchar(500) default '' not null comment '内容';
......@@ -4,6 +4,7 @@ public class KylinRedisConst {
public static final String FIELDS = "kylin:fields:id";
public static final String PERFORMANCES = "kylin:performances:id:";
public static final String PERFORMANCES_INVOICE_REMINDER = "kylin:performances:invoice_reminder:id:";
public static final String PERFORMANCES_NOTICE_REMIND_STATUS = "kylin:performances:noticeRemindStatus:id:";
public static final String PERFORMANCES_TRUE_NAME = "kylin:performances_true_name:id:";
public static final String PERFORMANCES_LIST_CITY = "kylin:performances:city:";
public static final String PERFORMANCES_LIST_SYSTEM_RECOMMEND = "kylin:performances:systemRecommend";
......
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
......@@ -124,6 +124,7 @@ public class PerformancePartnerVo implements Serializable, Cloneable {
@ApiModelProperty(value = "是否保存", example = "")
private Integer isCreateSave;
public Integer getIdCount() {
return idCount==null?limitCount:idCount;
}
......
......@@ -89,4 +89,5 @@ public class PerformanceStep1Param implements Serializable {
@ApiModelProperty(value = "", example = "")
@JsonIgnore
private String createdAt;
}
......@@ -50,6 +50,10 @@ public class PerformanceStep2Param implements Serializable,Cloneable {
@ApiModelProperty(value = "场次数据",hidden = true)
private List<TicketTimesTicketCreatePartnerVo> ticketTimes;
@ApiModelProperty(value = "须知提醒 0:不提醒 1:提醒")
@NotNull(message = "须知提醒不能为空")
private Integer noticeRemindStatus;
private static final PerformanceStep2Param obj = new PerformanceStep2Param();
public static PerformanceStep2Param getNew() {
try {
......
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.dto.vo.middle;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import lombok.Data;
@Data
......@@ -16,6 +15,8 @@ public class KylinBuyNoticeVo implements Cloneable {
private Integer sort;
private Integer noticeType;
private static final KylinBuyNoticeVo obj = new KylinBuyNoticeVo();
public static KylinBuyNoticeVo getNew() {
try {
......
......@@ -3,6 +3,7 @@ package com.liquidnet.service.kylin.dto.vo.mongo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.kylin.dto.param.PerformancePartnerVo;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundage;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.entity.KylinFields;
......@@ -21,7 +22,7 @@ import java.util.List;
@ApiModel
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class KylinPerformanceVo implements Serializable, Cloneable {
public class KylinPerformanceVo implements Serializable, Cloneable {
private Integer mid;
@ApiModelProperty(value = "主键")
......@@ -146,6 +147,15 @@ public class KylinPerformanceVo implements Serializable, Cloneable {
@ApiModelProperty(value = "开票提醒 0为不提醒", example = "0")
private Integer isInvoiceReminder;
@ApiModelProperty(value = "场地地址")
private String fieldAddress;
@ApiModelProperty(value = "须知提醒 0:不提醒 1:提醒")
private Integer noticeRemindStatus;
@ApiModelProperty(value = "阶梯退票规则")
private List<OrderRefundPoundage> refundPoundages;
public Integer getIdCount() {
return idCount == null ? limitCount : idCount;
}
......
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.service.kylin.service.partner;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
import java.util.List;
......@@ -24,7 +21,7 @@ public interface IKylinBuyNoticePartnerService {
*
* @return 分页 mysql 数据
*/
PageInfo<KylinBuyNoticeVo> getBuyNotice();
List<KylinBuyNoticeVo> getBuyNotice();
ResponseDto<List<KylinExpressModuleVo>> getExpressList();
......
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;如不上传,前端展示默认<img class="img-circle img-xs" data-height="300" data-width="600" data-target="self" src="https://img.zhengzai.tv/notice/2026/01/26/43f5c64be2ba433d9e00aa62d40b8a60.png">图标</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: '创建时间',
formatter: function(value, row, index) {
if (value) {
// 将LocalDateTime格式转换为可读的日期格式
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 '';
}
},
{
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;如不上传,前端展示默认<img class="img-circle img-xs" data-height="300" data-width="600" data-target="self" src="https://img.zhengzai.tv/notice/2026/01/26/43f5c64be2ba433d9e00aa62d40b8a60.png">图标</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
......@@ -28,7 +28,7 @@
<input name="roadShowId" th:value="*{roadShowId}" type="hidden">
<div class="remote_wrapper" style="position: relative;">
<input name="ids" type="hidden">
<input type="text" id="remoteSearch">
<input type="text" id="remoteSearch" style="width: 100%">
</div>
</div>
</div>
......
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.ArrayList;
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;
@Value("${liquidnet.aliyun.oss.imgUrl}")
private String imgUrl;
/**
* 创建须知
*/
public Boolean create(BuyNoticeParam param) {
try {
String buyNoticeId = IDGenerator.nextSnowId();
LocalDateTime createdAt = LocalDateTime.now();
KylinBuyNotice kylinBuyNotice = param.getFields(buyNoticeId, createdAt);
if (kylinBuyNotice.getImgUrl().isEmpty()) {
kylinBuyNotice.setImgUrl(imgUrl + "notice/2026/01/26/43f5c64be2ba433d9e00aa62d40b8a60.png");
}
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);
if (params.getImgUrl().isEmpty()) {
params.setImgUrl(imgUrl + "notice/2026/01/26/43f5c64be2ba433d9e00aa62d40b8a60.png");
}
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
......@@ -72,6 +72,10 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService {
for (int i = initCount; i >= finalCount; i--) {
String orderId = orderIds.get(i);
GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
if (orderVo == null) {
log.info("[orderList] goblin order is null, orderId: {}", orderId);
continue;
}
GoblinAppOrderListVo vo = GoblinAppOrderListVo.getNew();
BeanUtils.copyProperties(orderVo, vo);
vo.setRestTime(getRestTime(orderVo));
......
......@@ -66,8 +66,15 @@ public class GoblinJobServiceImpl {
}
//排序
nftDetailsList = nftDetailsList.stream().sorted(Comparator.comparing(GoblinMixDetailsVo::getTimeStart)).collect(Collectors.toList());
skuDetailsList = skuDetailsList.stream().sorted(Comparator.comparing(GoblinMixDetailsVo::getTimeStart)).collect(Collectors.toList());
nftDetailsList = nftDetailsList.stream().filter(vo -> {
String ts = vo.getTimeStart();
return ts != null && !ts.trim().isEmpty();
}).sorted(Comparator.comparing(GoblinMixDetailsVo::getTimeStart)).collect(Collectors.toList());
skuDetailsList = skuDetailsList.stream().filter(vo -> {
String ts = vo.getTimeStart();
return ts != null && !ts.trim().isEmpty();
}).sorted(Comparator.comparing(GoblinMixDetailsVo::getTimeStart)).collect(Collectors.toList());
LocalDateTime nt = LocalDateTime.now();
//筛选 活动中 和 活动中且售罄的
......
......@@ -49,6 +49,12 @@
<artifactId>liquidnet-service-goblin-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-service-slime-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
......
......@@ -15,6 +15,7 @@ import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.param.KylinCandyItemParam;
import com.liquidnet.service.kylin.dto.param.KylinPerformanceSubscribeParam;
import com.liquidnet.service.kylin.dto.vo.KylinPerformanceSubscribeUpushVo;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundage;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinCandyVo;
......@@ -315,6 +316,10 @@ public class KylinPerformancesServiceImpl implements IKylinPerformancesService {
performancesInfo.setIsVip(dataUtils.isMemberByUser(uid));
}
performancesInfo.setIsInvoiceReminder(dataUtils.getPerformanceInvoiceReminder(performancesId));
performancesInfo.setFieldAddress(dataUtils.getFieldAddressByFieldId(performancesInfo.getFieldId()));
performancesInfo.setNoticeRemindStatus(dataUtils.getPerformanceNoticeRemindStatus(performancesId));
List<OrderRefundPoundage> result = dataUtils.getRefundPoundage(1, performancesId);
performancesInfo.setRefundPoundages(result);
return performancesInfo;
}
......@@ -639,11 +644,19 @@ public class KylinPerformancesServiceImpl implements IKylinPerformancesService {
}
List<KylinTicketTimesVo> ticketTimeList = info.getTicketTimeList();
List<KylinTicketTimesVo> ticketTimeListNew = ObjectUtil.getKylinTicketTimesVoArrayList();
// 票种售罄数量
int ticketSoldOutTotal = 0;
// 票种总数量
int ticketTotal = 0;
for (KylinTicketTimesVo ticketTime : ticketTimeList) {
List<KylinTicketVo> ticketList = ticketTime.getTicketList();
List<KylinTicketVo> ticketListNew = ObjectUtil.getKylinTicketVoArrayList();
for (KylinTicketVo ticket : ticketList) {
ticketTotal++;
int status = checkTicketStatus(ticket);
if (status == 8) {
ticketSoldOutTotal++;
}
ticket.setStatus(status);
// 会员状态
Integer isMemberStatus = getIsMemberStatus(ticket);
......@@ -662,6 +675,12 @@ public class KylinPerformancesServiceImpl implements IKylinPerformancesService {
if (CollectionUtils.isEmpty(ticketTimeListNew) && 7 != info.getAppStatus()) { //列表的时候无需判断 因为列表不展示状态标签
info.setAppStatus(11); // 所有票种下架 演出停售
}
if (ticketSoldOutTotal == ticketTotal) {
// 所有票售罄
info.setAppStatus(8);
}
// 当前时间大于停售时间 小于结束时间 是 停售
String nowTimeStr = DateUtil.getNowTime();
String stopSellTime = info.getStopSellTime();
......@@ -706,6 +725,9 @@ public class KylinPerformancesServiceImpl implements IKylinPerformancesService {
status = 8;
getStatus = 8;
}
if (1 == DateUtil.compareStrDay(ticketItem.getTimeStart(), DateUtil.getNowTime())) {// 未开始
getStatus = 9;
}
if (null != ticketItem) {
// 判断售罄
if (6 == getStatus || 9 == getStatus || 10 == getStatus) {
......
......@@ -32,6 +32,8 @@ import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.KylinLuckyBagActivityMapper;
import com.liquidnet.service.kylin.mapper.KylinLuckyBagMapper;
import com.liquidnet.service.kylin.mapper.KylinRewardUserMapper;
import com.liquidnet.service.slime.constant.SlimeRedisConst;
import com.liquidnet.service.slime.dto.vo.SlimeFieldsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
......@@ -1614,6 +1616,20 @@ public class DataUtils {
KylinTicketPartnerVo.class.getSimpleName());
}
public String getFieldAddressByFieldId(String fieldId){
String key = SlimeRedisConst.INFO_FIELD.concat(fieldId);
SlimeFieldsVo vo = (SlimeFieldsVo) redisUtil.get(key);
if (null == vo) {
vo = mongoTemplate.findOne(Query.query(Criteria.where("fieldId").is(fieldId)), SlimeFieldsVo.class, SlimeFieldsVo.class.getSimpleName());
redisUtil.set(SlimeRedisConst.INFO_FIELD.concat(fieldId), vo);
}
if (null == vo) {
log.error("[getFieldAddressByFieldId] 场地信息为空, fieldId: {}", fieldId);
return "";
}
return vo.getAddress();
}
/**
* 获取福袋活动列表
......@@ -1691,4 +1707,21 @@ public class DataUtils {
.eq(KylinRewardUser::getLuckyBagId, luckyBagId);
return kylinRewardUserMapper.selectList(lambdaQueryWrapper);
}
/**
*
* 获取演出须知提醒状态
* @param performanceId
* @return 0:不提醒 1:提醒
*/
public Integer getPerformanceNoticeRemindStatus(String performanceId) {
String redisKey = KylinRedisConst.PERFORMANCES_NOTICE_REMIND_STATUS + performanceId;
Object obj = redisUtil.get(redisKey);
if (obj == null) {
return 0;
}else {
return (int) obj;
}
}
}
......@@ -7,14 +7,12 @@ import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.constant.LnsRegex;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamUserMemberVo;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.UserPathDto;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.candy.constant.CandyRedisConst;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
......@@ -39,8 +37,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
......@@ -585,9 +581,13 @@ public class GoblinOrderServiceImpl implements IGoblinOrderService {
if (preParam.getDeviceFrom().equals("micropay")) {
dragonPayBaseReqDto.setAuthCode(preParam.getAuthCode());
}
String name = preParam.getStoreName();
if (StringUtil.isNotNull(preParam.getStoreName()) && preParam.getStoreName().length() >= 32) {
name = name.substring(0, 32);
// String name = preParam.getStoreName();
// if (StringUtil.isNotNull(preParam.getStoreName()) && preParam.getStoreName().length() >= 32) {
// name = name.substring(0, 32);
// }
String name = PaySubjectUtils.cleanSubject(PaySubjectUtils.formatSpuNameNumByGoblinOrderSqlParamList(sqlParams));
if (name.isEmpty()) {
name = preParam.getStoreName();
}
dragonPayBaseReqDto.setName(name);
dragonPayBaseReqDto.setDetail("正在现场");
......@@ -851,9 +851,11 @@ public class GoblinOrderServiceImpl implements IGoblinOrderService {
}
BigDecimal price = BigDecimal.ZERO;
String[] orderIds = redisUtils.getMasterCode(storeOrderVo.getMasterOrderCode());
List<String> orderSkuIdList = new ArrayList<>();
for (String orderId : orderIds) {
GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
price = price.add(orderVo.getPriceActual());
orderSkuIdList.addAll(orderVo.getOrderSkuVoIds());
}
GoblinPayInnerResultVo payInnerResultVo = GoblinPayInnerResultVo.getNew();
// if (!storeOrderVo.getPayType().equals("FREE") && storeOrderVo.getPayType().equals(param.getPayType()) && storeOrderVo.getDeviceFrom().equals(param.getDeviceFrom())) {
......@@ -885,10 +887,20 @@ public class GoblinOrderServiceImpl implements IGoblinOrderService {
}
dragonPayBaseReqDto.setType("PRODUCT");
dragonPayBaseReqDto.setPrice(price);
String name = storeOrderVo.getStoreName();
if (StringUtil.isNotNull(storeOrderVo.getStoreName()) && storeOrderVo.getStoreName().length() >= 32) {
name = name.substring(0, 32);
// String name = storeOrderVo.getStoreName();
// if (StringUtil.isNotNull(storeOrderVo.getStoreName()) && storeOrderVo.getStoreName().length() >= 32) {
// name = name.substring(0, 32);
// }
List<GoblinOrderSkuVo> goblinOrderSkuVos = new ArrayList<>();
for (String orderSkuId : orderSkuIdList) {
GoblinOrderSkuVo goblinOrderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuId);
goblinOrderSkuVos.add(goblinOrderSkuVo);
}
String name = PaySubjectUtils.cleanSubject(PaySubjectUtils.formatSpuNameNumSummaryFromSkuVos(goblinOrderSkuVos));
if (name.isEmpty()) {
name = storeOrderVo.getStoreName();
}
dragonPayBaseReqDto.setName(name);
dragonPayBaseReqDto.setDetail("正在现场");
dragonPayBaseReqDto.setOrderCode(storeOrderVo.getMasterOrderCode());
......
......@@ -735,8 +735,11 @@ public class KylinOrderTicketsServiceImpl implements IKylinOrderTicketsOrderServ
if (orderTickets.getPriceActual().compareTo(BigDecimal.valueOf(0)) > 0) {
String name = dataUtils.getTicketPayTxt(ticketData.getTicketsId());
if (name.equals("")) {
name = "正在现场";
if (name.isEmpty()) {
name = PaySubjectUtils.cleanSubject(performanceData.getTitle());
if (name.isEmpty()) {
name = "正在现场";
}
}
// // 调用支付
// if (payOrderParam.getPayType().equalsIgnoreCase(DragonConstant.PayChannelEnum.WEPAY.getCode())) {
......@@ -754,9 +757,9 @@ public class KylinOrderTicketsServiceImpl implements IKylinOrderTicketsOrderServ
}
dragonPayBaseReqDto.setType("TICKET");
dragonPayBaseReqDto.setPrice(orderTickets.getPriceActual());
if (StringUtil.isNotNull(name) && name.length() >= 32) {
name = name.substring(0, 32);
}
// if (StringUtil.isNotNull(name) && name.length() >= 32) {
// name = name.substring(0, 32);
// }
dragonPayBaseReqDto.setName(name);
dragonPayBaseReqDto.setDetail("正在现场");
dragonPayBaseReqDto.setOrderCode(orderTickets.getOrderCode());
......@@ -865,8 +868,11 @@ public class KylinOrderTicketsServiceImpl implements IKylinOrderTicketsOrderServ
return ResponseDto.failure(ErrorMapping.get("20004"));
}
String name = dataUtils.getTicketPayTxt(orderTicketData.getTicketId());
if (name.equals("")) {
name = "正在现场";
if (name.isEmpty()) {
name = PaySubjectUtils.cleanSubject(orderTicketData.getPerformanceTitle());
if (name.isEmpty()) {
name = "正在现场";
}
}
// if (payAgainParam.getPayType().equalsIgnoreCase(DragonConstant.PayChannelEnum.WEPAY.getCode())) {
// if (payAgainParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.JS.getCode()) || payAgainParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.APPLET.getCode())) {
......@@ -883,9 +889,9 @@ public class KylinOrderTicketsServiceImpl implements IKylinOrderTicketsOrderServ
}
dragonPayBaseReqDto.setType("TICKET");
dragonPayBaseReqDto.setPrice(orderTicketData.getPriceActual());
if (StringUtil.isNotNull(name) && name.length() >= 32) {
name = name.substring(0, 32);
}
// if (StringUtil.isNotNull(name) && name.length() >= 32) {
// name = name.substring(0, 32);
// }
dragonPayBaseReqDto.setName(name);
dragonPayBaseReqDto.setDetail("正在现场");
dragonPayBaseReqDto.setOrderCode(orderTicketData.getOrderCode());
......
package com.liquidnet.service.order.utils;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.entity.GoblinOrderSku;
import com.liquidnet.service.goblin.param.GoblinOrderSqlParam;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Slf4j
public class PaySubjectUtils {
/**
* 清理 subject,只保留中文、英文、数字和空格,其他字符替换为 -
* @param subject 原始商品名称
* @return 清理后的 subject
*/
public static String cleanSubject(String subject) {
if (subject == null || subject.trim().isEmpty()) {
return "";
}
try {
subject = subject.trim();
// 长度限制(支付宝限制256字符)
if (subject.length() > 100) {
subject = subject.substring(0, 100);
}
// 正则表达式:匹配非中文、非英文、非数字、非空格的字符
// 中文范围:\u4e00-\u9fa5
// 英文范围:a-zA-Z
// 数字范围:0-9
// 空格:保留
Pattern pattern = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z0-9]");
// 替换所有不符合的字符为 -
String cleaned = pattern.matcher(subject).replaceAll("-");
// 4. 显式移除易混淆的“竖线类”字符(即使它们是汉字或全角符号)
cleaned = cleaned.replace("丨", "-") // U+4E28: CJK 汉字(部首),支付宝可能拦截
.replace("|", "-"); // U+FF5C: 全角竖线,支付宝明确不友好
// 处理多个连续的 - 替换为单个 -
cleaned = cleaned.replaceAll("-+", "-");
// 去除首尾的 -(保留空格)
cleaned = cleaned.replaceAll("^-+|-+$", "");
return "正在现场-" + cleaned;
}catch (Exception e){
log.error("error", e);
}
return "";
}
/**
* 将订单 SKU 列表汇总并格式化为 "正在现场-spuName-num,spuName-num..." 的字符串。
* 相同 spuName 的数量会自动累加。
*
* @param sqlParams 订单参数列表,可能为 null 或包含 null 元素
* @return 格式化后的字符串,若无有效 SKU 则返回 "正在现场-"
*/
public static String formatSpuNameNumByGoblinOrderSqlParamList(List<GoblinOrderSqlParam> sqlParams) {
if (sqlParams == null || sqlParams.isEmpty()) {
return "";
}
try {
// 聚合 spuName -> totalNum(安全处理 null)
Map<String, Integer> aggregated = sqlParams.stream()
.filter(Objects::nonNull)
.map(GoblinOrderSqlParam::getOrderSkuList)
.filter(Objects::nonNull)
.flatMap(List::stream)
.filter(Objects::nonNull)
.filter(sku -> sku.getSpuName() != null && !sku.getSpuName().trim().isEmpty())
.collect(Collectors.groupingBy(
GoblinOrderSku::getSpuName,
Collectors.summingInt(sku -> sku.getNum() == null ? 0 : sku.getNum())
));
// 按 spuName 排序(可选,使输出更稳定)
return aggregated.entrySet().stream()
.sorted(Map.Entry.comparingByKey()) // 可选:按商品名排序
.map(entry -> entry.getKey() + "-" + entry.getValue())
.collect(Collectors.joining(","));
}catch (Exception e) {
log.error("error", e);
}
return "";
}
public static String formatSpuNameNumSummaryFromSkuVos(List<GoblinOrderSkuVo> skuVos) {
if (skuVos == null || skuVos.isEmpty()) {
return "";
}
Map<String, Integer> aggregated = skuVos.stream()
.filter(Objects::nonNull)
.filter(vo -> vo.getSpuName() != null && !vo.getSpuName().trim().isEmpty())
.collect(Collectors.groupingBy(
GoblinOrderSkuVo::getSpuName,
Collectors.summingInt(vo -> vo.getNum() == null ? 0 : vo.getNum())
));
String detailPart = aggregated.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(e -> e.getKey() + "-" + e.getValue())
.collect(Collectors.joining(","));
return detailPart;
}
public static void main(String[] args) {
String text = "「发呆的下午」| 北京的第一次“发呆冲击” 鸟撞x虎啸春x大叫控";
String text2 = "Don't \"mid way\" 「独 步」【了】丨 ·广州站";
String text3 = "Matt吕彦良2025-Fresh-ME-新鲜之旅巡演-Refresh-with-Matt-Lv-长沙站Matt吕彦良2025-Fresh-ME-新鲜之旅巡演-Refr鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅鲜之旅";
System.out.println(cleanSubject(text));
System.out.println(cleanSubject(text2));
System.out.println(cleanSubject(text3));
}
}
package com.liquidnet.service.platform.controller.partner;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
import com.liquidnet.service.kylin.service.partner.IKylinBuyNoticePartnerService;
......@@ -39,11 +38,11 @@ public class KylinBuyNoticeParnterController {
@ApiOperation(value = "购票须知列表", position = 1)
@ApiResponse(code = 200, message = "接口返回对象参数")
public ResponseDto<List<KylinBuyNoticeVo>> getBuyNotice() {
PageInfo<KylinBuyNoticeVo> result = buyNoticePartnerService.getBuyNotice();
List<KylinBuyNoticeVo> result = buyNoticePartnerService.getBuyNotice();
if (null == result) {
return ResponseDto.failure("查询失败");
} else {
return ResponseDto.success(result.getList());
return ResponseDto.success(result);
}
}
......
package com.liquidnet.service.platform.service.impl.partner;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
......@@ -33,11 +30,10 @@ public class KylinBuyNoticePartnerServiceImpl extends ServiceImpl<KylinBuyNotice
private KylinBuyNoticeMapper kylinBuyNoticeMapper;
@Override
public PageInfo<KylinBuyNoticeVo> getBuyNotice() {
PageInfo<KylinBuyNoticeVo> pageInfoTmp = null;
PageHelper.startPage(1, 20);
List<KylinBuyNotice> buyNoticeList = kylinBuyNoticeMapper.selectList(Wrappers.lambdaQuery(KylinBuyNotice.class).eq(KylinBuyNotice::getStatus, 1).orderByDesc(KylinBuyNotice::getSort).orderByDesc(KylinBuyNotice::getMid));
public List<KylinBuyNoticeVo> getBuyNotice() {
List<KylinBuyNotice> buyNoticeList = kylinBuyNoticeMapper.selectList(
Wrappers.lambdaQuery(KylinBuyNotice.class).eq(KylinBuyNotice::getStatus, 1)
.orderByDesc(KylinBuyNotice::getSort).orderByDesc(KylinBuyNotice::getMid));
List<KylinBuyNoticeVo> kylinBuyNoticeVoList = new ArrayList<>();
for (KylinBuyNotice item : buyNoticeList) {
......@@ -45,9 +41,8 @@ public class KylinBuyNoticePartnerServiceImpl extends ServiceImpl<KylinBuyNotice
BeanUtils.copyProperties(item, kylinBuyNoticeVo);
kylinBuyNoticeVoList.add(kylinBuyNoticeVo);
}
pageInfoTmp = new PageInfo(kylinBuyNoticeVoList);
return pageInfoTmp;
return kylinBuyNoticeVoList;
}
@Override
......
package com.liquidnet.service.slime.controller;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
......@@ -56,11 +55,11 @@ public class KylinBuyNoticeParnterController {
@ApiOperation(value = "购票须知列表", position = 1)
@ApiResponse(code = 200, message = "接口返回对象参数")
public ResponseDto<List<KylinBuyNoticeVo>> getBuyNotice() {
PageInfo<KylinBuyNoticeVo> result = buyNoticePartnerService.getBuyNotice();
List<KylinBuyNoticeVo> result = buyNoticePartnerService.getBuyNotice();
if (null == result) {
return ResponseDto.failure("查询失败");
} else {
return ResponseDto.success(result.getList());
return ResponseDto.success(result);
}
}
......
package com.liquidnet.service.slime.service.impl;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
......@@ -26,10 +25,9 @@ public class KylinBuyNoticePartnerServiceImpl implements IKylinBuyNoticePartnerS
RedisSlimeUtils slimeUtils;
@Override
public PageInfo<KylinBuyNoticeVo> getBuyNotice() {
public List<KylinBuyNoticeVo> getBuyNotice() {
List<KylinBuyNoticeVo> buyNoticeList = slimeUtils.getBuyNotice();
PageInfo<KylinBuyNoticeVo> pageInfoTmp = new PageInfo(buyNoticeList);
return pageInfoTmp;
return buyNoticeList;
}
@Override
......
......@@ -215,6 +215,7 @@ public class KylinPerformancesPartnerServiceImpl implements IKylinPerformancesPa
// 无 performancesId 则 创建
if (!step2Param.getPerformancesId().isEmpty()) { // 获取 create 数据 status = 0 或 无数据 创建
redisSlimeUtils.setPerformanceInvoiceReminder(step2Param.getPerformancesId(), step2Param.getIsInvoiceReminder());
redisSlimeUtils.setPerformanceNoticeRemindStatus(step2Param.getPerformancesId(), step2Param.getNoticeRemindStatus());
KylinPerformanceVo vo = redisSlimeUtils.getPerformanceVo(step2Param.getPerformancesId());
if (vo == null || vo.getAppStatus() == 0 || vo.getAppStatus() == 1 || (vo.getAppStatus() == 4 && vo.getAuditStatus() == 2)) {
result = createStep2(step2Param);
......@@ -553,6 +554,7 @@ public class KylinPerformancesPartnerServiceImpl implements IKylinPerformancesPa
performanceStep2Param.setTicketTimes(ticketTimesTicketCreatePartnerVoList);
performanceStep2Param.setIsInvoiceReminder(redisSlimeUtils.getPerformanceInvoiceReminder(performancesId));
performanceStep2Param.setNoticeRemindStatus(redisSlimeUtils.getPerformanceNoticeRemindStatus(performancesId));
log.info(UserPathDto.setPartnerData("0", "getStep2", "performancesId=" + performancesId, performanceStep2Param));
return ResponseDto.success(performanceStep2Param);
}
......
......@@ -311,4 +311,25 @@ public class RedisSlimeUtils {
String redisKey = KylinRedisConst.PERFORMANCES_INVOICE_REMINDER + performanceId;
redisUtil.set(redisKey, invoiceReminder);
}
/**
*
* 获取演出须知提醒状态
* @param performanceId
* @return 0:不提醒 1:提醒
*/
public Integer getPerformanceNoticeRemindStatus(String performanceId) {
String redisKey = KylinRedisConst.PERFORMANCES_NOTICE_REMIND_STATUS + performanceId;
Object obj = redisUtil.get(redisKey);
if (obj == null) {
return 0;
}else {
return (int) obj;
}
}
public void setPerformanceNoticeRemindStatus(String performanceId, Integer noticeRemindStatus) {
String redisKey = KylinRedisConst.PERFORMANCES_NOTICE_REMIND_STATUS + performanceId;
redisUtil.set(redisKey, noticeRemindStatus);
}
}
......@@ -20,8 +20,8 @@ liquidnet:
# username: admin
# password: admin
config:
# location: /Users/jiangxiulong/IdeaProjects/liquidnet-bus-v1/liquidnet-bus-config/liquidnet-config
location: /app/support-config
# location: 'D:/Work/ModernSky/projects/zhengzai/config/liquidnet-config'
location: 'D:/Work/ModernSky/projects/zhengzai/liquidnet-bus-v1/liquidnet-bus-config/liquidnet-config'
# end-dev-这里是配置信息基本值
spring:
......
......@@ -2,4 +2,4 @@ spring:
application:
name: liquidnet-support-eureka
profiles:
active: test
\ No newline at end of file
active: dev
\ 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