添加视频缓存和商品缓存和获取
This commit is contained in:
parent
71139a21c3
commit
701efaadea
@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
@ -12,6 +13,7 @@ import org.springframework.context.annotation.ComponentScan;
|
||||
*/
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@ComponentScan(basePackages = {"org.dromara", "com.wzj.soopin"})
|
||||
public class DromaraApplication {
|
||||
|
||||
|
@ -181,6 +181,8 @@ tenant:
|
||||
- sys_version
|
||||
- ums_member_wechat
|
||||
- sys_tenant_extend
|
||||
- commission_template
|
||||
- commission_rate_range
|
||||
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import com.wzj.soopin.content.domain.bo.IndexListBO;
|
||||
import com.wzj.soopin.content.domain.bo.MyListBO;
|
||||
import com.wzj.soopin.content.domain.bo.SimpleListBO;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -303,4 +304,43 @@ public class VlogController extends BaseInfoProperties {
|
||||
return R.ok(vlogService.getVlogBeLikedCounts(vlogId));
|
||||
}
|
||||
|
||||
@Tag(name = "手动触发缓存点赞最多视频")
|
||||
@PostMapping("/cacheTopLikedVlogs")
|
||||
public R<Void> cacheTopLikedVlogs(@RequestParam(defaultValue = "100") int limit) {
|
||||
try {
|
||||
vlogService.cacheTopLikedVlogs(limit);
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
log.error("手动触发缓存点赞最多视频失败", e);
|
||||
return R.fail("缓存失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(name = "获取缓存中的点赞最多视频")
|
||||
@GetMapping("/getTopLikedVlogs")
|
||||
public R<Object> getTopLikedVlogs(@RequestParam(defaultValue = "") String date) {
|
||||
try {
|
||||
String redisKey;
|
||||
if (StringUtils.isBlank(date)) {
|
||||
// 如果没有指定日期,使用今天的日期
|
||||
redisKey = "top_liked_vlogs:" + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} else {
|
||||
redisKey = "top_liked_vlogs:" + date;
|
||||
}
|
||||
|
||||
String cachedData = redis.get(redisKey);
|
||||
if (StringUtils.isNotBlank(cachedData)) {
|
||||
// 解析JSON数据
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<Map<String, Object>> vlogList = objectMapper.readValue(cachedData, new com.fasterxml.jackson.core.type.TypeReference<List<Map<String, Object>>>() {});
|
||||
return R.ok(vlogList);
|
||||
} else {
|
||||
return R.fail("未找到缓存数据,请先执行缓存任务");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取缓存中的点赞最多视频失败", e);
|
||||
return R.fail("获取缓存失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -112,4 +112,31 @@ public interface VlogMapper extends BaseMapper<Vlog> {
|
||||
"ORDER BY " +
|
||||
" DATE_FORMAT(create_time, '%Y-%m')")
|
||||
List<Map<String, Object>> getMonthlyVlog();
|
||||
|
||||
/**
|
||||
* 查询所有公开的视频列表(用于从Redis获取点赞数)
|
||||
* @return 视频信息列表
|
||||
*/
|
||||
@Select("SELECT " +
|
||||
" v.id, " +
|
||||
" v.vloger_id, " +
|
||||
" v.url, " +
|
||||
" v.cover, " +
|
||||
" v.title, " +
|
||||
" v.width, " +
|
||||
" v.height, " +
|
||||
" v.like_counts, " +
|
||||
" v.comments_counts, " +
|
||||
" v.is_private, " +
|
||||
" v.create_time, " +
|
||||
" v.update_time, " +
|
||||
" v.status, " +
|
||||
" v.file_id, " +
|
||||
" v.reason, " +
|
||||
"city_code,"+
|
||||
" v.first_frame_img " +
|
||||
"FROM t_vlog v " +
|
||||
"WHERE v.status = 1 AND v.is_private = 0 " +
|
||||
"ORDER BY v.create_time DESC")
|
||||
List<Map<String, Object>> selectAllPublicVlogs();
|
||||
}
|
||||
|
@ -137,4 +137,10 @@ public interface VlogService {
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<Map<String, Object>> getVlogListByMobile(Page<Map<String, Object>> page, VlogBO vlogBO);
|
||||
|
||||
/**
|
||||
* 查询点赞最多的视频列表并存储到Redis
|
||||
* @param limit 查询数量限制
|
||||
*/
|
||||
void cacheTopLikedVlogs(int limit);
|
||||
}
|
||||
|
@ -47,7 +47,10 @@ import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.ArrayList;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
@ -598,4 +601,73 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
return vlogMapper.selectVlogListWithAggregatedData(page, vlogBO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheTopLikedVlogs(int limit) {
|
||||
try {
|
||||
log.info("开始查询点赞最多的{}条视频", limit);
|
||||
|
||||
// 查询所有公开的视频列表
|
||||
List<Map<String, Object>> allVlogs = vlogMapper.selectAllPublicVlogs();
|
||||
|
||||
if (allVlogs != null && !allVlogs.isEmpty()) {
|
||||
// 从Redis获取每个视频的点赞数量
|
||||
List<Map<String, Object>> vlogsWithLikeCounts = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> vlog : allVlogs) {
|
||||
String vlogId = vlog.get("id").toString();
|
||||
String redisLikeKey = REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId;
|
||||
String likeCountStr = redis.get(redisLikeKey);
|
||||
|
||||
// 获取Redis中的点赞数,如果没有则使用数据库中的默认值
|
||||
int likeCount = 0;
|
||||
if (likeCountStr != null && !likeCountStr.isEmpty()) {
|
||||
try {
|
||||
likeCount = Integer.parseInt(likeCountStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的点赞数格式错误: {}", vlogId, likeCountStr);
|
||||
likeCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加Redis中的点赞数到视频信息中
|
||||
vlog.put("redis_like_count", likeCount);
|
||||
vlogsWithLikeCounts.add(vlog);
|
||||
}
|
||||
|
||||
// 按Redis中的点赞数排序,获取前limit个
|
||||
vlogsWithLikeCounts.sort((v1, v2) -> {
|
||||
int count1 = (Integer) v1.get("redis_like_count");
|
||||
int count2 = (Integer) v2.get("redis_like_count");
|
||||
return Integer.compare(count2, count1); // 降序排列
|
||||
});
|
||||
|
||||
// 取前limit个
|
||||
List<Map<String, Object>> topLikedVlogs = vlogsWithLikeCounts.stream()
|
||||
.limit(limit)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!topLikedVlogs.isEmpty()) {
|
||||
// 将结果存储到Redis中,使用JSON格式
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 注册JavaTimeModule以支持LocalDateTime序列化
|
||||
objectMapper.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
|
||||
objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
String jsonData = objectMapper.writeValueAsString(topLikedVlogs);
|
||||
|
||||
// 存储到Redis,设置24小时过期时间
|
||||
String redisKey = "top_liked_vlogs:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
redis.set(redisKey, jsonData, 24 * 60 * 60); // 24小时过期
|
||||
|
||||
log.info("成功缓存{}条点赞最多的视频到Redis,key: {}", topLikedVlogs.size(), redisKey);
|
||||
} else {
|
||||
log.warn("未查询到点赞最多的视频数据");
|
||||
}
|
||||
} else {
|
||||
log.warn("未查询到公开的视频数据");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("缓存点赞最多视频到Redis失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import com.wzj.soopin.order.domain.form.DeliverProductForm;
|
||||
import com.wzj.soopin.order.domain.form.OrderPayForm;
|
||||
import com.wzj.soopin.order.domain.vo.*;
|
||||
import com.wzj.soopin.order.service.OrderService;
|
||||
import com.wzj.soopin.order.service.OrderItemService;
|
||||
import com.wzj.soopin.order.service.impl.OrderServiceImpl;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -24,12 +25,14 @@ import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.redis.redis.RedisService;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
/**
|
||||
* 订单表Controller
|
||||
*
|
||||
@ -47,6 +50,7 @@ public class OrderController extends BaseController {
|
||||
private final OrderConvert convert;
|
||||
private final RedisService redisService;
|
||||
private final OrderService orderService;
|
||||
private final OrderItemService orderItemService;
|
||||
|
||||
|
||||
@Tag(name ="查询订单列表")
|
||||
@ -146,9 +150,41 @@ public class OrderController extends BaseController {
|
||||
return service.decryptPhone(orderId);
|
||||
}
|
||||
|
||||
@Tag(name = "手动触发缓存交易量最多商品")
|
||||
@PostMapping("/cacheTopTradingProducts")
|
||||
public R<Void> cacheTopTradingProducts(@RequestParam(defaultValue = "100") int limit) {
|
||||
try {
|
||||
orderItemService.cacheTopTradingProducts(limit);
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
log.error("手动触发缓存交易量最多商品失败", e);
|
||||
return R.fail("缓存失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Tag(name = "获取缓存交易量最多商品")
|
||||
@GetMapping("/getTopTradingProducts")
|
||||
public R<Object> getTopTradingProducts(@RequestParam(required = false) String date) {
|
||||
try {
|
||||
String redisKey;
|
||||
if (date != null && !date.isEmpty()) {
|
||||
redisKey = "top_trading_products:" + date;
|
||||
} else {
|
||||
redisKey = "top_trading_products:" + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
}
|
||||
|
||||
String jsonData = RedisUtils.getCacheObject(redisKey);
|
||||
if (jsonData != null && !jsonData.isEmpty()) {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
|
||||
return R.ok(objectMapper.readValue(jsonData, Object.class));
|
||||
} else {
|
||||
return R.ok("未找到缓存数据");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取缓存交易量最多商品失败", e);
|
||||
return R.fail("获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 订单中所包含的商品Mapper接口
|
||||
@ -34,4 +35,29 @@ public interface OrderItemMapper extends BaseMapper<OrderItem> {
|
||||
"WHERE oi.order_id = #{orderId} " +
|
||||
"LIMIT 1")
|
||||
String getName(Long orderId);
|
||||
|
||||
/**
|
||||
* 查询交易量最多的商品列表
|
||||
* 统计已完成订单中商品的销售数量
|
||||
*
|
||||
* @param limit 查询数量限制
|
||||
* @return 商品交易量信息列表
|
||||
*/
|
||||
@Select("SELECT " +
|
||||
" oi.product_id, " +
|
||||
" oi.product_name, " +
|
||||
" oi.pic, " +
|
||||
" oi.out_product_id, " +
|
||||
" oi.product_category_id, " +
|
||||
" SUM(oi.quantity) as total_quantity, " +
|
||||
" SUM(oi.quantity * oi.sale_price) as total_amount, " +
|
||||
" COUNT(DISTINCT o.id) as order_count " +
|
||||
"FROM oms_order_item oi " +
|
||||
"JOIN oms_order o ON oi.order_id = o.id " +
|
||||
"WHERE o.status = 3 " + // 已完成订单
|
||||
" AND o.delete_status = 0 " + // 未删除订单
|
||||
"GROUP BY oi.product_id, oi.product_name, oi.pic, oi.out_product_id, oi.product_category_id " +
|
||||
"ORDER BY total_quantity DESC " +
|
||||
"LIMIT #{limit}")
|
||||
List<Map<String, Object>> selectTopTradingProducts(int limit);
|
||||
}
|
||||
|
@ -9,5 +9,9 @@ public interface OrderItemService extends IService<OrderItem> {
|
||||
|
||||
List<OrderItem> findByOrderId(Long orderId);
|
||||
|
||||
|
||||
/**
|
||||
* 缓存交易量最多的商品列表到Redis
|
||||
* @param limit 查询数量限制
|
||||
*/
|
||||
void cacheTopTradingProducts(int limit);
|
||||
}
|
||||
|
@ -5,9 +5,17 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.wzj.soopin.order.domain.entity.OrderItem;
|
||||
import com.wzj.soopin.order.mapper.OrderItemMapper;
|
||||
import com.wzj.soopin.order.service.OrderItemService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.wzj.soopin.content.utils.RedisOperator;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 订单中所包含的商品Service业务层处理
|
||||
@ -15,12 +23,45 @@ import java.util.List;
|
||||
*
|
||||
* @author zcc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem> implements OrderItemService {
|
||||
|
||||
@Autowired
|
||||
private RedisOperator redis;
|
||||
|
||||
@Override
|
||||
public List<OrderItem> findByOrderId(Long orderId) {
|
||||
return baseMapper.selectList(new QueryWrapper<OrderItem>().lambda()
|
||||
.eq(OrderItem::getOrderId, orderId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheTopTradingProducts(int limit) {
|
||||
try {
|
||||
log.info("开始查询交易量最多的{}个商品", limit);
|
||||
|
||||
// 查询交易量最多的商品列表
|
||||
List<Map<String, Object>> topTradingProducts = baseMapper.selectTopTradingProducts(limit);
|
||||
|
||||
if (topTradingProducts != null && !topTradingProducts.isEmpty()) {
|
||||
// 将结果存储到Redis中,使用JSON格式
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 注册JavaTimeModule以支持LocalDateTime序列化
|
||||
objectMapper.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
|
||||
objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
String jsonData = objectMapper.writeValueAsString(topTradingProducts);
|
||||
|
||||
// 存储到Redis,设置24小时过期时间
|
||||
String redisKey = "top_trading_products:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
redis.set(redisKey, jsonData, 24 * 60 * 60); // 24小时过期
|
||||
|
||||
log.info("成功缓存{}个交易量最多的商品到Redis,key: {}", topTradingProducts.size(), redisKey);
|
||||
} else {
|
||||
log.warn("未查询到交易量最多的商品数据");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("缓存交易量最多商品到Redis失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
package org.dromara.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.convert.SysTenantAccountConvert;
|
||||
import org.dromara.system.domain.CommissionSection;
|
||||
import org.dromara.system.domain.SysTenantAccount;
|
||||
import org.dromara.system.domain.bo.CommissionSectionBo;
|
||||
import org.dromara.system.domain.bo.SysTenantAccountBo;
|
||||
import org.dromara.system.domain.vo.CommissionSectionVo;
|
||||
import org.dromara.system.domain.vo.SysTenantAccountVo;
|
||||
import org.dromara.system.service.ISysTenantAccountService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "租户账户管理接口")
|
||||
@RestController
|
||||
@RequestMapping("/system/tenant/account")
|
||||
@RequiredArgsConstructor
|
||||
public class SysTenantAccountController {
|
||||
|
||||
private final ISysTenantAccountService service;
|
||||
private final SysTenantAccountConvert convert;
|
||||
|
||||
@Operation(summary = "查询租户账户列表")
|
||||
@PostMapping("/list")
|
||||
public R<IPage<SysTenantAccountVo>> fansList(@RequestBody SysTenantAccountBo bo, @RequestBody Page<SysTenantAccount> page) {
|
||||
LambdaQueryWrapper<SysTenantAccount> fansQuery = new LambdaQueryWrapper<>();
|
||||
Page<SysTenantAccount> fans = service.page(page, fansQuery);
|
||||
return R.ok(convert.toVO(fans));
|
||||
}
|
||||
|
||||
@Operation(summary = "导出租户账户列表")
|
||||
@Log(title = "租户账户", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export")
|
||||
public R<String> export(SysTenantAccountBo query) {
|
||||
List<SysTenantAccount> list = service.list(query);
|
||||
ExcelUtil<SysTenantAccountVo> util = new ExcelUtil<>(SysTenantAccountVo.class);
|
||||
return R.ok(util.writeExcel(convert.toVO(list), "租户账户数据"));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取租户账户详细信息")
|
||||
@GetMapping(value = "/{id}")
|
||||
public R<SysTenantAccountVo> getInfo(@Parameter(description = "租户账户ID") @PathVariable("id") Long id) {
|
||||
return R.ok(convert.toVO(service.getById(id)));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增租户账户")
|
||||
@Log(title = "租户账户", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
public R<Object> add(@RequestBody SysTenantAccountBo tenantAccount) {
|
||||
return R.ok(service.save(convert.toPo(tenantAccount)));
|
||||
}
|
||||
|
||||
@Operation(summary = "修改租户账户")
|
||||
@Log(title = "租户账户", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/update")
|
||||
public R<Object> edit(@RequestBody SysTenantAccountBo tenantAccount) {
|
||||
return R.ok(service.updateById(convert.toPo(tenantAccount)));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除租户账户")
|
||||
@Log(title = "租户账户", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public R<Object> remove(@Parameter(description = "租户账户ID") @PathVariable Long id) {
|
||||
return R.ok(service.removeById(id));
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.dromara.system.domain.dto;
|
||||
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "分成比例区间批量添加DTO")
|
||||
public class CommissionSectionBatchAddDTO {
|
||||
|
||||
@Schema(description = "模板ID")
|
||||
private Integer templateId;
|
||||
|
||||
@Schema(description = "区间列表,字符串形式的JSON数组")
|
||||
private String templateList;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user