From 35c503eb6cb486f82af2f2110fe7a0dcc90d4676 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:26:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20mysql=20=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 14 ++-- .../resources/db/init/00_init_db_and_user.sql | 17 ++++ .../src/main/resources/db/init/01_schema.sql | 57 +++++++++++++ .../main/resources/db/init/02_seed_data.sql | 36 +++++++++ .../main/resources/db/init/init_script.sql | 81 ------------------- docker/docker-compose.yaml | 29 +++++-- 6 files changed, 140 insertions(+), 94 deletions(-) create mode 100644 backend/src/main/resources/db/init/00_init_db_and_user.sql create mode 100644 backend/src/main/resources/db/init/01_schema.sql create mode 100644 backend/src/main/resources/db/init/02_seed_data.sql delete mode 100644 backend/src/main/resources/db/init/init_script.sql diff --git a/.env.example b/.env.example index 09c6104c2..d3466c33d 100644 --- a/.env.example +++ b/.env.example @@ -19,9 +19,9 @@ OPENSEARCH_HOST=opensearch # === Database Configuration === MYSQL_DATABASE=openisle -MYSQL_ROOT_PASSWORD= -MYSQL_USER= -MYSQL_PASSWORD= +MYSQL_ROOT_PASSWORD=openisle +MYSQL_USER=openisle +MYSQL_PASSWORD=openisle MYSQL_HOST=mysql # === Redis Configuration === @@ -81,12 +81,12 @@ LOG_LEVEL=INFO # === Frontend (Nuxt) === -# NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 -NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com +NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 +# NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com # NUXT_PUBLIC_API_BASE_URL=https://www.staging.open-isle.com -# NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 -NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com +NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 +# NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com # NUXT_PUBLIC_WEBSOCKET_URL=https://www.staging.open-isle.com NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 diff --git a/backend/src/main/resources/db/init/00_init_db_and_user.sql b/backend/src/main/resources/db/init/00_init_db_and_user.sql new file mode 100644 index 000000000..bbdceed25 --- /dev/null +++ b/backend/src/main/resources/db/init/00_init_db_and_user.sql @@ -0,0 +1,17 @@ +-- 统一字符集 +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; +SET collation_connection = utf8mb4_0900_ai_ci; + +-- 创建数据库(如果不存在) +CREATE DATABASE IF NOT EXISTS `openisle` + CHARACTER SET utf8mb4 + COLLATE utf8mb4_0900_ai_ci; + +-- 创建业务账号(容器会基于环境变量自动创建;此处再兜底 + 幂等) +CREATE USER IF NOT EXISTS 'openisle'@'%' IDENTIFIED BY 'openisle'; +GRANT ALL PRIVILEGES ON `openisle`.* TO 'openisle'@'%'; +FLUSH PRIVILEGES; + +-- 切换到目标库 +USE `openisle`; diff --git a/backend/src/main/resources/db/init/01_schema.sql b/backend/src/main/resources/db/init/01_schema.sql new file mode 100644 index 000000000..0844e5799 --- /dev/null +++ b/backend/src/main/resources/db/init/01_schema.sql @@ -0,0 +1,57 @@ +USE `openisle`; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- users 表 +CREATE TABLE IF NOT EXISTS `users` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `approved` bit(1) DEFAULT NULL, + `avatar` varchar(255) DEFAULT NULL, + `created_at` datetime(6) DEFAULT NULL, + `display_medal` varchar(255) DEFAULT NULL, + `email` varchar(255) NOT NULL, + `experience` int DEFAULT NULL, + `introduction` text, + `password` varchar(255) NOT NULL, + `password_reset_code` varchar(255) DEFAULT NULL, + `point` int DEFAULT NULL, + `register_reason` text, + `role` varchar(20) DEFAULT 'USER', + `username` varchar(50) NOT NULL, + `verification_code` varchar(255) DEFAULT NULL, + `verified` bit(1) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_users_email` (`email`), + UNIQUE KEY `UK_users_username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- categories 表 +CREATE TABLE IF NOT EXISTS `categories` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `description` text, + `icon` varchar(255) DEFAULT NULL, + `name` varchar(50) NOT NULL, + `small_icon` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_categories_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- tags 表(依赖 users.id 外键) +CREATE TABLE IF NOT EXISTS `tags` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `approved` bit(1) DEFAULT NULL, + `created_at` datetime(6) DEFAULT NULL, + `description` text, + `icon` varchar(255) DEFAULT NULL, + `name` varchar(50) NOT NULL, + `small_icon` varchar(255) DEFAULT NULL, + `creator_id` bigint DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_tags_name` (`name`), + KEY `FK_tags_creator` (`creator_id`), + CONSTRAINT `FK_tags_creator` FOREIGN KEY (`creator_id`) REFERENCES `users` (`id`) + ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/backend/src/main/resources/db/init/02_seed_data.sql b/backend/src/main/resources/db/init/02_seed_data.sql new file mode 100644 index 000000000..d217be9a7 --- /dev/null +++ b/backend/src/main/resources/db/init/02_seed_data.sql @@ -0,0 +1,36 @@ +USE `openisle`; +SET FOREIGN_KEY_CHECKS = 0; + +-- 清空并灌入演示数据(幂等处理:先删再插) +DELETE FROM `tags`; +DELETE FROM `categories`; +DELETE FROM `users`; + +-- users(密码已是 bcrypt;账号:admin/user1/user2,明文 123321) +INSERT INTO `users` +(`id`,`approved`,`avatar`,`created_at`,`display_medal`,`email`,`experience`,`introduction`, + `password`,`password_reset_code`,`point`,`register_reason`,`role`,`username`,`verification_code`,`verified`) +VALUES +(1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'), +(2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'), +(3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1'); + +-- categories +INSERT INTO `categories` (`id`,`description`,`icon`,`name`,`small_icon`) VALUES +(1,'测试用分类1','1','测试用分类1',NULL), +(2,'测试用分类2','2','测试用分类2',NULL), +(3,'测试用分类3','3','测试用分类3',NULL); + +-- tags(此处不绑定 creator_id,避免外键顺序依赖;如需可填 1/2/3) +INSERT INTO `tags` (`id`,`approved`,`created_at`,`description`,`icon`,`name`,`small_icon`,`creator_id`) VALUES +(1,b'1','2025-09-02 10:51:56.000000','测试用标签1',NULL,'测试用标签1',NULL,NULL), +(2,b'1','2025-09-02 10:51:56.000000','测试用标签2',NULL,'测试用标签2',NULL,NULL), +(3,b'1','2025-09-02 10:51:56.000000','测试用标签3',NULL,'测试用标签3',NULL,NULL); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/backend/src/main/resources/db/init/init_script.sql b/backend/src/main/resources/db/init/init_script.sql deleted file mode 100644 index 3ea4bd2c1..000000000 --- a/backend/src/main/resources/db/init/init_script.sql +++ /dev/null @@ -1,81 +0,0 @@ --- 2025-09-02 --- 本地化开发,初始化脚本 --- 抽奖的时候奖品图片是必须的,把相关代码注释掉即可跳过check - --- 设置字符集和排序规则 -SET NAMES utf8; -SET CHARACTER SET utf8; -SET collation_connection = utf8_general_ci; - --- 创建 users 表(如果不存在) -CREATE TABLE IF NOT EXISTS `users` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `approved` bit(1) DEFAULT NULL, - `avatar` varchar(255) DEFAULT NULL, - `created_at` datetime(6) DEFAULT NULL, - `display_medal` varchar(255) DEFAULT NULL, - `email` varchar(255) NOT NULL, - `experience` int DEFAULT NULL, - `introduction` text, - `password` varchar(255) NOT NULL, - `password_reset_code` varchar(255) DEFAULT NULL, - `point` int DEFAULT NULL, - `register_reason` text, - `role` varchar(20) DEFAULT 'USER', - `username` varchar(50) NOT NULL, - `verification_code` varchar(255) DEFAULT NULL, - `verified` bit(1) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_users_email` (`email`), - UNIQUE KEY `UK_users_username` (`username`) -); - --- 清空users表 -DELETE FROM `users`; --- 插入用户,两个普通用户,一个管理员 --- username:admin/user1/user2 password:123321 -INSERT INTO `users` (`id`, `approved`, `avatar`, `created_at`, `display_medal`, `email`, `experience`, `introduction`, `password`, `password_reset_code`, `point`, `register_reason`, `role`, `username`, `verification_code`, `verified`) VALUES - (1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'), - (2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'), - (3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1'); - --- 创建 tags 表(如果不存在) -CREATE TABLE IF NOT EXISTS `tags` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `approved` bit(1) DEFAULT NULL, - `created_at` datetime(6) DEFAULT NULL, - `description` text, - `icon` varchar(255) DEFAULT NULL, - `name` varchar(50) NOT NULL, - `small_icon` varchar(255) DEFAULT NULL, - `creator_id` bigint DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_tags_name` (`name`), - KEY `FK_tags_creator` (`creator_id`), - CONSTRAINT `FK_tags_creator` FOREIGN KEY (`creator_id`) REFERENCES `users` (`id`) -); --- 清空tags表 -DELETE FROM `tags`; --- 插入标签,三个测试用标签 -INSERT INTO `tags` (`id`, `approved`, `created_at`, `description`, `icon`, `name`, `small_icon`, `creator_id`) VALUES - (1, b'1', '2025-09-02 10:51:56.000000', '测试用标签1', NULL, '测试用标签1', NULL, NULL), - (2, b'1', '2025-09-02 10:51:56.000000', '测试用标签2', NULL, '测试用标签2', NULL, NULL), - (3, b'1', '2025-09-02 10:51:56.000000', '测试用标签3', NULL, '测试用标签3', NULL, NULL); - --- 创建 categories 表(如果不存在) -CREATE TABLE IF NOT EXISTS `categories` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `description` text, - `icon` varchar(255) DEFAULT NULL, - `name` varchar(50) NOT NULL, - `small_icon` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_categories_name` (`name`) -); --- 清空categories表 -DELETE FROM `categories`; --- 插入分类,三个测试用分类 -INSERT INTO `categories` (`id`, `description`, `icon`, `name`, `small_icon`) VALUES - (1, '测试用分类1', '1', '测试用分类1', NULL), - (2, '测试用分类2', '2', '测试用分类2', NULL), - (3, '测试用分类3', '3', '测试用分类3', NULL); \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 4e02f0904..0746dcbe6 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -11,6 +11,10 @@ services: volumes: - mysql-data:/var/lib/mysql - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d + command: > + --character-set-server=utf8mb4 + --collation-server=utf8mb4_0900_ai_ci + --default-time-zone=+80:00 networks: - openisle-network healthcheck: @@ -236,37 +240,50 @@ services: image: alpine/socat container_name: loopback-8080 # 监听“frontend_dev 容器自身的” 127.0.0.1:8080 → 转发到 springboot:8080 - command: ["-d","-d","-ly","TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork","TCP4:springboot:8080"] + command: + [ + "-d", + "-d", + "-ly", + "TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork", + "TCP4:springboot:8080", + ] depends_on: springboot: condition: service_started network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: - test: ["CMD","sh","-c","nc -z 127.0.0.1 8080"] + test: ["CMD", "sh", "-c", "nc -z 127.0.0.1 8080"] interval: 5s timeout: 3s retries: 20 start_period: 10s - + loopback_8082: image: alpine/socat container_name: loopback-8082 # 监听 127.0.0.1:8082 → 转发到 websocket-service:8082(WS 纯 TCP 可直接过) - command: ["-d","-d","-ly","TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork","TCP4:websocket-service:8082"] + command: + [ + "-d", + "-d", + "-ly", + "TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork", + "TCP4:websocket-service:8082", + ] depends_on: websocket-service: condition: service_started network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: - test: ["CMD","sh","-c","nc -z 127.0.0.1 8082"] + test: ["CMD", "sh", "-c", "nc -z 127.0.0.1 8082"] interval: 5s timeout: 3s retries: 20 start_period: 10s - networks: openisle-network: driver: bridge