feat(gerp): 新增按公司查询已启用应用接口 /API/App/CompanyApps

公司详情页需要展示该公司启用的应用并支持卸载/配置,原 /API/App/ManageCompanies 是反向(按应用查公司安装状态),故补正查接口:AppManager.ListCompanyEnabledApps 按公司列出 InstallStatus=1 的应用,AppCompanyAppsView 按可管理范围校验(super=全部 / tenant=本租户 / company=被授权公司)。
This commit is contained in:
TermiNexus committed 2026-09-29 18:50:10 +08:00
1 parent 6bff657664
commit 792b76fb46
4 files changed
+57

No files matched your search

+24
View File
@@ -793,6 +793,30 @@ class AppManager:
}
return result
@staticmethod
def ListCompanyEnabledApps(CompanyUUID):
"""列出指定公司已启用(InstallStatus=1)的应用(公司详情页用)
与 ListAppCompanyInstalls 互补:后者按应用反查公司安装状态,
本方法按公司列出已装应用,供公司详情页展示 + 卸载/配置入口。
Returns:
list[dict]:_AppFlat 结构 + InstallStatus,按 AppSort/AppName 排序
"""
company_bytes = _ToBytes(CompanyUUID)
if not company_bytes:
return []
rows = []
for ca in SdkAppManager.ListCompanyApps(company_bytes, InstallStatus=1):
app = AppManager.GetApp(ca.AppUUID)
if app is None:
continue
row = _AppFlat(app)
row['InstallStatus'] = ca.InstallStatus
rows.append(row)
rows.sort(key=lambda r: (r.get('AppSort') or 0, r.get('AppName') or ''))
return rows
@staticmethod
def ListAppCompanyInstalls(AppUUID, CompanyUUIDs):
"""查询指定应用在若干公司的安装状态(管理弹窗用)
+1
View File
@@ -149,6 +149,7 @@ from .app import (
AppMarketView,
AppMyAppsView,
AppManageCompaniesView,
AppCompanyAppsView,
AppInstallView,
AppUninstallView,
AppUserEnableView,
+31
View File
@@ -295,6 +295,37 @@ class AppManageCompaniesView(ELTAuthenticatedAPIView):
return Response({'code': 0, 'data': {'Scope': scope, 'Companies': rows, 'Roles': roles}})
class AppCompanyAppsView(ELTAuthenticatedAPIView):
"""指定公司已启用的应用列表(公司详情页用)
GET /API/App/CompanyApps?CompanyUUID=xxx
- 返回该公司 InstallStatus=1 的应用(含图标/名称/编码/描述/前端入口)
- 权限:管理员 + 该公司在可管理范围内
(admin:super=全部 / admin:tenant=本租户 / admin:company=被授权公司)
与 /API/App/ManageCompanies 互补:后者按应用反查各公司安装状态,
本接口按公司列出已装应用,供公司详情页展示"已启用应用"并做卸载/配置。
"""
permission_classes = [IsAuthenticated, IsAdminUser]
def get(self, request):
company_str = (request.query_params.get('CompanyUUID') or '').strip()
if not company_str:
return Response({'code': 1, 'msg': '缺少公司 UUID'}, status=400)
try:
company_bytes = UUIDObj(company_str).bytes
except Exception:
return Response({'code': 1, 'msg': '无效的公司 UUID'}, status=400)
manageable, scope = AppManager.GetManageableCompanies(request)
if not scope:
return Response({'code': 403, 'msg': '无权查看该公司应用:您不是管理员'}, status=403)
if scope != 'all' and company_bytes.hex() not in {c.hex() for c in manageable}:
return Response({'code': 403, 'msg': '无权查看该公司应用(不在您的管理范围)'}, status=403)
rows = AppManager.ListCompanyEnabledApps(company_bytes)
return Response({'code': 0, 'data': {'list': rows, 'total': len(rows)}})
class AppInstallView(ELTAuthenticatedAPIView):
"""管理员:安装企业功能。
+1
View File
@@ -155,6 +155,7 @@ urlpatterns = [
path('API/App/Market', gerp_views.AppMarketView.as_view(), name='app_market'),
path('API/App/MyApps', gerp_views.AppMyAppsView.as_view(), name='app_my_apps'),
path('API/App/ManageCompanies', gerp_views.AppManageCompaniesView.as_view(), name='app_manage_companies'),
path('API/App/CompanyApps', gerp_views.AppCompanyAppsView.as_view(), name='app_company_apps'),
path('API/App/Install', gerp_views.AppInstallView.as_view(), name='app_install'),
path('API/App/Uninstall', gerp_views.AppUninstallView.as_view(), name='app_uninstall'),
path('API/App/Enable', gerp_views.AppUserEnableView.as_view(), name='app_enable'),