新增小程序后端代码,包括数据库、路由、服务层等。

小程序前后端打通,包括登录、注册、绑定设备、查询绑定信息,修改小朋友名称等功能。
This commit is contained in:
HycJack
2026-04-13 01:54:57 +08:00
parent 33715373b0
commit a22fcafea9
46 changed files with 3713 additions and 268 deletions

BIN
mini-program/database/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,227 @@
-- 家长微信账号表
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-1000为关闭',
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`;

View File

@@ -0,0 +1,214 @@
-- New tables per design.md
-- Supports both MySQL and SQLite
-- parents table
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),
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
);
-- SQLite uses TRIGGER for updated_at, MySQL uses ON UPDATE
-- For SQLite compatibility, we'll handle in app layer
CREATE INDEX IF NOT EXISTS idx_parents_unionid ON parents(unionid);
CREATE INDEX IF NOT EXISTS idx_parents_phone ON parents(phone);
-- children table
CREATE TABLE IF NOT EXISTS children (
child_id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_name VARCHAR(32) NOT NULL,
child_gender TINYINT NOT NULL DEFAULT 2,
child_birthday DATE,
status TINYINT NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- parent_child_relations table
CREATE TABLE IF NOT EXISTS parent_child_relations (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
child_id BIGINT NOT NULL,
relation_type TINYINT NOT NULL DEFAULT 9,
is_primary TINYINT(1) NOT NULL DEFAULT 0,
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)
);
-- device_bindings table
CREATE TABLE IF NOT EXISTS device_bindings (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(64) NOT NULL,
child_id BIGINT NOT NULL,
status TINYINT NOT NULL DEFAULT 1,
bound_at DATETIME NOT NULL,
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)
);
-- device_bind_sessions table
CREATE TABLE IF NOT EXISTS device_bind_sessions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
bind_token CHAR(36) UNIQUE NOT NULL,
device_id VARCHAR(64) NOT NULL,
initiator_user_id BIGINT NOT NULL,
target_child_id BIGINT,
challenge_code_hash CHAR(64),
challenge_set_at DATETIME,
expires_at DATETIME NOT NULL,
max_attempt_count TINYINT UNSIGNED NOT NULL DEFAULT 5,
attempt_count TINYINT UNSIGNED NOT NULL DEFAULT 0,
status TINYINT NOT NULL DEFAULT 1,
confirmed_at DATETIME,
consumed_at DATETIME,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- device_bind_history table
CREATE TABLE IF NOT EXISTS device_bind_history (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(64) NOT NULL,
child_id BIGINT NOT NULL,
bound_by_user_id BIGINT NOT NULL,
unbound_by_user_id BIGINT,
bind_source TINYINT NOT NULL DEFAULT 1,
bound_at DATETIME NOT NULL,
unbound_at DATETIME,
unbind_reason VARCHAR(191),
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- cards table
CREATE TABLE IF NOT EXISTS cards (
card_id BIGINT PRIMARY KEY AUTO_INCREMENT,
card_uuid VARCHAR(64) UNIQUE NOT NULL,
device_id VARCHAR(64) UNIQUE,
card_name VARCHAR(64),
status TINYINT NOT NULL DEFAULT 0,
total_swaps INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- device_settings table
CREATE TABLE IF NOT EXISTS device_settings (
setting_id BIGINT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(64) NOT NULL UNIQUE,
sleep_mode TINYINT NOT NULL DEFAULT 0,
disable_time_start TIME,
disable_time_end TIME,
timezone VARCHAR(32) NOT NULL DEFAULT 'Asia/Shanghai',
volume TINYINT UNSIGNED,
brightness TINYINT UNSIGNED,
disable_weekdays VARCHAR(32),
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- im_conversations table
CREATE TABLE IF NOT EXISTS im_conversations (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
conversation_type TINYINT UNSIGNED NOT NULL,
participant_a_type TINYINT UNSIGNED NOT NULL,
participant_a_id VARCHAR(64) NOT NULL,
participant_b_type TINYINT UNSIGNED NOT NULL,
participant_b_id VARCHAR(64) NOT NULL,
pair_key VARCHAR(191) NOT NULL,
status TINYINT NOT NULL DEFAULT 1,
last_seq BIGINT UNSIGNED NOT NULL DEFAULT 0,
message_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
last_message_preview VARCHAR(255),
last_message_at DATETIME,
ext_json JSON,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (conversation_type, pair_key)
);
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);
-- im_messages table
CREATE TABLE IF NOT EXISTS im_messages (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
conversation_id BIGINT UNSIGNED NOT NULL,
seq BIGINT UNSIGNED NOT NULL,
sender_type TINYINT UNSIGNED NOT NULL,
sender_id VARCHAR(64) NOT NULL,
receiver_type TINYINT UNSIGNED NOT NULL,
receiver_id VARCHAR(64) NOT NULL,
content_type TINYINT UNSIGNED NOT NULL,
content_text MEDIUMTEXT,
content_json JSON,
media_file_key VARCHAR(255),
media_duration_ms INT UNSIGNED,
media_mime_type VARCHAR(64),
media_size_bytes BIGINT UNSIGNED,
media_transcript_text TEXT,
client_msg_id VARCHAR(64),
sender_name_snapshot VARCHAR(64),
sender_avatar_snapshot VARCHAR(255),
receiver_name_snapshot VARCHAR(64),
receiver_avatar_snapshot VARCHAR(255),
ext_json JSON,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at DATETIME,
UNIQUE (conversation_id, seq),
UNIQUE (conversation_id, client_msg_id)
);
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);
-- child_location_current table
CREATE TABLE IF NOT EXISTS child_location_current (
child_id BIGINT UNSIGNED PRIMARY KEY,
device_id VARCHAR(64) NOT NULL,
coord_type VARCHAR(16) NOT NULL DEFAULT 'gcj02',
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
accuracy_m INT UNSIGNED,
altitude_m DECIMAL(8,2),
speed_mps DECIMAL(8,2),
heading_deg SMALLINT UNSIGNED,
source TINYINT UNSIGNED NOT NULL,
battery_pct TINYINT UNSIGNED,
device_time DATETIME NOT NULL,
server_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- child_location_history table
CREATE TABLE IF NOT EXISTS child_location_history (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT UNSIGNED NOT NULL,
device_id VARCHAR(64) NOT NULL,
coord_type VARCHAR(16) NOT NULL DEFAULT 'gcj02',
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
accuracy_m INT UNSIGNED,
altitude_m DECIMAL(8,2),
speed_mps DECIMAL(8,2),
heading_deg SMALLINT UNSIGNED,
source TINYINT UNSIGNED NOT NULL,
battery_pct TINYINT UNSIGNED,
device_time DATETIME NOT NULL,
server_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_child_loc_hist_child ON child_location_history(child_id, created_at);