feat(temple): add Temple modal with Tools browser and Skills management
This commit is contained in:
133
frontend/src/pages/temple/composables/useTemple.ts
Normal file
133
frontend/src/pages/temple/composables/useTemple.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { toolsApi, type ToolCategory, type ToolInfo, type ToolsResponse } from '@/api/tools'
|
||||
|
||||
export type TabType = 'tools' | 'skills'
|
||||
|
||||
export function useTemple() {
|
||||
// ===== State =====
|
||||
const activeTab = ref<TabType>('tools')
|
||||
const toolsLoading = ref(false)
|
||||
const toolsError = ref<string | null>(null)
|
||||
|
||||
// Tools data
|
||||
const categories = ref<ToolCategory[]>([])
|
||||
const summary = ref({
|
||||
total_commands: 0,
|
||||
active_commands: 0,
|
||||
total_tools: 0,
|
||||
manifest_tools: 0,
|
||||
agent_tools: 0,
|
||||
})
|
||||
|
||||
// Selection state (Tools Tab)
|
||||
const selectedCategory = ref<string | null>(null) // 大分类名,如 "注册层"
|
||||
const selectedSubgroup = ref<string | null>(null) // 子分类名,如 "文件操作"
|
||||
const selectedTool = ref<ToolInfo | null>(null)
|
||||
|
||||
// ===== Computed =====
|
||||
|
||||
/** 展平所有工具列表 */
|
||||
const allTools = computed(() => {
|
||||
return categories.value.flatMap((cat) =>
|
||||
cat.subgroups.flatMap((sub) => sub.tools)
|
||||
)
|
||||
})
|
||||
|
||||
/** 当前选中的大分类下的子分类 */
|
||||
const currentSubgroups = computed(() => {
|
||||
if (!selectedCategory.value) return []
|
||||
const cat = categories.value.find((c) => c.name === selectedCategory.value)
|
||||
return cat?.subgroups ?? []
|
||||
})
|
||||
|
||||
/** 当前选中子分类下的工具 */
|
||||
const currentTools = computed(() => {
|
||||
if (!selectedSubgroup.value) return []
|
||||
for (const cat of categories.value) {
|
||||
const sub = cat.subgroups.find((s) => s.name === selectedSubgroup.value)
|
||||
if (sub) return sub.tools
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
/** 当前选中工具的详情 */
|
||||
const currentToolDetail = computed(() => selectedTool.value)
|
||||
|
||||
// ===== Actions =====
|
||||
|
||||
async function fetchTools() {
|
||||
toolsLoading.value = true
|
||||
toolsError.value = null
|
||||
try {
|
||||
const res = await toolsApi.list()
|
||||
const data: ToolsResponse = res.data
|
||||
categories.value = data.categories
|
||||
summary.value = data.summary
|
||||
// 默认选中第一个分类和子分类
|
||||
if (categories.value.length > 0) {
|
||||
const firstCat = categories.value[0]
|
||||
selectedCategory.value = firstCat.name
|
||||
if (firstCat.subgroups.length > 0) {
|
||||
selectedSubgroup.value = firstCat.subgroups[0].name
|
||||
}
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
toolsError.value = e instanceof Error ? e.message : 'Failed to load tools'
|
||||
console.error('[useTemple] fetchTools error:', e)
|
||||
} finally {
|
||||
toolsLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function selectCategory(name: string) {
|
||||
selectedCategory.value = name
|
||||
selectedSubgroup.value = null
|
||||
selectedTool.value = null
|
||||
// 自动选中第一个子分类
|
||||
const cat = categories.value.find((c) => c.name === name)
|
||||
if (cat && cat.subgroups.length > 0) {
|
||||
selectedSubgroup.value = cat.subgroups[0].name
|
||||
}
|
||||
}
|
||||
|
||||
function selectSubgroup(name: string) {
|
||||
selectedSubgroup.value = name
|
||||
selectedTool.value = null
|
||||
}
|
||||
|
||||
function selectTool(tool: ToolInfo) {
|
||||
selectedTool.value = tool
|
||||
}
|
||||
|
||||
function clearToolSelection() {
|
||||
selectedTool.value = null
|
||||
}
|
||||
|
||||
function switchTab(tab: TabType) {
|
||||
activeTab.value = tab
|
||||
}
|
||||
|
||||
return {
|
||||
// State
|
||||
activeTab,
|
||||
toolsLoading,
|
||||
toolsError,
|
||||
categories,
|
||||
summary,
|
||||
selectedCategory,
|
||||
selectedSubgroup,
|
||||
selectedTool,
|
||||
// Computed
|
||||
allTools,
|
||||
currentSubgroups,
|
||||
currentTools,
|
||||
currentToolDetail,
|
||||
// Actions
|
||||
fetchTools,
|
||||
selectCategory,
|
||||
selectSubgroup,
|
||||
selectTool,
|
||||
clearToolSelection,
|
||||
switchTab,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user