feat: 审核体系全面改造 — 多维度评分 + 卖点优先级 + AI 语义匹配 + 品牌方 AI 状态通知
后端: - 审核结果拆分为 4 个独立维度 (法规合规/平台规则/品牌安全/Brief匹配度) - 卖点优先级从 required:bool 改为三级 (core/recommended/reference) - AI 语义匹配卖点覆盖 + AI 整体 Brief 匹配度分析 - BriefMatchDetail 评分详情 (覆盖率+亮点+问题点) - min_selling_points 代理商可配置最少卖点数 + Alembic 迁移 - AI 语境复核过滤误报 - Brief AI 解析 + 规则 AI 解析 - AI 未配置/异常时通知品牌方 - 种子数据更新 (新格式审核结果+brief_match_detail) 前端: - 三端审核页面展示四维度评分卡片 - 卖点编辑改为三级优先级选择器 - BriefMatchDetail 展示 (覆盖率进度条+亮点+问题) - min_selling_points 配置 UI - AI 配置页未配置时静默处理 - 文件预览/下载/签名 URL 优化 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
0c59797d5b
commit
0ef7650c09
@@ -477,15 +477,36 @@ export default function AgencyCreatorsPage() {
|
||||
setOpenMenuId(null)
|
||||
}
|
||||
|
||||
// 确认分配项目
|
||||
const handleConfirmAssign = () => {
|
||||
// 确认分配项目(创建任务)
|
||||
const handleConfirmAssign = async () => {
|
||||
const projectList = USE_MOCK ? mockProjects : projects
|
||||
if (assignModal.creator && selectedProject) {
|
||||
const project = projectList.find(p => p.id === selectedProject)
|
||||
if (!assignModal.creator || !selectedProject) return
|
||||
|
||||
const project = projectList.find(p => p.id === selectedProject)
|
||||
|
||||
if (USE_MOCK) {
|
||||
toast.success(`已将达人「${assignModal.creator.name}」分配到项目「${project?.name}」`)
|
||||
setAssignModal({ open: false, creator: null })
|
||||
setSelectedProject('')
|
||||
return
|
||||
}
|
||||
|
||||
setSubmitting(true)
|
||||
try {
|
||||
await api.createTask({
|
||||
project_id: selectedProject,
|
||||
creator_id: assignModal.creator.creatorId,
|
||||
})
|
||||
toast.success(`已将达人「${assignModal.creator.name}」分配到项目「${project?.name}」`)
|
||||
setAssignModal({ open: false, creator: null })
|
||||
setSelectedProject('')
|
||||
await fetchData() // 刷新列表
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : '分配失败'
|
||||
toast.error(message)
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
setAssignModal({ open: false, creator: null })
|
||||
setSelectedProject('')
|
||||
}
|
||||
|
||||
// 骨架屏
|
||||
@@ -761,43 +782,45 @@ export default function AgencyCreatorsPage() {
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-text-tertiary">{creator.joinedAt}</td>
|
||||
<td className="px-6 py-4">
|
||||
<div className="relative">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setOpenMenuId(openMenuId === creator.id ? null : creator.id)}
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenAssign(creator)}
|
||||
className="px-3 py-1.5 text-xs font-medium text-accent-indigo bg-accent-indigo/10 hover:bg-accent-indigo/20 rounded-lg transition-colors flex items-center gap-1.5"
|
||||
>
|
||||
<MoreVertical size={16} />
|
||||
</Button>
|
||||
{/* 下拉菜单 */}
|
||||
{openMenuId === creator.id && (
|
||||
<div className="absolute right-0 top-full mt-1 w-40 bg-bg-card rounded-xl shadow-lg border border-border-subtle z-10 overflow-hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenRemark(creator)}
|
||||
className="w-full px-4 py-2.5 text-left text-sm text-text-primary hover:bg-bg-elevated flex items-center gap-2"
|
||||
>
|
||||
<MessageSquareText size={14} className="text-text-secondary" />
|
||||
{creator.remark ? '编辑备注' : '添加备注'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenAssign(creator)}
|
||||
className="w-full px-4 py-2.5 text-left text-sm text-text-primary hover:bg-bg-elevated flex items-center gap-2"
|
||||
>
|
||||
<FolderPlus size={14} className="text-text-secondary" />
|
||||
分配到项目
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenDelete(creator)}
|
||||
className="w-full px-4 py-2.5 text-left text-sm text-accent-coral hover:bg-accent-coral/10 flex items-center gap-2"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
移除达人
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<FolderPlus size={13} />
|
||||
分配项目
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenDelete(creator)}
|
||||
className="p-1.5 text-text-tertiary hover:text-accent-coral hover:bg-accent-coral/10 rounded-lg transition-colors"
|
||||
title="移除达人"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
<div className="relative">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpenMenuId(openMenuId === creator.id ? null : creator.id)}
|
||||
className="p-1.5 text-text-tertiary hover:text-text-primary hover:bg-bg-elevated rounded-lg transition-colors"
|
||||
title="更多操作"
|
||||
>
|
||||
<MoreVertical size={14} />
|
||||
</button>
|
||||
{openMenuId === creator.id && (
|
||||
<div className="absolute right-0 top-full mt-1 w-36 bg-bg-card rounded-xl shadow-lg border border-border-subtle z-10 overflow-hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenRemark(creator)}
|
||||
className="w-full px-4 py-2.5 text-left text-sm text-text-primary hover:bg-bg-elevated flex items-center gap-2"
|
||||
>
|
||||
<MessageSquareText size={14} className="text-text-secondary" />
|
||||
{creator.remark ? '编辑备注' : '添加备注'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1042,8 +1065,8 @@ export default function AgencyCreatorsPage() {
|
||||
<Button variant="ghost" onClick={() => { setAssignModal({ open: false, creator: null }); setSelectedProject(''); }}>
|
||||
取消
|
||||
</Button>
|
||||
<Button onClick={handleConfirmAssign} disabled={!selectedProject}>
|
||||
<FolderPlus size={16} />
|
||||
<Button onClick={handleConfirmAssign} disabled={!selectedProject || submitting}>
|
||||
{submitting ? <Loader2 size={16} className="animate-spin" /> : <FolderPlus size={16} />}
|
||||
确认分配
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user