mixvideo-v2/apps/desktop/src/store/materialSegmentViewStore.ts

270 lines
7.6 KiB
TypeScript

import { create } from 'zustand';
import { invoke } from '@tauri-apps/api/core';
import {
MaterialSegmentView,
MaterialSegmentQuery,
MaterialSegmentViewMode,
SegmentActionRequest,
SegmentActionType,
} from '../types/materialSegmentView';
interface MaterialSegmentViewState {
// 数据状态
currentView: MaterialSegmentView | null;
viewMode: MaterialSegmentViewMode;
isLoading: boolean;
error: string | null;
// 查询状态
currentQuery: MaterialSegmentQuery | null;
// UI状态
selectedSegmentIds: Set<string>;
expandedGroups: Set<string>;
// Actions
loadProjectSegmentView: (projectId: string) => Promise<void>;
loadProjectSegmentViewWithQuery: (query: MaterialSegmentQuery) => Promise<void>;
setViewMode: (mode: MaterialSegmentViewMode) => void;
updateQuery: (updates: Partial<MaterialSegmentQuery>) => void;
clearQuery: () => void;
// 选择管理
selectSegment: (segmentId: string) => void;
deselectSegment: (segmentId: string) => void;
selectAllSegments: () => void;
clearSelection: () => void;
// 分组管理
expandGroup: (groupId: string) => void;
collapseGroup: (groupId: string) => void;
toggleGroup: (groupId: string) => void;
expandAllGroups: () => void;
collapseAllGroups: () => void;
// 片段操作
executeSegmentAction: (request: SegmentActionRequest) => Promise<void>;
// 工具方法
refreshCurrentView: () => Promise<void>;
clearError: () => void;
}
export const useMaterialSegmentViewStore = create<MaterialSegmentViewState>((set, get) => ({
// 初始状态
currentView: null,
viewMode: MaterialSegmentViewMode.ByClassification,
isLoading: false,
error: null,
currentQuery: null,
selectedSegmentIds: new Set(),
expandedGroups: new Set(),
// 加载项目的MaterialSegment聚合视图
loadProjectSegmentView: async (projectId: string) => {
set({ isLoading: true, error: null });
try {
const view = await invoke<MaterialSegmentView>('get_project_segment_view', { projectId });
set({
currentView: view,
isLoading: false,
currentQuery: { project_id: projectId }
});
} catch (error) {
const errorMessage = typeof error === 'string' ? error : '加载MaterialSegment视图失败';
set({ error: errorMessage, isLoading: false });
throw new Error(errorMessage);
}
},
// 根据查询条件加载MaterialSegment聚合视图
loadProjectSegmentViewWithQuery: async (query: MaterialSegmentQuery) => {
set({ isLoading: true, error: null });
try {
const view = await invoke<MaterialSegmentView>('get_project_segment_view_with_query', { query });
set({
currentView: view,
isLoading: false,
currentQuery: query
});
} catch (error) {
const errorMessage = typeof error === 'string' ? error : '加载MaterialSegment视图失败';
set({ error: errorMessage, isLoading: false });
throw new Error(errorMessage);
}
},
// 设置视图模式
setViewMode: (mode: MaterialSegmentViewMode) => {
const currentQuery = get().currentQuery;
set({ viewMode: mode });
// 如果有当前查询,重新加载数据以应用新的视图模式
if (currentQuery) {
console.log('视图模式切换到:', mode === MaterialSegmentViewMode.ByClassification ? '按分类' : '按模特');
// 视图模式是前端状态,不需要传递给后端,只需要重新加载当前数据
get().loadProjectSegmentViewWithQuery(currentQuery);
}
},
// 更新查询条件
updateQuery: (updates: Partial<MaterialSegmentQuery>) => {
const currentQuery = get().currentQuery;
if (!currentQuery) return;
const newQuery = { ...currentQuery, ...updates };
get().loadProjectSegmentViewWithQuery(newQuery);
},
// 清除查询条件
clearQuery: () => {
const currentQuery = get().currentQuery;
if (!currentQuery) return;
const baseQuery: MaterialSegmentQuery = {
project_id: currentQuery.project_id,
};
get().loadProjectSegmentViewWithQuery(baseQuery);
},
// 选择片段
selectSegment: (segmentId: string) => {
set(state => ({
selectedSegmentIds: new Set([...state.selectedSegmentIds, segmentId])
}));
},
// 取消选择片段
deselectSegment: (segmentId: string) => {
set(state => {
const newSelection = new Set(state.selectedSegmentIds);
newSelection.delete(segmentId);
return { selectedSegmentIds: newSelection };
});
},
// 选择所有片段
selectAllSegments: () => {
const view = get().currentView;
if (!view) return;
const allSegmentIds = new Set<string>();
// 根据当前视图模式收集所有片段ID
if (get().viewMode === MaterialSegmentViewMode.ByClassification) {
view.by_classification.forEach(group => {
group.segments.forEach(segment => {
allSegmentIds.add(segment.segment.id);
});
});
} else {
view.by_model.forEach(group => {
group.segments.forEach(segment => {
allSegmentIds.add(segment.segment.id);
});
});
}
set({ selectedSegmentIds: allSegmentIds });
},
// 清除选择
clearSelection: () => {
set({ selectedSegmentIds: new Set() });
},
// 展开分组
expandGroup: (groupId: string) => {
set(state => ({
expandedGroups: new Set([...state.expandedGroups, groupId])
}));
},
// 折叠分组
collapseGroup: (groupId: string) => {
set(state => {
const newExpanded = new Set(state.expandedGroups);
newExpanded.delete(groupId);
return { expandedGroups: newExpanded };
});
},
// 切换分组展开状态
toggleGroup: (groupId: string) => {
const expandedGroups = get().expandedGroups;
if (expandedGroups.has(groupId)) {
get().collapseGroup(groupId);
} else {
get().expandGroup(groupId);
}
},
// 展开所有分组
expandAllGroups: () => {
const view = get().currentView;
if (!view) return;
const allGroupIds = new Set<string>();
if (get().viewMode === MaterialSegmentViewMode.ByClassification) {
view.by_classification.forEach(group => {
allGroupIds.add(group.category);
});
} else {
view.by_model.forEach(group => {
allGroupIds.add(group.model_id);
});
}
set({ expandedGroups: allGroupIds });
},
// 折叠所有分组
collapseAllGroups: () => {
set({ expandedGroups: new Set() });
},
// 执行片段操作
executeSegmentAction: async (request: SegmentActionRequest) => {
set({ isLoading: true, error: null });
try {
// 根据操作类型调用相应的后端命令
switch (request.action_type) {
case SegmentActionType.Reclassify:
// TODO: 实现重新分类逻辑
break;
case SegmentActionType.EditModel:
// TODO: 实现编辑模特关联逻辑
break;
case SegmentActionType.Delete:
// TODO: 实现删除逻辑
break;
case SegmentActionType.ViewDetails:
// TODO: 实现查看详情逻辑
break;
}
// 刷新当前视图
await get().refreshCurrentView();
set({ isLoading: false });
} catch (error) {
const errorMessage = typeof error === 'string' ? error : '执行操作失败';
set({ error: errorMessage, isLoading: false });
throw new Error(errorMessage);
}
},
// 刷新当前视图
refreshCurrentView: async () => {
const currentQuery = get().currentQuery;
if (!currentQuery) return;
await get().loadProjectSegmentViewWithQuery(currentQuery);
},
// 清除错误
clearError: () => {
set({ error: null });
},
}));