#!/usr/bin/env bash set -euo pipefail # 用法: # bash scripts/batch_insert_users.sh [count] [star_id] [start_index] [mobile_prefix] [nickname_prefix] # 示例: # bash scripts/batch_insert_users.sh 30 0 1 19988 批量用户 # # 说明: # - star_id 传 0 时,会自动选择一个激活明星;若不存在会自动创建一个测试明星 # - 默认 DB 连接参数与测试代码一致,可通过环境变量覆盖 COUNT="${1:-30}" STAR_ID="${2:-0}" START_INDEX="${3:-1}" MOBILE_PREFIX="${4:-19988}" NICKNAME_PREFIX="${5:-批量用户}" DB_HOST="${DB_HOST:-localhost}" DB_PORT="${DB_PORT:-5432}" DB_USER="${DB_USER:-haihuizhu}" DB_PASSWORD="${DB_PASSWORD:-admin}" DB_NAME="${DB_NAME:-top-fans}" DB_SSLMODE="${DB_SSLMODE:-disable}" if ! command -v psql >/dev/null 2>&1; then echo "❌ 未检测到 psql,请先安装 PostgreSQL 客户端" exit 1 fi export PGPASSWORD="$DB_PASSWORD" echo "======================================" echo "开始批量插入用户" echo "======================================" echo "count=$COUNT, star_id=$STAR_ID, start_index=$START_INDEX" echo "mobile_prefix=$MOBILE_PREFIX, nickname_prefix=$NICKNAME_PREFIX" echo "db=$DB_USER@$DB_HOST:$DB_PORT/$DB_NAME" echo psql \ -h "$DB_HOST" \ -p "$DB_PORT" \ -U "$DB_USER" \ -d "$DB_NAME" \ -v ON_ERROR_STOP=1 \ -v count="$COUNT" \ -v star_id="$STAR_ID" \ -v start_index="$START_INDEX" \ -v mobile_prefix="$MOBILE_PREFIX" \ -v nickname_prefix="$NICKNAME_PREFIX" \ <<'SQL' WITH params AS ( SELECT :count::INT AS count, :star_id::BIGINT AS input_star_id, :start_index::INT AS start_index, :'mobile_prefix'::TEXT AS mobile_prefix, :'nickname_prefix'::TEXT AS nickname_prefix, (extract(epoch from now()) * 1000)::BIGINT AS ts ), picked AS ( SELECT s.star_id FROM stars s WHERE s.is_active = true ORDER BY s.star_id ASC LIMIT 1 ), created AS ( INSERT INTO stars (name, identity_id, is_active, created_at, updated_at) SELECT '批量测试明星', 'batch_seed_' || (SELECT ts FROM params)::TEXT, true, (SELECT ts FROM params), (SELECT ts FROM params) WHERE (SELECT input_star_id FROM params) = 0 AND NOT EXISTS (SELECT 1 FROM picked) RETURNING star_id ) SELECT COALESCE( NULLIF((SELECT input_star_id FROM params), 0), (SELECT star_id FROM picked), (SELECT star_id FROM created) ) AS resolved_star_id \gset INSERT INTO users (mobile, password_hash, is_active, created_at, updated_at) SELECT :'mobile_prefix' || lpad((:start_index::INT + gs.i)::TEXT, 6, '0') AS mobile, '$2a$10$LC8XORj6Nx9nT6j5QHfN5u2nB4z8e0v2dWm7X2uF5m6W6br8NnDPS' AS password_hash, true, (extract(epoch from now()) * 1000)::BIGINT, (extract(epoch from now()) * 1000)::BIGINT FROM generate_series(0, :count::INT - 1) AS gs(i) ON CONFLICT (mobile) DO UPDATE SET is_active = true, updated_at = EXCLUDED.updated_at; INSERT INTO fan_profiles ( user_id, star_id, nickname, level, times, social, experience, coin_balance, crystal_balance, tags, starbook_limit, slot_limit, assets_count, is_active, created_at, updated_at ) SELECT u.id, :resolved_star_id::BIGINT, :'nickname_prefix' || '_' || :resolved_star_id::TEXT || '_' || lpad((:start_index::INT + gs.i)::TEXT, 3, '0') AS nickname, (1 + ((:start_index::INT + gs.i) % 10))::INT, 1, 0, 0, 0, 1000, '[]'::jsonb, 3, 3, 0, true, (extract(epoch from now()) * 1000)::BIGINT, (extract(epoch from now()) * 1000)::BIGINT FROM generate_series(0, :count::INT - 1) AS gs(i) JOIN users u ON u.mobile = (:'mobile_prefix' || lpad((:start_index::INT + gs.i)::TEXT, 6, '0')) ON CONFLICT (user_id, star_id) DO UPDATE SET nickname = EXCLUDED.nickname, level = EXCLUDED.level, updated_at = EXCLUDED.updated_at; SELECT :resolved_star_id::BIGINT AS star_id, :count::INT AS requested_count, COUNT(*)::INT AS affected_profiles FROM fan_profiles WHERE star_id = :resolved_star_id::BIGINT AND nickname LIKE (:'nickname_prefix' || '_' || :resolved_star_id::TEXT || '_%'); SQL echo echo "✅ 批量插入完成" echo "默认密码(若业务校验 hash,请按需重置): password123"