mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-06 20:02:49 +08:00
fix: sidebar clock icon + cron button loading + #35 _normalizeBaseUrl crash
- sidebar.js: add clock SVG to ICONS map for 定时任务 nav item - cron.js: add loading feedback to toggle/delete buttons - dev-api.js: extract _normalizeBaseUrl from handlers object to standalone function Fixes #35: 'Cannot read properties of undefined (reading _normalizeBaseUrl)' Root cause: handlers are called as standalone functions via API middleware, so 'this' is undefined. Moving to a standalone function fixes it.
This commit is contained in:
@@ -992,6 +992,15 @@ const ALWAYS_LOCAL = new Set([
|
||||
'assistant_ensure_data_dir', 'assistant_save_image', 'assistant_load_image', 'assistant_delete_image',
|
||||
])
|
||||
|
||||
// === 工具函数 ===
|
||||
|
||||
// 清理 base URL:去掉尾部斜杠和已知端点路径,防止路径重复
|
||||
function _normalizeBaseUrl(raw) {
|
||||
let base = (raw || '').replace(/\/+$/, '')
|
||||
base = base.replace(/\/(chat\/completions|completions|responses|messages|models)\/?$/, '')
|
||||
return base.replace(/\/+$/, '')
|
||||
}
|
||||
|
||||
// === API Handlers ===
|
||||
|
||||
const handlers = {
|
||||
@@ -2291,16 +2300,9 @@ const handlers = {
|
||||
return { current, latest: null, update_available: false, source: 'chinese' }
|
||||
},
|
||||
|
||||
// 清理 base URL:去掉尾部斜杠和已知端点路径,防止路径重复
|
||||
_normalizeBaseUrl(raw) {
|
||||
let base = raw.replace(/\/+$/, '')
|
||||
base = base.replace(/\/(chat\/completions|completions|responses|messages|models)\/?$/, '')
|
||||
return base.replace(/\/+$/, '')
|
||||
},
|
||||
|
||||
// 模型测试
|
||||
async test_model({ baseUrl, apiKey, modelId }) {
|
||||
const url = `${this._normalizeBaseUrl(baseUrl)}/chat/completions`
|
||||
const url = `${_normalizeBaseUrl(baseUrl)}/chat/completions`
|
||||
const body = JSON.stringify({
|
||||
model: modelId,
|
||||
messages: [{ role: 'user', content: 'Hi' }],
|
||||
@@ -2332,7 +2334,7 @@ const handlers = {
|
||||
},
|
||||
|
||||
async list_remote_models({ baseUrl, apiKey }) {
|
||||
const url = `${this._normalizeBaseUrl(baseUrl)}/models`
|
||||
const url = `${_normalizeBaseUrl(baseUrl)}/models`
|
||||
const headers = {}
|
||||
if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`
|
||||
const controller = new AbortController()
|
||||
|
||||
@@ -91,6 +91,7 @@ const ICONS = {
|
||||
skills: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/></svg>',
|
||||
docker: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="11" width="4" height="3" rx=".5"/><rect x="6" y="11" width="4" height="3" rx=".5"/><rect x="11" y="11" width="4" height="3" rx=".5"/><rect x="6" y="7" width="4" height="3" rx=".5"/><rect x="11" y="7" width="4" height="3" rx=".5"/><rect x="16" y="11" width="4" height="3" rx=".5"/><rect x="11" y="3" width="4" height="3" rx=".5"/><path d="M2 17c1 3 4 5 10 5s9-2 10-5"/></svg>',
|
||||
channels: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>',
|
||||
clock: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',
|
||||
debug: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/><circle cx="12" cy="12" r="3"/></svg>',
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user