fix(ai): treat unchanged AI settings as successful save
update_option returns false when values are identical, which made POST /ai/settings respond 400 with "保存失败" on no-op saves and masked-key re-saves. Normalize config, accept no-op as success, and only send a new API key from the admin form when entered.
This commit is contained in:
@@ -216,9 +216,17 @@ export default {
|
|||||||
async function saveSettings() {
|
async function saveSettings() {
|
||||||
saving.value = true;
|
saving.value = true;
|
||||||
try {
|
try {
|
||||||
const payload = { ...form };
|
const payload = {
|
||||||
if (!payload.api_key && status.value.configured) {
|
enabled: form.enabled,
|
||||||
payload.api_key = '***';
|
provider: form.provider,
|
||||||
|
api_base: form.api_base,
|
||||||
|
model: form.model,
|
||||||
|
max_tokens: form.max_tokens,
|
||||||
|
rate_limit: form.rate_limit,
|
||||||
|
};
|
||||||
|
// Only send api_key when the user entered a new one.
|
||||||
|
if (form.api_key && form.api_key !== '***') {
|
||||||
|
payload.api_key = form.api_key;
|
||||||
}
|
}
|
||||||
const json = await api.updateAiSettings(payload);
|
const json = await api.updateAiSettings(payload);
|
||||||
alert(json.message || '设置已保存');
|
alert(json.message || '设置已保存');
|
||||||
|
|||||||
@@ -130,7 +130,10 @@ class AKSRT_Admin_AI_Controller extends AKSRT_Admin_Controller_Base {
|
|||||||
|
|
||||||
$success = AKSRT_AI::get_instance()->update_config($config);
|
$success = AKSRT_AI::get_instance()->update_config($config);
|
||||||
if ($success) {
|
if ($success) {
|
||||||
return $this->success(['message' => __('AI 设置已保存', 'aksrt')]);
|
return $this->success([
|
||||||
|
'message' => __('AI 设置已保存', 'aksrt'),
|
||||||
|
'data' => AKSRT_AI::get_instance()->get_status(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
return $this->error(__('保存失败', 'aksrt'));
|
return $this->error(__('保存失败', 'aksrt'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,11 +54,60 @@ class AKSRT_AI {
|
|||||||
$current = $this->get_config();
|
$current = $this->get_config();
|
||||||
$merged = array_merge($current, $config);
|
$merged = array_merge($current, $config);
|
||||||
|
|
||||||
|
// Preserve existing key when client sends the masked placeholder.
|
||||||
if (isset($config['api_key']) && $config['api_key'] === '***') {
|
if (isset($config['api_key']) && $config['api_key'] === '***') {
|
||||||
$merged['api_key'] = $current['api_key'];
|
$merged['api_key'] = $current['api_key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_option('aksrt_ai_settings', $merged);
|
$merged['enabled'] = !empty($merged['enabled']);
|
||||||
|
$merged['provider'] = sanitize_key((string) ($merged['provider'] ?? self::PROVIDER_NONE));
|
||||||
|
$merged['api_key'] = (string) ($merged['api_key'] ?? '');
|
||||||
|
$merged['api_base'] = esc_url_raw((string) ($merged['api_base'] ?? 'https://api.openai.com/v1'));
|
||||||
|
$merged['model'] = sanitize_text_field((string) ($merged['model'] ?? 'gpt-3.5-turbo'));
|
||||||
|
$merged['max_tokens'] = max(100, min(4000, (int) ($merged['max_tokens'] ?? 1000)));
|
||||||
|
$merged['rate_limit'] = max(1, min(100, (int) ($merged['rate_limit'] ?? 10)));
|
||||||
|
|
||||||
|
// Persist only the known keys so shape stays stable.
|
||||||
|
$to_store = [
|
||||||
|
'enabled' => $merged['enabled'],
|
||||||
|
'provider' => $merged['provider'],
|
||||||
|
'api_key' => $merged['api_key'],
|
||||||
|
'api_base' => $merged['api_base'],
|
||||||
|
'model' => $merged['model'],
|
||||||
|
'max_tokens' => $merged['max_tokens'],
|
||||||
|
'rate_limit' => $merged['rate_limit'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$before = get_option('aksrt_ai_settings', []);
|
||||||
|
$updated = update_option('aksrt_ai_settings', $to_store);
|
||||||
|
if ($updated) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_option returns false when the value is unchanged — treat as success.
|
||||||
|
if (is_array($before)) {
|
||||||
|
$before_normalized = array_merge([
|
||||||
|
'enabled' => false,
|
||||||
|
'provider' => self::PROVIDER_NONE,
|
||||||
|
'api_key' => '',
|
||||||
|
'api_base' => 'https://api.openai.com/v1',
|
||||||
|
'model' => 'gpt-3.5-turbo',
|
||||||
|
'max_tokens' => 1000,
|
||||||
|
'rate_limit' => 10,
|
||||||
|
], $before);
|
||||||
|
$before_normalized['enabled'] = !empty($before_normalized['enabled']);
|
||||||
|
$before_normalized['provider'] = sanitize_key((string) ($before_normalized['provider'] ?? self::PROVIDER_NONE));
|
||||||
|
$before_normalized['api_key'] = (string) ($before_normalized['api_key'] ?? '');
|
||||||
|
$before_normalized['api_base'] = esc_url_raw((string) ($before_normalized['api_base'] ?? 'https://api.openai.com/v1'));
|
||||||
|
$before_normalized['model'] = sanitize_text_field((string) ($before_normalized['model'] ?? 'gpt-3.5-turbo'));
|
||||||
|
$before_normalized['max_tokens'] = max(100, min(4000, (int) ($before_normalized['max_tokens'] ?? 1000)));
|
||||||
|
$before_normalized['rate_limit'] = max(1, min(100, (int) ($before_normalized['rate_limit'] ?? 10)));
|
||||||
|
|
||||||
|
return maybe_serialize($before_normalized) === maybe_serialize($to_store)
|
||||||
|
|| $before_normalized == $to_store;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maybe_serialize($before) === maybe_serialize($to_store);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user