7.8 本地+线上两套配置
This commit is contained in:
parent
ee61a75512
commit
43d4994d30
@ -11,57 +11,14 @@ services:
|
|||||||
container_name: group-buy-market-front
|
container_name: group-buy-market-front
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- '80:80'
|
- '86:80'
|
||||||
- '443:443'
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/html:/usr/share/nginx/html
|
- ./nginx/html:/usr/share/nginx/html
|
||||||
privileged: true
|
privileged: true
|
||||||
networks:
|
networks:
|
||||||
- my-network
|
- my-network
|
||||||
|
|
||||||
# 2. MySQL
|
# 2. Java 后端
|
||||||
mysql:
|
|
||||||
image: mysql:8.0
|
|
||||||
container_name: mysql
|
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
MYSQL_ROOT_PASSWORD: 123456
|
|
||||||
ports:
|
|
||||||
- '13306:3306'
|
|
||||||
volumes:
|
|
||||||
- ./mysql/my.cnf:/etc/mysql/conf.d/mysql.cnf:ro
|
|
||||||
- ./mysql/sql:/docker-entrypoint-initdb.d
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 10
|
|
||||||
start_period: 15s
|
|
||||||
networks:
|
|
||||||
- my-network
|
|
||||||
|
|
||||||
# 3. Redis
|
|
||||||
redis:
|
|
||||||
image: redis:6.2
|
|
||||||
container_name: redis
|
|
||||||
restart: always
|
|
||||||
hostname: redis
|
|
||||||
ports:
|
|
||||||
- '16379:6379'
|
|
||||||
volumes:
|
|
||||||
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
|
|
||||||
command: redis-server /usr/local/etc/redis/redis.conf
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD', 'redis-cli', 'ping']
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
networks:
|
|
||||||
- my-network
|
|
||||||
|
|
||||||
# 4. Java 后端
|
|
||||||
group-buying-sys:
|
group-buying-sys:
|
||||||
build:
|
build:
|
||||||
context: ../.. # 从 docs/dev-ops 回到项目根
|
context: ../.. # 从 docs/dev-ops 回到项目根
|
||||||
@ -96,39 +53,3 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- my-network
|
- my-network
|
||||||
|
|
||||||
# 5. phpMyAdmin(只有在 webui profile 下才启动)
|
|
||||||
phpmyadmin:
|
|
||||||
image: phpmyadmin:5.2.1
|
|
||||||
container_name: phpmyadmin
|
|
||||||
hostname: phpmyadmin
|
|
||||||
depends_on:
|
|
||||||
mysql:
|
|
||||||
condition: service_healthy
|
|
||||||
ports:
|
|
||||||
- '8899:80'
|
|
||||||
environment:
|
|
||||||
- PMA_HOST=mysql
|
|
||||||
- PMA_PORT=3306
|
|
||||||
- MYSQL_ROOT_PASSWORD=123456
|
|
||||||
networks:
|
|
||||||
- my-network
|
|
||||||
profiles: ["webui"]
|
|
||||||
|
|
||||||
# 6. Redis Commander(只有在 webui profile 下才启动)
|
|
||||||
redis-admin:
|
|
||||||
image: spryker/redis-commander:0.8.0
|
|
||||||
container_name: redis-admin
|
|
||||||
hostname: redis-commander
|
|
||||||
restart: always
|
|
||||||
depends_on:
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
ports:
|
|
||||||
- '8081:8081'
|
|
||||||
environment:
|
|
||||||
- REDIS_HOSTS=local:redis:6379
|
|
||||||
- HTTP_USER=admin
|
|
||||||
- HTTP_PASSWORD=admin
|
|
||||||
networks:
|
|
||||||
- my-network
|
|
||||||
profiles: ["webui"]
|
|
||||||
|
133
docs/tag/v1.0/docker-compose-app-v1.0.yml
Normal file
133
docs/tag/v1.0/docker-compose-app-v1.0.yml
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
my-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
services:
|
||||||
|
# 1. 前端
|
||||||
|
group-buy-market-front:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: group-buy-market-front
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- '86:80'
|
||||||
|
volumes:
|
||||||
|
- ./nginx/html:/usr/share/nginx/html
|
||||||
|
privileged: true
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
|
||||||
|
# 2. MySQL
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: mysql
|
||||||
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
MYSQL_ROOT_PASSWORD: 123456
|
||||||
|
ports:
|
||||||
|
- '13306:3306'
|
||||||
|
volumes:
|
||||||
|
- ./mysql/my.cnf:/etc/mysql/conf.d/mysql.cnf:ro
|
||||||
|
- ./mysql/sql:/docker-entrypoint-initdb.d
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 10
|
||||||
|
start_period: 15s
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
|
||||||
|
# 3. Redis
|
||||||
|
redis:
|
||||||
|
image: redis:6.2
|
||||||
|
container_name: redis
|
||||||
|
restart: always
|
||||||
|
hostname: redis
|
||||||
|
ports:
|
||||||
|
- '16379:6379'
|
||||||
|
volumes:
|
||||||
|
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
|
||||||
|
command: redis-server /usr/local/etc/redis/redis.conf
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'redis-cli', 'ping']
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
|
||||||
|
# 4. Java 后端
|
||||||
|
group-buying-sys:
|
||||||
|
build:
|
||||||
|
context: ../../.. # 从 docs/tag/v1.0 回到项目根
|
||||||
|
dockerfile: group-buying-sys-app/Dockerfile
|
||||||
|
image: smile/group-buying-sys:latest
|
||||||
|
container_name: group-buying-sys
|
||||||
|
restart: on-failure
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- '8091:8091'
|
||||||
|
environment:
|
||||||
|
- TZ=PRC
|
||||||
|
- SERVER_PORT=8091
|
||||||
|
- SPRING_DATASOURCE_USERNAME=root
|
||||||
|
- SPRING_DATASOURCE_PASSWORD=123456
|
||||||
|
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/big_market?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
|
||||||
|
- REDIS_SDK_CONFIG_PORT=6379
|
||||||
|
volumes:
|
||||||
|
- ./log:/data/log
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: '10m'
|
||||||
|
max-file: '3'
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
|
||||||
|
# 5. phpMyAdmin(只有在 webui profile 下才启动)
|
||||||
|
phpmyadmin:
|
||||||
|
image: phpmyadmin:5.2.1
|
||||||
|
container_name: phpmyadmin
|
||||||
|
hostname: phpmyadmin
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- '8899:80'
|
||||||
|
environment:
|
||||||
|
- PMA_HOST=mysql
|
||||||
|
- PMA_PORT=3306
|
||||||
|
- MYSQL_ROOT_PASSWORD=123456
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
profiles: ["webui"]
|
||||||
|
|
||||||
|
# 6. Redis Commander(只有在 webui profile 下才启动)
|
||||||
|
redis-admin:
|
||||||
|
image: spryker/redis-commander:0.8.0
|
||||||
|
container_name: redis-admin
|
||||||
|
hostname: redis-commander
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- '8081:8081'
|
||||||
|
environment:
|
||||||
|
- REDIS_HOSTS=local:redis:6379
|
||||||
|
- HTTP_USER=admin
|
||||||
|
- HTTP_PASSWORD=admin
|
||||||
|
networks:
|
||||||
|
- my-network
|
||||||
|
profiles: ["webui"]
|
24
docs/tag/v1.0/mysql/my.cnf
Normal file
24
docs/tag/v1.0/mysql/my.cnf
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[client]
|
||||||
|
port = 3306
|
||||||
|
default-character-set = utf8mb4
|
||||||
|
|
||||||
|
[mysqld]
|
||||||
|
user = mysql
|
||||||
|
port = 3306
|
||||||
|
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
|
||||||
|
|
||||||
|
default-storage-engine = InnoDB
|
||||||
|
default-authentication-plugin = mysql_native_password
|
||||||
|
character-set-server = utf8mb4
|
||||||
|
collation-server = utf8mb4_unicode_ci
|
||||||
|
init_connect = 'SET NAMES utf8mb4'
|
||||||
|
|
||||||
|
slow_query_log
|
||||||
|
#long_query_time = 3
|
||||||
|
slow-query-log-file = /var/log/mysql/mysql.slow.log
|
||||||
|
log-error = /var/log/mysql/mysql.error.log
|
||||||
|
|
||||||
|
default-time-zone = '+8:00'
|
||||||
|
|
||||||
|
[mysql]
|
||||||
|
default-character-set = utf8mb4
|
289
docs/tag/v1.0/mysql/sql/0707group_buying_sys.sql
Normal file
289
docs/tag/v1.0/mysql/sql/0707group_buying_sys.sql
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
Navicat Premium Data Transfer
|
||||||
|
|
||||||
|
Source Server : group_buy
|
||||||
|
Source Server Type : MySQL
|
||||||
|
Source Server Version : 80042
|
||||||
|
Source Host : localhost:13306
|
||||||
|
Source Schema : group_buying_sys
|
||||||
|
|
||||||
|
Target Server Type : MySQL
|
||||||
|
Target Server Version : 80042
|
||||||
|
File Encoding : 65001
|
||||||
|
|
||||||
|
Date: 07/07/2025 16:48:53
|
||||||
|
*/
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crowd_tags
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crowd_tags`;
|
||||||
|
CREATE TABLE `crowd_tags` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群ID',
|
||||||
|
`tag_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群名称',
|
||||||
|
`tag_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群描述',
|
||||||
|
`statistics` int NOT NULL COMMENT '人群标签统计量',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_tag_id`(`tag_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of crowd_tags
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `crowd_tags` VALUES (1, 'RQ_KJHKL98UU78H66554GFDV', '潜在消费用户', '潜在消费用户', 28, '2025-06-26 09:12:22', '2025-06-28 11:02:00');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crowd_tags_detail
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crowd_tags_detail`;
|
||||||
|
CREATE TABLE `crowd_tags_detail` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群ID',
|
||||||
|
`user_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户ID',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_tag_user`(`tag_id` ASC, `user_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签明细' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of crowd_tags_detail
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `crowd_tags_detail` VALUES (20, 'RQ_KJHKL98UU78H66554GFDV', 'zy123', '2025-06-28 10:53:23', '2025-06-28 10:53:23');
|
||||||
|
INSERT INTO `crowd_tags_detail` VALUES (21, 'RQ_KJHKL98UU78H66554GFDV', 'smile', '2025-06-28 10:53:23', '2025-06-28 10:53:23');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crowd_tags_job
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crowd_tags_job`;
|
||||||
|
CREATE TABLE `crowd_tags_job` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标签ID',
|
||||||
|
`batch_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '批次ID',
|
||||||
|
`tag_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '标签类型(参与量、消费金额)',
|
||||||
|
`tag_rule` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标签规则(限定类型 N次)',
|
||||||
|
`stat_start_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计数据,开始时间',
|
||||||
|
`stat_end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计数据,结束时间',
|
||||||
|
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态;0初始、1计划(进入执行阶段)、2重置、3完成',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_batch_id`(`batch_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签任务' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of crowd_tags_job
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `crowd_tags_job` VALUES (1, 'RQ_KJHKL98UU78H66554GFDV', '10001', 0, '100', '2025-06-26 09:13:31', '2025-06-26 09:13:31', 0, '2025-06-26 09:13:31', '2025-06-26 09:13:31');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for group_buy_activity
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `group_buy_activity`;
|
||||||
|
CREATE TABLE `group_buy_activity` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增',
|
||||||
|
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||||
|
`activity_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '活动名称',
|
||||||
|
`discount_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣ID',
|
||||||
|
`group_type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '拼团方式(0自动成团、1达成目标拼团)',
|
||||||
|
`take_limit_count` int NOT NULL DEFAULT 1 COMMENT '拼团次数限制',
|
||||||
|
`target` int NOT NULL DEFAULT 1 COMMENT '拼团目标',
|
||||||
|
`valid_time` int NOT NULL DEFAULT 15 COMMENT '拼团时长(分钟)',
|
||||||
|
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '活动状态(0创建、1生效、2过期、3废弃)',
|
||||||
|
`start_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动开始时间',
|
||||||
|
`end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动结束时间',
|
||||||
|
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签规则标识',
|
||||||
|
`tag_scope` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签规则范围(多选;1可见限制、2参与限制)',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_activity_id`(`activity_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团活动' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of group_buy_activity
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `group_buy_activity` VALUES (1, 100123, '测试活动', '25120207', 0, 1, 3, 60, 1, '2025-06-19 10:19:40', '2025-07-31 10:19:40', null, null, '2025-06-19 10:19:40', '2025-07-03 18:25:55');
|
||||||
|
INSERT INTO `group_buy_activity` VALUES (2, 100124, '测试活动2', '25120207', 0, 1, 1, 60, 1, '2025-07-05 13:39:52', '2025-09-28 13:39:34', null, null, '2025-07-05 13:39:52', '2025-07-05 13:40:06');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for group_buy_discount
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `group_buy_discount`;
|
||||||
|
CREATE TABLE `group_buy_discount` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`discount_id` int NOT NULL COMMENT '折扣ID',
|
||||||
|
`discount_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣标题',
|
||||||
|
`discount_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣描述',
|
||||||
|
`discount_type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '折扣类型(0:base、1:tag)',
|
||||||
|
`market_plan` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'ZJ' COMMENT '营销优惠计划(ZJ:直减、MJ:满减、ZK:折扣、N元购)',
|
||||||
|
`market_expr` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '营销优惠表达式',
|
||||||
|
`tag_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签,特定优惠限定',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_discount_id`(`discount_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '折扣配置' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of group_buy_discount
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `group_buy_discount` VALUES (1, 25120207, '直减优惠20元', '直减优惠20元', 0, 'ZJ', '20', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||||
|
INSERT INTO `group_buy_discount` VALUES (2, 25120208, '满减优惠100-10元', '满减优惠100-10元', 0, 'MJ', '100,10', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||||
|
INSERT INTO `group_buy_discount` VALUES (4, 25120209, '折扣优惠8折', '折扣优惠8折', 0, 'ZK', '0.8', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||||
|
INSERT INTO `group_buy_discount` VALUES (5, 25120210, 'N元购买优惠', 'N元购买优惠', 0, 'N', '1.99', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for group_buy_order
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `group_buy_order`;
|
||||||
|
CREATE TABLE `group_buy_order` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||||
|
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||||
|
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||||
|
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||||
|
`original_price` decimal(8, 2) NOT NULL COMMENT '原始价格',
|
||||||
|
`deduction_price` decimal(8, 2) NOT NULL COMMENT '折扣金额',
|
||||||
|
`pay_price` decimal(8, 2) NOT NULL COMMENT '支付价格',
|
||||||
|
`target_count` int NOT NULL COMMENT '目标数量',
|
||||||
|
`complete_count` int NOT NULL COMMENT '完成数量',
|
||||||
|
`lock_count` int NOT NULL COMMENT '锁单数量',
|
||||||
|
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态(0-拼单中、1-完成、2-失败)',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`valid_start_time` datetime NOT NULL COMMENT '拼团开始时间',
|
||||||
|
`valid_end_time` datetime NOT NULL COMMENT '拼团结束时间',
|
||||||
|
`notify_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '回调地址',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_team_id`(`team_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团订单表' ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of group_buy_order
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `group_buy_order` VALUES (8, '90158161', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:46', '2025-07-07 16:34:46', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (9, '19145860', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:46', '2025-07-07 16:34:46', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (10, '70182334', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:46', '2025-07-07 16:34:46', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (11, '60650637', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (12, '97514643', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (13, '02159215', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (14, '84484715', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (15, '47124351', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
INSERT INTO `group_buy_order` VALUES (16, '82549363', 100123, 's01', 'c01', 100.00, 20.00, 80.00, 3, 0, 1, 0, '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '2025-07-07 17:34:47', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for group_buy_order_list
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `group_buy_order_list`;
|
||||||
|
CREATE TABLE `group_buy_order_list` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户ID',
|
||||||
|
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||||
|
`order_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '订单ID',
|
||||||
|
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||||
|
`start_time` datetime NOT NULL COMMENT '活动开始时间',
|
||||||
|
`end_time` datetime NOT NULL COMMENT '活动结束时间',
|
||||||
|
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||||
|
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||||
|
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||||
|
`original_price` decimal(8, 2) NOT NULL COMMENT '原始价格',
|
||||||
|
`deduction_price` decimal(8, 2) NOT NULL COMMENT '折扣金额',
|
||||||
|
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态;0初始锁定、1消费完成',
|
||||||
|
`out_trade_no` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '外部交易单号-确保外部调用唯一幂等',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`biz_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '业务唯一ID',
|
||||||
|
`out_trade_time` datetime NULL DEFAULT NULL COMMENT '外部交易时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_order_id`(`order_id` ASC) USING BTREE,
|
||||||
|
INDEX `idx_user_id_activity_id`(`user_id` ASC, `activity_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团订单明细表' ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of group_buy_order_list
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (17, 'smile01', '90158161', '370749711302', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '915501586360', '2025-07-07 16:34:46', '2025-07-07 16:34:46', '100123_smile01_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (18, 'smile02', '19145860', '579584267705', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '281937053290', '2025-07-07 16:34:46', '2025-07-07 16:34:46', '100123_smile02_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (19, 'smile03', '70182334', '847661746282', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '379287705124', '2025-07-07 16:34:46', '2025-07-07 16:34:46', '100123_smile03_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (20, 'smile04', '60650637', '461093784717', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '255698706695', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile04_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (21, 'smile05', '97514643', '573505795059', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '815692003652', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile05_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (22, 'smile06', '02159215', '340085487395', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '141413367243', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile06_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (23, 'smile07', '84484715', '008099967739', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '000328929417', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile07_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (24, 'smile08', '47124351', '400938346390', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '669593424363', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile08_1', NULL);
|
||||||
|
INSERT INTO `group_buy_order_list` VALUES (25, 'smile09', '82549363', '964821189731', 100123, '2025-06-19 10:19:40', '2025-07-31 10:19:40', '9890001', 's01', 'c01', 100.00, 20.00, 0, '885248112084', '2025-07-07 16:34:47', '2025-07-07 16:34:47', '100123_smile09_1', NULL);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for notify_task
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `notify_task`;
|
||||||
|
CREATE TABLE `notify_task` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||||
|
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||||
|
`notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '回调接口',
|
||||||
|
`notify_count` int NOT NULL COMMENT '回调次数',
|
||||||
|
`notify_status` tinyint(1) NOT NULL COMMENT '回调状态【0初始、1完成、2重试、3失败】',
|
||||||
|
`parameter_json` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '参数对象',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_team_id`(`team_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of notify_task
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `notify_task` VALUES (1, 100123, '26432069', '暂无', 1, 1, '{\"teamId\":\"26432069\",\"outTradeNoList\":[\"052609289877\",\"621314246005\",\"192426946598\"]}', '2025-07-02 19:34:43', '2025-07-05 13:30:30');
|
||||||
|
INSERT INTO `notify_task` VALUES (2, 100124, '43505978', 'http://127.0.0.1:8091/api/v1/test/group_buy_notify', 1, 1, '{\"teamId\":\"43505978\",\"outTradeNoList\":[\"451247062978\"]}', '2025-07-05 13:46:16', '2025-07-05 13:46:16');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for sc_sku_activity
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `sc_sku_activity`;
|
||||||
|
CREATE TABLE `sc_sku_activity` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||||
|
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||||
|
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||||
|
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_sc_goodsid`(`source` ASC, `channel` ASC, `goods_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '渠道商品活动配置关联表' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of sc_sku_activity
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `sc_sku_activity` VALUES (1, 's01', 'c01', 100123, '9890001', '2025-06-26 17:15:54', '2025-06-26 17:15:54');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for sku
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `sku`;
|
||||||
|
CREATE TABLE `sku` (
|
||||||
|
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||||
|
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||||
|
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||||
|
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||||
|
`goods_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称',
|
||||||
|
`original_price` decimal(10, 2) NOT NULL COMMENT '商品价格',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `uq_goods_id`(`goods_id` ASC) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '商品信息' ROW_FORMAT = DYNAMIC;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of sku
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `sku` VALUES (1, 's01', 'c01', '9890001', '《手写MyBatis:渐进式源码实践》', 100.00, '2025-06-22 11:10:06', '2025-06-22 11:10:06');
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
170
docs/tag/v1.0/nginx/html/css/index.css
Normal file
170
docs/tag/v1.0/nginx/html/css/index.css
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/* ========== 全局 ========== */
|
||||||
|
*{
|
||||||
|
margin:0;padding:0;box-sizing:border-box;
|
||||||
|
font-family:'PingFang SC','Helvetica Neue',Arial,sans-serif;
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
background:#f5f5f5;
|
||||||
|
color:#333;
|
||||||
|
max-width:500px;
|
||||||
|
margin:0 auto;
|
||||||
|
position:relative;
|
||||||
|
padding-bottom:30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 轮播图 ========== */
|
||||||
|
.swiper-container{
|
||||||
|
width:100%;height:375px;position:relative;overflow:hidden;
|
||||||
|
}
|
||||||
|
.swiper-wrapper{display:flex;transition:transform .3s;}
|
||||||
|
.swiper-slide{flex:0 0 100%;height:375px;}
|
||||||
|
.swiper-slide img{width:100%;height:100%;object-fit:contain;background:#fff;}
|
||||||
|
|
||||||
|
.swiper-pagination{
|
||||||
|
position:absolute;bottom:10px;left:50%;
|
||||||
|
transform:translateX(-50%);display:flex;gap:6px;
|
||||||
|
}
|
||||||
|
.swiper-dot{
|
||||||
|
width:8px;height:8px;border-radius:50%;
|
||||||
|
background:rgba(255,255,255,.5);transition:all .3s;
|
||||||
|
}
|
||||||
|
.swiper-dot.active{background:#ff5000;width:16px;border-radius:4px;}
|
||||||
|
|
||||||
|
/* ========== 商品信息 ========== */
|
||||||
|
.product-info{background:#fff;padding:15px;margin-bottom:10px;}
|
||||||
|
.price-row{display:flex;align-items:center;margin-bottom:12px;}
|
||||||
|
.current-price{color:#ff5000;font-size:28px;font-weight:bold;}
|
||||||
|
.current-price::before{content:"¥";font-size:18px;}
|
||||||
|
.original-price{
|
||||||
|
color:#999;font-size:16px;text-decoration:line-through;margin-left:8px;
|
||||||
|
}
|
||||||
|
.original-price::before{content:"¥";}
|
||||||
|
.title{font-size:18px;font-weight:bold;line-height:1.4;margin-bottom:10px;}
|
||||||
|
|
||||||
|
/* 促销行 */
|
||||||
|
.promo-row{display:flex;align-items:center;gap:6px;margin-top:6px;}
|
||||||
|
.promo-tag{
|
||||||
|
flex-shrink:0;
|
||||||
|
display:inline-block;
|
||||||
|
background:linear-gradient(90deg,#ff2c2c,#ff6b22);
|
||||||
|
color:#fff;font-size:12px;padding:2px 6px;border-radius:2px;
|
||||||
|
}
|
||||||
|
.promo-box{
|
||||||
|
display:inline-block;font-size:13px;padding:2px 6px;
|
||||||
|
border-radius:4px;font-weight:600;line-height:1.2;white-space:nowrap;
|
||||||
|
}
|
||||||
|
.promo-box.drop,
|
||||||
|
.promo-box.sold{
|
||||||
|
background:linear-gradient(90deg,#ff7e00,#ff5000);
|
||||||
|
color:#fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* “xx人在抢” */
|
||||||
|
.group-left{margin-right:4px;color:#ff5000;font-weight:bold;}
|
||||||
|
|
||||||
|
/* ========== 火焰小图标行 ========== */
|
||||||
|
.promo-info{color:#ff5000;font-size:14px;margin:8px 0;display:flex;align-items:center;}
|
||||||
|
.promo-info i{margin-right:5px;}
|
||||||
|
|
||||||
|
/* ========== 拼单列表 ========== */
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
.section-title::before{
|
||||||
|
content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
|
||||||
|
width:3px;height:16px;background:#ff5000;border-radius:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-users{height:120px;position:relative;overflow:hidden;}
|
||||||
|
.user-list{position:absolute;top:0;left:0;width:100%;transition:transform .5s ease;}
|
||||||
|
.user-item{
|
||||||
|
display:flex;align-items:center;padding:8px 0;border-bottom:1px solid #f5f5f5;
|
||||||
|
}
|
||||||
|
.user-item:last-child{border-bottom:none;}
|
||||||
|
.user-avatar{
|
||||||
|
width:40px;height:40px;border-radius:50%;background:#f5f5f5;
|
||||||
|
display:flex;align-items:center;justify-content:center;margin-right:10px;
|
||||||
|
color:#999;font-size:20px;
|
||||||
|
}
|
||||||
|
.user-info{flex:1;}
|
||||||
|
.user-name{font-size:15px;font-weight:bold;margin-bottom:4px;}
|
||||||
|
.user-status{font-size:13px;color:#666;}
|
||||||
|
.left-num{color:#666;margin-right:4px;font-weight:bold;}
|
||||||
|
.countdown{
|
||||||
|
display:inline-block;background:#ff5000;color:#fff;
|
||||||
|
padding:1px 4px;border-radius:2px;margin-left:5px;
|
||||||
|
}
|
||||||
|
.buy-btn{
|
||||||
|
background:linear-gradient(90deg,#ff2c2c,#ff6b22);
|
||||||
|
color:#fff;border:none;border-radius:4px;padding:6px 15px;
|
||||||
|
font-size:14px;font-weight:bold;cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 底部操作栏 ========== */
|
||||||
|
.action-bar{
|
||||||
|
position:fixed;inset-inline:0;bottom:0;max-width:500px;margin:0 auto;
|
||||||
|
background:#fff;display:flex;height:60px;
|
||||||
|
box-shadow:0 -2px 10px rgba(0,0,0,.1);z-index:100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 左侧 3 个图标按钮 */
|
||||||
|
.action-btn{
|
||||||
|
flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
|
font-size:12px;color:#666;
|
||||||
|
}
|
||||||
|
.action-btn i{font-size:20px;margin-bottom:4px;}
|
||||||
|
|
||||||
|
/* 右侧购买区域 */
|
||||||
|
.purchase-btn{flex:2;display:flex;}
|
||||||
|
|
||||||
|
/* 公共:双行按钮布局 */
|
||||||
|
.btn-single,
|
||||||
|
.btn-group{
|
||||||
|
flex:1;
|
||||||
|
/* 纵向排布价格与文案 */
|
||||||
|
display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
|
gap:2px;
|
||||||
|
border:none;cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 各自背景色保持不变 */
|
||||||
|
.btn-single{background:#ff9500;color:#fff;}
|
||||||
|
.btn-group {background:#ff5000;color:#fff;}
|
||||||
|
|
||||||
|
/* 价格行 */
|
||||||
|
.btn-price{
|
||||||
|
font-size:18px;
|
||||||
|
font-weight:700;
|
||||||
|
line-height:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文字行 */
|
||||||
|
.btn-label{
|
||||||
|
font-size:12px;
|
||||||
|
line-height:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 支付弹窗 ========== */
|
||||||
|
.pay-mask{
|
||||||
|
position:fixed;inset:0;z-index:999;background:rgba(0,0,0,.45);
|
||||||
|
display:none;align-items:center;justify-content:center;
|
||||||
|
}
|
||||||
|
.pay-box{
|
||||||
|
width:92%;max-width:420px;background:#fff;border-radius:10px;
|
||||||
|
padding:28px 24px;text-align:center;
|
||||||
|
}
|
||||||
|
.pay-title{margin:0 0 12px;font-size:20px;font-weight:600;}
|
||||||
|
.pay-amount{margin-bottom:20px;font-size:16px;color:#666;}
|
||||||
|
.qr-code{
|
||||||
|
width:260px;max-width:100%;height:auto;display:block;margin:0 auto 32px;
|
||||||
|
border-radius:12px;object-fit:contain;
|
||||||
|
}
|
||||||
|
.pay-btns{display:flex;gap:16px;justify-content:center;}
|
||||||
|
.btn-primary,
|
||||||
|
.btn-secondary{
|
||||||
|
flex:1;padding:12px 0;border:none;border-radius:10px;
|
||||||
|
font-size:16px;font-weight:600;cursor:pointer;
|
||||||
|
}
|
||||||
|
.btn-primary{background:#12a400;color:#fff;}
|
||||||
|
.btn-secondary{background:#f0f0f0;}
|
91
docs/tag/v1.0/nginx/html/css/login.css
Normal file
91
docs/tag/v1.0/nginx/html/css/login.css
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* 整体布局 */
|
||||||
|
*{margin:0;padding:0;box-sizing:border-box;font-family:'PingFang SC','Helvetica Neue',Arial,sans-serif;}
|
||||||
|
|
||||||
|
body{
|
||||||
|
height:100vh;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
background:#d5d1e8; /* 柔和紫色背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.container{
|
||||||
|
width:90%;max-width:420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form{
|
||||||
|
background:#fff;
|
||||||
|
padding:36px 28px;
|
||||||
|
border-radius:14px;
|
||||||
|
box-shadow:0 4px 12px rgba(0,0,0,.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form h2{
|
||||||
|
font-size:24px;
|
||||||
|
font-weight:600;
|
||||||
|
text-align:center;
|
||||||
|
margin-bottom:32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框组 */
|
||||||
|
.input-group{
|
||||||
|
position:relative;
|
||||||
|
margin-bottom:26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group input{
|
||||||
|
width:100%;
|
||||||
|
padding:14px 16px;
|
||||||
|
font-size:16px;
|
||||||
|
border:2px solid #aaa3;
|
||||||
|
border-radius:10px;
|
||||||
|
outline:none;
|
||||||
|
transition:border .25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group input:focus{
|
||||||
|
border-color:#1296ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group label{
|
||||||
|
position:absolute;
|
||||||
|
left:18px;
|
||||||
|
top:50%;
|
||||||
|
transform:translateY(-50%);
|
||||||
|
color:#999;
|
||||||
|
pointer-events:none;
|
||||||
|
transition:all .25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 上浮效果 */
|
||||||
|
.input-group input:focus + label,
|
||||||
|
.input-group input:not(:placeholder-shown) + label{
|
||||||
|
top:0;
|
||||||
|
transform:translateY(-50%) scale(.86);
|
||||||
|
background:#fff;
|
||||||
|
padding:0 4px;
|
||||||
|
color:#1296ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 登录按钮 */
|
||||||
|
button[type="submit"]{
|
||||||
|
width:100%;
|
||||||
|
padding:14px 0;
|
||||||
|
font-size:18px;
|
||||||
|
font-weight:600;
|
||||||
|
color:#fff;
|
||||||
|
background:#1296ff;
|
||||||
|
border:none;
|
||||||
|
border-radius:10px;
|
||||||
|
cursor:pointer;
|
||||||
|
transition:opacity .25s;
|
||||||
|
}
|
||||||
|
button[type="submit"]:hover{opacity:.9;}
|
||||||
|
|
||||||
|
.error-message{
|
||||||
|
margin-top:18px;
|
||||||
|
font-size:14px;
|
||||||
|
color:#e02424;
|
||||||
|
text-align:center;
|
||||||
|
display:none;
|
||||||
|
}
|
BIN
docs/tag/v1.0/nginx/html/images/goods_info1.png
Normal file
BIN
docs/tag/v1.0/nginx/html/images/goods_info1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 347 KiB |
BIN
docs/tag/v1.0/nginx/html/images/goods_info2.png
Normal file
BIN
docs/tag/v1.0/nginx/html/images/goods_info2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 281 KiB |
BIN
docs/tag/v1.0/nginx/html/images/goods_info3.png
Normal file
BIN
docs/tag/v1.0/nginx/html/images/goods_info3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
docs/tag/v1.0/nginx/html/images/qrcode.png
Normal file
BIN
docs/tag/v1.0/nginx/html/images/qrcode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 455 KiB |
91
docs/tag/v1.0/nginx/html/index.html
Normal file
91
docs/tag/v1.0/nginx/html/index.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>手写 MyBatis:渐进式源码实践 - 拼多多</title>
|
||||||
|
|
||||||
|
<!-- 现成样式 -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
|
||||||
|
<link rel="stylesheet" href="css/index.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- 顶部轮播图 -->
|
||||||
|
<div class="swiper-container">
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
<div class="swiper-slide"><img src="images/goods_info2.png" /></div>
|
||||||
|
<div class="swiper-slide"><img src="images/goods_info3.png" /></div>
|
||||||
|
<div class="swiper-slide"><img src="images/goods_info1.png" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="swiper-pagination"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 商品信息 -->
|
||||||
|
<div class="product-info">
|
||||||
|
<div class="price-row">
|
||||||
|
<div class="current-price" id="currentPrice"></div>
|
||||||
|
<div class="original-price" id="originalPrice"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标题写死即可,如需从接口取也可在 JS 中替换 -->
|
||||||
|
<div class="title" id="goodsTitle">手写 MyBatis:渐进式源码实践(全彩)</div>
|
||||||
|
|
||||||
|
<div class="promo-row">
|
||||||
|
<span class="promo-tag">大促优惠</span>
|
||||||
|
<span class="promo-box drop" id="dropPrice"></span>
|
||||||
|
<span class="promo-box sold" id="soldBox"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 拼单区域 -->
|
||||||
|
<div class="group-buying">
|
||||||
|
<div class="section-title" id="groupTitle"></div>
|
||||||
|
|
||||||
|
<div class="group-users">
|
||||||
|
<!-- 列表由 JS 动态注入 -->
|
||||||
|
<div class="user-list" id="userList"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部操作栏 -->
|
||||||
|
<div class="action-bar">
|
||||||
|
<div class="action-btn">
|
||||||
|
<i class="fas fa-home"></i><span>首页</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn">
|
||||||
|
<i class="fas fa-heart"></i><span>收藏</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn">
|
||||||
|
<i class="fas fa-shopping-cart"></i><span>购物车</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="purchase-btn">
|
||||||
|
<button class="btn-single" id="btnSingle" data-price="">
|
||||||
|
<span class="btn-price" id="singlePrice"></span>
|
||||||
|
<span class="btn-label">单独购买</span>
|
||||||
|
</button>
|
||||||
|
<button class="btn-group" id="btnGroup" data-price="">
|
||||||
|
<span class="btn-price" id="groupPrice"></span>
|
||||||
|
<span class="btn-label">开团购买</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 支付弹窗 -->
|
||||||
|
<div id="paymentModal" class="pay-mask">
|
||||||
|
<div class="pay-box">
|
||||||
|
<h2 class="pay-title">请扫码支付</h2>
|
||||||
|
<p class="pay-amount" id="paymentAmount"></p>
|
||||||
|
<img src="images/qrcode.png" alt="支付二维码" class="qr-code" />
|
||||||
|
<div class="pay-btns">
|
||||||
|
<button id="cancelPayment" class="btn-secondary">取消支付</button>
|
||||||
|
<button id="completePayment" class="btn-primary">支付完成</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 逻辑脚本 -->
|
||||||
|
<script src="js/index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
253
docs/tag/v1.0/nginx/html/js/index.js
Normal file
253
docs/tag/v1.0/nginx/html/js/index.js
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/* -------------------------------------------------------
|
||||||
|
* Author : 你
|
||||||
|
* Desc : 改进版拼团页面脚本(userId 从 cookie 里读)
|
||||||
|
* ----------------------------------------------------- */
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
|
/* ========== 通用工具 ========== */
|
||||||
|
const getCookie = (k) =>
|
||||||
|
document.cookie
|
||||||
|
.split(';')
|
||||||
|
.map((c) => c.trim())
|
||||||
|
.find((c) => c.startsWith(k + '='))?.split('=')[1] || null;
|
||||||
|
|
||||||
|
/* ----------- 0. DOM 快捷引用 ----------- */
|
||||||
|
const $ = (id) => document.getElementById(id);
|
||||||
|
const currentPrice = $('currentPrice');
|
||||||
|
const originalPriceElem = $('originalPrice');
|
||||||
|
const dropPrice = $('dropPrice');
|
||||||
|
const soldBox = $('soldBox');
|
||||||
|
const groupTitle = $('groupTitle');
|
||||||
|
const userList = $('userList');
|
||||||
|
const singlePriceSpan = $('singlePrice');
|
||||||
|
const groupPriceSpan = $('groupPrice');
|
||||||
|
const btnSingle = $('btnSingle');
|
||||||
|
const btnGroup = $('btnGroup');
|
||||||
|
|
||||||
|
/* =====================================================
|
||||||
|
* 1. 取接口数据并渲染
|
||||||
|
* =================================================== */
|
||||||
|
const API_URL = 'http://124.71.159.195:8091/api/v1/gbm/index/query_group_buy_market_config';
|
||||||
|
|
||||||
|
// 读取 cookie 中的 username 当作 userId
|
||||||
|
const username = getCookie('username');
|
||||||
|
|
||||||
|
// 如果没登录,直接跳去登录页,免得后面接口 401/判空
|
||||||
|
if (!username) {
|
||||||
|
location.href = 'login.html';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const POST_BODY = {
|
||||||
|
userId : username, // 不再写死
|
||||||
|
source : 's01',
|
||||||
|
channel: 'c01',
|
||||||
|
goodsId: '9890001'
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch(API_URL, {
|
||||||
|
method : 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body : JSON.stringify(POST_BODY),
|
||||||
|
})
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then(({ code, info, data }) => {
|
||||||
|
if (code !== '0000' || !data) {
|
||||||
|
console.error('接口异常:', info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
renderGoods(data.goods);
|
||||||
|
renderStatistic(data.teamStatistic);
|
||||||
|
renderTeams(data.teamList, data.goods?.payPrice);
|
||||||
|
})
|
||||||
|
.catch((e) => console.error('接口请求失败:', e));
|
||||||
|
|
||||||
|
/* ------------- 渲染商品信息 ------------- */
|
||||||
|
function renderGoods(g = {}) {
|
||||||
|
const { originalPrice = 0, payPrice = 0, deductionPrice = 0 } = g;
|
||||||
|
currentPrice.textContent = payPrice;
|
||||||
|
originalPriceElem.textContent = originalPrice;
|
||||||
|
dropPrice.textContent = `直降 ¥${deductionPrice}`;
|
||||||
|
|
||||||
|
singlePriceSpan.textContent = `¥${originalPrice}`;
|
||||||
|
groupPriceSpan.textContent = `¥${payPrice}`;
|
||||||
|
btnSingle.dataset.price = originalPrice;
|
||||||
|
btnGroup.dataset.price = payPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------- 渲染统计信息 ------------- */
|
||||||
|
function renderStatistic(stat = {}) {
|
||||||
|
const { allTeamUserCount = 0 } = stat;
|
||||||
|
groupTitle.textContent = `${allTeamUserCount}人在抢,参与可立即拼成`;
|
||||||
|
soldBox.textContent = `${allTeamUserCount}人再抢`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------- 渲染拼团列表 ------------- */
|
||||||
|
function renderTeams(list = [], groupPrice = 0) {
|
||||||
|
if (!list || list.length === 0) {
|
||||||
|
groupTitle.textContent = '小伙伴,赶紧去开团吧,做村里最靓的仔。';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
userList.innerHTML = '';
|
||||||
|
list.forEach((t) => userList.appendChild(makeItem(t, groupPrice)));
|
||||||
|
initUserMarquee();
|
||||||
|
initCountdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeItem(team, price) {
|
||||||
|
const { userId, targetCount, lockCount, validTimeCountdown } = team;
|
||||||
|
const leftNum = Math.max(targetCount - lockCount, 0);
|
||||||
|
const timeText = validTimeCountdown || '00:00:00';
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.className = 'user-item';
|
||||||
|
div.innerHTML = `
|
||||||
|
<div class="user-avatar"><i class="fas fa-user"></i></div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-name">${userId}</div>
|
||||||
|
<div class="user-status">
|
||||||
|
仅剩${leftNum}人成团
|
||||||
|
<span class="countdown">${timeText}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="buy-btn" data-price="${price}">参与拼团</button>
|
||||||
|
`;
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================
|
||||||
|
* 2. 拼单列表纵向轮播
|
||||||
|
* =================================================== */
|
||||||
|
function initUserMarquee() {
|
||||||
|
const items = userList.querySelectorAll('.user-item');
|
||||||
|
if (items.length <= 1) return;
|
||||||
|
|
||||||
|
const itemH = items[0].offsetHeight;
|
||||||
|
userList.appendChild(items[0].cloneNode(true)); // 无缝衔接
|
||||||
|
|
||||||
|
let idx = 0;
|
||||||
|
userList.addEventListener('transitionend', () => {
|
||||||
|
if (idx >= items.length) {
|
||||||
|
userList.style.transition = 'none';
|
||||||
|
userList.style.transform = 'translateY(0)';
|
||||||
|
idx = 0;
|
||||||
|
void userList.offsetWidth;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
idx++;
|
||||||
|
userList.style.transition = 'transform .5s ease';
|
||||||
|
userList.style.transform = `translateY(${-idx * itemH}px)`;
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================
|
||||||
|
* 3. 倒计时
|
||||||
|
* =================================================== */
|
||||||
|
let countdownData = [];
|
||||||
|
|
||||||
|
function initCountdown() {
|
||||||
|
const els = document.querySelectorAll('.countdown');
|
||||||
|
countdownData = Array.from(els).map((el) => ({
|
||||||
|
el,
|
||||||
|
remain: toSec(el.textContent.trim()),
|
||||||
|
}));
|
||||||
|
setInterval(tick, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toSec = (t) => {
|
||||||
|
if (!t.includes(':')) return 0;
|
||||||
|
const [h = '00', m = '00', s = '00'] = t.split(':');
|
||||||
|
return +h * 3600 + +m * 60 + +s;
|
||||||
|
};
|
||||||
|
const fmt = (n) => String(n).padStart(2, '0');
|
||||||
|
const format = (s) => `${fmt(s / 3600 | 0)}:${fmt((s % 3600) / 60 | 0)}:${fmt(s % 60)}`;
|
||||||
|
|
||||||
|
function tick() {
|
||||||
|
countdownData.forEach((c) => {
|
||||||
|
if (c.remain > 0) {
|
||||||
|
c.remain--;
|
||||||
|
c.el.textContent = format(c.remain);
|
||||||
|
if (c.remain === 0) expire(c.el);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function expire(el) {
|
||||||
|
el.textContent = '00:00:00';
|
||||||
|
const item = el.closest('.user-item');
|
||||||
|
item?.classList.add('expired');
|
||||||
|
item?.querySelector('.buy-btn')?.setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================
|
||||||
|
* 4. 支付弹窗(事件委托)
|
||||||
|
* =================================================== */
|
||||||
|
const modal = $('paymentModal');
|
||||||
|
const amountText = $('paymentAmount');
|
||||||
|
const cancelPayment = $('cancelPayment');
|
||||||
|
const completePayment= $('completePayment');
|
||||||
|
|
||||||
|
document.body.addEventListener('click', (e) => {
|
||||||
|
const btn = e.target.closest('.buy-btn, .btn-single, .btn-group');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
// 再次确认 cookie,防止手动删 cookie
|
||||||
|
if (!getCookie('username')) {
|
||||||
|
location.href = 'login.html';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
amountText.textContent = `支付金额 ¥${btn.dataset.price || 0}`;
|
||||||
|
modal.style.display = 'flex';
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelPayment.onclick = () => modal.style.display = 'none';
|
||||||
|
completePayment.onclick= () => { alert('支付成功!'); modal.style.display = 'none'; };
|
||||||
|
modal.addEventListener('click', (e) => { if (e.target === modal) modal.style.display = 'none'; });
|
||||||
|
|
||||||
|
/* =====================================================
|
||||||
|
* 5. 顶部横向轮播(原逻辑保留)
|
||||||
|
* =================================================== */
|
||||||
|
const wrapper = document.querySelector('.swiper-wrapper');
|
||||||
|
const slides = [...wrapper.children];
|
||||||
|
const pagination = document.querySelector('.swiper-pagination');
|
||||||
|
const count = slides.length;
|
||||||
|
|
||||||
|
let current = 0, startX = 0, dragging = false, timer;
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.className = 'swiper-dot' + (i === 0 ? ' active' : '');
|
||||||
|
dot.onclick = () => goTo(i);
|
||||||
|
pagination.appendChild(dot);
|
||||||
|
}
|
||||||
|
const dots = pagination.children;
|
||||||
|
|
||||||
|
const goTo = (i) => {
|
||||||
|
current = (i + count) % count;
|
||||||
|
wrapper.style.transition = 'transform .3s ease';
|
||||||
|
wrapper.style.transform = `translateX(-${current * 100}%)`;
|
||||||
|
[...dots].forEach((d, j) => d.classList.toggle('active', j === current));
|
||||||
|
};
|
||||||
|
const auto = () => { timer = setInterval(() => goTo(current + 1), 3000); };
|
||||||
|
const stop = () => clearInterval(timer);
|
||||||
|
auto();
|
||||||
|
|
||||||
|
const getX = (e) => (e.touches ? e.touches[0].clientX : e.clientX);
|
||||||
|
wrapper.addEventListener('pointerdown', (e) => { stop(); dragging = true; startX = getX(e); wrapper.style.transition = 'none'; });
|
||||||
|
wrapper.addEventListener('pointermove', (e) => { if (!dragging) return; const diff = getX(e) - startX; wrapper.style.transform = `translateX(calc(${-current * 100}% + ${diff}px))`; });
|
||||||
|
wrapper.addEventListener('pointerup', endSwipe);
|
||||||
|
wrapper.addEventListener('pointercancel',endSwipe);
|
||||||
|
wrapper.addEventListener('pointerleave', endSwipe);
|
||||||
|
|
||||||
|
function endSwipe(e) {
|
||||||
|
if (!dragging) return;
|
||||||
|
dragging = false;
|
||||||
|
const diff = getX(e) - startX;
|
||||||
|
const limit = wrapper.offsetWidth * 0.15;
|
||||||
|
if (diff > limit) goTo(current - 1);
|
||||||
|
else if (diff < -limit) goTo(current + 1);
|
||||||
|
else goTo(current);
|
||||||
|
auto();
|
||||||
|
}
|
||||||
|
});
|
28
docs/tag/v1.0/nginx/html/js/login.js
Normal file
28
docs/tag/v1.0/nginx/html/js/login.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const loginForm = document.getElementById('loginForm');
|
||||||
|
const errorMessage = document.getElementById('errorMessage');
|
||||||
|
|
||||||
|
loginForm.addEventListener('submit',e=>{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const username = document.getElementById('username').value.trim();
|
||||||
|
const password = document.getElementById('password').value.trim();
|
||||||
|
|
||||||
|
if(!username || !password){
|
||||||
|
errorMessage.textContent = '用户名和密码不能为空';
|
||||||
|
errorMessage.style.display = 'block';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 这里可替换为真实校验逻辑 —— 目前直接视为成功 */
|
||||||
|
errorMessage.style.display = 'none';
|
||||||
|
|
||||||
|
/* 写入 cookie,1 天有效 */
|
||||||
|
const expire = new Date();
|
||||||
|
expire.setDate(expire.getDate() + 1);
|
||||||
|
document.cookie = `username=${encodeURIComponent(username)}; expires=${expire.toUTCString()}; path=/`;
|
||||||
|
|
||||||
|
/* 登录后跳回首页(商品详情页) */
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
});
|
||||||
|
});
|
31
docs/tag/v1.0/nginx/html/login.html
Normal file
31
docs/tag/v1.0/nginx/html/login.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
|
||||||
|
<title>欢迎登录 - 宇哥拼团</title>
|
||||||
|
<link rel="stylesheet" href="css/login.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<form id="loginForm" class="login-form">
|
||||||
|
<h2>欢迎登录 - 宇哥拼团</h2>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" id="username" required/>
|
||||||
|
<label for="username">用户名</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="password" id="password" required/>
|
||||||
|
<label for="password">密码</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">登录</button>
|
||||||
|
<p class="error-message" id="errorMessage"></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="js/login.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,5 +1,3 @@
|
|||||||
spring:
|
spring:
|
||||||
config:
|
|
||||||
name: group-buying-sys-app
|
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: prod
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
|
select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
|
||||||
notify_url
|
notify_url
|
||||||
from group_buy_order
|
from group_buy_order
|
||||||
where status = 0 and target_count > lock_count and team_id in
|
where status = 0 and target_count > lock_count and valid_end_time > now() and team_id in
|
||||||
<foreach item="teamId" collection="teamIds" open="(" separator="," close=")">
|
<foreach item="teamId" collection="teamIds" open="(" separator="," close=")">
|
||||||
#{teamId}
|
#{teamId}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user