zhaoqingang 1 年間 前
コミット
08c8e8c9a4

+ 53 - 0
alembic/versions/3845dc998475_menu_table_add.py

@@ -0,0 +1,53 @@
+"""menu table add 
+
+Revision ID: 3845dc998475
+Revises: abc6bb9129ed
+Create Date: 2024-12-10 14:22:03.798597
+
+"""
+from typing import Sequence, Union
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import mysql
+
+# revision identifiers, used by Alembic.
+revision: str = '3845dc998475'
+down_revision: Union[str, None] = 'abc6bb9129ed'
+branch_labels: Union[str, Sequence[str], None] = None
+depends_on: Union[str, Sequence[str], None] = None
+
+
+def upgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('menu_capacity',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('menu_id', sa.Integer(), nullable=True),
+    sa.Column('capacity_id', sa.String(length=36), nullable=True),
+    sa.Column('capacity_type', sa.Integer(), nullable=True),
+    sa.PrimaryKeyConstraint('id'),
+    sa.UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix')
+    )
+    op.create_index(op.f('ix_menu_capacity_id'), 'menu_capacity', ['id'], unique=False)
+    op.create_table('web_menu',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('title', sa.String(length=128), nullable=True),
+    sa.Column('dialog', sa.String(length=1000), nullable=True),
+    sa.Column('desc', sa.String(length=1000), nullable=True),
+    sa.Column('icon', sa.String(length=16), nullable=True),
+    sa.Column('img', sa.String(length=255), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.create_index(op.f('ix_web_menu_id'), 'web_menu', ['id'], unique=False)
+    op.drop_column('knowledgebase', 'count')
+    # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('knowledgebase', sa.Column('count', mysql.VARCHAR(length=32), nullable=True))
+    op.drop_index(op.f('ix_web_menu_id'), table_name='web_menu')
+    op.drop_table('web_menu')
+    op.drop_index(op.f('ix_menu_capacity_id'), table_name='menu_capacity')
+    op.drop_table('menu_capacity')
+    # ### end Alembic commands ###

+ 32 - 0
alembic/versions/92ece82bc5a4_menu_table_update.py

@@ -0,0 +1,32 @@
+"""menu table update
+
+Revision ID: 92ece82bc5a4
+Revises: 3845dc998475
+Create Date: 2024-12-10 16:00:04.324833
+
+"""
+from typing import Sequence, Union
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import mysql
+
+# revision identifiers, used by Alembic.
+revision: str = '92ece82bc5a4'
+down_revision: Union[str, None] = '3845dc998475'
+branch_labels: Union[str, Sequence[str], None] = None
+depends_on: Union[str, Sequence[str], None] = None
+
+
+def upgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('web_menu', sa.Column('describe', sa.String(length=1000), nullable=True))
+    op.drop_column('web_menu', 'dialog')
+    # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('web_menu', sa.Column('dialog', mysql.VARCHAR(length=1000), nullable=True))
+    op.drop_column('web_menu', 'describe')
+    # ### end Alembic commands ###

+ 30 - 0
alembic/versions/f49ae5b5f2c8_group_type_add.py

@@ -0,0 +1,30 @@
+"""group type add 
+
+Revision ID: f49ae5b5f2c8
+Revises: 92ece82bc5a4
+Create Date: 2024-12-10 16:26:34.371685
+
+"""
+from typing import Sequence, Union
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision: str = 'f49ae5b5f2c8'
+down_revision: Union[str, None] = '92ece82bc5a4'
+branch_labels: Union[str, Sequence[str], None] = None
+depends_on: Union[str, Sequence[str], None] = None
+
+
+def upgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('group', sa.Column('group_type', sa.Integer(), nullable=True))
+    # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_column('group', 'group_type')
+    # ### end Alembic commands ###

+ 0 - 0
app/service/common/__init__.py → app/__init__.py


+ 4 - 4
app/api/agent.py

@@ -42,7 +42,7 @@ async def chat_list(
     if agent.agent_type == AgentType.RAGFLOW:
         ragflow_service = RagflowService(base_url=settings.fwr_base_url)
         try:
-            token = get_ragflow_token(db, current_user.id)
+            token = await get_ragflow_token(db, current_user.id)
             result = await ragflow_service.get_chat_sessions(token, agent_id)
             if not result:
                 result = await get_session_history(db, current_user.id, agent_id)
@@ -53,7 +53,7 @@ async def chat_list(
     elif agent.agent_type == AgentType.BISHENG:
         bisheng_service = BishengService(base_url=settings.sgb_base_url)
         try:
-            token = get_bisheng_token(db, current_user.id)
+            token = await get_bisheng_token(db, current_user.id)
             result = await bisheng_service.get_chat_sessions(token, agent_id,  page, limit)
         except Exception as e:
             raise HTTPException(status_code=500, detail=str(e))
@@ -84,7 +84,7 @@ async def session_log(agent_id: str, conversation_id: str, db: Session = Depends
     if agent.agent_type == AgentType.RAGFLOW:
         ragflow_service = RagflowService(base_url=settings.fwr_base_url)
         try:
-            token = get_ragflow_token(db, current_user.id)
+            token = await get_ragflow_token(db, current_user.id)
             result = await ragflow_service.get_session_log(token, conversation_id)
             if 'session_log' in result and 'reference' in result:
                 combined_logs = []
@@ -118,7 +118,7 @@ async def session_log(agent_id: str, conversation_id: str, db: Session = Depends
             is_join = True
         bisheng_service = BishengService(base_url=settings.sgb_base_url)
         try:
-            token = get_bisheng_token(db, current_user.id)
+            token = await get_bisheng_token(db, current_user.id)
             result = await bisheng_service.get_session_log(token, agent_id, conversation_id)
             combined_logs = []
             last_question = None

+ 6 - 9
app/api/auth.py

@@ -18,7 +18,7 @@ from app.models.user_model import UserModel
 from app.service.auth import authenticate_user, create_access_token, is_valid_password, save_register_user, \
     update_user_token, UserAppDao
 from app.service.bisheng import BishengService
-from app.service.common.app_register import AppRegisterDao
+from app.service.v2.app_register import AppRegisterDao
 from app.service.difyService import DifyService
 from app.service.ragflow import RagflowService
 from sqlalchemy.future import select
@@ -96,13 +96,10 @@ async def login(login_data: LoginData, db: Session = Depends(get_db)):
 @router.get("/token", response_model=Response)
 async def token_api(db: Session = Depends(get_db), current_user: UserModel = Depends(get_current_user)):
     # 查询现有记录
-    token = get_token(db, current_user.id)
+    token = await get_token(db, current_user.id)
     if token is None:
         return Response(code=400, msg="token not found")
-    return Response(code=200, msg="success", data={
-        "ragflow_token": token.ragflow_token,
-        "bisheng_token": token.bisheng_token,
-    })
+    return Response(code=200, msg="success", data=token)
 
 
 @router.post("/v2/login", response_model=Response)
@@ -123,7 +120,7 @@ async def login_v2(login_data: LoginData, db: Session = Depends(get_db), pdb: As
             logger.error("未知注册应用---")
             continue
         try:
-            user_app = UserAppDao(db).get_data_by_id(user.id, app["id"])
+            user_app = await UserAppDao(db).get_data_by_id(user.id, app["id"])
             if user_app:
                 name  = user_app.username
             token = await service.login(name, login_data.password)
@@ -134,7 +131,7 @@ async def login_v2(login_data: LoginData, db: Session = Depends(get_db), pdb: As
     # 创建本地token
     access_token = create_access_token(data={"sub": user.username, "user_id": user.id})
 
-    await update_token(db, user.id, access_token, token_dict)
+    # await update_token(db, user.id, access_token, token_dict)
     await update_user_token(db, user.id, token_dict)
     result = await pdb.execute(select(AppToken).where(AppToken.id == user.id))
     db_app_token = result.scalars().first()
@@ -184,7 +181,7 @@ async def register_v2(user: UserCreate, db=Depends(get_db)):
         try:
             name = app["id"] + str(int(time.time()))
             register_info = await service.register(name, user.password)
-            print(register_info)
+            # print(register_info)
             register_dict[app['id']] = {"id":register_info.get("id"), "name": name, "email": register_info.get("email")}
         except Exception as e:
             return Response(code=500, msg=f"Failed to register with {app['id']}: {str(e)}")

+ 3 - 3
app/api/chat.py

@@ -14,7 +14,7 @@ from app.config.const import IMAGE_TO_TEXT, DOCUMENT_TO_REPORT, DOCUMENT_TO_CLEA
 from app.models.agent_model import AgentModel, AgentType
 from app.models.base_model import get_db
 from app.models.user_model import UserModel
-from app.service.common.api_token import DfTokenDao
+from app.service.v2.api_token import DfTokenDao
 from app.service.dialog import update_session_history
 from app.service.basic import BasicService
 from app.service.difyService import DifyService
@@ -49,7 +49,7 @@ async def handle_client(websocket: WebSocket,
 
     if agent_type == AgentType.RAGFLOW:
         ragflow_service = RagflowService(settings.fwr_base_url)
-        token = get_ragflow_token(db, current_user.id)
+        token = await get_ragflow_token(db, current_user.id)
         try:
             async def forward_to_ragflow():
                 while True:
@@ -135,7 +135,7 @@ async def handle_client(websocket: WebSocket,
                         pass
 
     elif agent_type == AgentType.BISHENG:
-        token = get_bisheng_token(db, current_user.id)
+        token = await get_bisheng_token(db, current_user.id)
         service_uri = f"{settings.sgb_websocket_url}/api/v1/assistant/chat/{agent_id}?t=&chat_id={chat_id}"
         headers = {'cookie': f"access_token_cookie={token};"}
 

+ 3 - 3
app/api/files.py

@@ -15,7 +15,7 @@ from app.models.base_model import get_db
 from app.models.user_model import UserModel
 from app.service.basic import BasicService
 from app.service.bisheng import BishengService
-from app.service.common.api_token import DfTokenDao
+from app.service.v2.api_token import DfTokenDao
 from app.service.difyService import DifyService
 from app.service.ragflow import RagflowService
 from app.service.service_token import get_ragflow_token, get_bisheng_token
@@ -50,7 +50,7 @@ async def upload_files(
             return Response(code=400, msg=str(e))
 
         if agent.agent_type == AgentType.RAGFLOW:
-            token = get_ragflow_token(db, current_user.id)
+            token = await get_ragflow_token(db, current_user.id)
             ragflow_service = RagflowService(base_url=settings.fwr_base_url)
             # 查询会话是否存在,不存在先创建会话
             history = await ragflow_service.get_session_history(token, chat_id)
@@ -65,7 +65,7 @@ async def upload_files(
         elif agent.agent_type == AgentType.BISHENG:
             bisheng_service = BishengService(base_url=settings.sgb_base_url)
             try:
-                token = get_bisheng_token(db, current_user.id)
+                token = await get_bisheng_token(db, current_user.id)
                 result = await bisheng_service.upload(token, file.filename, file_content)
             except Exception as e:
                 raise HTTPException(status_code=500, detail=str(e))

+ 2 - 2
app/api/report.py

@@ -36,7 +36,7 @@ async def report_chat(websocket: WebSocket,
         ret = {"message": "Agent error", "type": "close"}
         return websocket.send_json(ret)
 
-    token = get_bisheng_token(db, current_user.id)
+    token = await get_bisheng_token(db, current_user.id)
     service_uri = f"{settings.sgb_websocket_url}/api/v1/chat/{agent_id}?type=L1&t=&chat_id={chat_id}"
     headers = {'cookie': f"access_token_cookie={token};"}
 
@@ -165,7 +165,7 @@ async def get_variables(agent_id: str = Query(..., description="The ID of the ag
         return ResponseList(code=404, msg="Agent not found")
     bisheng_service = BishengService(base_url=settings.sgb_base_url)
     try:
-        token = get_bisheng_token(db, current_user.id)
+        token = await get_bisheng_token(db, current_user.id)
         result = await bisheng_service.variable_list(token, agent_id)
     except Exception as e:
         raise HTTPException(status_code=500, detail=str(e))

+ 11 - 3
app/api/user.py

@@ -1,11 +1,11 @@
 from fastapi import APIRouter, Depends
-from app.api import Response, pwd_context, get_current_user
+from app.api import Response, pwd_context, get_current_user, ResponseList
 from app.models.public_api_model import AppRegisterModel
 from app.models.base_model import get_db
 from app.models.user import PageParameter, UserStatus, UserInfo, LoginData
 from app.models.user_model import UserModel
 from app.service.user import get_user_list, edit_user_status, delete_user_data, create_user, edit_user_data, \
-    edit_user_pwd, get_user_info, get_user_routers
+    edit_user_pwd, get_user_info, get_user_routers, get_user_menus
 
 user_router = APIRouter()
 
@@ -95,4 +95,12 @@ async def user_routers(current_user: UserModel = Depends(get_current_user),db=De
     routers = await get_user_routers(db,  current_user.id)
     if not routers:
         return Response(code=500, msg="user get failure", data={})
-    return Response(code=200, msg="successfully", data=routers)
+    return Response(code=200, msg="successfully", data=routers)
+
+
+@user_router.get("/menus", response_model=ResponseList)
+async def user_menus(current_user: UserModel = Depends(get_current_user),db=Depends(get_db)):
+    menus = await get_user_menus(db,  current_user.id)
+    # return Response(code=200, msg="successfully", data=menus)
+    # result = [item.to_dict() for item in agents]
+    return ResponseList(code=200, msg="successfully", data=menus)

+ 0 - 0
app/api/v2/__init__.py


+ 0 - 0
app/api/v2/conversation.py


+ 16 - 4
app/api/public_api.py → app/api/v2/public_api.py

@@ -8,8 +8,9 @@ from app.api.auth import login
 from app.config.const import IMAGE_TO_TEXT, DOCUMENT_TO_CLEANING, DOCUMENT_TO_REPORT, DIFY, BISHENG, RAGFLOW
 from app.models.base_model import get_db
 from app.models.public_api_model import DfToken, AppRegister
-from app.service.common.api_token import DfTokenDao
-from app.service.common.app_register import AppRegisterDao
+from app.service.v2.api_token import DfTokenDao
+from app.service.v2.app_register import AppRegisterDao
+from app.service.v2.initialize_data import dialog_menu_sync
 from app.task.sync_resources import sync_knowledge, sync_dialog, sync_agent, sync_llm, sync_resource
 
 public_api = APIRouter()
@@ -47,7 +48,7 @@ async def sync_app_register(apr: AppRegister, db=Depends(get_db)):
 
 
 @public_api.get("/sync/resource", response_model=Response)
-async def user_group_list(resource_type:int, db=Depends(get_db)):
+async def sync_resource_data(resource_type:int, db=Depends(get_db)):
     if resource_type == 1:
         await sync_knowledge()
     elif resource_type == 2:
@@ -59,4 +60,15 @@ async def user_group_list(resource_type:int, db=Depends(get_db)):
     else:
         await sync_resource()
 
-    return Response(code=200, msg="", data={})
+    return Response(code=200, msg="", data={})
+
+
+@public_api.get("/sync/dialog_menu", response_model=Response)
+async def sync_dialog_menu(db=Depends(get_db)):
+    try:
+        await dialog_menu_sync(db)
+    except Exception as e:
+        logger.error(e)
+        return Response(code=500, msg="failed", data={})
+
+    return Response(code=200, msg="success", data={})

+ 1 - 0
app/models/__init__.py

@@ -14,6 +14,7 @@ from .user_model import *
 from .token_model import *
 from .session_model import SessionModel
 from .public_api_model import *
+from .menu_model import *
 
 
 # 获取当前时区的时间

+ 1 - 0
app/models/group_model.py

@@ -39,6 +39,7 @@ class GroupModel(Base):
     created_at = Column(DateTime, default=datetime.now())
     updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
     creator = Column(Integer)
+    group_type = Column(Integer, default=1)
 
 
     knowledges = relationship('KnowledgeModel',

+ 39 - 0
app/models/menu_model.py

@@ -0,0 +1,39 @@
+from datetime import datetime
+from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey, UniqueConstraint
+from app.models.base_model import Base
+
+
+
+class WebMenuModel(Base):
+    __tablename__ = 'web_menu'
+    id = Column(Integer, primary_key=True, index=True)
+    title = Column(String(128))
+    describe = Column(String(1000))
+    desc = Column(String(1000))
+    icon = Column(String(16))
+    img = Column(String(255))
+
+
+    def to_dict(self):
+        return {
+            'id': self.id,
+            'title': self.title,
+            'icon': self.icon,
+            'img': self.img,
+            'desc': self.desc,
+            'dialog': self.describe
+        }
+
+    def __repr__(self):
+        return '<Role name:%r description:%r iconCls:%r seq:%r>\n' \
+            % (self.NAME, self.DESCRIPTION, self.ICONCLS, self.SEQ)
+
+
+class MenuCapacityModel(Base):
+    __tablename__ = 'menu_capacity'
+    __table_args__ = (UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix'),)
+    id = Column(Integer, primary_key=True, index=True)
+    menu_id = Column(Integer)
+    capacity_id = Column(String(36))
+    capacity_type = Column(Integer)
+

+ 6 - 3
app/models/token_model.py

@@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
 from Log import logger
 from app.config.const import RAGFLOW
 from app.models.base_model import Base
+from app.service.auth import UserAppDao
 
 
 class TokenModel(Base):
@@ -59,7 +60,7 @@ async def update_token(db: Session, user_id: int, access_token: str, token: dict
     if not isinstance(user_id, int) or user_id <= 0:
         return
     db_token = None
-    print(token)
+    # print(token)
     try:
         # 查询现有记录
         db_token = db.query(TokenModel).filter_by(user_id=user_id).first()
@@ -88,5 +89,7 @@ async def update_token(db: Session, user_id: int, access_token: str, token: dict
         db.rollback()  # 回滚事务
 
 
-def get_token(db: Session, user_id: int) -> Type[TokenModel] | None:
-    return db.query(TokenModel).filter_by(user_id=user_id).first()
+async def get_token(db: Session, user_id: int):
+    # return db.query(TokenModel).filter_by(user_id=user_id).first()
+
+    return {i.app_type.replace("app", "token"): i.access_token for i in await UserAppDao(db).get_user_datas(user_id)}

+ 18 - 15
app/service/auth.py

@@ -77,7 +77,7 @@ async def save_register_user(db, username, password, email, register_dict):
         db.refresh(db_user)
         user_id = db_user.id
         for k, v in register_dict.items():
-            UserAppDao(db).update_and_insert_token(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k)
+            await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k)
 
     except Exception as e:
         logger.error(e)
@@ -89,11 +89,10 @@ async def save_register_user(db, username, password, email, register_dict):
 
 
 async def update_user_token(db, user_id, token_dict):
-
     try:
         for k, v in token_dict.items():
-            UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k},
-                                                {"access_token": v, "token_at": datetime.now()})
+            await UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k},
+                                                      {"access_token": v, "token_at": datetime.now()})
 
     except Exception as e:
         logger.error(e)
@@ -105,11 +104,11 @@ class UserAppDao:
     def __init__(self, db: Session):
         self.db = db
 
-    def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None:
+    async def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None:
         session = self.db.query(UserAppModel).filter_by(user_id=user_id, app_type=app_type).first()
         return session
 
-    def update_user_app_data(self, query: int, update_data: str):
+    async def update_user_app_data(self, query: dict, update_data: dict):
 
         logger.error("更新数据df update_app_data---------------------------")
         try:
@@ -120,7 +119,8 @@ class UserAppDao:
             self.db.rollback()
             raise Exception("更新失败!")
 
-    def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str, app_type: int):
+    async def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str,
+                                   app_type: int):
         logger.error("新增数据df insert_user_app_data---------------------------")
         new_session = UserAppModel(
             username=username,
@@ -135,15 +135,18 @@ class UserAppDao:
         self.db.refresh(new_session)
         return new_session
 
-    def update_and_insert_token(self, username: str, password: str, email: str, user_id: int, app_id: str,
-                                app_type: int):
+    async def update_and_insert_data(self, username: str, password: str, email: str, user_id: int, app_id: str,
+                                     app_type: int):
 
         logger.error("更新或者添加数据 update_and_insert_token---------------------------")
-        token_boj = self.get_data_by_id(user_id, app_type)
+        token_boj = await self.get_data_by_id(user_id, app_type)
         if token_boj:
-            self.update_user_app_data({"id": token_boj.id}, {"username": username,
-                                                             "password": password, "email": email, "username": username,
-                                                             "updated_at": datetime.now(),
-                                                             })
+            await self.update_user_app_data({"id": token_boj.id}, {"username": username,
+                                                                   "password": password, "email": email,
+                                                                   "updated_at": datetime.now(),
+                                                                   })
         else:
-            self.insert_user_app_data(username, password, email, user_id, app_id, app_type)
+            await self.insert_user_app_data(username, password, email, user_id, app_id, app_type)
+
+    async def get_user_datas(self, user_id: int):
+        return self.db.query(UserAppModel).filter_by(user_id=user_id).all()

+ 1 - 1
app/service/group.py

@@ -81,7 +81,7 @@ async def save_user_to_group(db, user_id, group_id, user_list):
                          UserModel.id.in_(user_list)).all()}
         print(user_dict)
         ragflow_service = RagflowService(settings.fwr_base_url)
-        token = get_ragflow_token(db, user_id)
+        token = await get_ragflow_token(db, user_id)
 
         try:
             for old_user in group_user_list:

+ 9 - 6
app/service/service_token.py

@@ -1,23 +1,26 @@
 from Log import logger
 from app.config.config import settings
+from app.config.const import BISHENG, RAGFLOW
 from app.models import UserModel
 from app.models.token_model import TokenModel
+from app.service.auth import UserAppDao
 from app.service.bisheng import BishengService
 from app.service.ragflow import RagflowService
 
 
-def get_bisheng_token(db, user_id: int):
-    token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
+async def get_bisheng_token(db, user_id: int):
+    # token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
+    token = await UserAppDao.get_data_by_id(user_id, BISHENG)
     if not token:
         return None
-    return token.bisheng_token
+    return token.access_token
 
 
-def get_ragflow_token(db, user_id: int):
-    token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
+async def get_ragflow_token(db, user_id: int):
+    token = await UserAppDao.get_data_by_id(user_id, RAGFLOW)
     if not token:
         return None
-    return token.ragflow_token
+    return token.access_token
 
 
 async def get_ragflow_new_token(db, user_id: int, app_type):

+ 105 - 36
app/service/user.py

@@ -1,30 +1,35 @@
+import time
 from datetime import datetime
 
 from app.api import pwd_context
 from app.config.config import settings
+from app.config.const import RAGFLOW, BISHENG, DIFY
 from app.models import RoleModel, GroupModel, AgentType, role_resource_table
+from app.models.menu_model import WebMenuModel, MenuCapacityModel
 from app.models.user_model import UserModel
 from Log import logger
+from app.service.auth import UserAppDao
 from app.service.bisheng import BishengService
-from app.service.common.app_register import AppRegisterDao
+from app.service.v2.app_register import AppRegisterDao
+from app.service.difyService import DifyService
 from app.service.ragflow import RagflowService
 from app.service.service_token import get_ragflow_token, get_bisheng_token, get_ragflow_new_token
 
 
-async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key:str, user_id):
-    query = db.query(UserModel).filter(UserModel.permission!="admin")
+async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key: str, user_id):
+    query = db.query(UserModel).filter(UserModel.permission != "admin")
     # if role_key != "admin":
     #     query.filter(UserModel.creator==user_id)
     if keyword:
         query = query.filter(UserModel.group_name.like('%{}%'.format(keyword)))
     users = query.order_by(UserModel.id.desc()).limit(page_size).offset(
         (page_index - 1) * page_size).all()
-    return {"total": query.count(), "rows":  [user.to_json() for user in users]}
+    return {"total": query.count(), "rows": [user.to_json() for user in users]}
 
 
 async def edit_user_status(db, status: str, user_id: int):
     try:
-        db.query(UserModel).filter(UserModel.id == user_id).update({"status":status})
+        db.query(UserModel).filter(UserModel.id == user_id).update({"status": status})
         db.commit()
     except Exception as e:
         logger.error(e)
@@ -35,7 +40,7 @@ async def edit_user_status(db, status: str, user_id: int):
 
 async def delete_user_data(db, user_id: str):
     try:
-        db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission!="admin").delete()
+        db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission != "admin").delete()
         db.commit()
     except Exception as e:
         logger.error(e)
@@ -46,38 +51,65 @@ async def delete_user_data(db, user_id: str):
 
 async def create_user(db, user_name, email, phone, login_name, password, roles, groups, user_id):
     try:
-        bisheng_service = BishengService(settings.sgb_base_url)
-        ragflow_service = RagflowService(settings.fwr_base_url)
-
-        # 注册到毕昇
-        try:
-            bisheng_info = await bisheng_service.register(user_name, password)
-        except Exception as e:
-            logger.error(f"Failed to register with Bisheng: {str(e)}")
-            return False
-
-        # 注册到ragflow
-        try:
-            ragflow_info = await ragflow_service.register(user_name, password)
-        except Exception as e:
-            logger.error(f"Failed to register with Ragflow: {str(e)}")
-            return False
+        # bisheng_service = BishengService(settings.sgb_base_url)
+        # ragflow_service = RagflowService(settings.fwr_base_url)
+        #
+        # # 注册到毕昇
+        # try:
+        #     bisheng_info = await bisheng_service.register(user_name, password)
+        # except Exception as e:
+        #     logger.error(f"Failed to register with Bisheng: {str(e)}")
+        #     return False
+        #
+        # # 注册到ragflow
+        # try:
+        #     ragflow_info = await ragflow_service.register(user_name, password)
+        # except Exception as e:
+        #     logger.error(f"Failed to register with Ragflow: {str(e)}")
+        #     return False
+        app_register = AppRegisterDao(db).get_apps()
+        register_dict = {}
+        for app in app_register:
+            if app["id"] == RAGFLOW:
+                service = RagflowService(settings.fwr_base_url)
+            elif app["id"] == BISHENG:
+                service = BishengService(settings.sgb_base_url)
+            elif app["id"] == DIFY:
+                service = DifyService(settings.dify_base_url)
+            else:
+                logger.error("未知注册应用---")
+                continue
+            try:
+                name = app["id"] + str(int(time.time()))
+                register_info = await service.register(name, password)
+                # print(register_info)
+                register_dict[app['id']] = {"id": register_info.get("id"), "name": name,
+                                            "email": register_info.get("email")}
+            except Exception as e:
+                logger.error(e)
+                return False
 
         # 存储用户信息
         hashed_password = pwd_context.hash(password)
-        user_model =  UserModel(username=user_name, hashed_password=hashed_password, email=email,ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"),
-                                phone=phone,login_name=login_name)
 
+        user_model = UserModel(username=user_name, hashed_password=hashed_password, email=email,
+                               ## ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"),
+                               phone=phone, login_name=login_name)
+        pwd = user_model.encrypted_password(password)
         user_model.roles = [db.get(RoleModel, roleId) for roleId in roles]
+        user_model.password = pwd
         if groups:
             user_model.groups = [db.get(GroupModel, groupId) for groupId in groups]
         user_model.creator = user_id
         db.add(user_model)
         db.commit()
         db.refresh(user_model)
+        u_id = user_model.id
+        for k, v in register_dict.items():
+            await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), u_id, str(v.get("id")), k)
     except Exception as e:
         logger.error(e)
-        db.rollback()
+        # db.rollback()
         return False
     return True
 
@@ -100,21 +132,21 @@ async def edit_user_data(db, user_id, email, phone, login_name, roles, groups):
     return True
 
 
-async def edit_user_pwd(db, user_id, current_user_id ,new_password="000000"):
+async def edit_user_pwd(db, user_id, current_user_id, new_password="000000"):
     try:
         user = db.query(UserModel).filter(UserModel.id == user_id).first()
         pwd = user.decrypted_password()
-        for app_type in AppRegisterDao(db).get_app():
-            if app_type == AgentType.RAGFLOW:
-                token = await get_ragflow_new_token(db, user_id, app_type)
+        for app in AppRegisterDao(db).get_apps():
+            if app.get("id") == RAGFLOW:
+                token = await get_ragflow_new_token(db, user_id, 1)
                 ragflow_service = RagflowService(settings.fwr_base_url)
                 await ragflow_service.set_user_password(token, pwd, new_password)
-            elif app_type == AgentType.BISHENG:
-                token = get_bisheng_token(db, current_user_id)
+            elif app.get("id") == BISHENG:
+                token = await get_bisheng_token(db, current_user_id)
                 bisheng_service = BishengService(settings.sgb_base_url)
                 await bisheng_service.change_password_public(token, user.username, pwd, new_password)
             else:
-                logger.error("注册未知应用:{}".format(app_type))
+                logger.error("注册未知应用:{}".format(app.get("id")))
         # hashed_password = pwd_context.hash(password)
         hashed_password = user.encrypted_password(new_password)
 
@@ -148,7 +180,7 @@ async def get_user_info(db, user_id):
     if user.permission == "admin":
         permissions = ["*:*:*"]
 
-    return {"permissions": list(permissions), "dept": dept , "roles":  roles, "user": user.to_dict()}
+    return {"permissions": list(permissions), "dept": dept, "roles": roles, "user": user.to_dict()}
 
 
 async def role_resource(role_set, role_list, permissions, roles):
@@ -167,6 +199,7 @@ async def get_user_routers(db, user_id):
     dept_set = set()
     user = db.query(UserModel).filter_by(id=user_id).first()
     parent_id = ""
+
     async def role_resource(role_set, permissions, roles):
         nonlocal parent_id
         for role in roles:
@@ -192,14 +225,50 @@ async def get_user_routers(db, user_id):
                 parent_ogt = parent_ogt.parent
     tmp_dit = {}
     for permission in permissions.values():
-        tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) +[permission]
+        tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) + [permission]
+
     def get_child(parent_id):
         res = permissions[parent_id]
         res["children"] = [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])]
         return res
 
-    print(parent_id)
-    print(tmp_dit)
     return {"routers": [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])]}
 
 
+async def get_user_menus(db, user_id):
+    dialog_list = []
+    agent_list = []
+    menu_dict = {}
+    res = []
+    user = db.query(UserModel).filter_by(id=user_id).first()
+    for group in user.groups:
+        for dialog in group.dialogs:
+            dialog_list.append(dialog.id)
+        for agent in group.agents:
+            agent_list.append(agent.id)
+    menu_list = db.query(WebMenuModel.id, WebMenuModel.title, WebMenuModel.describe, WebMenuModel.icon, WebMenuModel.desc,
+                         WebMenuModel.img, MenuCapacityModel.capacity_id, MenuCapacityModel.capacity_type).outerjoin(
+        MenuCapacityModel, WebMenuModel.id == MenuCapacityModel.menu_id).all()
+
+    for menu in menu_list:
+        menu_dict[menu.id] = menu_dict.get(menu.id, []) + [menu]
+    # print(dialog_list)
+    for menus in menu_dict.values():
+
+        for m in menus:
+            if user.permission == "admin":
+                continue
+            elif not m.capacity_type or m.capacity_type == 1 and m.capacity_id not in dialog_list:
+                break
+            elif not m.capacity_type or m.capacity_type == 2 and m.capacity_id not in agent_list:
+                break
+        else:
+            res.append({
+            'id': menus[0].id,
+            'title': menus[0].title,
+            'icon': menus[0].icon,
+            'img': menus[0].img,
+            'desc': menus[0].desc,
+            'dialog': menus[0].describe
+        })
+    return res

+ 0 - 0
app/service/v2/__init__.py


+ 0 - 0
app/service/common/api_token.py → app/service/v2/api_token.py


+ 0 - 0
app/service/common/app_register.py → app/service/v2/app_register.py


+ 36 - 0
app/service/v2/initialize_data.py

@@ -0,0 +1,36 @@
+import json
+
+from Log import logger
+from app.models import MenuCapacityModel, WebMenuModel, GroupModel
+
+
+async def dialog_menu_sync(db):
+    menu_list = []
+    with open("env_conf/menu_conf.json", 'r', encoding='utf-8') as file:
+        # 加载JSON数据
+        data = json.load(file)
+        menu_list = data.get("data", [])
+
+    db.query(WebMenuModel).delete()
+    db.query(MenuCapacityModel).delete()
+    db.commit()
+
+    for menu in menu_list:
+        # print(menu)
+        agent = menu.pop("agent", [])
+        for i in agent:
+            capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=2)
+            db.add(capacity)
+        dialog = menu.pop("dialog", [])
+        for i in dialog:
+            capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=1)
+            db.add(capacity)
+        menu_obj = WebMenuModel(**menu)
+        db.add(menu_obj)
+    db.commit()
+
+
+async def default_group_sync(db):
+    group = db.query(GroupModel).filter_by(group_type=2).first()
+    if not group:
+        logger.error("未初始化")

+ 12 - 0
app/task/fetch_agent.py

@@ -1,12 +1,14 @@
 from typing import Dict, List, Tuple
 
 from sqlalchemy import create_engine, Column, String, Integer
+from sqlalchemy.dialects.postgresql import array
 from sqlalchemy.exc import IntegrityError
 from sqlalchemy.orm import sessionmaker
 
 from app.config.config import settings
 from app.models.agent_model import AgentModel
 from app.models.base_model import SessionLocal, Base
+from app.service.v2.initialize_data import dialog_menu_sync
 
 # 创建数据库引擎和会话工厂
 engine_bisheng = create_engine(settings.sgb_db_url)
@@ -147,3 +149,13 @@ def sync_agents():
         print("Agents synchronized successfully")
     except Exception as e:
         print(f"Failed to sync agents: {str(e)}")
+
+
+async def sync_web_menu():
+    db = SessionLocal()
+    await dialog_menu_sync(db)
+
+
+async def sync_default_group():
+    db = SessionLocal()
+    await dialog_menu_sync(db)

+ 104 - 0
env_conf/menu_conf.json

@@ -0,0 +1,104 @@
+{
+  "data": [
+    {
+      "id": 10,
+      "title": "报告生成",
+      "icon": "2",
+      "img": "/src/assets/index/2.png",
+      "desc": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
+      "describe": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
+      "agent" : [],
+      "dialog": ["1"]
+    },
+    {
+      "id": 1,
+      "title": "报表合并",
+      "icon": "6",
+      "img": "/src/assets/index/6.png",
+      "desc": "基于您上传的报表进行合并,助您快速完成报表整合与分析",
+      "describe": "基于您上传的报表进行合并,助您快速完成报表整合与分析",
+      "agent" : [],
+      "dialog": ["2"]
+    },
+    {
+      "id": 2,
+      "title": "知识问答",
+      "icon": "5",
+      "img": "/src/assets/index/5.png",
+      "desc": "遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考",
+      "describe": "垂域知识的问答助手,针对你的提问,我们将遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考。",
+      "agent" : [],
+      "dialog": []
+    },
+    {
+      "id": 3,
+      "title": "文档智能",
+      "icon": "7",
+      "img": "/src/assets/index/7.png",
+      "desc": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档",
+      "describe": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档,大小在30M以内。",
+      "agent" : [],
+      "dialog": ["3"]
+    },
+    {
+      "id": 4,
+      "title": "智能问答",
+      "icon": "1",
+      "img": "/src/assets/index/1.png",
+      "desc": "能够理解和学习人类的语言,具备多轮对话的能力",
+      "describe": "我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~",
+      "agent" : [],
+      "dialog": []
+    },
+    {
+      "id": 5,
+      "title": "智能数据",
+      "icon": "8",
+      "img": "/src/assets/index/8.png",
+      "desc": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
+      "describe": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
+      "agent" : ["3", "4"],
+      "dialog": []
+    },
+    {
+      "id": 6,
+      "title": "小数绘图",
+      "icon": "7",
+      "img": "/src/assets/index/7.png",
+      "desc": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
+      "describe": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
+      "agent" : ["3"],
+      "dialog": []
+    },
+    {
+      "id": 7,
+      "title": "文档出卷",
+      "icon": "6",
+      "img": "/src/assets/index/6.png",
+      "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+      "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+      "agent" : [],
+      "dialog": []
+    },
+    {
+      "id": 8,
+      "title": "出题组卷",
+      "icon": "6",
+      "img": "/src/assets/index/6.png",
+      "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+      "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+      "agent" : ["4"],
+      "dialog": []
+    },
+    {
+      "id": 9,
+      "title": "文档报告",
+      "icon": "2",
+      "img": "/src/assets/index/2.png",
+      "desc": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。",
+      "describe": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。",
+      "agent" : [],
+      "dialog": []
+    }
+  ]
+}

+ 4 - 4
main.py

@@ -14,16 +14,14 @@ from app.api.files import router as files_router
 from app.api.knowledge import knowledge_router
 from app.api.llm import llm_router
 from app.api.organization import dept_router
-from app.api.public_api import public_api
+from app.api.v2.public_api import public_api
 from app.api.report import router as report_router
 from app.api.resource import menu_router
 # from app.api.sync_data import sync_router
 from app.api.user import user_router
 from app.api.group import group_router
 from app.api.role import role_router
-from app.models.base_model import init_db
-from app.task.fetch_agent import sync_agents, initialize_agents
-from app.task.sync_resources import sync_resource
+from app.task.fetch_agent import sync_agents, initialize_agents, sync_web_menu
 
 
 # 使用 Lifespan 事件处理程序
@@ -33,6 +31,8 @@ async def lifespan(app: FastAPI):
     initialize_agents()
     # 在应用启动时同步代理
     sync_agents()
+    await sync_default_group()
+    await sync_web_menu()
     yield
     # 在应用关闭时执行清理操作(如果需要)
     pass