diff --git a/mini-program/database/sql/003_new_tables.sql b/mini-program/database/init.sql similarity index 74% rename from mini-program/database/sql/003_new_tables.sql rename to mini-program/database/init.sql index 6981c73..5df5d79 100644 --- a/mini-program/database/sql/003_new_tables.sql +++ b/mini-program/database/init.sql @@ -1,26 +1,29 @@ --- New tables per design.md --- Supports both MySQL and SQLite +-- Current MySQL schema for mini-program --- parents table +CREATE DATABASE IF NOT EXISTS mini_program + DEFAULT CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE mini_program; + +-- parents CREATE TABLE IF NOT EXISTS parents ( user_id BIGINT PRIMARY KEY AUTO_INCREMENT, openid VARCHAR(64) UNIQUE NOT NULL, unionid VARCHAR(64), nickname VARCHAR(64), avatar_url VARCHAR(255), + avatar_file_key VARCHAR(255), phone VARCHAR(20), status TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- SQLite uses TRIGGER for updated_at, MySQL uses ON UPDATE --- For SQLite compatibility, we'll handle in app layer +CREATE INDEX idx_parents_unionid ON parents(unionid); +CREATE INDEX idx_parents_phone ON parents(phone); -CREATE INDEX IF NOT EXISTS idx_parents_unionid ON parents(unionid); -CREATE INDEX IF NOT EXISTS idx_parents_phone ON parents(phone); - --- children table +-- children CREATE TABLE IF NOT EXISTS children ( child_id BIGINT PRIMARY KEY AUTO_INCREMENT, child_name VARCHAR(32) NOT NULL, @@ -29,9 +32,9 @@ CREATE TABLE IF NOT EXISTS children ( status TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- parent_child_relations table +-- parent_child_relations CREATE TABLE IF NOT EXISTS parent_child_relations ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, @@ -41,10 +44,13 @@ CREATE TABLE IF NOT EXISTS parent_child_relations ( status TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE (user_id, child_id) -); + CONSTRAINT uq_user_child UNIQUE (user_id, child_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- device_bindings table +CREATE INDEX idx_pcr_user_id ON parent_child_relations(user_id); +CREATE INDEX idx_pcr_child_id ON parent_child_relations(child_id); + +-- device_bindings CREATE TABLE IF NOT EXISTS device_bindings ( id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) NOT NULL, @@ -55,13 +61,13 @@ CREATE TABLE IF NOT EXISTS device_bindings ( unbound_at DATETIME, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE (device_id), - UNIQUE (child_id) -); + CONSTRAINT uq_device_binding_device UNIQUE (device_id), + CONSTRAINT uq_device_binding_child UNIQUE (child_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -CREATE INDEX IF NOT EXISTS idx_device_bindings_owner_user_id ON device_bindings(owner_user_id); +CREATE INDEX idx_device_bindings_owner_user_id ON device_bindings(owner_user_id); --- device_bind_sessions table +-- device_bind_sessions CREATE TABLE IF NOT EXISTS device_bind_sessions ( id BIGINT PRIMARY KEY AUTO_INCREMENT, bind_token CHAR(36) UNIQUE NOT NULL, @@ -78,9 +84,9 @@ CREATE TABLE IF NOT EXISTS device_bind_sessions ( consumed_at DATETIME, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- device_bind_history table +-- device_bind_history CREATE TABLE IF NOT EXISTS device_bind_history ( id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) NOT NULL, @@ -92,9 +98,9 @@ CREATE TABLE IF NOT EXISTS device_bind_history ( unbound_at DATETIME, unbind_reason VARCHAR(191), created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- cards table +-- cards CREATE TABLE IF NOT EXISTS cards ( card_id BIGINT PRIMARY KEY AUTO_INCREMENT, card_uuid VARCHAR(64) UNIQUE NOT NULL, @@ -104,9 +110,9 @@ CREATE TABLE IF NOT EXISTS cards ( total_swaps INT NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- device_settings table +-- device_settings CREATE TABLE IF NOT EXISTS device_settings ( setting_id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) NOT NULL UNIQUE, @@ -119,9 +125,9 @@ CREATE TABLE IF NOT EXISTS device_settings ( disable_weekdays VARCHAR(32), created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- im_conversations table +-- im_conversations CREATE TABLE IF NOT EXISTS im_conversations ( id BIGINT PRIMARY KEY AUTO_INCREMENT, conversation_type TINYINT UNSIGNED NOT NULL, @@ -138,14 +144,14 @@ CREATE TABLE IF NOT EXISTS im_conversations ( ext_json JSON, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE (conversation_type, pair_key) -); + CONSTRAINT uq_conv_type_pair UNIQUE (conversation_type, pair_key) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -CREATE INDEX IF NOT EXISTS idx_im_conv_participant_a ON im_conversations(participant_a_type, participant_a_id); -CREATE INDEX IF NOT EXISTS idx_im_conv_participant_b ON im_conversations(participant_b_type, participant_b_id); -CREATE INDEX IF NOT EXISTS idx_im_conv_last_message_at ON im_conversations(last_message_at); +CREATE INDEX idx_im_conv_participant_a ON im_conversations(participant_a_type, participant_a_id); +CREATE INDEX idx_im_conv_participant_b ON im_conversations(participant_b_type, participant_b_id); +CREATE INDEX idx_im_conv_last_message_at ON im_conversations(last_message_at); --- im_messages table +-- im_messages CREATE TABLE IF NOT EXISTS im_messages ( id BIGINT PRIMARY KEY AUTO_INCREMENT, conversation_id BIGINT UNSIGNED NOT NULL, @@ -170,14 +176,14 @@ CREATE TABLE IF NOT EXISTS im_messages ( ext_json JSON, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at DATETIME, - UNIQUE (conversation_id, seq), - UNIQUE (conversation_id, client_msg_id) -); + CONSTRAINT uq_im_msg_conv_seq UNIQUE (conversation_id, seq), + CONSTRAINT uq_im_msg_client UNIQUE (conversation_id, client_msg_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -CREATE INDEX IF NOT EXISTS idx_im_msg_sender ON im_messages(sender_type, sender_id, created_at); -CREATE INDEX IF NOT EXISTS idx_im_msg_receiver ON im_messages(receiver_type, receiver_id, created_at); +CREATE INDEX idx_im_msg_sender ON im_messages(sender_type, sender_id, created_at); +CREATE INDEX idx_im_msg_receiver ON im_messages(receiver_type, receiver_id, created_at); --- child_location_current table +-- child_location_current CREATE TABLE IF NOT EXISTS child_location_current ( child_id BIGINT UNSIGNED PRIMARY KEY, device_id VARCHAR(64) NOT NULL, @@ -193,9 +199,9 @@ CREATE TABLE IF NOT EXISTS child_location_current ( device_time DATETIME NOT NULL, server_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- child_location_history table +-- child_location_history CREATE TABLE IF NOT EXISTS child_location_history ( id BIGINT PRIMARY KEY AUTO_INCREMENT, child_id BIGINT UNSIGNED NOT NULL, @@ -212,6 +218,6 @@ CREATE TABLE IF NOT EXISTS child_location_history ( device_time DATETIME NOT NULL, server_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -CREATE INDEX IF NOT EXISTS idx_child_loc_hist_child ON child_location_history(child_id, created_at); +CREATE INDEX idx_child_loc_hist_child ON child_location_history(child_id, created_at); diff --git a/mini-program/database/sql/001_init_chat.sql b/mini-program/database/sql/001_init_chat.sql deleted file mode 100644 index a8c6a02..0000000 --- a/mini-program/database/sql/001_init_chat.sql +++ /dev/null @@ -1,305 +0,0 @@ --- Chat schema and seed data for mini-program --- Target: MySQL 8+ - -CREATE DATABASE IF NOT EXISTS mini_program - DEFAULT CHARACTER SET utf8mb4 - COLLATE utf8mb4_unicode_ci; - -USE mini_program; - -SET FOREIGN_KEY_CHECKS=0; -DROP TABLE IF EXISTS chat_message; -DROP TABLE IF EXISTS chat_conversation_member; -DROP TABLE IF EXISTS chat_conversation; -DROP TABLE IF EXISTS chat_user_auth; -DROP TABLE IF EXISTS chat_user; -SET FOREIGN_KEY_CHECKS=1; - -CREATE TABLE IF NOT EXISTS chat_user ( - id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - nickname VARCHAR(64) NULL, - avatar_file_key VARCHAR(255) NULL COMMENT 'Stored file key, not URL', - status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-active 2-disabled 3-deleted', - last_login_at DATETIME(3) NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (id), - KEY idx_status (status), - KEY idx_created_at (created_at) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE IF NOT EXISTS chat_user_auth ( - id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - user_id BIGINT UNSIGNED NOT NULL, - auth_type TINYINT UNSIGNED NOT NULL COMMENT '1-wechat_miniapp_openid 2-wechat_unionid 3-phone_sms 4-email_magic_link 5-oauth 6-username_password', - auth_identifier VARCHAR(191) NOT NULL COMMENT 'openid/unionid/phone/email/oauth-sub/username', - password_hash CHAR(64) NULL COMMENT 'sha256 hex for demo only; production should use bcrypt/argon2', - credential_json JSON NULL COMMENT 'Extra auth payload, e.g. app_id/provider/phone_area', - is_primary TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-primary login identity 0-secondary', - status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-active 2-disabled 3-revoked', - last_login_at DATETIME(3) NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (id), - UNIQUE KEY uk_auth_type_identifier (auth_type, auth_identifier), - KEY idx_user_status (user_id, status), - KEY idx_last_login_at (last_login_at), - CONSTRAINT fk_user_auth_user - FOREIGN KEY (user_id) REFERENCES chat_user(id) - ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE IF NOT EXISTS chat_conversation ( - id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - user_low_id BIGINT UNSIGNED NOT NULL COMMENT 'Smaller user_id in direct chat pair', - user_high_id BIGINT UNSIGNED NOT NULL COMMENT 'Larger user_id in direct chat pair', - status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-active 2-archived', - last_seq BIGINT UNSIGNED NOT NULL DEFAULT 0, - message_count BIGINT UNSIGNED NOT NULL DEFAULT 0, - last_message_preview VARCHAR(255) NULL, - last_message_at DATETIME(3) NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (id), - UNIQUE KEY uk_direct_pair (user_low_id, user_high_id), - KEY idx_last_message_at (last_message_at), - KEY idx_user_low_id (user_low_id), - KEY idx_user_high_id (user_high_id), - CONSTRAINT fk_conv_user_low - FOREIGN KEY (user_low_id) REFERENCES chat_user(id) - ON DELETE CASCADE, - CONSTRAINT fk_conv_user_high - FOREIGN KEY (user_high_id) REFERENCES chat_user(id) - ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE IF NOT EXISTS chat_message ( - id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - conversation_id BIGINT UNSIGNED NOT NULL, - seq BIGINT UNSIGNED NOT NULL COMMENT 'Conversation-local incremental sequence', - sender_user_id BIGINT UNSIGNED NULL COMMENT 'Null means assistant/system sender', - role TINYINT UNSIGNED NOT NULL COMMENT '1-user 2-assistant 3-system 4-tool', - content_type TINYINT UNSIGNED NOT NULL COMMENT '1-text 2-audio 3-image 4-json', - content_text MEDIUMTEXT NULL, - content_json JSON NULL, - media_file_key VARCHAR(255) NULL COMMENT 'Stored file key, not URL', - media_duration_ms INT UNSIGNED NULL, - client_msg_id VARCHAR(64) NULL COMMENT 'Idempotency key from client', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - deleted_at DATETIME(3) NULL, - PRIMARY KEY (id), - UNIQUE KEY uk_conv_seq (conversation_id, seq), - UNIQUE KEY uk_conv_client_msg (conversation_id, client_msg_id), - KEY idx_conv_created (conversation_id, created_at), - KEY idx_sender_created (sender_user_id, created_at), - CONSTRAINT fk_msg_conv - FOREIGN KEY (conversation_id) REFERENCES chat_conversation(id) - ON DELETE CASCADE, - CONSTRAINT fk_msg_sender_user - FOREIGN KEY (sender_user_id) REFERENCES chat_user(id) - ON DELETE SET NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -INSERT INTO chat_user ( - id, - nickname, - avatar_file_key, - status, - last_login_at, - created_at, - updated_at -) -VALUES - ( - 1, - 'Parent A', - 'avatars/parent-a.png', - 1, - '2026-03-25 09:58:00.000', - '2026-03-25 09:00:00.000', - '2026-03-25 09:58:00.000' - ), - ( - 2, - 'Parent B', - 'avatars/parent-b.png', - 1, - '2026-03-25 10:01:00.000', - '2026-03-25 09:20:00.000', - '2026-03-25 10:01:00.000' - ), - ( - 3, - 'Parent C', - 'avatars/parent-c.png', - 1, - '2026-03-25 21:11:00.000', - '2026-03-25 20:30:00.000', - '2026-03-25 21:11:00.000' - ); - -INSERT INTO chat_user_auth ( - id, - user_id, - auth_type, - auth_identifier, - password_hash, - credential_json, - is_primary, - status, - last_login_at, - created_at, - updated_at -) -VALUES - ( - 1, - 1, - 6, - 'test1', - SHA2('123', 256), - JSON_OBJECT('provider', 'local_account'), - 1, - 1, - '2026-03-25 09:58:00.000', - '2026-03-25 09:00:00.000', - '2026-03-25 09:58:00.000' - ), - ( - 2, - 2, - 6, - 'test2', - SHA2('123', 256), - JSON_OBJECT('provider', 'local_account'), - 1, - 1, - '2026-03-25 10:01:00.000', - '2026-03-25 09:20:00.000', - '2026-03-25 10:01:00.000' - ), - ( - 3, - 3, - 6, - 'test3', - SHA2('123', 256), - JSON_OBJECT('provider', 'local_account'), - 1, - 1, - '2026-03-25 21:11:00.000', - '2026-03-25 20:30:00.000', - '2026-03-25 21:11:00.000' - ); - -INSERT INTO chat_conversation ( - id, - user_low_id, - user_high_id, - status, - last_seq, - message_count, - last_message_preview, - last_message_at, - created_at, - updated_at -) -VALUES - ( - 1, - 1, - 2, - 1, - 5, - 5, - 'user: Thanks, I understand now.', - '2026-03-25 10:00:40.000', - '2026-03-25 10:00:00.000', - '2026-03-25 10:00:40.000' - ); - -INSERT INTO chat_message ( - id, - conversation_id, - seq, - sender_user_id, - role, - content_type, - content_text, - content_json, - media_file_key, - media_duration_ms, - client_msg_id, - created_at -) -VALUES - ( - 1001, - 1, - 1, - 1, - 1, - 1, - 'Hi, did you finish homework?', - JSON_OBJECT('lang', 'en'), - NULL, - NULL, - 'c1-m1', - '2026-03-25 10:00:05.000' - ), - ( - 1002, - 1, - 2, - 2, - 1, - 1, - 'Almost done, one question left.', - JSON_OBJECT('lang', 'en'), - NULL, - NULL, - 'c1-m2', - '2026-03-25 10:00:12.000' - ), - ( - 1003, - 1, - 3, - NULL, - 2, - 1, - 'I can help explain the last question.', - JSON_OBJECT('tone', 'assistant'), - NULL, - NULL, - 'c1-m3', - '2026-03-25 10:00:20.000' - ), - ( - 1004, - 1, - 4, - 1, - 1, - 1, - 'Great, explain how to solve it.', - JSON_OBJECT('lang', 'en'), - NULL, - NULL, - 'c1-m4', - '2026-03-25 10:00:30.000' - ), - ( - 1005, - 1, - 5, - 2, - 1, - 1, - 'Thanks, I understand now.', - JSON_OBJECT('lang', 'en'), - NULL, - NULL, - 'c1-m5', - '2026-03-25 10:00:40.000' - ); diff --git a/mini-program/database/sql/002_new_db.sql b/mini-program/database/sql/002_new_db.sql deleted file mode 100644 index 4a2aafe..0000000 --- a/mini-program/database/sql/002_new_db.sql +++ /dev/null @@ -1,227 +0,0 @@ --- 家长微信账号表 -CREATE TABLE parents ( - user_id BIGINT PRIMARY KEY AUTO_INCREMENT, - openid VARCHAR(64) UNIQUE NOT NULL COMMENT '微信openid', - unionid VARCHAR(64) COMMENT '微信unionid', - nickname VARCHAR(64) COMMENT '家长昵称', - avatar_url VARCHAR(255), - phone VARCHAR(20), - status TINYINT DEFAULT 1 COMMENT '0禁用 1正常', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_unionid (unionid), - INDEX idx_phone (phone) -) ENGINE=InnoDB COMMENT='家长用户表'; - -CREATE TABLE children ( - profile_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '档案主键', - user_id BIGINT NOT NULL COMMENT '所属家长ID', - - -- 核心资料 - child_name VARCHAR(32) NOT NULL COMMENT '儿童昵称(设备唤醒名)', - child_gender TINYINT DEFAULT 2 COMMENT '性别:0女 1男 2保密', - child_birthday DATE COMMENT '出生日期', - child_age TINYINT UNSIGNED GENERATED ALWAYS AS ( - TIMESTAMPDIFF(YEAR, child_birthday, CURDATE()) - ) STORED COMMENT '自动计算年龄(用于适龄内容过滤)', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- 约束与索引 - FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, -)ENGINE=InnoDB COMMENT='儿童档案表(一个家长可创建多个档案)'; - -CREATE TABLE cards ( - card_id BIGINT PRIMARY KEY AUTO_INCREMENT, - card_uuid VARCHAR(64) UNIQUE NOT NULL COMMENT 'NFC卡片UUID', - device_id BIGINT UNIQUE COMMENT '绑定设备ID', - card_name VARCHAR(64) COMMENT '名片名称', - status TINYINT DEFAULT 0 COMMENT '0未绑定 1已绑定 2挂失', - total_swaps INT DEFAULT 0 COMMENT '交换次数', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - - FOREIGN KEY (device_id) REFERENCES devices(device_id), - INDEX idx_uuid (card_uuid), - INDEX idx_device (device_id) -) ENGINE=InnoDB COMMENT='实体交友名片表'; --- Todo 待修改 -CREATE TABLE device_settings ( - setting_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '设置主键', - device_id BIGINT NOT NULL UNIQUE COMMENT '设备ID(一对一)', - - -- 休眠与时间管理(防熬夜) - sleep_mode TINYINT DEFAULT 0 COMMENT '休眠模式:0关闭 1定时休眠 2连续使用限制', - sleep_start TIME COMMENT '定时休眠开始时间,如 22:00:00', - sleep_end TIME COMMENT '定时休眠结束时间,如 07:00:00', - timezone VARCHAR(32) DEFAULT 'Asia/Shanghai' COMMENT '时区,解决跨时区问题', - - -- 音量与硬件控制 - volume TINYINT UNSIGNED DEFAULT 80 COMMENT '系统音量 0-100', - brightness TINYINT UNSIGNED DEFAULT 100 COMMENT '指示灯亮度 0-100(0为关闭)', - - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - -) ENGINE=InnoDB COMMENT='设备设置表(家长远程管控配置)'; - --- 初始化数据库表 - --- 创建device_configs表 -CREATE TABLE IF NOT EXISTS `device_configs` ( - `id` INT NOT NULL AUTO_INCREMENT, - `device_id` VARCHAR(64) NOT NULL, - `selected_role_key` VARCHAR(64) NOT NULL, - `preferred_language` VARCHAR(10) NULL, - `volume` INT NULL, - `last_update_time` FLOAT NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `device_id_UNIQUE` (`device_id` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建conversation_histories表 -CREATE TABLE IF NOT EXISTS `conversation_histories` ( - `id` INT NOT NULL AUTO_INCREMENT, - `device_id` VARCHAR(64) NOT NULL, - `role_key` VARCHAR(64) NOT NULL, - `last_interaction_time` FLOAT NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - INDEX `idx_device_id` (`device_id` ASC), - INDEX `idx_role_key` (`role_key` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建conversation_messages表 -CREATE TABLE IF NOT EXISTS `conversation_messages` ( - `id` INT NOT NULL AUTO_INCREMENT, - `conversation_id` INT NOT NULL, - `is_user` TINYINT(1) NOT NULL DEFAULT 0, - `content` TEXT NOT NULL, - `timestamp` FLOAT NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - INDEX `idx_conversation_id` (`conversation_id` ASC), - CONSTRAINT `fk_messages_conversation` - FOREIGN KEY (`conversation_id`) - REFERENCES `conversation_histories` (`id`) - ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建roles表 -CREATE TABLE IF NOT EXISTS `roles` ( - `id` INT NOT NULL AUTO_INCREMENT, - `role_key` VARCHAR(64) NOT NULL, - `name` VARCHAR(128) NOT NULL, - `description` TEXT NULL, - `content` TEXT NOT NULL, - `default_language` VARCHAR(10) NULL, - `asr_provider` VARCHAR(64) NULL, - `llm_provider` VARCHAR(64) NULL, - `tts_provider` VARCHAR(64) NULL, - `competitive_llm_mode` TINYINT(1) NULL, - `volcano_model_id` VARCHAR(64) NULL, - `volcano_voice_type` VARCHAR(64) NULL, - `tencent_voice_type` VARCHAR(64) NULL, - `aliyun_voice_name` VARCHAR(64) NULL, - `minimax_voice_id` VARCHAR(64) NULL, - `url` VARCHAR(255) NULL, - `homophones` JSON NULL, - `enabled` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `role_key_UNIQUE` (`role_key` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建role_languages表 -CREATE TABLE IF NOT EXISTS `role_languages` ( - `id` INT NOT NULL AUTO_INCREMENT, - `role_id` INT NOT NULL, - `language_code` VARCHAR(10) NOT NULL, - `name` VARCHAR(128) NULL, - `content` TEXT NULL, - `asr_provider` VARCHAR(64) NULL, - `llm_provider` VARCHAR(64) NULL, - `tts_provider` VARCHAR(64) NULL, - `volcano_voice_type` VARCHAR(64) NULL, - `tencent_voice_type` VARCHAR(64) NULL, - `aliyun_voice_name` VARCHAR(64) NULL, - `minimax_voice_id` VARCHAR(64) NULL, - `url` VARCHAR(255) NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `uix_role_language` (`role_id`, `language_code`), - CONSTRAINT `fk_role_languages_role` - FOREIGN KEY (`role_id`) - REFERENCES `roles` (`id`) - ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建device_auth表 -CREATE TABLE IF NOT EXISTS `device_auth` ( - `id` INT NOT NULL AUTO_INCREMENT, - `device_id` VARCHAR(64) NOT NULL, - `serial_number` VARCHAR(64) NOT NULL, - `batch_id` VARCHAR(20) NULL, - `is_active` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `device_id_UNIQUE` (`device_id` ASC), - INDEX `idx_batch_id` (`batch_id` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建device_firmware_update表 -CREATE TABLE IF NOT EXISTS `device_firmware_update` ( - `id` INT NOT NULL AUTO_INCREMENT, - `device_id` VARCHAR(64) NOT NULL, - `serial_number` VARCHAR(64) NOT NULL, - `mac_address` VARCHAR(512) NULL, - `firmware_version` VARCHAR(64) NOT NULL, - `update_status` VARCHAR(32) NOT NULL DEFAULT 'success', - `progress` FLOAT NULL DEFAULT 0.0, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `device_id_UNIQUE` (`device_id` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 创建system_config表 -CREATE TABLE IF NOT EXISTS `system_config` ( - `id` INT NOT NULL AUTO_INCREMENT, - `config_key` VARCHAR(128) NOT NULL, - `config_value` TEXT NULL, - `description` VARCHAR(255) NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE INDEX `config_key_UNIQUE` (`config_key` ASC) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- 添加初始角色配置 -INSERT INTO `device_configs` (`device_id`, `selected_role_key`, `preferred_language`, `last_update_time`) -VALUES ('default', 'assistant', 'zh', UNIX_TIMESTAMP()) -ON DUPLICATE KEY UPDATE `selected_role_key`=`selected_role_key`; - --- 添加默认系统配置 -INSERT INTO `system_config` (`config_key`, `config_value`, `description`) -VALUES -('latest_firmware_version', '1.0.0', '最新固件版本'), -('update_firmware_url', 'https://example.com/firmware/latest.bin', '固件更新URL') -ON DUPLICATE KEY UPDATE `config_value`=`config_value`; - --- 添加默认角色 -INSERT INTO `roles` (`role_key`, `name`, `description`, `content`, `default_language`, `enabled`) -VALUES ( - 'assistant', - '智能助手', - '默认智能助手角色', - '你是一个友好的智能助手,乐于帮助用户解答问题。', - 'zh', - 1 -) -ON DUPLICATE KEY UPDATE `role_key`=`role_key`; \ No newline at end of file diff --git a/mini-program/database/sql/004_device_bindings_owner_user_migration.sql b/mini-program/database/sql/004_device_bindings_owner_user_migration.sql deleted file mode 100644 index 47ead87..0000000 --- a/mini-program/database/sql/004_device_bindings_owner_user_migration.sql +++ /dev/null @@ -1,46 +0,0 @@ --- Migration: support "bind device first, then set child profile" --- Target: MySQL 8.x - --- 1) Add owner_user_id on device_bindings. -ALTER TABLE device_bindings - ADD COLUMN owner_user_id BIGINT NULL AFTER device_id; - --- 2) Backfill owner_user_id from active parent-child relation (prefer primary relation). -UPDATE device_bindings b -SET owner_user_id = ( - SELECT r.user_id - FROM parent_child_relations r - WHERE r.child_id = b.child_id - AND r.status = 1 - ORDER BY r.is_primary DESC, r.id ASC - LIMIT 1 -) -WHERE b.owner_user_id IS NULL; - --- 3) Fallback backfill from latest bind history. -UPDATE device_bindings b -SET owner_user_id = ( - SELECT h.bound_by_user_id - FROM device_bind_history h - WHERE h.device_id = b.device_id - ORDER BY h.bound_at DESC, h.id DESC - LIMIT 1 -) -WHERE b.owner_user_id IS NULL; - --- 4) Ensure no NULL owner before setting NOT NULL. --- If this query returns rows, handle manually before continuing: --- SELECT id, device_id, child_id FROM device_bindings WHERE owner_user_id IS NULL; - --- 5) Make schema changes for new flow. -ALTER TABLE device_bindings - MODIFY COLUMN owner_user_id BIGINT NOT NULL; - -ALTER TABLE device_bindings - MODIFY COLUMN child_id BIGINT NULL; - -ALTER TABLE device_bindings - ADD INDEX idx_device_bindings_owner_user_id (owner_user_id); - -ALTER TABLE device_bind_history - MODIFY COLUMN child_id BIGINT NULL;