knowledge-vault/work/client-projects/MCN/张洋输入/可行性工程/review_app.py

169 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import streamlit as st
import os
import json
import shutil
# --- 配置 ---
# 定义文件目录
SOURCE_DIR = "processed_json_outputs"
APPROVED_DIR = "reviewed_approved"
REJECTED_DIR = "reviewed_rejected"
# --- 核心功能 ---
def get_pending_files():
"""获取所有待审核的JSON文件列表"""
if not os.path.exists(SOURCE_DIR):
return []
# 创建目标文件夹(如果不存在)
os.makedirs(APPROVED_DIR, exist_ok=True)
os.makedirs(REJECTED_DIR, exist_ok=True)
processed_files = set(os.listdir(SOURCE_DIR))
approved_files = set(os.listdir(APPROVED_DIR))
rejected_files = set(os.listdir(REJECTED_DIR))
# 待审核文件 = 源文件 - (已通过的文件 + 已驳回的文件)
pending_files = list(processed_files - approved_files - rejected_files)
return sorted(pending_files)
def display_knowledge_card(data, index):
"""以美观的卡片形式展示单个知识点"""
with st.expander(f"**知识点 {index+1}: {data.get('summary', '无摘要')}**", expanded=True):
st.info(f"**摘要:** {data.get('summary', 'N/A')}")
st.subheader("核心策略/方法论")
for step in data.get('core_strategy', []):
st.markdown(f"**- 第 {step.get('step')} 步: {step.get('title')}**")
st.markdown(f"> {step.get('content')}")
st.subheader("话术示例")
examples = data.get('script_examples', [])
if examples:
for ex in examples:
st.code(ex, language='text')
else:
st.caption("")
st.subheader("常见误区")
pitfalls = data.get('common_pitfalls', [])
if pitfalls:
for pit in pitfalls:
st.warning(f"- {pit}")
else:
st.caption("")
# 案例和来源信息
col1, col2 = st.columns(2)
with col1:
case = data.get('case_study', {})
st.subheader("相关案例")
st.caption(f"主播: {case.get('streamer_name', 'N/A')}")
st.caption(f"描述: {case.get('description', 'N/A')}")
with col2:
ref = data.get('source_reference', {})
st.subheader("来源参考")
st.caption(f"文件名: {ref.get('video_title', 'N/A')}")
st.caption(f"时间戳: {ref.get('timestamp', 'N/A')}")
def display_editable_card(data, key_prefix):
"""以可编辑的形式展示单个知识点"""
edited_data = data.copy() # 创建副本以存储编辑内容
edited_data['summary'] = st.text_input("摘要", value=data.get('summary', ''), key=f"{key_prefix}_summary")
st.subheader("核心策略/方法论")
edited_strategies = []
for i, step in enumerate(data.get('core_strategy', [])):
with st.container(border=True):
edited_step = step.copy()
edited_step['title'] = st.text_input(f"步骤 {i+1} 标题", value=step.get('title', ''), key=f"{key_prefix}_step{i}_title")
edited_step['content'] = st.text_area(f"步骤 {i+1} 内容", value=step.get('content', ''), key=f"{key_prefix}_step{i}_content")
edited_strategies.append(edited_step)
edited_data['core_strategy'] = edited_strategies
# 其他字段为了简化,这里只做展示,也可以按需添加编辑功能
st.subheader("话术示例 (暂不可编辑)")
st.json(data.get('script_examples', []))
st.subheader("常见误区 (暂不可编辑)")
st.json(data.get('common_pitfalls', []))
return edited_data
# --- Streamlit 页面布局 ---
st.set_page_config(layout="wide", page_title="直播知识库审核平台")
st.title("💡 直播知识库审核平台")
st.markdown("在这里审核由AI处理生成的知识点。操作后文件会自动归档。")
# --- 侧边栏 ---
pending_files = get_pending_files()
if not pending_files:
st.sidebar.success("🎉 恭喜!所有文件都已审核完毕!")
st.balloons()
else:
st.sidebar.header("待审核文件")
selected_file = st.sidebar.radio("请选择一个文件进行审核:", pending_files, key="file_selector")
# --- 主界面 ---
if selected_file:
file_path = os.path.join(SOURCE_DIR, selected_file)
with open(file_path, 'r', encoding='utf-8') as f:
try:
content_data = json.load(f)
except json.JSONDecodeError:
st.error(f"文件 {selected_file} 格式错误不是有效的JSON。")
content_data = None
if content_data:
st.header(f"正在审核: `{selected_file}`")
# 使用Session State来控制编辑模式
if 'edit_mode' not in st.session_state:
st.session_state.edit_mode = False
# --- 操作按钮 ---
col1, col2, col3, _ = st.columns([1,1,1,3])
if col1.button("✅ 通过", use_container_width=True):
shutil.copy(file_path, os.path.join(APPROVED_DIR, selected_file))
st.success(f"文件 '{selected_file}' 已通过并归档!")
st.rerun() # 重新运行脚本以刷新列表
if col2.button("❌ 驳回", use_container_width=True):
shutil.copy(file_path, os.path.join(REJECTED_DIR, selected_file))
st.warning(f"文件 '{selected_file}' 已驳回并归档。")
st.rerun()
if col3.button("✏️ 编辑", use_container_width=True):
st.session_state.edit_mode = not st.session_state.edit_mode
st.rerun()
st.markdown("---")
# --- 内容展示 ---
if st.session_state.edit_mode:
st.subheader("📝 编辑模式")
edited_content = []
for i, item in enumerate(content_data):
edited_item = display_editable_card(item, key_prefix=f"item_{i}")
edited_content.append(edited_item)
if st.button("💾 保存修改并通过", type="primary"):
# 将修改后的内容保存到 "approved" 目录
save_path = os.path.join(APPROVED_DIR, selected_file)
with open(save_path, 'w', encoding='utf-8') as f:
json.dump(edited_content, f, ensure_ascii=False, indent=2)
st.success(f"文件 '{selected_file}' 的修改已保存并通过!")
st.session_state.edit_mode = False
st.rerun()
else:
st.subheader("👁️‍🗨️ 预览模式")
for i, item in enumerate(content_data):
display_knowledge_card(item, i)