diff --git a/.gitignore b/.gitignore index d51d64e..50ca57a 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ build/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store +/docs/local-zy.txt diff --git a/docs/dev-ops/docker-compose-app.yml b/docs/dev-ops/docker-compose-app.yml index 4b80fba..8c9e31f 100644 --- a/docs/dev-ops/docker-compose-app.yml +++ b/docs/dev-ops/docker-compose-app.yml @@ -38,7 +38,7 @@ services: - SERVER_PORT=8091 - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=123456 - - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/group_buying_sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/group-buying-sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver - SPRING_HIKARI_POOL_NAME=Retail_HikariCP - REDIS_SDK_CONFIG_HOST=redis diff --git a/docs/dev-ops/mysql/sql/0719group_buying_sys.sql b/docs/dev-ops/mysql/sql/0719group_buying_sys.sql index 4781fbc..4a2fa8d 100644 --- a/docs/dev-ops/mysql/sql/0719group_buying_sys.sql +++ b/docs/dev-ops/mysql/sql/0719group_buying_sys.sql @@ -13,6 +13,16 @@ Date: 19/07/2025 18:10:09 */ +-- 如果存在,则删除旧的数据库 +DROP DATABASE IF EXISTS `group-buying-sys`; + +-- 创建新的数据库(可根据需要指定字符集和排序规则) +CREATE DATABASE `group-buying-sys` + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +-- 切换到新创建的数据库 +USE `group-buying-sys`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; diff --git a/docs/dev-ops/nginx/html/css/index.css b/docs/dev-ops/nginx/html/css/index.css index f35e1f4..7ec93be 100644 --- a/docs/dev-ops/nginx/html/css/index.css +++ b/docs/dev-ops/nginx/html/css/index.css @@ -14,7 +14,7 @@ body{ /* ========== 轮播图 ========== */ .swiper-container{ - width:100%;height:375px;position:relative;overflow:hidden;margin-top: 10px; + width:100%;height:375px;position:relative;overflow:hidden; } .swiper-wrapper{display:flex;transition:transform .3s;} .swiper-slide{flex:0 0 100%;height:375px;} @@ -62,14 +62,7 @@ body{ } /* ========== 拼单列表 ========== */ -.group-buying { - background: #fff; - padding: 15px; - margin-bottom: 10px; /* 如果还想保留一点外边距 */ - min-height: 230px; /* 根据需要调整数值 */ - position: relative; - overflow: hidden; -} +.group-buying{background:#fff;padding:15px;margin-bottom:10px;position:relative;overflow:hidden;} .section-title{ font-size:16px;font-weight:bold;margin-bottom:12px;position:relative;padding-left:10px; } @@ -78,7 +71,7 @@ body{ width:3px;height:16px;background:#ff5000;border-radius:2px; } -.group-users{height:180px;position:relative;overflow:hidden;} +.group-users{height:120px;position:relative;overflow:hidden;} .user-list{position:absolute;top:0;left:0;width:100%;transition:transform .5s ease;} .user-item{ diff --git a/docs/dev-ops/nginx/html/js/index.js b/docs/dev-ops/nginx/html/js/index.js index 387a64e..3ac23e3 100644 --- a/docs/dev-ops/nginx/html/js/index.js +++ b/docs/dev-ops/nginx/html/js/index.js @@ -73,9 +73,12 @@ document.addEventListener('DOMContentLoaded', () => { /* ------------- 渲染统计信息 ------------- */ function renderStatistic(stat = {}) { - const { allTeamUserCount = 0 } = stat; - groupTitle.textContent = `${allTeamUserCount}人在抢,参与可立即拼成`; - soldBox.textContent = `${allTeamUserCount}人再抢`; + const { + allTeamUserCount = 0, + inTeamUserCount = 0 + } = stat; + groupTitle.textContent = `${inTeamUserCount}人在抢,参与可立即拼成`; + soldBox.textContent = `${allTeamUserCount}人已抢`; } /* ------------- 渲染拼团列表 ------------- */ @@ -86,7 +89,7 @@ document.addEventListener('DOMContentLoaded', () => { } userList.innerHTML = ''; list.forEach(t => userList.appendChild(makeItem(t, groupPrice))); - initUserMarquee(); + initUserMarquee(3); initCountdown(); } @@ -137,28 +140,61 @@ document.addEventListener('DOMContentLoaded', () => { /* ===================================================== * 2. 拼单列表纵向轮播 * =================================================== */ - function initUserMarquee() { - const items = userList.querySelectorAll('.user-item'); - if (items.length <= 1) return; + function initUserMarquee(visibleCount = 3, interval = 3000, duration = 500) { + const box = document.querySelector('.group-users'); + const listEl = userList; + let originals = Array.from(listEl.children); + const total = originals.length; - const itemH = items[0].offsetHeight; - userList.appendChild(items[0].cloneNode(true)); + if (total === 0) return; + // 如果原本就 <= 可见数,直接定高,不滚 + if (total <= visibleCount) { + const h0 = originals[0].offsetHeight; + box.style.height = (h0 * visibleCount) + 'px'; + return; + } - let idx = 0; - userList.addEventListener('transitionend', () => { - if (idx >= items.length) { - userList.style.transition = 'none'; - userList.style.transform = 'translateY(0)'; - idx = 0; - void userList.offsetWidth; + // 1. 复制整份加入末尾 + originals.forEach(item => listEl.appendChild(item.cloneNode(true))); + + // 2. 重新测量单条高度(此时 DOM 完整) + const itemH = listEl.children[0].offsetHeight; + + // 3. 设定窗口高度 + box.style.height = (itemH * visibleCount) + 'px'; + + // 4. 状态 + let index = 0; + let ticking = false; + + function step() { + index++; + listEl.style.transition = `transform ${duration}ms ease`; + listEl.style.transform = `translateY(-${index * itemH}px)`; + } + + listEl.addEventListener('transitionend', () => { + ticking = false; + // 5. 到达复制段的“第一帧”(index === total)就无缝重置 + if (index === total) { + listEl.style.transition = 'none'; + listEl.style.transform = 'translateY(0)'; + index = 0; + // 强制 reflow 再恢复 transition + void listEl.offsetHeight; + listEl.style.transition = `transform ${duration}ms ease`; } }); - setInterval(() => { - idx++; - userList.style.transition = 'transform .5s ease'; - userList.style.transform = `translateY(${-idx * itemH}px)`; - }, 3000); + const timer = setInterval(() => { + if (!ticking) { + ticking = true; + step(); + } + }, interval); + + // 可选:鼠标悬停暂停 + listEl.addEventListener('mouseenter', () => clearInterval(timer)); } /* ===================================================== diff --git a/group-buying-sys-api/src/main/java/edu/whut/api/dto/GoodsMarketResponseDTO.java b/group-buying-sys-api/src/main/java/edu/whut/api/dto/GoodsMarketResponseDTO.java index 2b7094f..125e6cc 100644 --- a/group-buying-sys-api/src/main/java/edu/whut/api/dto/GoodsMarketResponseDTO.java +++ b/group-buying-sys-api/src/main/java/edu/whut/api/dto/GoodsMarketResponseDTO.java @@ -110,6 +110,8 @@ public class GoodsMarketResponseDTO { private Integer allTeamCompleteCount; // 参团人数总量 - 一个商品的总参团人数 private Integer allTeamUserCount; + //在拼人数 status=0 且当前时间在拼团有效时间内 + private Integer inTeamUserCount; } } diff --git a/group-buying-sys-app/src/main/resources/application-dev.yml b/group-buying-sys-app/src/main/resources/application-dev.yml index f01bfb1..99ac3ef 100644 --- a/group-buying-sys-app/src/main/resources/application-dev.yml +++ b/group-buying-sys-app/src/main/resources/application-dev.yml @@ -18,7 +18,7 @@ spring: datasource: username: root password: 123456 - url: jdbc:mysql://127.0.0.1:13306/group_buying_sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=true + url: jdbc:mysql://127.0.0.1:13306/group-buying-sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=true driver-class-name: com.mysql.cj.jdbc.Driver hikari: pool-name: Retail_HikariCP diff --git a/group-buying-sys-app/src/main/resources/application-prod.yml b/group-buying-sys-app/src/main/resources/application-prod.yml index a02dfd2..0e0c7c0 100644 --- a/group-buying-sys-app/src/main/resources/application-prod.yml +++ b/group-buying-sys-app/src/main/resources/application-prod.yml @@ -16,7 +16,7 @@ thread: spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://mysql:3306/group_buying_sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false + url: jdbc:mysql://mysql:3306/group-buying-sys?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 123456 hikari: diff --git a/group-buying-sys-app/src/main/resources/mybatis/mapper/group_buy_order_mapper.xml b/group-buying-sys-app/src/main/resources/mybatis/mapper/group_buy_order_mapper.xml index 47eec1b..90a350d 100644 --- a/group-buying-sys-app/src/main/resources/mybatis/mapper/group_buy_order_mapper.xml +++ b/group-buying-sys-app/src/main/resources/mybatis/mapper/group_buy_order_mapper.xml @@ -113,4 +113,17 @@ WHERE activity_id = #{activityId} and status IN (0, 1) + + + + diff --git a/group-buying-sys-app/src/test/java/edu/whut/test/domain/trade/TradeSettlementOrderServiceTest.java b/group-buying-sys-app/src/test/java/edu/whut/test/domain/trade/TradeSettlementOrderServiceTest.java index fe4265a..558392b 100644 --- a/group-buying-sys-app/src/test/java/edu/whut/test/domain/trade/TradeSettlementOrderServiceTest.java +++ b/group-buying-sys-app/src/test/java/edu/whut/test/domain/trade/TradeSettlementOrderServiceTest.java @@ -35,8 +35,8 @@ public class TradeSettlementOrderServiceTest { TradePaySuccessEntity tradePaySuccessEntity = new TradePaySuccessEntity(); tradePaySuccessEntity.setSource("s01"); tradePaySuccessEntity.setChannel("c01"); - tradePaySuccessEntity.setUserId("smile02"); - tradePaySuccessEntity.setOutTradeNo("334152190173"); + tradePaySuccessEntity.setUserId("smile01"); + tradePaySuccessEntity.setOutTradeNo("018750238789"); tradePaySuccessEntity.setOutTradeTime(new Date()); //交易时间 TradePaySettlementEntity tradePaySettlementEntity = tradeSettlementOrderService.settlementMarketPayOrder(tradePaySuccessEntity); log.info("请求参数:{}", JSON.toJSONString(tradePaySuccessEntity)); diff --git a/group-buying-sys-app/src/test/java/edu/whut/test/trigger/MarketTradeControllerTest.java b/group-buying-sys-app/src/test/java/edu/whut/test/trigger/MarketTradeControllerTest.java index 22f4a92..de189ea 100644 --- a/group-buying-sys-app/src/test/java/edu/whut/test/trigger/MarketTradeControllerTest.java +++ b/group-buying-sys-app/src/test/java/edu/whut/test/trigger/MarketTradeControllerTest.java @@ -27,7 +27,8 @@ public class MarketTradeControllerTest { @Test public void test_lockMarketPayOrder_mq() throws InterruptedException { LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO(); - lockMarketPayOrderRequestDTO.setUserId("smile02"); + lockMarketPayOrderRequestDTO.setUserId("smile01" + + ""); lockMarketPayOrderRequestDTO.setTeamId(null); lockMarketPayOrderRequestDTO.setActivityId(100124L); lockMarketPayOrderRequestDTO.setGoodsId("9890001"); diff --git a/group-buying-sys-domain/src/main/java/edu/whut/domain/activity/model/valobj/TeamStatisticVO.java b/group-buying-sys-domain/src/main/java/edu/whut/domain/activity/model/valobj/TeamStatisticVO.java index b471c72..829619a 100644 --- a/group-buying-sys-domain/src/main/java/edu/whut/domain/activity/model/valobj/TeamStatisticVO.java +++ b/group-buying-sys-domain/src/main/java/edu/whut/domain/activity/model/valobj/TeamStatisticVO.java @@ -20,5 +20,7 @@ public class TeamStatisticVO { private Integer allTeamCompleteCount; // 参团人数总量 - 一个商品的总参团人数 private Integer allTeamUserCount; + //在拼人数 status=0 且当前时间在拼团有效时间内 + private Integer inTeamUserCount; } diff --git a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/ActivityRepository.java b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/ActivityRepository.java index 7ebd94e..8e8da70 100644 --- a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/ActivityRepository.java +++ b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/ActivityRepository.java @@ -219,19 +219,21 @@ public class ActivityRepository implements IActivityRepository { // 1. 根据活动ID查询所有拼团队伍id List teamIds = groupBuyOrderDao.queryActiveTeamIdsByActivityId(activityId); if(null==teamIds || teamIds.isEmpty()) - return new TeamStatisticVO(0, 0, 0); + return new TeamStatisticVO(0, 0, 0,0); Set teamIdSet = new HashSet<>(teamIds); // 2. 统计数据 Integer allTeamCount = groupBuyOrderDao.queryAllTeamCount(teamIdSet); //该活动下的总拼团数 Integer allTeamCompleteCount = groupBuyOrderDao.queryAllTeamCompleteCount(teamIdSet); //该活动下已完成的拼团数 Integer allTeamUserCount = groupBuyOrderDao.queryAllUserCount(teamIdSet); //该活动下累计参与拼团人数 + Integer inTeamUserCount = groupBuyOrderDao.queryInUserCount(teamIdSet); //该活动下在拼人数 // 3. 构建对象 return TeamStatisticVO.builder() .allTeamCount(allTeamCount) .allTeamCompleteCount(allTeamCompleteCount) .allTeamUserCount(allTeamUserCount) + .inTeamUserCount(inTeamUserCount) .build(); } diff --git a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/TradeRepository.java b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/TradeRepository.java index b609ba6..e6caaea 100644 --- a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/TradeRepository.java +++ b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/TradeRepository.java @@ -304,6 +304,7 @@ public class TradeRepository implements ITradeRepository { task.setNotifyUrl(NotifyTypeEnumVO.HTTP.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyUrl() : null); task.setNotifyCount(0); task.setNotifyStatus(0); + //setParameterJson:回调的消息,返回拼团成功的团队id和外部交易单号list,便于外部系统做后续处理,如发货 task.setParameterJson(JSON.toJSONString(new HashMap() {{ put("teamId", team.getTeamId()); put("outTradeNoList", outTradeNoList); diff --git a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/dao/IGroupBuyOrderDao.java b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/dao/IGroupBuyOrderDao.java index b1cff0e..68f84f5 100644 --- a/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/dao/IGroupBuyOrderDao.java +++ b/group-buying-sys-infrastructure/src/main/java/edu/whut/infrastructure/dao/IGroupBuyOrderDao.java @@ -51,4 +51,5 @@ public interface IGroupBuyOrderDao { List queryActiveTeamIdsByActivityId(Long activityId); + Integer queryInUserCount(@Param("teamIds") Set teamIdSet); }