param( [ValidateRange(1, 1300)] [int]$UserCount = 1300, [ValidateSet("AllScope", "Authorized")] [string]$PermissionMode = "AllScope", [ValidatePattern("^[0-9a-fA-F]{32}$")] [string]$ActivityId = "11619eee67574256ad8ccc8a16630023", [string]$OutputFile = (Join-Path $PSScriptRoot "data\brand-activity-users.csv"), [string]$ApplicationConfig = (Join-Path $PSScriptRoot "..\src\main\resources\application.yaml") ) $ErrorActionPreference = "Stop" function Get-YamlScalar { param( [string[]]$Lines, [string]$Name ) $matchedLine = $Lines | Where-Object { $_ -match ("^\s*" + [regex]::Escape($Name) + "\s*:\s*(.+?)\s*$") } | Select-Object -First 1 if (-not $matchedLine) { throw "未在 application.yaml 中找到配置项:$Name" } return ([regex]::Match($matchedLine, "^\s*[^:]+:\s*(.+?)\s*$")).Groups[1].Value.Trim('"', "'") } if (-not (Test-Path -LiteralPath $ApplicationConfig)) { throw "找不到应用配置文件:$ApplicationConfig" } $mysqlCommand = Get-Command mysql -ErrorAction SilentlyContinue if (-not $mysqlCommand) { throw "未找到 mysql 命令,请先把 MySQL 客户端 bin 目录加入 PATH。" } $configLines = Get-Content -LiteralPath $ApplicationConfig -Encoding UTF8 $jdbcUrl = Get-YamlScalar -Lines $configLines -Name "url" $dbUser = Get-YamlScalar -Lines $configLines -Name "username" $dbPassword = Get-YamlScalar -Lines $configLines -Name "password" $jdbcMatch = [regex]::Match($jdbcUrl, "jdbc:mysql://(?[^:/?]+)(:(?\d+))?/(?[^?]+)") if (-not $jdbcMatch.Success) { throw "无法解析 JDBC 地址:$jdbcUrl" } $dbHost = $jdbcMatch.Groups["host"].Value $dbPort = if ($jdbcMatch.Groups["port"].Success) { $jdbcMatch.Groups["port"].Value } else { "3306" } $database = $jdbcMatch.Groups["database"].Value # 仅导出活动范围内、账号未禁用且尚未报名的人员;不读取密码、身份证号、手机号等敏感字段。 $permissionCondition = if ($PermissionMode -eq "Authorized") { @" AND EXISTS ( SELECT 1 FROM sys_user_role ur JOIN sys_role_menu rm ON rm.roleId = ur.roleId JOIN sys_menu m ON m.id = rm.menuId WHERE ur.userId = u.id AND m.permission IN ('trainSignUp.apply', 'h5.trainSignUp.apply') ) "@ } else { "" } $query = @" SELECT u.loginname, CASE WHEN EXISTS ( SELECT 1 FROM sys_user_role ur JOIN sys_role_menu rm ON rm.roleId = ur.roleId JOIN sys_menu m ON m.id = rm.menuId WHERE ur.userId = u.id AND m.permission IN ('trainSignUp.apply', 'h5.trainSignUp.apply') ) THEN 1 ELSE 0 END AS expectedAuthorized FROM train_sign_up_activity a JOIN activity_user_scope aus ON aus.groupId = a.activityGroupId JOIN sys_user u ON u.id = aus.userId LEFT JOIN train_sign_up_user su ON su.activityId = a.id AND su.userId = u.id WHERE a.id = '$ActivityId' AND u.disabled = 0 AND u.loginname IS NOT NULL AND u.loginname <> '' AND su.id IS NULL $permissionCondition GROUP BY u.id, u.loginname ORDER BY expectedAuthorized DESC, u.loginname LIMIT $UserCount; "@ $previousMysqlPassword = $env:MYSQL_PWD try { $env:MYSQL_PWD = $dbPassword $rows = @(& $mysqlCommand.Source --batch --raw --skip-column-names -h $dbHost -P $dbPort -u $dbUser $database -e $query) if ($LASTEXITCODE -ne 0) { throw "查询压测人员失败,mysql 退出码:$LASTEXITCODE" } } finally { $env:MYSQL_PWD = $previousMysqlPassword } $users = @($rows | Where-Object { $_ -and $_.Trim() } | ForEach-Object { $columns = $_ -split "`t", 2 [pscustomobject]@{ loginname = $columns[0] expectedAuthorized = $columns[1] } }) if ($users.Count -lt $UserCount) { throw "符合条件的人员只有 $($users.Count) 人,少于要求的 $UserCount 人。PermissionMode=$PermissionMode" } $outputDirectory = Split-Path -Parent $OutputFile if (-not (Test-Path -LiteralPath $outputDirectory)) { New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null } $users | Export-Csv -LiteralPath $OutputFile -NoTypeInformation -Encoding UTF8 -UseQuotes Always $authorizedCount = @($users | Where-Object { $_.expectedAuthorized -eq "1" }).Count $unauthorizedCount = $users.Count - $authorizedCount Write-Host "已生成 UTF-8 用户文件:$OutputFile" Write-Host "总人数:$($users.Count),具备报名权限:$authorizedCount,无报名权限:$unauthorizedCount" if ($unauthorizedCount -gt 0) { Write-Warning "无报名权限的线程仍会访问报名接口,但会被权限校验拒绝。" }