From 7a3e9ad1c7ba3f0ade9edf34c284341e890af428 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Wed, 19 Nov 2025 11:49:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E7=BF=BB=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes app.zip | Bin 65866 -> 65959 bytes app/api/endpoints/meetings.py | 104 ++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/.DS_Store b/.DS_Store index 778775b77cfcf8297ece80b2a24132b1f9e2b6a0..8ef9355b9543b73cab39087dbe59ada5d0761452 100644 GIT binary patch delta 18 ZcmZp1XmQw(CcqlYz`(F%g9;Quw!!I$1qB5G5fBhrEI}}V0DXB$UdQ*&JNNtV|J{GN=icxAb_sto z8J`ggjb>9oQW*R8nhs8mcY#AtwH(I*CO#R(7nI^r97eb-$85nxq9-0T{z2*|$_;OD zP{#mNlTD%QObW=HAqzz0H&`NU1j^ES3l8eEV&&{z0+Y?p31}RSzV825WC?AJ4go4O z!wrolPI{6+hMO_O%Ag3E-G-EiFi^CB^w>xs2~1CNmC=01{45p8>!FL8 z6oGB{SppFTpDf!Q?FgmA&Zuan1`!5|3e@3Vy)g2}UIp;eHUYkflqhZ6=n4gCKQd+m z28&P%x<)N}_498dffK0mPPp~0 zs+z)>c8TXiVeKsS1wVr{m%q<3jI-%iwHY0|j;?iX5cm|wAIy*AtXsHI%B(P!kkgQNKKQa@ANfg4}E!A8dMJ$zXV z%(Kz(M8Z3pon6gmSmM$6l`*HB&x7qed5p2Pmf|ZfSdvQ(d(w;wlDvI+jA#S5?f=#L z>0Dym>7b!lo@0cqM0jg;;#6(IH~VYO{Stt$Jv!Gs((P7h$J*-4 zy{vKz)taHln0LMFdW>`5^s)i{U_!(oi+FG{oqvdk`RG!G$GPle%%dp}C z1~?bGCTs2g_R7UtGPL&#=8#H2!SLDqrgo-&atQ^(#@=uTdHqle_p=dUa=5SN+DhK` z!ib5pdSVq9C!%uf{c~PE5C&tfg2A{rLGblchF_^XHD(zDeK84dRqtkn0X#cNf~JlUCB=k* z_QV{O&yxNgRK5h>gUN~*F@Q0Vi>z>+)CU_U3lTgrr3<1VGMJo9MeXn37NFQ+iYLbp zkg@1p8#201>VlN%N)$WK9F$9a5UTQ04to|4w#~|T-LsETe#2Zjg5ms#jC0=8Q5lD| z4!~=X`M2-w(0S>eN@F_z@f3|?H(!flwh#}t2oFhx9ry^DsIY&vpbtdCdX(3_;3(B| z(CkJAdq12(C0!c(&IehINsAJcpTFdY=y!EN6-a{ji}=wU)pOsE5r}*n=Qbg}rH{U- zoWt=DIsfa_0FFrZw~|Xa+U5iC7ToSMfEDll4BLnnM<)rM$1&_Igl>X1{Gij&|lU7Im;BBZ8l8b3aHsyXn({NDn#VT zGT5wm;TnpOh}Vj#DCGl8`LRSsF_gIB#w!s@oUz%}g!*EgiW?a~s7(VDMO3acmJ0nch)}u7*i+aM?g-XS>g5?=vHFC&6ViX}pR@uZ A)Bpeg delta 2187 zcmY*a3p7-D9Gj3PtNN6v%8#reUp9O)Wa2%f`hv3+s5;=!OvY)7~Bs}<*)=ZrX1i(t$5ack; z;2W`YStoOxNJW6}Y)gU6O1q3Wr(7>H)or5SHN^UQ3#YLKS_Uh@LB%TIWS{~{U=488 zV4YgG3&VE^`OIw~(=x25;}v|(n;DCy=(VSTXS+?{_*nYywj44Q`JT@NMb0!?sl%@M zu|>eml?LK?9Qau@T~^9#BU2GDKQ^{g356yzbBkBO``LfDdA@lOEJU{58E}+BMZlu8 z4MBD=K*-ZUff`f<;1iUXml9^fSkEtSa-7;+bNcn9 znv;1{mDh1i5ajsF{un+%6sLcPUKQ-G|s7V%6ZI0zW9%G#F$VfdC zw7sN2YjCI7Ww6hxRU!4O+)($%GBb&I$)U4okBo6QP(;(9W|FEB^NlrmDrOB+5v_>>>*-NVY5)CAXRPSyVM z4Hy41wM`qSEJ#vI_Wmrhs&s^Tw&qcXNKOO1XFArb=fY*9aYaOz8{D=mk!|juB(=QA zTc1y>UCDm+qgC$XNle0aOn(ZnP(m~EMExbJrOgEYU4fA34W?n^8s`E1qRi5D%y zzg}!B@E9I2cw6sTVkT(K&(M{zJ$hPA~I&Gr?JHuF@=j{M#D1GwK1^K}+D19wgFUR-rOx z`zEj`2gk6zAN1awj!v=9JN>@7KHK+hcXht^c6XeAw-Uww|vNP6oT0 z84nk`c^}x3ax-#dOH)}|B7>L~eW#io8x}kfQmi!edM%nUnm$^U*?LkoN!aU1RjC+H zFo$6R0lh4H9bpoapn|*u-HwBmfCEC5G|UzhpKJk4#aO`CkvnG*Ye1nQVE)d@+QB`{ zWMr2TB53$UzLq9Y#e>4EMqND6c-&9M15xcp+^#@x3r%Lz_OHE6z2FevCw z#8ON9^?-lRtvRd%Qr?mPS254c#tMaG0e@owCIR<%sd$|gz3Dja=#}DF+GmCOEg0xK zj@xZ%zdjK5f6_P%%sMx_b9csYzp~G^#=c$n| zQD?nu%LFNXG|)EUj2kSP;yhY{OF8fDP+tY5yjgAH`+c~*qS~b&p5oe%AKG!O{Lc>a z(;P__C>_xQ-edc4e?{|Nj_t=Rm6P}Y z+1p8}4%J2j#>5&RR4!R`me3wKN*0t50|FC2iX{1`PL(q(s7{V41dVL8R{SO+3yNsLlzOcz=4-`Ek;lAN eR2kn+^n@b1P{ma*B2gceTn$A4#kHG&y#5E&dlBgX diff --git a/app/api/endpoints/meetings.py b/app/api/endpoints/meetings.py index 3a7ae2b..860720e 100644 --- a/app/api/endpoints/meetings.py +++ b/app/api/endpoints/meetings.py @@ -624,6 +624,110 @@ def get_meeting_llm_tasks(meeting_id: int, current_user: dict = Depends(get_curr except Exception as e: return create_api_response(code="500", message=f"Failed to get LLM tasks: {str(e)}") +@router.get("/meetings/{meeting_id}/navigation") +def get_meeting_navigation( + meeting_id: int, + current_user: dict = Depends(get_current_user), + user_id: Optional[int] = None, + filter_type: str = "all", + search: Optional[str] = None, + tags: Optional[str] = None +): + """ + 获取当前会议在列表中的上一条和下一条 + + Query params: + - user_id: 当前用户ID + - filter_type: 筛选类型 ('all', 'created', 'attended') + - search: 搜索关键词 (可选) + - tags: 标签列表,逗号分隔 (可选) + """ + try: + with get_db_connection() as connection: + cursor = connection.cursor(dictionary=True) + + # 构建WHERE子句 - 与get_meetings保持一致 + where_conditions = [] + params = [] + has_attendees_join = False + + # 按类型过滤 + if user_id: + if filter_type == "created": + where_conditions.append("m.user_id = %s") + params.append(user_id) + elif filter_type == "attended": + where_conditions.append("m.user_id != %s AND a.user_id = %s") + params.extend([user_id, user_id]) + has_attendees_join = True + else: # all + where_conditions.append("(m.user_id = %s OR a.user_id = %s)") + params.extend([user_id, user_id]) + has_attendees_join = True + + # 搜索关键词过滤 + if search and search.strip(): + search_pattern = f"%{search.strip()}%" + where_conditions.append("(m.title LIKE %s OR u.caption LIKE %s)") + params.extend([search_pattern, search_pattern]) + + # 标签过滤 + if tags and tags.strip(): + tag_list = [t.strip() for t in tags.split(',') if t.strip()] + if tag_list: + tag_conditions = [] + for tag in tag_list: + tag_conditions.append("m.tags LIKE %s") + params.append(f"%{tag}%") + where_conditions.append(f"({' OR '.join(tag_conditions)})") + + # 构建查询 - 只获取meeting_id,按meeting_time降序排序 + query = ''' + SELECT m.meeting_id + FROM meetings m + JOIN users u ON m.user_id = u.user_id + ''' + + if has_attendees_join: + query += " LEFT JOIN attendees a ON m.meeting_id = a.meeting_id" + + if where_conditions: + query += f" WHERE {' AND '.join(where_conditions)}" + + if has_attendees_join: + query += " GROUP BY m.meeting_id" + + query += " ORDER BY m.meeting_time DESC, m.created_at DESC" + + cursor.execute(query, params) + all_meetings = cursor.fetchall() + all_meeting_ids = [m['meeting_id'] for m in all_meetings] + + # 找到当前会议在列表中的位置 + try: + current_index = all_meeting_ids.index(meeting_id) + except ValueError: + return create_api_response(code="200", message="当前会议不在筛选结果中", data={ + 'prev_meeting_id': None, + 'next_meeting_id': None, + 'current_index': None, + 'total_count': len(all_meeting_ids) + }) + + # 计算上一条和下一条 + prev_meeting_id = all_meeting_ids[current_index - 1] if current_index > 0 else None + next_meeting_id = all_meeting_ids[current_index + 1] if current_index < len(all_meeting_ids) - 1 else None + + return create_api_response(code="200", message="获取导航信息成功", data={ + 'prev_meeting_id': prev_meeting_id, + 'next_meeting_id': next_meeting_id, + 'current_index': current_index, + 'total_count': len(all_meeting_ids) + }) + + except Exception as e: + return create_api_response(code="500", message=f"获取导航信息失败: {str(e)}") + @router.get("/meetings/{meeting_id}/preview-data") def get_meeting_preview_data(meeting_id: int): """