fix(skills): P3 frontend polish for skill/agent category split
Deploy to Production / deploy (push) Waiting to run
Details
Deploy to Production / deploy (push) Waiting to run
Details
- skills.ts: make category/agent_type/execution_mode/task_mode optional in ISkillInfo and ISkillDetail for backward compat during rollout - SkillCard.vue: remove dead size="small" on a-tag, add title attr for a11y, add isEngine computed, CSS fallback cleanup, category fallback in class binding - SkillsView.vue: fix a-empty condition to use grouped counts so orphan skills (category mismatch) don't render a blank page - SkillsTab.vue: add type tag (引擎/技能) and category-based icon (thunderbolt for engine, appstore for business), remove size="small", add engine icon color variant
This commit is contained in:
parent
a672dddc9a
commit
3d108dd08e
|
|
@ -13,11 +13,11 @@ export interface ISkillInfo {
|
|||
capabilities: string[]
|
||||
dependencies: string[]
|
||||
status: string
|
||||
/** "agent_template" = 通用执行引擎 (react/direct/rewoo/...); "business_skill" = 业务领域技能 */
|
||||
category: SkillCategory
|
||||
agent_type: string
|
||||
execution_mode: string
|
||||
task_mode: string
|
||||
/** "agent_template" = 通用执行引擎 (react/direct/rewoo/...); "business_skill" = 业务领域技能. Optional for backward compat during rollout. */
|
||||
category?: SkillCategory
|
||||
agent_type?: string
|
||||
execution_mode?: string
|
||||
task_mode?: string
|
||||
}
|
||||
|
||||
export interface ISkillDetail {
|
||||
|
|
@ -28,10 +28,10 @@ export interface ISkillDetail {
|
|||
dependencies: string[]
|
||||
config: Record<string, unknown>
|
||||
health_status: string
|
||||
category: SkillCategory
|
||||
agent_type: string
|
||||
execution_mode: string
|
||||
task_mode: string
|
||||
category?: SkillCategory
|
||||
agent_type?: string
|
||||
execution_mode?: string
|
||||
task_mode?: string
|
||||
}
|
||||
|
||||
export interface ICapabilityInfo {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,19 @@
|
|||
v-for="skill in skillsStore.skills"
|
||||
:key="skill.name"
|
||||
class="skills-tab__item"
|
||||
:class="`skills-tab__item--${skill.category || 'business_skill'}`"
|
||||
@click="openSkill(skill.name)"
|
||||
>
|
||||
<div class="skills-tab__item-header">
|
||||
<AppstoreOutlined class="skills-tab__item-icon" />
|
||||
<component :is="iconFor(skill)" class="skills-tab__item-icon" />
|
||||
<span class="skills-tab__item-name">{{ skill.name }}</span>
|
||||
<a-tag
|
||||
class="skills-tab__item-type"
|
||||
:color="isEngine(skill) ? 'purple' : 'blue'"
|
||||
:title="isEngine(skill) ? '执行引擎模板' : '业务领域技能'"
|
||||
>
|
||||
{{ isEngine(skill) ? '引擎' : '技能' }}
|
||||
</a-tag>
|
||||
<a-badge
|
||||
class="skills-tab__item-status"
|
||||
:status="skill.status === 'active' ? 'success' : 'default'"
|
||||
|
|
@ -33,7 +41,7 @@
|
|||
</div>
|
||||
<p class="skills-tab__item-desc">{{ skill.description || '暂无描述' }}</p>
|
||||
<div class="skills-tab__item-tags">
|
||||
<a-tag v-for="cap in skill.capabilities.slice(0, 3)" :key="cap" size="small">
|
||||
<a-tag v-for="cap in skill.capabilities.slice(0, 3)" :key="cap">
|
||||
{{ cap }}
|
||||
</a-tag>
|
||||
<span v-if="skill.capabilities.length > 3" class="skills-tab__item-more">
|
||||
|
|
@ -53,13 +61,22 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { AppstoreOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||
import { AppstoreOutlined, ThunderboltOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||
import { useSkillsStore } from '@/stores/skills'
|
||||
import type { ISkillInfo } from '@/api/skills'
|
||||
import SkillDetail from '@/components/skills/SkillDetail.vue'
|
||||
|
||||
const skillsStore = useSkillsStore()
|
||||
const detailVisible = ref(false)
|
||||
|
||||
function isEngine(skill: ISkillInfo): boolean {
|
||||
return skill.category === 'agent_template'
|
||||
}
|
||||
|
||||
function iconFor(skill: ISkillInfo) {
|
||||
return isEngine(skill) ? ThunderboltOutlined : AppstoreOutlined
|
||||
}
|
||||
|
||||
async function openSkill(name: string): Promise<void> {
|
||||
await skillsStore.fetchSkillDetail(name)
|
||||
detailVisible.value = true
|
||||
|
|
@ -130,6 +147,14 @@ onMounted(() => {
|
|||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.skills-tab__item--agent_template .skills-tab__item-icon {
|
||||
color: var(--accent-board);
|
||||
}
|
||||
|
||||
.skills-tab__item-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.skills-tab__item-name {
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--text-primary);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="skill-card" :class="`skill-card--${skill.category}`" @click="$emit('click')">
|
||||
<div class="skill-card" :class="`skill-card--${skill.category || 'business_skill'}`" @click="$emit('click')">
|
||||
<a-card hoverable size="small">
|
||||
<template #title>
|
||||
<div class="skill-card__title">
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
<template #extra>
|
||||
<div class="skill-card__badges">
|
||||
<a-tag
|
||||
:color="skill.category === 'agent_template' ? 'purple' : 'blue'"
|
||||
size="small"
|
||||
:color="isEngine ? 'purple' : 'blue'"
|
||||
class="skill-card__type-tag"
|
||||
:title="isEngine ? '执行引擎模板' : '业务领域技能'"
|
||||
>
|
||||
{{ skill.category === 'agent_template' ? '引擎' : '技能' }}
|
||||
{{ isEngine ? '引擎' : '技能' }}
|
||||
</a-tag>
|
||||
<a-badge
|
||||
:status="skill.status === 'active' ? 'success' : 'default'"
|
||||
|
|
@ -28,13 +28,13 @@
|
|||
<code class="skill-card__mode-value">{{ modeText }}</code>
|
||||
</div>
|
||||
<div class="skill-card__tags">
|
||||
<a-tag v-for="cap in skill.capabilities" :key="cap" size="small" color="blue">
|
||||
<a-tag v-for="cap in skill.capabilities" :key="cap" color="blue">
|
||||
{{ cap }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div v-if="skill.dependencies.length > 0" class="skill-card__deps">
|
||||
<span class="skill-card__deps-label">依赖:</span>
|
||||
<a-tag v-for="dep in skill.dependencies.slice(0, 3)" :key="dep" size="small">
|
||||
<a-tag v-for="dep in skill.dependencies.slice(0, 3)" :key="dep">
|
||||
{{ dep }}
|
||||
</a-tag>
|
||||
<span v-if="skill.dependencies.length > 3" class="skill-card__more">
|
||||
|
|
@ -61,22 +61,18 @@ defineEmits<{
|
|||
click: []
|
||||
}>()
|
||||
|
||||
const isEngine = computed(() => props.skill.category === 'agent_template')
|
||||
|
||||
// Differentiate icon by category: engine = thunderbolt, business = appstore
|
||||
const titleIcon = computed(() =>
|
||||
props.skill.category === 'agent_template' ? ThunderboltOutlined : AppstoreOutlined
|
||||
)
|
||||
const titleIcon = computed(() => (isEngine.value ? ThunderboltOutlined : AppstoreOutlined))
|
||||
|
||||
// Show the most relevant mode field.
|
||||
// Agent templates: execution_mode (react/direct/rewoo/...).
|
||||
// Business skills: agent_type (the domain identifier).
|
||||
const modeText = computed(() =>
|
||||
props.skill.category === 'agent_template'
|
||||
? props.skill.execution_mode
|
||||
: props.skill.agent_type
|
||||
)
|
||||
const modeLabel = computed(() =>
|
||||
props.skill.category === 'agent_template' ? '执行模式' : '领域类型'
|
||||
isEngine.value ? props.skill.execution_mode : props.skill.agent_type
|
||||
)
|
||||
const modeLabel = computed(() => (isEngine.value ? '执行模式' : '领域类型'))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -118,7 +114,7 @@ const modeLabel = computed(() =>
|
|||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-bottom: var(--space-2);
|
||||
font-size: var(--font-xs, 12px);
|
||||
font-size: var(--font-xs);
|
||||
}
|
||||
|
||||
.skill-card__mode-label {
|
||||
|
|
@ -128,7 +124,7 @@ const modeLabel = computed(() =>
|
|||
.skill-card__mode-value {
|
||||
font-family: 'SF Mono', 'Fira Code', Menlo, Consolas, monospace;
|
||||
color: var(--text-secondary);
|
||||
background: var(--bg-secondary, rgba(0, 0, 0, 0.04));
|
||||
background: var(--bg-secondary);
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
</section>
|
||||
|
||||
<a-empty
|
||||
v-if="!skillsStore.isLoading && skillsStore.skills.length === 0"
|
||||
v-if="!skillsStore.isLoading && skillsStore.agentTemplates.length + skillsStore.businessSkills.length === 0"
|
||||
description="暂无已注册技能"
|
||||
/>
|
||||
</a-spin>
|
||||
|
|
|
|||
Loading…
Reference in New Issue