feat(ollama): 按模型请求刷新云端用量

将 Ollama Cloud settings HTML 自动抓取从固定间隔轮询改为请求驱动的
trailing debounce + max-wait:无新请求不再抓取,连续请求最晚在
max-wait 强制刷新;失败退避仍优先于活动 due。新增 debounce_minutes
(默认 1),interval_minutes 保留为最长等待兼容字段。
This commit is contained in:
alfadb
2026-07-25 15:37:05 +08:00
parent 43d4bae246
commit 0f72b7dca7
17 changed files with 504 additions and 122 deletions
+38 -17
View File
@@ -4220,23 +4220,43 @@
data-testid="ollama-cloud-usage-global-enabled"
/>
</div>
<div v-if="ollamaCloudUsageForm.enabled" class="border-t border-gray-100 pt-4 dark:border-dark-700">
<label class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300" for="ollama-cloud-usage-interval">
{{ t("admin.settings.ollamaCloudUsage.intervalMinutes") }}
</label>
<input
id="ollama-cloud-usage-interval"
v-model.number="ollamaCloudUsageForm.interval_minutes"
type="number"
min="15"
max="1440"
class="input w-32"
data-testid="ollama-cloud-usage-global-interval"
@keydown.enter.prevent="saveOllamaCloudUsageSettings"
/>
<p class="mt-1.5 text-xs text-gray-500 dark:text-gray-400">
{{ t("admin.settings.ollamaCloudUsage.intervalHint") }}
</p>
<div v-if="ollamaCloudUsageForm.enabled" class="space-y-4 border-t border-gray-100 pt-4 dark:border-dark-700">
<div>
<label class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300" for="ollama-cloud-usage-debounce">
{{ t("admin.settings.ollamaCloudUsage.debounceMinutes") }}
</label>
<input
id="ollama-cloud-usage-debounce"
v-model.number="ollamaCloudUsageForm.debounce_minutes"
type="number"
min="1"
max="60"
class="input w-32"
data-testid="ollama-cloud-usage-global-debounce"
@keydown.enter.prevent="saveOllamaCloudUsageSettings"
/>
<p class="mt-1.5 text-xs text-gray-500 dark:text-gray-400">
{{ t("admin.settings.ollamaCloudUsage.debounceHint") }}
</p>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300" for="ollama-cloud-usage-interval">
{{ t("admin.settings.ollamaCloudUsage.intervalMinutes") }}
</label>
<input
id="ollama-cloud-usage-interval"
v-model.number="ollamaCloudUsageForm.interval_minutes"
type="number"
min="15"
max="1440"
class="input w-32"
data-testid="ollama-cloud-usage-global-interval"
@keydown.enter.prevent="saveOllamaCloudUsageSettings"
/>
<p class="mt-1.5 text-xs text-gray-500 dark:text-gray-400">
{{ t("admin.settings.ollamaCloudUsage.intervalHint") }}
</p>
</div>
</div>
<div class="flex justify-end border-t border-gray-100 pt-4 dark:border-dark-700">
<button
@@ -7934,6 +7954,7 @@ const ollamaCloudUsageSaving = ref(false);
const ollamaCloudUsageForm = reactive({
enabled: false,
interval_minutes: 60,
debounce_minutes: 1,
});
// Overload Cooldown (529) 状态
@@ -50,6 +50,7 @@ const {
getOllamaCloudUsageSettings: vi.fn().mockResolvedValue({
enabled: false,
interval_minutes: 60,
debounce_minutes: 1,
}),
updateOllamaCloudUsageSettings: vi.fn().mockImplementation(async (payload) => payload),
getGroups: vi.fn(),
@@ -647,6 +648,7 @@ describe("admin SettingsView payment visible method controls", () => {
getOllamaCloudUsageSettings.mockResolvedValue({
enabled: false,
interval_minutes: 60,
debounce_minutes: 1,
});
updateOllamaCloudUsageSettings.mockImplementation(async (payload) => payload);
getGroups.mockResolvedValue([]);
@@ -1007,6 +1009,7 @@ describe("admin SettingsView payment visible method controls", () => {
expect(card.find('[data-testid="ollama-cloud-usage-global-interval"]').exists()).toBe(false);
await card.get('[data-testid="ollama-cloud-usage-global-enabled"]').setValue(true);
await card.get('[data-testid="ollama-cloud-usage-global-debounce"]').setValue(3);
await card.get('[data-testid="ollama-cloud-usage-global-interval"]').setValue(90);
await card.get('[data-testid="ollama-cloud-usage-global-save"]').trigger("click");
await flushPromises();
@@ -1014,6 +1017,7 @@ describe("admin SettingsView payment visible method controls", () => {
expect(updateOllamaCloudUsageSettings).toHaveBeenCalledWith({
enabled: true,
interval_minutes: 90,
debounce_minutes: 3,
});
});