You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

493 lines
20 KiB

7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
  1. package com.example.demo.controller.coin;
  2. import com.example.demo.Util.BusinessException;
  3. import com.example.demo.Util.JWTUtil;
  4. import com.example.demo.Util.LanguageTranslationUtil;
  5. import com.example.demo.Util.RedisLockUtil;
  6. import com.example.demo.config.interfac.Log;
  7. import com.example.demo.domain.DTO.GoldDetailDTO;
  8. import com.example.demo.domain.DTO.GoldUserDTO;
  9. import com.example.demo.domain.entity.Admin;
  10. import com.example.demo.domain.entity.User;
  11. import com.example.demo.domain.vo.coin.GoldDetail;
  12. import com.example.demo.domain.vo.coin.GoldUser;
  13. import com.example.demo.domain.vo.coin.Page;
  14. import com.example.demo.domain.vo.coin.Result;
  15. import com.example.demo.service.coin.GoldDetailService;
  16. import com.example.demo.service.coin.MarketService;
  17. import com.example.demo.service.coin.TranslationService;
  18. import com.example.demo.serviceImpl.coin.AiEmotionServiceImpl;
  19. import com.github.pagehelper.PageInfo;
  20. import jakarta.servlet.http.HttpServletRequest;
  21. import jakarta.validation.Valid;
  22. import lombok.RequiredArgsConstructor;
  23. import lombok.extern.slf4j.Slf4j;
  24. import org.apache.commons.lang3.StringUtils;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.util.ObjectUtils;
  27. import org.springframework.web.bind.annotation.*;
  28. import org.springframework.web.context.request.RequestContextHolder;
  29. import org.springframework.web.context.request.ServletRequestAttributes;
  30. import java.util.Arrays;
  31. import java.util.List;
  32. import java.util.UUID;
  33. /**
  34. * @program: GOLD
  35. * @ClassName GoldDetailController
  36. * @description:
  37. * @author: huangqizhen
  38. * @create: 202506-23 14:41
  39. * @Version 1.0
  40. **/
  41. @RestController
  42. @RequestMapping("/goldDetail")
  43. @RequiredArgsConstructor
  44. @Slf4j
  45. @CrossOrigin
  46. public class GoldDetailController {
  47. @Autowired
  48. private GoldDetailService goldDetailService;
  49. @Autowired
  50. private LanguageTranslationUtil languageTranslationUtil;
  51. @Autowired
  52. private RedisLockUtil redisLockUtil;
  53. @Autowired
  54. private AiEmotionServiceImpl aiEmotionServiceImpl;
  55. @Autowired
  56. MarketService marketService;
  57. @Autowired
  58. private TranslationService translationService;
  59. @Log("获取金币明细")
  60. @PostMapping("/getGoldDetail")
  61. public Result getGoldDetail(@RequestBody Page page, @RequestHeader(defaultValue = "zh_CN") String lang) throws Exception {
  62. // 解析语言代码
  63. String languageCode = parseLanguageCode(lang);
  64. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  65. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  66. convertGoldDetailTranslatedFieldsToChinese(page.getGoldDetail(), languageCode);
  67. }
  68. // 获取当前请求对象
  69. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  70. String token = request.getHeader("token");
  71. // 解析 token 获取用户信息
  72. Admin admin = (Admin) JWTUtil.getUserDetailsList(String.valueOf(token), Admin.class);
  73. List<String> userMarkets = Arrays.asList(StringUtils.split(admin.getMarkets(), ","));
  74. List<String> markets = marketService.getMarketIds(userMarkets);
  75. // 校验分页参数
  76. if (ObjectUtils.isEmpty(page.getPageNum())) {
  77. return Result.error("页码数为空!");
  78. }
  79. if (ObjectUtils.isEmpty(page.getPageSize())) {
  80. return Result.error("页大小为空!");
  81. }
  82. // 获取传入的市场列表
  83. List<String> requestedMarkets = page.getGoldDetail() != null ? page.getGoldDetail().getMarkets() : null;
  84. // 权限校验逻辑
  85. if (markets.contains("9") || markets.contains("9999")) {
  86. // 特权市场:9 或 9999,跳过权限校验,直接放行传入的 markets
  87. // 如果业务需要,也可以在这里做空值处理
  88. if (page.getGoldDetail() != null) {
  89. // 保持 requestedMarkets 不变,原样接受
  90. // 可选:如果 requestedMarkets 为 null,可设为默认值或保持 null
  91. }
  92. } else {
  93. // 普通用户:必须校验权限
  94. if (requestedMarkets == null || requestedMarkets.isEmpty()) {
  95. page.getGoldDetail().setMarkets(markets);
  96. }
  97. if (!markets.containsAll(requestedMarkets)) {
  98. return Result.error("无权限!请求的市场不在授权范围内。");
  99. }
  100. // 校验通过,保持 requestedMarkets 不变
  101. }
  102. // 返回详情数据
  103. Result result = Result.success(goldDetailService.getGoldDetail(
  104. page.getPageNum(),
  105. page.getPageSize(),
  106. page.getGoldDetail()
  107. ));
  108. // 对返回结果进行多语言转换
  109. if (result.getCode() == 200 && result.getData() instanceof PageInfo) {
  110. PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) result.getData();
  111. translateGoldDetails(pageInfo, lang);
  112. }
  113. return result;
  114. }
  115. @Log("客户金币明细金币合计数统计")
  116. @PostMapping("/getTotal")
  117. public Result getTotal(@RequestBody Page page) throws Exception {
  118. Integer pageNum = page.getPageNum();
  119. Integer pageSize = page.getPageSize();
  120. GoldDetail goldDetail = page.getGoldDetail();
  121. // 获取当前请求对象
  122. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  123. String token = request.getHeader("token");
  124. // 解析 token 获取用户信息
  125. Admin admin = (Admin) JWTUtil.getUserDetailsList(String.valueOf(token), Admin.class);
  126. List<String> userMarkets = Arrays.asList(StringUtils.split(admin.getMarkets(), ","));
  127. List<String> markets = marketService.getMarketIds(userMarkets);
  128. // 获取传入的市场列表
  129. List<String> requestedMarkets = page.getGoldDetail() != null ? page.getGoldDetail().getMarkets() : null;
  130. // 权限校验逻辑
  131. if (markets.contains("9") || markets.contains("9999")) {
  132. // 特权市场:9 或 9999,跳过权限校验,直接放行传入的 markets
  133. // 如果业务需要,也可以在这里做空值处理
  134. if (page.getGoldDetail() != null) {
  135. // 保持 requestedMarkets 不变,原样接受
  136. // 可选:如果 requestedMarkets 为 null,可设为默认值或保持 null
  137. }
  138. } else {
  139. // 普通用户:必须校验权限
  140. if (requestedMarkets == null || requestedMarkets.isEmpty()) {
  141. page.getGoldDetail().setMarkets(markets);
  142. }
  143. if (!markets.containsAll(requestedMarkets)) {
  144. return Result.error("无权限!请求的市场不在授权范围内。");
  145. }
  146. // 校验通过,保持 requestedMarkets 不变
  147. }
  148. return Result.success(goldDetailService.sumGold(pageNum,pageSize,goldDetail));
  149. }
  150. @Log("客户金币余额金币合计数统计")
  151. @PostMapping("/goldTotal")
  152. public Result GoldTotal(@RequestBody User user) throws Exception {
  153. // 获取当前请求对象
  154. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  155. String token = request.getHeader("token");
  156. // 解析 token 获取用户信息
  157. Admin admin = (Admin) JWTUtil.getUserDetailsList(String.valueOf(token), Admin.class);
  158. List<String> userMarkets = Arrays.asList(StringUtils.split(admin.getMarkets(), ","));
  159. List<String> markets = marketService.getMarketIds(userMarkets);
  160. // 获取传入的市场列表
  161. List<String> requestedMarkets = user != null ? user.getMarkets() : null;
  162. // 权限校验逻辑
  163. if (markets.contains("9") || markets.contains("9999")) {
  164. // 特权市场:9 或 9999,跳过权限校验,直接放行传入的 markets
  165. // 如果业务需要,也可以在这里做空值处理
  166. if (user != null) {
  167. // 保持 requestedMarkets 不变,原样接受
  168. // 可选:如果 requestedMarkets 为 null,可设为默认值或保持 null
  169. }
  170. } else {
  171. // 普通用户:必须校验权限
  172. if (requestedMarkets == null || requestedMarkets.isEmpty()) {
  173. user.setMarkets(markets);
  174. }
  175. if (!markets.containsAll(requestedMarkets)) {
  176. return Result.error("无权限!请求的市场不在授权范围内。");
  177. }
  178. // 校验通过,保持 requestedMarkets 不变
  179. }
  180. return Result.success(goldDetailService.GoldTotal(user));
  181. }
  182. @Log("获取客户金币余额记录")
  183. @PostMapping("/getGold")
  184. public Result getGold(@RequestBody Page page, @RequestHeader(defaultValue = "zh_CN") String lang) throws Exception {
  185. // 解析语言代码
  186. String languageCode = parseLanguageCode(lang);
  187. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  188. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  189. convertUserTranslatedFieldsToChinese(page.getUser(), languageCode);
  190. }
  191. // 获取当前请求对象
  192. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  193. String token = request.getHeader("token");
  194. // 解析 token 获取用户信息
  195. Admin admin = (Admin) JWTUtil.getUserDetailsList(String.valueOf(token), Admin.class);
  196. List<String> userMarkets = Arrays.asList(StringUtils.split(admin.getMarkets(), ","));
  197. List<String> markets = marketService.getMarketIds(userMarkets);
  198. // 校验分页参数
  199. if (ObjectUtils.isEmpty(page.getPageNum())) {
  200. return Result.error("页码数为空!");
  201. }
  202. if (ObjectUtils.isEmpty(page.getPageSize())) {
  203. return Result.error("页大小为空!");
  204. }
  205. // 获取传入的市场列表
  206. List<String> requestedMarkets = page.getUser() != null ? page.getUser().getMarkets() : null;
  207. // 权限校验逻辑
  208. if (markets.contains("9") || markets.contains("9999")) {
  209. // 特权市场:9 或 9999,跳过权限校验,直接放行传入的 markets
  210. // 如果业务需要,也可以在这里做空值处理
  211. if (page.getUser() != null) {
  212. // 保持 requestedMarkets 不变,原样接受
  213. // 可选:如果 requestedMarkets 为 null,可设为默认值或保持 null
  214. }
  215. } else {
  216. // 普通用户:必须校验权限
  217. if (requestedMarkets == null || requestedMarkets.isEmpty()) {
  218. page.getUser().setMarkets(markets);
  219. }
  220. if (!markets.containsAll(requestedMarkets)) {
  221. return Result.error("无权限!请求的市场不在授权范围内。");
  222. }
  223. // 校验通过,保持 requestedMarkets 不变
  224. }
  225. Result result = Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser()));
  226. // 对返回结果进行多语言转换
  227. if (result.getCode() == 200 && result.getData() instanceof PageInfo) {
  228. PageInfo<User> pageInfo = (PageInfo<User>) result.getData();
  229. translateUsers(pageInfo, lang);
  230. }
  231. return result;
  232. }
  233. @PostMapping("/export")
  234. public Result export(@Valid @RequestBody GoldDetailDTO dto, @RequestHeader(defaultValue = "zh_CN") String lang) {
  235. String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key(可按用户/业务区分)
  236. String requestId = UUID.randomUUID().toString(); // 请求 ID(防止误删锁)
  237. long expireTime = 5000; // 锁过期时间(5秒)s
  238. dto.setLang(lang); // 设置语言参数
  239. // 解析语言代码
  240. String languageCode = parseLanguageCode(lang);
  241. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  242. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  243. convertGoldDetailTranslatedFieldsToChinese(dto.getGoldDetail(), languageCode);
  244. }
  245. try {
  246. // 尝试获取锁
  247. if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
  248. throw new BusinessException("操作太频繁,请稍后重试");
  249. }
  250. // 执行业务逻辑
  251. return goldDetailService.addExportRecord(dto);
  252. } finally {
  253. // 释放锁
  254. redisLockUtil.unlock(lockKey, requestId);
  255. }
  256. }
  257. @PostMapping("/exportGold")
  258. public Result export(@Valid @RequestBody GoldUserDTO dto, @RequestHeader(defaultValue = "zh_CN") String lang) {
  259. String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key(可按用户/业务区分)
  260. String requestId = UUID.randomUUID().toString(); // 请求 ID(防止误删锁)
  261. long expireTime = 5000; // 锁过期时间(5秒)s
  262. dto.setLang(lang);
  263. // 解析语言代码
  264. String languageCode = parseLanguageCode(lang);
  265. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  266. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  267. convertUserTranslatedFieldsToChinese(dto.getUser(), languageCode);
  268. }
  269. try {
  270. // 尝试获取锁
  271. if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
  272. throw new BusinessException("操作太频繁,请稍后重试");
  273. }
  274. // 执行业务逻辑
  275. return goldDetailService.addExportRecordGold(dto);
  276. } finally {
  277. // 释放锁
  278. redisLockUtil.unlock(lockKey, requestId);
  279. }
  280. }
  281. @PostMapping("/exportqqq")
  282. public Result ExcelGoldDetail(@RequestBody Page page, @RequestHeader(defaultValue = "zh_CN") String lang) throws Exception {
  283. // 解析语言代码
  284. String languageCode = parseLanguageCode(lang);
  285. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  286. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  287. convertGoldDetailTranslatedFieldsToChinese(page.getGoldDetail(), languageCode);
  288. }
  289. if(ObjectUtils.isEmpty(page.getPageNum())){
  290. String errorMsg = languageTranslationUtil.translate("页码数为空!", lang);
  291. return Result.error(errorMsg);
  292. }
  293. if(ObjectUtils.isEmpty(page.getPageSize())){
  294. String errorMsg = languageTranslationUtil.translate("页大小为空!", lang);
  295. return Result.error(errorMsg);
  296. }
  297. else{
  298. Result result = Result.success(goldDetailService.getGoldDetail(page.getPageNum(), page.getPageSize(), page.getGoldDetail()));
  299. // 对返回结果进行多语言转换
  300. if (result.getCode() == 200 && result.getData() instanceof PageInfo) {
  301. PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) result.getData();
  302. translateGoldDetails(pageInfo, lang);
  303. }
  304. return result;
  305. }
  306. }
  307. public Result ExcelGold(@RequestBody Page page, @RequestHeader(defaultValue = "zh_CN") String lang) throws Exception {
  308. // 解析语言代码
  309. String languageCode = parseLanguageCode(lang);
  310. // 如果不是中文环境,将查询条件中的翻译文本转换为中文简体
  311. if (!"zh".equalsIgnoreCase(languageCode) && !"zh_cn".equalsIgnoreCase(languageCode)) {
  312. convertUserTranslatedFieldsToChinese(page.getUser(), languageCode);
  313. }
  314. if(ObjectUtils.isEmpty(page.getPageNum())){
  315. String errorMsg = languageTranslationUtil.translate("页码数为空!", lang);
  316. return Result.error(errorMsg);
  317. }
  318. if(ObjectUtils.isEmpty(page.getPageSize())){
  319. String errorMsg = languageTranslationUtil.translate("页大小为空!", lang);
  320. return Result.error(errorMsg);
  321. }
  322. Result result = Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser()));
  323. // 对返回结果进行多语言转换
  324. if (result.getCode() == 200 && result.getData() instanceof PageInfo) {
  325. PageInfo<User> pageInfo = (PageInfo<User>) result.getData();
  326. translateUsers(pageInfo, lang);
  327. }
  328. return result;
  329. }
  330. //更新用户消费次数
  331. @PostMapping("/updateConsumeNum")
  332. public Result updateConsumeNum() {
  333. return goldDetailService.updateConsumeNum();
  334. }
  335. /**
  336. * 转换金币明细信息的多语言字段
  337. */
  338. private void translateGoldDetails(PageInfo<GoldDetail> pageInfo, String lang) {
  339. if (pageInfo != null && pageInfo.getList() != null) {
  340. for (GoldDetail detail : pageInfo.getList()) {
  341. // 翻译市场名称("所属地区")
  342. if (detail.getMarket() != null) {
  343. detail.setMarket(languageTranslationUtil.translate(detail.getMarket(), lang));
  344. }
  345. // 翻译类型("更新类型") - 需要根据type的值进行转换
  346. if (detail.getType() != null) {
  347. String typeDesc = convertTypeToString(detail.getType());
  348. detail.setTypeDesc(languageTranslationUtil.translate(typeDesc, lang));
  349. }
  350. // 翻译商品名称("商品名称")
  351. if (detail.getGoodsName() != null) {
  352. detail.setGoodsName(languageTranslationUtil.translate(detail.getGoodsName(), lang));
  353. }
  354. }
  355. }
  356. }
  357. /**
  358. * 将类型数字转换为中文描述
  359. */
  360. private String convertTypeToString(Integer type) {
  361. if (type == null) return "";
  362. switch (type) {
  363. case 0: return "充值";
  364. case 1: return "消耗";
  365. case 2: return "退款";
  366. default: return "其他";
  367. }
  368. }
  369. /**
  370. * 转换用户信息的多语言字段
  371. */
  372. private void translateUsers(PageInfo<User> pageInfo, String lang) {
  373. if (pageInfo != null && pageInfo.getList() != null) {
  374. for (User user : pageInfo.getList()) {
  375. // 翻译市场名称
  376. if (user.getMarket() != null) {
  377. user.setMarket(languageTranslationUtil.translate(user.getMarket(), lang));
  378. }
  379. }
  380. }
  381. }
  382. /**
  383. * 解析语言代码
  384. */
  385. private String parseLanguageCode(String langHeader) {
  386. if (langHeader == null || langHeader.isEmpty()) {
  387. return "zh";
  388. }
  389. // 处理类似 "en-US" 或 "zh-TW" 的情况
  390. if (langHeader.contains("-")) {
  391. String[] parts = langHeader.split("-");
  392. // 特殊处理中文繁体
  393. if ("zh".equalsIgnoreCase(parts[0]) && "TW".equalsIgnoreCase(parts[1])) {
  394. return "zh_TW";
  395. }
  396. return parts[0].toLowerCase();
  397. }
  398. return langHeader.toLowerCase();
  399. }
  400. /**
  401. * 将金币明细查询条件中的翻译字段转换为中文简体
  402. */
  403. private void convertGoldDetailTranslatedFieldsToChinese(GoldDetail goldDetail, String languageCode) {
  404. if (goldDetail != null) {
  405. // 转换市场名称
  406. if (goldDetail.getMarket() != null && !goldDetail.getMarket().isEmpty()) {
  407. String chineseMarket = translationService.findChineseSimplifiedByTranslation(
  408. goldDetail.getMarket(), languageCode);
  409. goldDetail.setMarket(chineseMarket);
  410. }
  411. // 转换商品名称
  412. if (goldDetail.getGoodsName() != null && !goldDetail.getGoodsName().isEmpty()) {
  413. String chineseGoodsName = translationService.findChineseSimplifiedByTranslation(
  414. goldDetail.getGoodsName(), languageCode);
  415. goldDetail.setGoodsName(chineseGoodsName);
  416. }
  417. }
  418. }
  419. /**
  420. * 将用户查询条件中的翻译字段转换为中文简体
  421. */
  422. private void convertUserTranslatedFieldsToChinese(User user, String languageCode) {
  423. if (user != null) {
  424. // 转换市场名称
  425. if (user.getMarket() != null && !user.getMarket().isEmpty()) {
  426. String chineseMarket = translationService.findChineseSimplifiedByTranslation(
  427. user.getMarket(), languageCode);
  428. user.setMarket(chineseMarket);
  429. }
  430. }
  431. }
  432. }