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)