feat(market): 技能/MCP 分类改为面向用户的业务场景(人群->场景),AI验证期按场景归类
This commit is contained in:
1 parent
6f3fb400a4
commit
9bcf15099f
4 files changed
+136
-38
No files matched your search
@@ -1744,10 +1744,26 @@
|
||||
.capability-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
padding: var(--space-sm) 0 0;
|
||||
}
|
||||
|
||||
.cap-group-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: var(--space-sm);
|
||||
padding: 0 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-tertiary);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.cap-group-label:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.cap-chip {
|
||||
padding: 4px 12px;
|
||||
font-size: var(--text-xs);
|
||||
|
||||
@@ -182,30 +182,53 @@ const typeIcons: Record<AppType, React.ReactNode> = {
|
||||
mcp: <McpIcon />,
|
||||
};
|
||||
|
||||
// ===== 能力分类(与后端 11 种能力保持一致) =====
|
||||
const CAPABILITIES: { id: string; label: string; color: string }[] = [
|
||||
{ id: 'text', label: '文本对话', color: '#5B5FED' },
|
||||
{ id: 'thinking', label: '推理思考', color: '#8B5CF6' },
|
||||
{ id: 'vision', label: '视觉理解', color: '#219B5E' },
|
||||
{ id: 'tool', label: '工具调用', color: '#3B82F6' },
|
||||
{ id: 'image', label: '图像生成', color: '#D9383A' },
|
||||
{ id: 'audio', label: '语音合成', color: '#E8922C' },
|
||||
{ id: 'asr', label: '语音识别', color: '#0EA5E9' },
|
||||
{ id: 'ocr', label: 'OCR识别', color: '#F59E0B' },
|
||||
{ id: 'embedding', label: '嵌入向量', color: '#10B981' },
|
||||
{ id: 'rerank', label: '重排序', color: '#EC4899' },
|
||||
{ id: 'video', label: '视频生成', color: '#EF4444' },
|
||||
// ===== 业务场景分类(面向用户的技能/MCP 分类,与后端模型路由能力解耦) =====
|
||||
// 两级:人群大类(SCENE_GROUPS) -> 业务场景(SCENES)。id 与后端 MARKET_SCENES 保持一致。
|
||||
const SCENES: { id: string; label: string; color: string; group: string }[] = [
|
||||
// 自由职业者
|
||||
{ id: 'freelance_content', label: '内容创作/自媒体', color: '#F59E0B', group: 'freelance' },
|
||||
{ id: 'freelance_client', label: '客户沟通/提案', color: '#F97316', group: 'freelance' },
|
||||
{ id: 'freelance_finance', label: '报价合同/记账', color: '#FBBF24', group: 'freelance' },
|
||||
// 上班从业者
|
||||
{ id: 'office_doc', label: '文档/会议纪要', color: '#3B82F6', group: 'office' },
|
||||
{ id: 'office_data', label: '数据/报表分析', color: '#6366F1', group: 'office' },
|
||||
{ id: 'office_email', label: '邮件/协作', color: '#0EA5E9', group: 'office' },
|
||||
{ id: 'office_pm', label: '项目/周报', color: '#8B5CF6', group: 'office' },
|
||||
// 育人教育者
|
||||
{ id: 'edu_prepare', label: '备课/课件', color: '#10B981', group: 'educator' },
|
||||
{ id: 'edu_grade', label: '作业批改/测评', color: '#14B8A6', group: 'educator' },
|
||||
{ id: 'edu_tutor', label: '学情辅导/答疑', color: '#22C55E', group: 'educator' },
|
||||
{ id: 'edu_home', label: '家校沟通', color: '#84CC16', group: 'educator' },
|
||||
// 电商创业
|
||||
{ id: 'biz_product', label: '商品/营销文案', color: '#EC4899', group: 'commerce' },
|
||||
{ id: 'biz_service', label: '客服/转化', color: '#F43F5E', group: 'commerce' },
|
||||
{ id: 'biz_ops', label: '运营/投放', color: '#D946EF', group: 'commerce' },
|
||||
// 通用提效
|
||||
{ id: 'general_write', label: '通用写作', color: '#64748B', group: 'general' },
|
||||
{ id: 'general_research', label: '资料/调研', color: '#06B6D4', group: 'general' },
|
||||
{ id: 'general_agent', label: '智能体/自动化', color: '#A855F7', group: 'general' },
|
||||
];
|
||||
const SCENE_GROUPS: { id: string; label: string }[] = [
|
||||
{ id: 'freelance', label: '自由职业者' },
|
||||
{ id: 'office', label: '上班从业者' },
|
||||
{ id: 'educator', label: '育人教育者' },
|
||||
{ id: 'commerce', label: '电商创业' },
|
||||
{ id: 'general', label: '通用提效' },
|
||||
];
|
||||
const SCENE_BY_GROUP: Record<string, typeof SCENES> = SCENE_GROUPS.reduce((acc, g) => {
|
||||
acc[g.id] = SCENES.filter(s => s.group === g.id);
|
||||
return acc;
|
||||
}, {} as Record<string, typeof SCENES>);
|
||||
|
||||
function CapabilityBadge({ capability }: { capability?: string | null }) {
|
||||
if (!capability) return null;
|
||||
const cap = CAPABILITIES.find(c => c.id === capability);
|
||||
const cap = SCENES.find(c => c.id === capability);
|
||||
if (!cap) return null;
|
||||
return (
|
||||
<span
|
||||
className="capability-badge"
|
||||
style={{ color: cap.color, background: cap.color + '1A', borderColor: cap.color + '40' }}
|
||||
title={`能力分类:${cap.label}`}
|
||||
title={`业务场景:${cap.label}`}
|
||||
>
|
||||
{cap.label}
|
||||
</span>
|
||||
@@ -751,7 +774,7 @@ const CreateToolModal: React.FC<CreateToolModalProps> = ({ appType, onClose, onS
|
||||
<label className="form-label">能力分类 <span className="cap-hint">(AI验证后自动识别,可修改)</span></label>
|
||||
<select className="form-input" value={capability} onChange={e => setCapability(e.target.value)}>
|
||||
<option value="">未指定(由AI自动归类)</option>
|
||||
{CAPABILITIES.map(c => (
|
||||
{SCENES.map(c => (
|
||||
<option key={c.id} value={c.id}>{c.label}</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -1134,7 +1157,7 @@ const HubImportModal: React.FC<HubImportModalProps> = ({ appType, platforms, onC
|
||||
<label className="form-label">能力分类 <span className="cap-hint">(AI验证后自动识别,可修改)</span></label>
|
||||
<select className="form-input" value={capability} onChange={e => setCap(e.target.value)}>
|
||||
<option value="">未指定(由AI自动归类)</option>
|
||||
{CAPABILITIES.map(c => (
|
||||
{SCENES.map(c => (
|
||||
<option key={c.id} value={c.id}>{c.label}</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -1460,7 +1483,7 @@ const AgentConnectModal: React.FC<AgentConnectModalProps> = ({ onClose, onConnec
|
||||
<label className="form-label">能力分类 <span className="cap-hint">(可选,未指定由AI自动归类)</span></label>
|
||||
<select className="form-input" value={capability} onChange={e => setCapability(e.target.value)}>
|
||||
<option value="">未指定(由AI自动归类)</option>
|
||||
{CAPABILITIES.map(c => (
|
||||
{SCENES.map(c => (
|
||||
<option key={c.id} value={c.id}>{c.label}</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -1799,19 +1822,24 @@ const MarketPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 能力分类筛选 */}
|
||||
{/* 业务场景筛选(按人群分组) */}
|
||||
<div className="capability-filter">
|
||||
<button
|
||||
className={`cap-chip ${!capabilityFilter ? 'active' : ''}`}
|
||||
onClick={() => setCapabilityFilter(null)}
|
||||
>全部能力</button>
|
||||
{CAPABILITIES.map(c => (
|
||||
<button
|
||||
key={c.id}
|
||||
className={`cap-chip ${capabilityFilter === c.id ? 'active' : ''}`}
|
||||
style={capabilityFilter === c.id ? { color: '#fff', background: c.color, borderColor: c.color } : { color: c.color, borderColor: c.color + '55' }}
|
||||
onClick={() => setCapabilityFilter(capabilityFilter === c.id ? null : c.id)}
|
||||
>{c.label}</button>
|
||||
>全部场景</button>
|
||||
{SCENE_GROUPS.map(g => (
|
||||
<React.Fragment key={g.id}>
|
||||
<span className="cap-group-label">{g.label}</span>
|
||||
{SCENE_BY_GROUP[g.id].map(c => (
|
||||
<button
|
||||
key={c.id}
|
||||
className={`cap-chip ${capabilityFilter === c.id ? 'active' : ''}`}
|
||||
style={capabilityFilter === c.id ? { color: '#fff', background: c.color, borderColor: c.color } : { color: c.color, borderColor: c.color + '55' }}
|
||||
onClick={() => setCapabilityFilter(capabilityFilter === c.id ? null : c.id)}
|
||||
>{c.label}</button>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user