Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import streamlit as st
|
|
|
|
| 2 |
import json
|
| 3 |
import time
|
| 4 |
import logging
|
|
@@ -115,7 +116,7 @@ def inject_custom_css():
|
|
| 115 |
.block-container {
|
| 116 |
position: fixed !important;
|
| 117 |
top: 7rem !important;
|
| 118 |
-
bottom:
|
| 119 |
left: 0 !important;
|
| 120 |
right: 0 !important;
|
| 121 |
overflow-y: auto !important;
|
|
@@ -173,11 +174,6 @@ def inject_custom_css():
|
|
| 173 |
margin-bottom: 0.5rem !important;
|
| 174 |
}
|
| 175 |
|
| 176 |
-
/* 主内容区域底部留出空间 */
|
| 177 |
-
.block-container {
|
| 178 |
-
bottom: 7rem !important;
|
| 179 |
-
}
|
| 180 |
-
|
| 181 |
/* 确保聊天容器可滚动 */
|
| 182 |
[data-testid="stVerticalBlockBorderWrapper"] {
|
| 183 |
overflow-y: auto !important;
|
|
@@ -256,14 +252,16 @@ def inject_custom_css():
|
|
| 256 |
|
| 257 |
inject_custom_css()
|
| 258 |
|
|
|
|
|
|
|
|
|
|
| 259 |
# 标题(固定在顶部)- 游客始终显示提示
|
| 260 |
-
_is_guest_init = not st.session_state.get("current_user")
|
| 261 |
_guest_tip = """<div style="text-align:center; padding:4px 0; color:#666; font-size:13px;">
|
| 262 |
🙋 当前为<b>游客模式</b>,可直接提问体验
|
| 263 |
-
</div>""" if
|
| 264 |
|
| 265 |
# 根据是否游客添加不同 class,用于 CSS 控制间距
|
| 266 |
-
_title_class = "main-title main-title-guest" if
|
| 267 |
|
| 268 |
st.markdown(
|
| 269 |
f"""
|
|
@@ -349,7 +347,10 @@ def _ensure_admin():
|
|
| 349 |
logger.error(f"创建管理员失败: {e}")
|
| 350 |
|
| 351 |
|
| 352 |
-
|
|
|
|
|
|
|
|
|
|
| 353 |
|
| 354 |
|
| 355 |
def _save_user(username, password_hash, role="user"):
|
|
@@ -434,8 +435,6 @@ if "current_role" not in st.session_state:
|
|
| 434 |
if "auth_mode" not in st.session_state:
|
| 435 |
st.session_state.auth_mode = "login"
|
| 436 |
|
| 437 |
-
IS_GUEST = not bool(st.session_state.get("current_user"))
|
| 438 |
-
|
| 439 |
with st.sidebar:
|
| 440 |
# 未登录时不用 expander,直接显示登录表单(避免手动收起后无法自动展开)
|
| 441 |
if IS_GUEST:
|
|
@@ -515,7 +514,6 @@ else:
|
|
| 515 |
# 登录后自动收起侧边栏(通过 JS 模拟点击收起按钮)
|
| 516 |
if not IS_GUEST and not st.session_state.get("_sidebar_collapsed_once"):
|
| 517 |
st.session_state["_sidebar_collapsed_once"] = True
|
| 518 |
-
import streamlit.components.v1 as components
|
| 519 |
components.html(
|
| 520 |
"""
|
| 521 |
<script>
|
|
@@ -744,9 +742,6 @@ def _delete_uploaded_file_from_storage(scope, filename):
|
|
| 744 |
|
| 745 |
def _clear_uploaded_files_storage(scope):
|
| 746 |
"""清空某个 scope 的所有上传文件。"""
|
| 747 |
-
files = _list_uploaded_files_db(scope)
|
| 748 |
-
paths = [f["storage_path"] for f in files] if files else []
|
| 749 |
-
# 从 uploaded_files 表拿 storage_path
|
| 750 |
try:
|
| 751 |
resp = _sb().table("uploaded_files").select("storage_path").eq("scope", scope).execute()
|
| 752 |
paths = [row["storage_path"] for row in resp.data]
|
|
@@ -1223,8 +1218,6 @@ with st.sidebar:
|
|
| 1223 |
pub_cnt = _count_chunks(PUBLIC_SCOPE)
|
| 1224 |
st.text(f"📚 公共库切片数: {pub_cnt}")
|
| 1225 |
|
| 1226 |
-
# 统计所有 scope
|
| 1227 |
-
resp = _sb().rpc("", {}).execute() if False else None # placeholder
|
| 1228 |
# 简单统计各用户私有库
|
| 1229 |
for uname, _ in user_list:
|
| 1230 |
cnt = _count_chunks(uname)
|
|
@@ -1470,7 +1463,6 @@ def _chat_fragment():
|
|
| 1470 |
response_container = st.empty()
|
| 1471 |
|
| 1472 |
# 滚动JS放在assistant块内部,不影响问题和回答之间的间距
|
| 1473 |
-
import streamlit.components.v1 as components
|
| 1474 |
components.html(
|
| 1475 |
"""<script>
|
| 1476 |
setTimeout(function(){
|
|
@@ -1518,7 +1510,7 @@ def _chat_fragment():
|
|
| 1518 |
_save_chat_message(CURRENT_USER, "assistant", full_response, meta_info)
|
| 1519 |
except Exception as e:
|
| 1520 |
logger.error(f"模型调用异常: {e}")
|
| 1521 |
-
|
| 1522 |
|
| 1523 |
|
| 1524 |
# =========================
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
+
import streamlit.components.v1 as components
|
| 3 |
import json
|
| 4 |
import time
|
| 5 |
import logging
|
|
|
|
| 116 |
.block-container {
|
| 117 |
position: fixed !important;
|
| 118 |
top: 7rem !important;
|
| 119 |
+
bottom: 7rem !important;
|
| 120 |
left: 0 !important;
|
| 121 |
right: 0 !important;
|
| 122 |
overflow-y: auto !important;
|
|
|
|
| 174 |
margin-bottom: 0.5rem !important;
|
| 175 |
}
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
/* 确保聊天容器可滚动 */
|
| 178 |
[data-testid="stVerticalBlockBorderWrapper"] {
|
| 179 |
overflow-y: auto !important;
|
|
|
|
| 252 |
|
| 253 |
inject_custom_css()
|
| 254 |
|
| 255 |
+
# 全局游客标识(session_state 在单次渲染中不变)
|
| 256 |
+
IS_GUEST = not bool(st.session_state.get("current_user"))
|
| 257 |
+
|
| 258 |
# 标题(固定在顶部)- 游客始终显示提示
|
|
|
|
| 259 |
_guest_tip = """<div style="text-align:center; padding:4px 0; color:#666; font-size:13px;">
|
| 260 |
🙋 当前为<b>游客模式</b>,可直接提问体验
|
| 261 |
+
</div>""" if IS_GUEST else ""
|
| 262 |
|
| 263 |
# 根据是否游客添加不同 class,用于 CSS 控制间距
|
| 264 |
+
_title_class = "main-title main-title-guest" if IS_GUEST else "main-title main-title-user"
|
| 265 |
|
| 266 |
st.markdown(
|
| 267 |
f"""
|
|
|
|
| 347 |
logger.error(f"创建管理员失败: {e}")
|
| 348 |
|
| 349 |
|
| 350 |
+
# 仅首次运行时检查管理员(避免每次刷新都查询)
|
| 351 |
+
if not st.session_state.get("_admin_ensured"):
|
| 352 |
+
_ensure_admin()
|
| 353 |
+
st.session_state["_admin_ensured"] = True
|
| 354 |
|
| 355 |
|
| 356 |
def _save_user(username, password_hash, role="user"):
|
|
|
|
| 435 |
if "auth_mode" not in st.session_state:
|
| 436 |
st.session_state.auth_mode = "login"
|
| 437 |
|
|
|
|
|
|
|
| 438 |
with st.sidebar:
|
| 439 |
# 未登录时不用 expander,直接显示登录表单(避免手动收起后无法自动展开)
|
| 440 |
if IS_GUEST:
|
|
|
|
| 514 |
# 登录后自动收起侧边栏(通过 JS 模拟点击收起按钮)
|
| 515 |
if not IS_GUEST and not st.session_state.get("_sidebar_collapsed_once"):
|
| 516 |
st.session_state["_sidebar_collapsed_once"] = True
|
|
|
|
| 517 |
components.html(
|
| 518 |
"""
|
| 519 |
<script>
|
|
|
|
| 742 |
|
| 743 |
def _clear_uploaded_files_storage(scope):
|
| 744 |
"""清空某个 scope 的所有上传文件。"""
|
|
|
|
|
|
|
|
|
|
| 745 |
try:
|
| 746 |
resp = _sb().table("uploaded_files").select("storage_path").eq("scope", scope).execute()
|
| 747 |
paths = [row["storage_path"] for row in resp.data]
|
|
|
|
| 1218 |
pub_cnt = _count_chunks(PUBLIC_SCOPE)
|
| 1219 |
st.text(f"📚 公共库切片数: {pub_cnt}")
|
| 1220 |
|
|
|
|
|
|
|
| 1221 |
# 简单统计各用户私有库
|
| 1222 |
for uname, _ in user_list:
|
| 1223 |
cnt = _count_chunks(uname)
|
|
|
|
| 1463 |
response_container = st.empty()
|
| 1464 |
|
| 1465 |
# 滚动JS放在assistant块内部,不影响问题和回答之间的间距
|
|
|
|
| 1466 |
components.html(
|
| 1467 |
"""<script>
|
| 1468 |
setTimeout(function(){
|
|
|
|
| 1510 |
_save_chat_message(CURRENT_USER, "assistant", full_response, meta_info)
|
| 1511 |
except Exception as e:
|
| 1512 |
logger.error(f"模型调用异常: {e}")
|
| 1513 |
+
response_container.error(f"❌ 抱歉,连接模型时出错了: {str(e)}")
|
| 1514 |
|
| 1515 |
|
| 1516 |
# =========================
|