|
|
@@ -1,5 +1,5 @@
|
|
|
import React, { useEffect, useState } from 'react'
|
|
|
-import { fetchSearch } from '../api.js'
|
|
|
+import { fetchJudgePrompts, fetchSearch } from '../api.js'
|
|
|
|
|
|
// 渠道分区展示:小红书 → 微信公众号 → 抖音;每区内「创作知识」在前、「非创作知识」单独起一行。
|
|
|
const PLATFORMS = [
|
|
|
@@ -11,15 +11,23 @@ const PLATFORMS = [
|
|
|
// 单条 query 的真实搜索结果详情:进来即「点进该 query 生成的多个视频里」。
|
|
|
export default function QueryDetail({ query }) {
|
|
|
const [data, setData] = useState({ total: 0, items: [] })
|
|
|
+ const [showPrompts, setShowPrompts] = useState(false)
|
|
|
useEffect(() => { fetchSearch({ query, size: 100 }).then(setData) }, [query])
|
|
|
|
|
|
const hits = data.items.filter((r) => r.ok)
|
|
|
|
|
|
return (
|
|
|
<div>
|
|
|
- <div className="detail-top"><a className="back" href="#/">← 返回 query 列表</a></div>
|
|
|
+ <div className="detail-top">
|
|
|
+ <a className="back" href="#/">← 返回 query 列表</a>
|
|
|
+ <button className="btn ghost" onClick={() => setShowPrompts(true)}>📋 创作知识判断提示词</button>
|
|
|
+ </div>
|
|
|
<h2 className="dq">🔎 {query}</h2>
|
|
|
- <div className="sub">该 query 搜到的真实帖子/视频 · 共 {hits.length} 个</div>
|
|
|
+ <div className="sub">该 query 搜到的真实帖子/视频 · 共 {hits.length} 个 ·
|
|
|
+ <span className="cls yes" style={{ margin: '0 4px' }}>创作知识</span>/
|
|
|
+ <span className="cls no" style={{ margin: '0 4px' }}>非创作知识</span> 由模型读真实内容判定</div>
|
|
|
+
|
|
|
+ {showPrompts && <JudgePromptModal onClose={() => setShowPrompts(false)} />}
|
|
|
|
|
|
{hits.length === 0 ? (
|
|
|
<div className="empty">这条 query 没搜到带媒体的结果。</div>
|
|
|
@@ -58,6 +66,32 @@ export default function QueryDetail({ query }) {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+// 创作知识判断提示词弹窗:图文 / 视频 两套真实提示词(extract.txt / extract_video.txt)。
|
|
|
+function JudgePromptModal({ onClose }) {
|
|
|
+ const [prompts, setPrompts] = useState([])
|
|
|
+ const [tab, setTab] = useState(0)
|
|
|
+ useEffect(() => { fetchJudgePrompts().then(setPrompts) }, [])
|
|
|
+ return (
|
|
|
+ <div className="modal-mask" onClick={onClose}>
|
|
|
+ <div className="modal wide" onClick={(e) => e.stopPropagation()}>
|
|
|
+ <div className="modal-hd"><b>创作知识判断提示词</b><span className="x" onClick={onClose}>✕</span></div>
|
|
|
+ <div className="modal-bd">
|
|
|
+ <p className="note">分类直接复用 pipeline 的真实提示词:图文用 extract.txt、视频用 extract_video.txt,
|
|
|
+ 让 Gemini 读真实内容后输出 is_empty 作为「创作 / 非创作」判据(不简化、不另造)。</p>
|
|
|
+ <div className="ptabs">
|
|
|
+ {prompts.map((p, i) => (
|
|
|
+ <button key={i} className={tab === i ? 'on' : ''} onClick={() => setTab(i)}>
|
|
|
+ {p.name} · {p.file}
|
|
|
+ </button>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ {prompts[tab] && <pre className="prompt">{prompts[tab].text}</pre>}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
function ClsBadge({ cls }) {
|
|
|
if (!cls || cls.is_creation === null) return <span className="cls none">未分类</span>
|
|
|
const yes = cls.is_creation === 1
|