diff --git a/.github/workflows/package_and_push.yml b/.github/workflows/package_and_push.yml index a4f6a14e..3ec89e7c 100644 --- a/.github/workflows/package_and_push.yml +++ b/.github/workflows/package_and_push.yml @@ -79,8 +79,9 @@ jobs: -czvf $package_online . #Sync files to OSS - ossutil cp -r ${package_offline} oss://$ALIYUN_OSS_BUCKET/sqlbot/${package_offline} --access-key-id=$ALIYUN_OSS_ACCESS_KEY --access-key-secret=$ALIYUN_OSS_ACCESS_SECRET --endpoint=${ALIYUN_OSS_BUCKET_ENDPOINT} - ossutil cp -r ${package_online} oss://$ALIYUN_OSS_BUCKET/sqlbot/${package_online} --access-key-id=$ALIYUN_OSS_ACCESS_KEY --access-key-secret=$ALIYUN_OSS_ACCESS_SECRET --endpoint=${ALIYUN_OSS_BUCKET_ENDPOINT} + ossutil cp -rf ${package_offline} oss://$ALIYUN_OSS_BUCKET/sqlbot/${package_offline} --access-key-id=$ALIYUN_OSS_ACCESS_KEY --access-key-secret=$ALIYUN_OSS_ACCESS_SECRET --endpoint=${ALIYUN_OSS_BUCKET_ENDPOINT} + ossutil cp -rf ${package_online} oss://$ALIYUN_OSS_BUCKET/sqlbot/${package_online} --access-key-id=$ALIYUN_OSS_ACCESS_KEY --access-key-secret=$ALIYUN_OSS_ACCESS_SECRET --endpoint=${ALIYUN_OSS_BUCKET_ENDPOINT} + diff --git a/.typos.toml b/.typos.toml index bb9c4600..90887b65 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,4 +1,5 @@ [default.extend-words] +sibing = "sibing" [default.extend-identifiers] maintain_column_froms = "maintain_column_froms" [files] diff --git a/backend/apps/system/api/aimodel.py b/backend/apps/system/api/aimodel.py index c60e1aa6..9e949af6 100644 --- a/backend/apps/system/api/aimodel.py +++ b/backend/apps/system/api/aimodel.py @@ -78,7 +78,7 @@ async def query( AiModelDetail.default_model) if keyword is not None: statement = statement.where(AiModelDetail.name.like(f"%{keyword}%")) - statement = statement.order_by(AiModelDetail.create_time.asc()) + statement = statement.order_by(AiModelDetail.default_model.desc(), AiModelDetail.name, AiModelDetail.create_time) items = session.exec(statement).all() return items diff --git a/backend/apps/system/api/assistant.py b/backend/apps/system/api/assistant.py index 40aa8814..fe9303e5 100644 --- a/backend/apps/system/api/assistant.py +++ b/backend/apps/system/api/assistant.py @@ -50,7 +50,7 @@ async def validator(session: SessionDep, id: int, virtual: Optional[int] = Query @router.get("", response_model=list[AssistantModel]) async def query(session: SessionDep): - list_result = session.exec(select(AssistantModel).order_by(AssistantModel.create_time.asc())).all() + list_result = session.exec(select(AssistantModel).order_by(AssistantModel.name, AssistantModel.create_time)).all() return list_result @router.post("") diff --git a/backend/apps/system/api/user.py b/backend/apps/system/api/user.py index be616134..69386e1e 100644 --- a/backend/apps/system/api/user.py +++ b/backend/apps/system/api/user.py @@ -59,7 +59,7 @@ async def pager( select(UserModel, UserWsModel.oid.label('ws_oid')) .join(UserWsModel, UserModel.id == UserWsModel.uid, isouter=True) .where(UserModel.id.in_(uid_list)) - .order_by(UserModel.create_time) + .order_by(UserModel.account, UserModel.create_time) ) user_workspaces = session.exec(stmt).all() merged = defaultdict(list) diff --git a/backend/apps/system/api/workspace.py b/backend/apps/system/api/workspace.py index 893333ca..0d795289 100644 --- a/backend/apps/system/api/workspace.py +++ b/backend/apps/system/api/workspace.py @@ -32,7 +32,7 @@ async def option_pager( stmt = select(UserModel.id, UserModel.account, UserModel.name).where( ~exists().where(UserWsModel.uid == UserModel.id, UserWsModel.oid == oid), UserModel.id != 1 - ).order_by(UserModel.create_time.asc()) + ).order_by(UserModel.account, UserModel.create_time) if keyword: keyword_pattern = f"%{keyword}%" @@ -97,7 +97,7 @@ async def pager( ).where( UserWsModel.oid == workspace_id, UserModel.id != 1 - ).order_by(UserModel.create_time.asc()) + ).order_by(UserModel.account, UserModel.create_time) if keyword: keyword_pattern = f"%{keyword}%" diff --git a/backend/apps/system/crud/user.py b/backend/apps/system/crud/user.py index 3dcd4ccf..69255a58 100644 --- a/backend/apps/system/crud/user.py +++ b/backend/apps/system/crud/user.py @@ -46,13 +46,13 @@ def authenticate(*, session: Session, account: str, password: str) -> BaseUserDT async def user_ws_options(session: Session, uid: int, trans: Optional[I18n] = None) -> list[UserWs]: if uid == 1: - stmt = select(WorkspaceModel.id, WorkspaceModel.name).order_by(WorkspaceModel.create_time) + stmt = select(WorkspaceModel.id, WorkspaceModel.name).order_by(WorkspaceModel.name, WorkspaceModel.create_time) else: stmt = select(WorkspaceModel.id, WorkspaceModel.name).join( UserWsModel, UserWsModel.oid == WorkspaceModel.id ).where( UserWsModel.uid == uid, - ).order_by(WorkspaceModel.create_time) + ).order_by(WorkspaceModel.name, WorkspaceModel.create_time) result = session.exec(stmt) if not trans: return result.all() diff --git a/backend/apps/system/crud/workspace.py b/backend/apps/system/crud/workspace.py index 38571fa9..fb2bc638 100644 --- a/backend/apps/system/crud/workspace.py +++ b/backend/apps/system/crud/workspace.py @@ -1,4 +1,5 @@ +from collections import defaultdict from typing import Optional from sqlmodel import Session, func, select, update @@ -25,17 +26,10 @@ async def reset_user_oid(session: Session, oid: int): select( UserModel.id, UserModel.oid, - func.coalesce( - func.array_remove( - func.array_agg(UserWsModel.oid), - None - ), - [] - ).label("oid_list") + UserWsModel.oid.label("associated_oid") ) .join(UserWsModel, UserModel.id == UserWsModel.uid, isouter=True) .where(UserModel.id != 1) - .group_by(UserModel.id) ) user_filter = ( @@ -46,17 +40,30 @@ async def reset_user_oid(session: Session, oid: int): ) stmt = stmt.where(UserModel.id.in_(user_filter)) - result_user_list = session.exec(stmt) - for row in result_user_list: - result_dict = {} - for item, key in zip(row, row._fields): - result_dict[key] = item - - origin_oid = result_dict['oid'] - oid_list: list = list(filter(lambda x: x != oid, result_dict['oid_list'])) + result_user_list = session.exec(stmt).all() + if not result_user_list: + return + + merged = defaultdict(list) + extra_attrs = {} + + for (id, oid, associated_oid) in result_user_list: + item = {"id": id, "oid": oid} + merged[id].append(associated_oid) + if id not in extra_attrs: + extra_attrs[id] = {k: v for k, v in item.items()} + + # 组合结果 + result = [ + {**extra_attrs[user_id], "oid_list": oid_list} + for user_id, oid_list in merged.items() + ] + + for row in result: + origin_oid = row['oid'] + oid_list: list = list(filter(lambda x: x != oid, row['oid_list'])) if origin_oid not in oid_list: - result_dict['oid'] = oid_list[0] if oid_list else 0 - if result_dict['oid'] != origin_oid: - result_dict.pop("oid_list", None) - update_stmt = update(UserModel).where(UserModel.id == result_dict['id']).values(oid=result_dict['oid']) + row['oid'] = oid_list[0] if oid_list else 0 + if row['oid'] != origin_oid: + update_stmt = update(UserModel).where(UserModel.id == row['id']).values(oid=row['oid']) session.exec(update_stmt) diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 44635bbb..d1b56379 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -6,6 +6,7 @@ "AI Model Configuration": "AI Model Configuration" }, "common": { + "no_model_yet": "No model yet", "intelligent_questioning_platform": "Welcome to the SQLBot Intelligent Questioning Platform", "login": "Login", "login_": "Login", diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json index 62a2ea54..b15ec2c4 100644 --- a/frontend/src/i18n/zh-CN.json +++ b/frontend/src/i18n/zh-CN.json @@ -6,6 +6,7 @@ "AI Model Configuration": "模型配置" }, "common": { + "no_model_yet": "暂无模型", "intelligent_questioning_platform": "欢迎使用 SQLBot 智能问数平台", "login": "账号登录", "login_": "登录", diff --git a/frontend/src/views/system/model/Model.vue b/frontend/src/views/system/model/Model.vue index fca417bc..c9ea6454 100644 --- a/frontend/src/views/system/model/Model.vue +++ b/frontend/src/views/system/model/Model.vue @@ -367,6 +367,22 @@ const submit = (item: any) => { + + + + + + + + + {{ t('model.add_model') }} + + + { .model-config { height: calc(100% - 16px); padding: 16px 0 16px 0; + + .datasource-yet { + padding-bottom: 0; + height: auto; + padding-top: 200px; + } .model-methods { display: flex; align-items: center;