fix: 修复保存满分后清登录;配置双写;设置显示账号/密码;抽取比例改按人数加权
- 修复:仅当连接信息(base_url/api_prefix/username/password/verify_ssl)真变化时才清 token + 重连; 保存满分/布局等不应触发登录卷王(bug:之前一律 unlink token.json,导致保存后所有用户都被踢) - 修复:默认满分不再误写当前卷;改为显式 apply_pid + apply_score 才会改 full_scores - 配置双写(DB+文件):避免 DB 不可用时静默回退到出厂默认 admin/123456; ny_save_config 同时写文件+DB;ny_load_config 在 DB 可用但无记录时从文件自动迁回 - 设置弹窗新增:登录账号可编辑、密码 type=password 不回显、留空表示不修改; 保存后根据 ping 自动给出成功/失败反馈(错误密码不再静默) - 抽取比例改为按组人数加权(默认)+ 各组均分 + 自定义比例 + 不分组,最大余额法守恒分配 - 抽出比例 UI:删除 5:5 复选框、改 #balanceMode 下拉 + 按组渲染比例输入框 - Db::lastError() 暴露 DB 错误用于诊断(config_get 返回 db_driver / db_connected / db_error) - e2e:test-draw-alloc 18→29 测试用例(加权/自定义/守恒 fuzz); 新增 test-config-save e2e 27 用例全过(连接信息变化检测 + 自动 ping + 密码不回显 + apply_pid) - mock-server:账户校验从 'admin' 改为 'mock' 接受 e2e 账号
This commit is contained in:
@@ -32,8 +32,14 @@ try {
|
||||
// ---------------- 配置 ----------------
|
||||
case 'config_get':
|
||||
$c = cfg();
|
||||
$c['has_password'] = $c['password'] !== '';
|
||||
$c['has_password'] = ((string)$c['password']) !== '';
|
||||
unset($c['password']);
|
||||
// 诊断信息:配置存在哪里、数据库通不通(登录卷王失败时优先看这里)
|
||||
$c['storage'] = ny_config_source();
|
||||
$c['db_driver'] = class_exists('Db') ? Db::driver() : '';
|
||||
$c['db_configured'] = class_exists('Db') && Db::isConfigured();
|
||||
$c['db_connected'] = class_exists('Db') && Db::isConnected();
|
||||
$c['db_error'] = class_exists('Db') ? Db::lastError() : '';
|
||||
ny_ok($c);
|
||||
|
||||
case 'config_save':
|
||||
@@ -43,13 +49,20 @@ try {
|
||||
$in = $_POST;
|
||||
}
|
||||
$old = cfg();
|
||||
$allowed = ['base_url', 'api_prefix', 'username', 'password', 'timeout', 'refresh_interval', 'page_size', 'name_keywords'];
|
||||
$allowed = ['base_url', 'api_prefix', 'username', 'timeout', 'refresh_interval', 'page_size', 'name_keywords'];
|
||||
$new = $old;
|
||||
foreach ($allowed as $k) {
|
||||
if (array_key_exists($k, $in)) {
|
||||
$new[$k] = is_string($in[$k]) ? trim((string)$in[$k]) : $in[$k];
|
||||
}
|
||||
}
|
||||
// 密码:与 install.php 一致不做 trim(保留首尾空格的原貌),空 / 占位符 = 不修改
|
||||
if (array_key_exists('password', $in)) {
|
||||
$pwdIn = (string)$in['password'];
|
||||
if ($pwdIn !== '' && $pwdIn !== '******') {
|
||||
$new['password'] = $pwdIn;
|
||||
}
|
||||
}
|
||||
foreach (['verify_ssl', 'include_temp_save', 'dedupe'] as $k) {
|
||||
if (array_key_exists($k, $in)) {
|
||||
$new[$k] = filter_var($in[$k], FILTER_VALIDATE_BOOL);
|
||||
@@ -63,33 +76,65 @@ try {
|
||||
if (array_key_exists('full_scores', $in) && is_array($in['full_scores'])) {
|
||||
$new['full_scores'] = $in['full_scores'];
|
||||
}
|
||||
$pwdIn = $in['password'] ?? null;
|
||||
if ($pwdIn === null || $pwdIn === '' || $pwdIn === '******') {
|
||||
$new['password'] = $old['password'];
|
||||
}
|
||||
$new['base_url'] = rtrim($new['base_url'], '/');
|
||||
$new['base_url'] = rtrim((string)$new['base_url'], '/');
|
||||
$new['api_prefix'] = '/' . trim((string)$new['api_prefix'], '/');
|
||||
$new['timeout'] = (int)$new['timeout'];
|
||||
$new['refresh_interval'] = (int)$new['refresh_interval'];
|
||||
if ($new['refresh_interval'] < 3) {
|
||||
$new['refresh_interval'] = 3;
|
||||
}
|
||||
// 每套试卷独立满分:选中试卷时写入 full_scores[projectId],否则更新全局默认
|
||||
// 默认满分
|
||||
$fs = (int)($in['full_score'] ?? $new['full_score'] ?? 100);
|
||||
if ($fs < 1) {
|
||||
$fs = 100;
|
||||
}
|
||||
$pid = trim((string)($in['project_id'] ?? ''));
|
||||
if ($pid !== '') {
|
||||
$new['full_score'] = $fs;
|
||||
// 各试卷独立满分:仅当显式指定 apply_pid 时才写入/清除该卷(修复 bug:之前会误用默认满分覆盖当前卷)
|
||||
$applyPid = trim((string)($in['apply_pid'] ?? ''));
|
||||
if ($applyPid !== '') {
|
||||
$scores = is_array($new['full_scores'] ?? null) ? $new['full_scores'] : [];
|
||||
$scores[$pid] = $fs;
|
||||
$applyScore = (int)($in['apply_score'] ?? 0);
|
||||
if ($applyScore > 0) {
|
||||
$scores[$applyPid] = $applyScore;
|
||||
} else {
|
||||
unset($scores[$applyPid]);
|
||||
}
|
||||
$new['full_scores'] = $scores;
|
||||
} else {
|
||||
$new['full_score'] = $fs;
|
||||
}
|
||||
// 仅当连接信息真的变了才清 token + 重连;保存满分/布局等不应触发登录卷王
|
||||
$connKeys = ['base_url', 'api_prefix', 'username', 'password', 'verify_ssl'];
|
||||
$connChanged = false;
|
||||
foreach ($connKeys as $k) {
|
||||
if ((string)($old[$k] ?? '') !== (string)($new[$k] ?? '')) {
|
||||
$connChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ny_save_config($new);
|
||||
@unlink(NY_DATA . '/cache/token.json'); // 清掉旧令牌
|
||||
ny_ok(['saved' => true, 'config' => ny_load_config()]);
|
||||
if ($connChanged) {
|
||||
@unlink(NY_DATA . '/cache/token.json');
|
||||
}
|
||||
// 返回的 config 不再带明文密码
|
||||
$outCfg = ny_load_config();
|
||||
$outCfg['has_password'] = ((string)$outCfg['password']) !== '';
|
||||
unset($outCfg['password']);
|
||||
$res = [
|
||||
'saved' => true,
|
||||
'config' => $outCfg,
|
||||
'conn_changed' => $connChanged,
|
||||
'storage' => ny_config_source(),
|
||||
];
|
||||
// 连接信息修改后自动测一次,给出明确结果(避免用户配置对错无从知晓)
|
||||
if ($connChanged) {
|
||||
try {
|
||||
$client = new SurveyKingClient(ny_load_config());
|
||||
$p = $client->ping();
|
||||
$res['ping'] = ['ok' => true, 'projects' => $p['projects'], 'elapsed' => $p['elapsed']];
|
||||
} catch (Throwable $e) {
|
||||
$res['ping'] = ['ok' => false, 'msg' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
ny_ok($res);
|
||||
|
||||
// ---------------- 连接测试 ----------------
|
||||
case 'ping':
|
||||
|
||||
Reference in New Issue
Block a user