场馆订 场馆预订平台 数据库设计
表设计
用户表(user)
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`user_name` varchar(30) NOT NULL COMMENT '用户账号',`open_id` varchar(50) NOT NULL COMMENT '微信openId',`nick_name` varchar(30) NOT NULL COMMENT '用户昵称',`user_type` tinyint NULL DEFAULT 100 COMMENT '用户类型 0:系统管理员 1:机构管理员 100:普通用户',`email` varchar(50) NULL DEFAULT '' COMMENT '用户邮箱',`phone_number` varchar(50) NULL DEFAULT '' COMMENT '手机号码',`gender` tinyint NULL DEFAULT 2 COMMENT '用户性别(0男 1女 2未知)',`avatar` varchar(500) NULL DEFAULT '' COMMENT '头像地址',`avatar_type` tinyint NULL DEFAULT 0 COMMENT '头像类型(0本地头像 1远程头像)',`password` varchar(100) NULL DEFAULT '' COMMENT '密码',`status` tinyint NULL DEFAULT 0 COMMENT '帐号状态(0正常 1停用)',`login_ip` varchar(128) NULL DEFAULT '' COMMENT '最后登录IP',`login_date` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间',`point` int NULL DEFAULT NULL COMMENT '积分',`profile` VARCHAR(500) NULL DEFAULT '' COMMENT '个人简介',`organization_id` bigint COMMENT '机构id,如果是机构管理员,必须填写;用户如果归属于某个机构,也要填写',PRIMARY KEY (`id`) USING BTREE
);-- 添加唯一约束(会自动创建唯一索引)
ALTER TABLE `user` ADD CONSTRAINT `uk_user_name` UNIQUE (`user_name`);
-- 添加唯一约束(需要进一步在注册中验证,不然会插入错误)
ALTER TABLE `user` ADD CONSTRAINT `uk_phone_number` UNIQUE (`phone_number`);
ALTER TABLE `user` ADD CONSTRAINT `uk_email` UNIQUE (`email`);
注意:密码、手机号、邮箱等敏感信息需要加密存储,后面直接使用 ShardingSphere 实现加密解密即可
openid-username路由表
微信登录的时候,需要根据 openid 查询用户。因为用户表是根据用户名作为分片键分片的,如果直接使用openid几进行查询,会触发读扩散。所以路由表的引导,即先使用 openid 去查询 用户名,再拿用户名去查询对应用户
DROP TABLE IF EXISTS `user_openid`;
CREATE TABLE `user_openid` (`open_id` varchar(50) NOT NULL COMMENT 'open_id',`user_name` varchar(30) NOT NULL COMMENT '用户名',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',PRIMARY KEY (`open_id`)
) COMMENT='openid-username路由表';
organizationId-username路由表
有时候需要查询机构用户,需要路由表的引导,否则触发读扩散
DROP TABLE IF EXISTS `user_organizationId`;
CREATE TABLE `user_organizationId` (`organization_id` bigint NOT NULL COMMENT 'organization_id',`user_name` varchar(30) NOT NULL COMMENT '用户名',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',PRIMARY KEY (`organization_id`)
) COMMENT='organizationId-username路由表';
机构表(organization)
不同场馆可能属于同一机构,例如大学有不同的校区,每个校区都有运动场馆
DROP TABLE IF EXISTS `organization`;
CREATE TABLE `organization`(`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`name` varchar(30) NOT NULL COMMENT '机构名称',`mark` varchar(30) NOT NULL COMMENT '机构唯一标识',`logo` varchar(100) NOT NULL COMMENT '机构logo',PRIMARY KEY (`id`) USING BTREE
);
ALTER TABLE `organization` ADD CONSTRAINT `uk_mark` UNIQUE (`mark`);
场馆表(venue)
DROP TABLE IF EXISTS `venue`;
CREATE TABLE `venue`(`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`organization_id` bigint NOT NULL COMMENT '所属机构ID',`name` varchar(30) NOT NULL COMMENT '场馆名称',`type` int NOT NULL COMMENT '场馆类型 1:篮球馆(场) 2:足球场 3:羽毛球馆(场) 4:排球馆(场)100:体育馆 1000:其他',`address` varchar(255) NOT NULL COMMENT '场馆地址名称',`latitude` DECIMAL(9, 6) NOT NULL COMMENT '纬度',`longitude` DECIMAL(9, 6) NOT NULL COMMENT '经度',`description` varchar(255) DEFAULT '' COMMENT '场馆描述,也可以说是否提供器材等等',`open_time` varchar(2000) NOT NULL COMMENT '场馆营业时间',`phone_number` varchar(11) NULL DEFAULT '' COMMENT '联系电话',`status` tinyint NOT NULL COMMENT '场馆状态 0:关闭 1:开放 2:维护中',`is_open` tinyint NOT NULL COMMENT '是否对外开放 0:否 1:是 如果不对外开放,需要相同机构的用户才可以预定',`advance_booking_day` int NOT NULL COMMENT '提前可预定天数,例如设置为1,即今天可预订明天的场',`start_booking_time` time NOT NULL COMMENT '开放预订时间',PRIMARY KEY (`id`) USING BTREE
)
营业时间使用json存储,如一下格式
{"Monday": ["09:00-18:00"],"Tuesday": ["09:00-18:00"],"Wednesday": ["09:00-18:00"],"Thursday": ["09:00-18:00"],"Friday": ["09:00-18:00"],"Saturday": ["10:00-16:00"],"Sunday": ["10:00-16:00"],"Holidays": {"2023-10-01": ["09:00-18:00"],"2023-10-02": ["10:00-16:00"]}
}
场区表(venue_partition)
一个场馆可以有多个区,如篮球区、羽毛球区、乒乓球室等等
DROP TABLE IF EXISTS `venue_partition`;
CREATE TABLE `venue_partition`(`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`venue_id` bigint NOT NULL COMMENT '场馆ID',`name` varchar(30) NOT NULL COMMENT '分区名称名称',`type` int NOT NULL COMMENT '分区类型 1:篮球 2:足球 3:羽毛球 4:排球',`description` varchar(255) DEFAULT '' COMMENT '描述,如是否提供器材等等',`num` int NOT NULL COMMENT '场区拥有的场数量',`status` int NOT NULL COMMENT '场区状态 0:关闭 1:开放 2:维护中',PRIMARY KEY (`id`) USING BTREE
);
实地图片放到 picture 表中
图片表(picture)
统一使用同一图片表来存储 场馆图片、分区图片、评论图片,后面通过类型来区分
DROP TABLE IF EXISTS `picture`;
CREATE TABLE `picture`(`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`item_id` bigint NOT NULL COMMENT '项目ID',`picture` varchar(100) DEFAULT '' COMMENT '图片',`item_type` tinyint NOT NULL COMMENT '项目类型 0:场馆图片 1:分区图片 2:评论图片',PRIMARY KEY (`id`) USING BTREE
);
时间段模版表(time_period_model)
时间段模版是给场馆管理员进行设置的,后面用于生成特定时间段给用户购买。例如设置 7:00到8:00、8:00到9:00、…… 供用户购买
DROP TABLE IF EXISTS `time_period_model`;
CREATE TABLE `time_period_model`( `id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`price` decimal(10,2) NOT NULL COMMENT '该时间段预订使用价格(元)',`venue_id` bigint NOT NULL COMMENT '场馆ID',`partition_id` bigint NOT NULL COMMENT '场区id',`begin_time` time NOT NULL COMMENT '时间段开始时间HH:mm(不用填日期)',`end_time` time NOT NULL COMMENT '时间段结束时间HH:mm(不用填日期)', `effective_start_date` date NOT NULL COMMENT '生效开始日期', `effective_end_date` date NOT NULL COMMENT '生效结束日期', `last_generated_date` date COMMENT '已生成到的日期',`status` tinyint default 0 COMMENT '0:启用;1:停用', PRIMARY KEY (`id`) USING BTREE,INDEX `idx_venue_id_partition_id` (`venue_id`,`partition_id`)
);
时间段表(time_period)
DROP TABLE IF EXISTS `time_period`;
CREATE TABLE `time_period`( `id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`partition_id` bigint NOT NULL COMMENT '场区id',`price` decimal(10,2) NOT NULL COMMENT '该时间段预订使用价格(元)',`stock` int NOT NULL COMMENT '库存',`booked_slots` bigint unsigned NOT NULL DEFAULT 0 COMMENT '已预订的场地(位图表示)',`period_date` date NOT NULL COMMENT '预定日期', `begin_time` time NOT NULL COMMENT '时间段开始时间HH:mm(不用填日期)',`end_time` time NOT NULL COMMENT '时间段结束时间HH:mm(不用填日期)', PRIMARY KEY (`id`) USING BTREE,INDEX `idx_partition_id` (`partition_id`),UNIQUE INDEX `idx_unique_partition_period_time` (`partition_id`, `period_date`, `begin_time`, `end_time`)
);
一个 bigint 可以存储 63 个场,一个 int 可以存储 31 个场,一个 tinyint 可以存储 7 个场
后续通过位运算即可快速标记一个场是否被占用,如果对位运算不了解,可以学习https://blog.csdn.net/laodanqiu/article/details/145592470
- 预订场地:假设要预订索引为 2 的场地。
UPDATE bookings
SET BookedSlots = BookedSlots | (1 << 2)
WHERE BookingID = 1;
- 取消预订:假设要取消预订索引为 2 的场地。
UPDATE bookings
SET BookedSlots = BookedSlots & ~(1 << 2)
WHERE BookingID = 1;
- 检查场地是否已预订:假设要检查索引为 2 的场地是否已预订。
SELECT (BookedSlots & (1 << 2)) > 0 AS IsBooked
FROM bookings
WHERE BookingID = 1;
刷新库存
UPDATE time_period_0 SET booked_slots = 0, stock = 63;
UPDATE time_period_1 SET booked_slots = 0, stock = 63;
UPDATE time_period_2 SET booked_slots = 0, stock = 63;
UPDATE time_period_3 SET booked_slots = 0, stock = 63;
UPDATE time_period_4 SET booked_slots = 0, stock = 63;
UPDATE time_period_5 SET booked_slots = 0, stock = 63;
UPDATE time_period_6 SET booked_slots = 0, stock = 63;
UPDATE time_period_7 SET booked_slots = 0, stock = 63;
UPDATE time_period_8 SET booked_slots = 0, stock = 63;
UPDATE time_period_9 SET booked_slots = 0, stock = 63;
UPDATE time_period_10 SET booked_slots = 0, stock = 63;
UPDATE time_period_11 SET booked_slots = 0, stock = 63;
UPDATE time_period_12 SET booked_slots = 0, stock = 63;
UPDATE time_period_13 SET booked_slots = 0, stock = 63;
UPDATE time_period_14 SET booked_slots = 0, stock = 63;
UPDATE time_period_15 SET booked_slots = 0, stock = 63;
订单表(time_period_order)
DROP TABLE IF EXISTS `time_period_order`;
CREATE TABLE `time_period_order`( `id` bigint NOT NULL COMMENT 'ID',`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`order_sn` varchar(30) NOT NULL COMMENT '订单号',`order_time` datetime NOT NULL COMMENT '下单时间',`venue_id` bigint NOT NULL COMMENT '场馆ID',`partition_id` bigint NOT NULL COMMENT '场区id',`court_index` int NOT NULL COMMENT '第几个场',`time_period_id` bigint NOT NULL COMMENT '时间段id',`period_date` date NOT NULL COMMENT '预定日期', `begin_time` time NOT NULL COMMENT '时间段开始时间HH:mm(不用填日期)',`end_time` time NOT NULL COMMENT '时间段结束时间HH:mm(不用填日期)', `user_id` bigint NOT NULL COMMENT '下单用户id',`user_name` varchar(30) NOT NULL COMMENT '下单用户名',`pay_amount` decimal(10, 2) COMMENT '支付金额',`order_status` tinyint NOT NULL COMMENT '订单状态 0:未支付 1:已支付,待使用 2:取消 3:退款 4:已核销 5:已过期',PRIMARY KEY (`id`) USING BTREE
);ALTER TABLE `time_period_order`
ADD UNIQUE INDEX `uniq_idx_order_sn` (`order_sn`);
支付表(time_period_pay)
DROP TABLE IF EXISTS `time_period_pay`;
CREATE TABLE `time_period_pay`( `id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`order_sn` varchar(30) NOT NULL COMMENT '订单号',`payment_method` tinyint COMMENT '支付方式,0:信用卡、1:支付宝、2:微信',`subject` varchar(512) NULL COMMENT '订单标题',`transaction_id` varchar(255) COMMENT '交易编号',`pay_time` datetime COMMENT '支付时间',`pay_amount` decimal(10, 2) COMMENT '支付金额',`refund_status` tinyint COMMENT '退款状态 0: 未退款 1: 部分退款 2: 全额退款',`refund_amount` decimal(10, 2) COMMENT '退款金额',`refund_time` datetime COMMENT '退款时间',PRIMARY KEY (`id`) USING BTREE
);
ALTER TABLE `time_period_pay`
ADD UNIQUE INDEX `uniq_idx_order_sn` (`order_sn`);
评价表(review)
DROP TABLE IF EXISTS `review`;
CREATE TABLE `review` (`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`user_id` bigint NOT NULL COMMENT '评价用户的ID',`venue_id` bigint NOT NULL COMMENT '被评价的场馆ID',`order_id` bigint COMMENT '关联的订单ID(如果适用)',`rating` tinyint NOT NULL COMMENT '评分,1-5分',`comment` text COMMENT '评价内容',`images` json COMMENT '评价图片,JSON数组格式存储图片URL',`status` tinyint NOT NULL DEFAULT 0 COMMENT '评价状态,0:待审核,1:已审核,2:审核未通过',PRIMARY KEY (`id`) USING BTREE
)
操作日志
DROP TABLE IF EXISTS `mt_biz_log`;
CREATE TABLE `mt_biz_log` (`id` bigint NOT NULL COMMENT 'ID',`create_time` datetime,`update_time` datetime,`is_deleted` tinyint default 0 COMMENT '逻辑删除 0:没删除 1:已删除',`tenant` varchar(50) DEFAULT NULL COMMENT '租户',`type` varchar(50) DEFAULT NULL COMMENT '类型',`sub_type` varchar(50) DEFAULT NULL COMMENT '子类型',`class_name` varchar(100) DEFAULT NULL COMMENT '方法名称',`method_name` varchar(100) DEFAULT NULL COMMENT '方法名称',`operator` varchar(50) DEFAULT NULL COMMENT '操作人员',`action` longtext COMMENT '操作',`extra` longtext COMMENT '其他补充',`status` tinyint DEFAULT NULL COMMENT '操作状态 (0正常 1异常)',PRIMARY KEY (`id`) USING BTREE
) COMMENT='操作日志表';