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

Commit 583f5927 authored by 姜秀龙's avatar 姜秀龙

收钱吧 admin商品绑定和 redis 相关优化

parent d7836fd9
......@@ -425,9 +425,18 @@ public class GoblinRedisConst {
/* ----------------------------------------------------------------- */
public static final String ERP_GOBLIN_GOODS_LIST = PREFIX.concat("erp:push:order:");
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
/* --------------------------------收钱吧相关--------------------------------- */
/**
* 收钱吧订单详情
*/
public static final String SQB_ORDER = PREFIX.concat("sqb:order:");
/**
* 演出关联收钱吧商品缓存
*/
public static final String SQB_PERFORMANCE_GOODS = PREFIX.concat("sqb:perf:goods:");
/**
* 收钱吧下单防重锁
*/
public static final String SQB_ORDER_LOCK = PREFIX.concat("sqb:order:lock:");
}
......@@ -2,6 +2,7 @@ package com.liquidnet.service.goblin.dto.vo;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class GoblinSqbPerfGoodsVo implements Serializable {
......@@ -10,7 +11,16 @@ public class GoblinSqbPerfGoodsVo implements Serializable {
private String spuName;
private String skuId;
private String skuName;
/** 商品原价(分/元,与原有 price 字段保持向后兼容) */
private Long price;
private String coverPic;
private Integer sort;
/** 换购价格(为 null 时按售价) */
private BigDecimal settlementPrice;
/** 演出结束自动下架 0-否 1-是 */
private Integer autoOffline;
/** 商品库存(管理后台展示用) */
private Integer stock;
/** 商品状态(管理后台展示用) */
private Integer status;
}
package com.liquidnet.client.admin.web.controller.zhengzai.goblin;
import com.liquidnet.client.admin.common.core.controller.BaseController;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.zhengzai.goblin.dto.SqbPerfGoodsBindItemParam;
import com.liquidnet.client.admin.zhengzai.goblin.service.ISqbPerformanceGoodsService;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 演出-收钱吧商品关联管理接口
* 演出-收钱吧商品关联管理
*/
@Slf4j
@RestController
@Controller
@Api(tags = "收钱吧-演出商品关联管理")
@RequestMapping("sqb/performance/goods")
public class SqbPerformanceGoodsController extends BaseController {
private final String prefix = "zhengzai/goblin/sqbGoods";
@Autowired
private ISqbPerformanceGoodsService sqbPerformanceGoodsService;
/**
* 关联商品管理页面(iframe 内嵌)
*/
@GetMapping("page/{performancesId}")
public String sqbGoodsPage(@PathVariable("performancesId") String performancesId, ModelMap mmap) {
mmap.put("performancesId", performancesId);
return prefix + "/index";
}
/**
* 搜索可选商品(skuType=33 的收钱吧商品)
*/
@GetMapping("search")
@ResponseBody
@ApiOperation("搜索收钱吧候选商品")
@ApiImplicitParams({
@ApiImplicitParam(type = "query", dataType = "String", name = "keyword", value = "关键词", required = false),
})
public AjaxResult searchGoods(@RequestParam(value = "keyword", required = false) String keyword) {
ResponseDto<List<GoblinSqbPerfGoodsVo>> resp = sqbPerformanceGoodsService.searchGoods(keyword);
if (resp.isSuccess()) {
return AjaxResult.success(resp.getData());
}
return AjaxResult.error(resp.getMessage());
}
/**
* 批量绑定/保存关联商品配置
*/
@PostMapping("bind")
@ApiOperation("关联演出与商品")
@ApiResponse(code = 200, message = "接口返回对象参数")
@ResponseBody
@ApiOperation("批量绑定演出与商品(含换购价、自动下架配置)")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "performancesId", value = "演出ID"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "skuIds", value = "SKU ID列表(多个逗号分隔)"),
@ApiImplicitParam(type = "form", required = false, dataType = "Integer", name = "sort", value = "排序权重", example = "0"),
})
public ResponseDto<Boolean> bind(@RequestParam("performancesId") String performancesId,
@RequestParam("skuIds") List<String> skuIds,
@RequestParam(value = "sort", required = false, defaultValue = "0") Integer sort) {
return sqbPerformanceGoodsService.bind(performancesId, skuIds, sort);
public AjaxResult bind(@RequestParam("performancesId") String performancesId,
@RequestBody List<SqbPerfGoodsBindItemParam> items) {
ResponseDto<Boolean> resp = sqbPerformanceGoodsService.bind(performancesId, items);
if (resp.isSuccess()) {
return AjaxResult.success("保存成功");
}
return AjaxResult.error(resp.getMessage());
}
@DeleteMapping("unbind")
/**
* 解除关联
*/
@PostMapping("unbind")
@ResponseBody
@ApiOperation("解除演出与商品关联")
@ApiResponse(code = 200, message = "接口返回对象参数")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "performancesId", value = "演出ID"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "skuId", value = "SKU ID"),
})
public ResponseDto<Boolean> unbind(@RequestParam("performancesId") String performancesId,
public AjaxResult unbind(@RequestParam("performancesId") String performancesId,
@RequestParam("skuId") String skuId) {
return sqbPerformanceGoodsService.unbind(performancesId, skuId);
ResponseDto<Boolean> resp = sqbPerformanceGoodsService.unbind(performancesId, skuId);
if (resp.isSuccess()) {
return AjaxResult.success("已取消关联");
}
return AjaxResult.error(resp.getMessage());
}
/**
* 查询演出已关联商品列表
*/
@GetMapping("list")
@ResponseBody
@ApiOperation("查询演出关联商品列表(管理后台)")
@ApiResponse(code = 200, message = "接口返回对象参数")
@ApiImplicitParams({
@ApiImplicitParam(type = "query", required = true, dataType = "String", name = "performancesId", value = "演出ID"),
})
public ResponseDto<List<GoblinSqbPerfGoodsVo>> list(@RequestParam("performancesId") String performancesId) {
return sqbPerformanceGoodsService.list(performancesId);
public AjaxResult list(@RequestParam("performancesId") String performancesId) {
ResponseDto<List<GoblinSqbPerfGoodsVo>> resp = sqbPerformanceGoodsService.list(performancesId);
if (resp.isSuccess()) {
return AjaxResult.success(resp.getData());
}
return AjaxResult.error(resp.getMessage());
}
}
......@@ -45,6 +45,8 @@
</li>
<li id="li-tab-12"><a data-toggle="tab" href="#tab-12" aria-expanded="false" onclick="artistLineupInfo()">演出阵容</a>
</li>
<li id="li-tab-13"><a data-toggle="tab" href="#tab-13" aria-expanded="false" onclick="sqbGoodsInfo()">关联推荐商品</a>
</li>
</ul>
<div class="tab-content">
<div id="tab-1" class="tab-pane">
......@@ -373,6 +375,13 @@
height=800px frameborder=0></iframe>
</div>
</div>
<div id="tab-13" class="tab-pane">
<div class="panel-body">
<iframe id="sqb_goods_iframe" name="sqb_goods_iframe" marginwidth=0 marginheight=0
width=100%
height=800px frameborder=0></iframe>
</div>
</div>
</div>
</div>
</div>
......@@ -578,6 +587,11 @@
document.getElementById("artist_lineup_iframe").src = "../artistLineup/" + '[[${kylinPerformanceMisVo.performancesId}]]'.replaceAll("\"", "");
}
//关联推荐商品
function sqbGoodsInfo() {
document.getElementById("sqb_goods_iframe").src = ctx + "sqb/performance/goods/page/" + '[[${kylinPerformanceMisVo.performancesId}]]'.replaceAll("\"", "");
}
$("#tab-nav-1").bind("click", function () {
$("#tab_iframe_1").attr("src", prefix + "/performanceStatic/" + '[[${kylinPerformanceMisVo.performancesId}]]'.replaceAll("\"", ""));
});
......
package com.liquidnet.client.admin.zhengzai.goblin.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 演出-商品关联绑定请求 DTO
*/
@Data
public class SqbPerfGoodsBindItemParam implements Serializable {
private static final long serialVersionUID = 1L;
/** SKU ID */
private String skuId;
/** 排序权重 */
private Integer sort;
/** 换购价格(null 表示不设置换购价,按原价售卖) */
private BigDecimal settlementPrice;
/** 演出结束自动下架 0-否 1-是 */
private Integer autoOffline;
}
package com.liquidnet.client.admin.zhengzai.goblin.service;
import com.liquidnet.client.admin.zhengzai.goblin.dto.SqbPerfGoodsBindItemParam;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
......@@ -11,14 +12,13 @@ import java.util.List;
public interface ISqbPerformanceGoodsService {
/**
* 关联演出与商品(批量)
* 关联演出与商品(批量,支持换购价/自动下架配置
*
* @param performancesId 演出ID
* @param skuIds SKU ID 列表
* @param sort 排序权重
* @param items 绑定项列表(含配置)
* @return 操作结果
*/
ResponseDto<Boolean> bind(String performancesId, List<String> skuIds, Integer sort);
ResponseDto<Boolean> bind(String performancesId, List<SqbPerfGoodsBindItemParam> items);
/**
* 解除演出与商品关联
......@@ -36,4 +36,12 @@ public interface ISqbPerformanceGoodsService {
* @return 商品列表
*/
ResponseDto<List<GoblinSqbPerfGoodsVo>> list(String performancesId);
/**
* 搜索收钱吧商品(skuType=33,供关联候选)
*
* @param keyword 商品名称关键词
* @return 商品列表
*/
ResponseDto<List<GoblinSqbPerfGoodsVo>> searchGoods(String keyword);
}
......@@ -249,4 +249,14 @@ public class GoblinRedisUtils {
rk = rk.concat(skuId);
return (int) redisDataSourceUtil.getRedisGoblinUtil().incr(rk, stock);
}
/**
* 清除演出关联收钱吧商品缓存
*
* @param performancesId 演出ID
*/
public void delPerformanceGoodsCache(String performancesId) {
String redisKey = GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId);
redisDataSourceUtil.getRedisGoblinUtil().del(redisKey);
}
}
......@@ -56,4 +56,19 @@ public class RedisKeyExpireConst {
// 演出关联阵容缓存过期时间
public static final long PERFORMANCES_ARTISTS_EXPIRE = 30 * 24 * 60 * 60;
/**
* 演出关联收钱吧商品缓存过期时间 (5分钟)
*/
public static final long SQB_PERFORMANCE_GOODS_EXPIRE = 5 * 60;
/**
* 收钱吧订单详情过期时间 (2小时)
*/
public static final long SQB_ORDER_EXPIRE = 2 * 60 * 60;
/**
* 收钱吧下单防重锁过期时间 (10秒)
*/
public static final long SQB_ORDER_LOCK_EXPIRE = 10;
}
......@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* <p>
......@@ -46,6 +47,16 @@ public class GoblinSqbPerformanceGoods implements Serializable {
*/
private Integer sort;
/**
* 换购价格(不设置则按商品售价售卖)
*/
private BigDecimal settlementPrice;
/**
* 演出结束自动下架 0-否 1-是
*/
private Integer autoOffline;
/**
* 状态 0-禁用 1-启用
*/
......
package com.liquidnet.service.goblin.util;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.List;
......@@ -19,53 +18,35 @@ import java.util.List;
@Component
public class GoblinSqbRedisUtils {
// Redis Key 前缀
private static final String KEY_SQB_ORDER = "goblin:sqb:order:";
private static final String KEY_SQB_PERF_GOODS = "goblin:sqb:perf:goods:";
private static final String KEY_SQB_ORDER_LOCK = "goblin:sqb:order:lock:";
// TTL 常量(秒)
private static final long TTL_ORDER = 2 * 60 * 60; // 2h
private static final long TTL_PERF_GOODS = 5 * 60; // 5min
private static final long TTL_ORDER_LOCK = 10; // 10s
@Autowired
private RedisUtil redisUtil;
/* ---------------------------------------- 订单操作(TTL 2h) ---------------------------------------- */
public void setSqbOrder(String orderId, GoblinSqbOrderVo vo) {
redisUtil.set(KEY_SQB_ORDER.concat(orderId), JsonUtils.toJson(vo), TTL_ORDER);
redisUtil.set(GoblinRedisConst.SQB_ORDER.concat(orderId), vo, RedisKeyExpireConst.SQB_ORDER_EXPIRE);
}
public GoblinSqbOrderVo getSqbOrder(String orderId) {
String valStr = (String) redisUtil.get(KEY_SQB_ORDER.concat(orderId));
if (StringUtils.isEmpty(valStr)) {
return null;
}
return JsonUtils.fromJson(valStr, GoblinSqbOrderVo.class);
return (GoblinSqbOrderVo) redisUtil.get(GoblinRedisConst.SQB_ORDER.concat(orderId));
}
public void delSqbOrder(String orderId) {
redisUtil.del(KEY_SQB_ORDER.concat(orderId));
redisUtil.del(GoblinRedisConst.SQB_ORDER.concat(orderId));
}
/* ---------------------------------------- 演出关联商品缓存(TTL 5min) ---------------------------------------- */
public void setPerfGoods(String performancesId, List<GoblinSqbPerfGoodsVo> list) {
redisUtil.set(KEY_SQB_PERF_GOODS.concat(performancesId), JsonUtils.toJson(list), TTL_PERF_GOODS);
redisUtil.set(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId), list, RedisKeyExpireConst.SQB_PERFORMANCE_GOODS_EXPIRE);
}
public List<GoblinSqbPerfGoodsVo> getPerfGoods(String performancesId) {
String valStr = (String) redisUtil.get(KEY_SQB_PERF_GOODS.concat(performancesId));
if (StringUtils.isEmpty(valStr)) {
return null;
}
return JsonUtils.fromJson(valStr, new TypeReference<List<GoblinSqbPerfGoodsVo>>() {});
return (List<GoblinSqbPerfGoodsVo>) redisUtil.get(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId));
}
public void delPerfGoods(String performancesId) {
redisUtil.del(KEY_SQB_PERF_GOODS.concat(performancesId));
redisUtil.del(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId));
}
/* ---------------------------------------- 下单防重锁(TTL 10s) ---------------------------------------- */
......@@ -78,8 +59,8 @@ public class GoblinSqbRedisUtils {
* @return true 获取成功,false 已被锁定
*/
public boolean tryOrderLock(String userId, String skuId) {
String key = KEY_SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
return redisUtil.lock(key, 1, TTL_ORDER_LOCK);
String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
return redisUtil.lock(key, 1, RedisKeyExpireConst.SQB_ORDER_LOCK_EXPIRE);
}
/**
......@@ -89,7 +70,7 @@ public class GoblinSqbRedisUtils {
* @param skuId SKU ID
*/
public void releaseOrderLock(String userId, String skuId) {
String key = KEY_SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
redisUtil.uLock(key);
}
}
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