fix: address code review findings
- fix(api): use effectiveTokenId in route channel insert to match duplicate detection logic - fix(css): rename keyframes to kebab-case (filter-bar-slide-down/up) - fix(web): wrap "保存中..." text with tr() in ManualRoutePanel - fix(web): use ref for fresh cache check and add error handling in useRouteChannels
This commit is contained in:
@@ -539,7 +539,7 @@ export async function tokensRoutes(app: FastifyInstance) {
|
||||
await db.insert(schema.routeChannels).values({
|
||||
routeId,
|
||||
accountId: item.accountId,
|
||||
tokenId: item.tokenId,
|
||||
tokenId: effectiveTokenId,
|
||||
sourceModel: sourceModel || null,
|
||||
priority: 0,
|
||||
weight: 10,
|
||||
|
||||
+4
-4
@@ -4101,19 +4101,19 @@ textarea {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
animation: filterBarSlideDown 0.22s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
animation: filter-bar-slide-down 0.22s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.route-filter-bar-expanded.is-closing {
|
||||
animation: filterBarSlideUp 0.18s ease forwards;
|
||||
animation: filter-bar-slide-up 0.18s ease forwards;
|
||||
}
|
||||
|
||||
@keyframes filterBarSlideDown {
|
||||
@keyframes filter-bar-slide-down {
|
||||
from { opacity: 0; max-height: 0; transform: translateY(-4px); }
|
||||
to { opacity: 1; max-height: 600px; transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes filterBarSlideUp {
|
||||
@keyframes filter-bar-slide-up {
|
||||
from { opacity: 1; max-height: 600px; }
|
||||
to { opacity: 0; max-height: 0; overflow: hidden; }
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ export default function ManualRoutePanel({
|
||||
className="spinner spinner-sm"
|
||||
style={{ borderTopColor: 'white', borderColor: 'rgba(255,255,255,0.3)' }}
|
||||
/>{' '}
|
||||
保存中...
|
||||
{tr('保存中...')}
|
||||
</>
|
||||
) : (
|
||||
tr(editingRouteId ? '保存群组' : '创建群组')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useRef } from 'react';
|
||||
import { api } from '../../api.js';
|
||||
import { normalizeChannels } from './utils.js';
|
||||
import type { RouteChannel } from './types.js';
|
||||
@@ -6,19 +6,24 @@ import type { RouteChannel } from './types.js';
|
||||
export function useRouteChannels() {
|
||||
const [channelsByRouteId, setChannelsByRouteId] = useState<Record<number, RouteChannel[]>>({});
|
||||
const [loadingChannelsByRouteId, setLoadingChannelsByRouteId] = useState<Record<number, boolean>>({});
|
||||
const channelsByRouteIdRef = useRef(channelsByRouteId);
|
||||
channelsByRouteIdRef.current = channelsByRouteId;
|
||||
|
||||
const loadChannels = useCallback(async (routeId: number, force = false) => {
|
||||
if (!force && channelsByRouteId[routeId]) return channelsByRouteId[routeId];
|
||||
if (!force && channelsByRouteIdRef.current[routeId]) return channelsByRouteIdRef.current[routeId];
|
||||
setLoadingChannelsByRouteId((prev) => ({ ...prev, [routeId]: true }));
|
||||
try {
|
||||
const channels = await api.getRouteChannels(routeId);
|
||||
const sorted = normalizeChannels(channels || []);
|
||||
setChannelsByRouteId((prev) => ({ ...prev, [routeId]: sorted }));
|
||||
return sorted;
|
||||
} catch (error) {
|
||||
console.error(`Failed to load channels for route ${routeId}:`, error);
|
||||
throw error;
|
||||
} finally {
|
||||
setLoadingChannelsByRouteId((prev) => ({ ...prev, [routeId]: false }));
|
||||
}
|
||||
}, [channelsByRouteId]);
|
||||
}, []);
|
||||
|
||||
const invalidateChannels = useCallback((routeId: number) => {
|
||||
setChannelsByRouteId((prev) => {
|
||||
|
||||
Reference in New Issue
Block a user