ABP vNext 多租戶系統實現登錄頁自定義 Logo 的最佳實踐

🚀 ABP vNext 多租戶系統實現登錄頁自定義 Logo 的最佳實踐


🧭 版本信息與運行環境

  • ABP Framework:v8.1.5
  • .NET SDK:8.0
  • 數據庫:PostgreSQL(支持 SQLServer、MySQL 等)
  • BLOB 存儲:本地/OSS/Azure Blob(推薦啟用 CDN)
  • 部署建議:支持單庫/多庫多租戶結構,推薦搭配 CI/CD 自動遷移

📚 目錄

  • 🚀 ABP vNext 多租戶系統實現登錄頁自定義 Logo 的最佳實踐
    • 🧭 版本信息與運行環境
    • 🔍 實現背景
    • 📦 總體思路與流程圖
    • 🧱 步驟一:擴展租戶實體添加 Logo 字段
      • 🔧 實體擴展配置流程
    • 🖼 步驟二:上傳并持久化租戶 Logo
      • 📥 Logo 上傳與持久化流程
    • 🌐 步驟三:登錄頁動態加載租戶 Logo
      • ?? 登錄頁 Logo 加載流程
      • 🏗? CI/CD 自動遷移流程
    • 🧠 最佳實踐建議


🔍 實現背景

ABP vNext 提供完備的多租戶能力,支持根據請求自動切換上下文。在實際項目中,為每個租戶提供個性化登錄 Logo 是增強品牌感、提升用戶體驗的重要方式。


📦 總體思路與流程圖

使用 ABP 的實體擴展和 Blob 模塊,結合租戶解析機制,動態加載 Logo:

訪問登錄頁
TenantResolutionMiddleware
當前租戶 ID 是否為空?
調用 AppService 獲取 Logo URL
使用默認 Logo
渲染 Logo 圖片

🧱 步驟一:擴展租戶實體添加 Logo 字段

🔧 實體擴展配置流程

應用啟動
觸發 PreConfigureServices
調用 MyTenantEntityExtension.Configure()
ObjectExtensionManager 注冊 LogoUrl 屬性
生成 EF Core Migration 包含 LogoUrl 字段

💡 推薦位置*.Domain.Shared + *.Domain

// MyTenantConsts.cs
public static class MyTenantConsts
{public const string LogoUrlPropertyName = "LogoUrl";
}
// MyTenantEntityExtension.cs
public static class MyTenantEntityExtension
{public static void Configure(){ObjectExtensionManager.Instance.Modules().ConfigureSaas(sa =>{sa.ConfigureTenant(t =>{t.AddOrUpdateProperty<string>(MyTenantConsts.LogoUrlPropertyName);});});}
}

在模塊類中 PreConfigureServices 階段調用:

public override void PreConfigureServices(ServiceConfigurationContext context)
{MyTenantEntityExtension.Configure();
}

? 確保遷移腳本包含新字段


🖼 步驟二:上傳并持久化租戶 Logo

📥 Logo 上傳與持久化流程

前端頁面 TenantUiAppService BlobContainer ITenantRepository UploadLogoAsync(tenantId, file) 校驗文件大小和格式 SaveAsync(blobPath, stream) 保存成功 GetAsync(tenantId) 返回 Tenant 實體 UpdateAsync(tenant.SetProperty) 持久化完成 返回帶簽名的下載 URL 前端頁面 TenantUiAppService BlobContainer ITenantRepository

💡 建議封裝至 Application Service:

public class TenantUiAppService : ApplicationService
{private readonly IBlobContainer _blobContainer;private readonly ITenantRepository _tenantRepository;public TenantUiAppService(IBlobContainer blobContainer, ITenantRepository tenantRepository){_blobContainer = blobContainer;_tenantRepository = tenantRepository;}public async Task<string> UploadLogoAsync(Guid tenantId, IFormFile file){if (file.Length > 1024 * 1024)throw new UserFriendlyException("文件不能超過 1MB");if (!file.ContentType.StartsWith("image/"))throw new UserFriendlyException("請上傳 PNG 或 JPG 圖片");var blobPath = $"{tenantId}/logo.png";using var stream = file.OpenReadStream();await _blobContainer.SaveAsync(blobPath, stream, overrideExisting: true);var tenant = await _tenantRepository.GetAsync(tenantId);tenant.SetProperty(MyTenantConsts.LogoUrlPropertyName, blobPath);await _tenantRepository.UpdateAsync(tenant); // 持久化return await _blobContainer.GetDownloadUrlAsync(blobPath); // 帶簽名 URL}
}

🌐 步驟三:登錄頁動態加載租戶 Logo

?? 登錄頁 Logo 加載流程

用戶訪問登錄頁
TenantUiQueryService.GetLogoUrlAsync()
CurrentTenant.Id 是否為空
返回默認 Logo 路徑
從 Repository 獲取 Tenant
ExtraProperties 中是否有 LogoUrl
BlobContainer.GetDownloadUrlAsync(rawPath)
返回簽名 URL
前端 渲染

封裝服務接口:

public class TenantUiQueryService : ApplicationService
{private readonly ITenantRepository _tenantRepository;private readonly IBlobContainer _blobContainer;public TenantUiQueryService(ITenantRepository tenantRepository, IBlobContainer blobContainer){_tenantRepository = tenantRepository;_blobContainer = blobContainer;}public async Task<string> GetLogoUrlAsync(){var tenantId = CurrentTenant.Id;if (tenantId == null)return "/images/default-logo.png";var tenant = await _tenantRepository.GetAsync(tenantId.Value);if (!tenant.ExtraProperties.TryGetValue(MyTenantConsts.LogoUrlPropertyName, out var rawPath) ||rawPath == null){return "/images/default-logo.png";}return await _blobContainer.GetDownloadUrlAsync(rawPath.ToString());}
}

前端渲染:

<img src="@logoUrl" onerror="this.src='/images/default-logo.png'" class="login-logo" />

🏗? CI/CD 自動遷移流程

CI/CD Pipeline Trigger
Checkout 代碼
Restore NuGet 包
Build 項目
為每個物理庫執行遷移腳本
Update-Database 或 flyway migrate
部署新版本到目標環境

🧠 最佳實踐建議

分類建議
性能租戶 Logo 可使用 IDistributedCache 緩存
用戶體驗加載失敗 fallback 默認圖
可擴展性建議將租戶個性化信息封裝至 TenantUiCustomization 模塊
安全Blob 下載 URL 推薦使用帶簽名的臨時訪問
發布配合數據庫遷移工具(Flyway、DbUp)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80390.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80390.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80390.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FastDFS分布式文件系統架構學習(一)

FastDFS分布式文件系統架構學習 1. FastDFS簡介 FastDFS是一個開源的輕量級分布式文件系統&#xff0c;由淘寶資深架構師余慶設計并開發。它專為互聯網應用量身定制&#xff0c;特別適合以中小文件&#xff08;如圖片、文檔、音視頻等&#xff09;為載體的在線服務。FastDFS不…

基于單片機的防盜報警器設計與實現

標題:基于51單片機的防盜報警器設計 內容:1.摘要 本文圍繞基于51單片機的防盜報警器設計展開。背景在于現代社會安全需求不斷提高&#xff0c;傳統防盜方式存在諸多不足。目的是設計一款成本低、可靠性高且易于使用的防盜報警器。方法上&#xff0c;以51單片機為核心控制單元&…

IDE/IoT/搭建物聯網(LiteOS)集成開發環境,基于 LiteOS Studio + GCC + JLink

文章目錄 概述LiteOS Studio不推薦&#xff1f;安裝和使用手冊呢?HCIP實驗的源碼呢&#xff1f; 軟件和依賴安裝軟件下載軟件安裝插件安裝依賴工具-方案2依賴工具-方案1 工程配置打開或新建工程板卡配置組件配置編譯器配置-gcc工具鏈編譯器配置-Makefile腳本其他配置編譯完成 …

【高斯擬合最終篇】Levenberg-Marquardt(LM)算法

Levenberg-Marquardt(LM)算法是一種結合高斯-牛頓法和梯度下降法的優化方法,特別適合非線性最小二乘問題,如高斯函數擬合。它通過引入阻尼因子(damping factor)平衡高斯-牛頓法的快速收斂和梯度下降法的穩定性。以下是基于之前的 gaussian_fit.py,加入 LM 算法實現高斯擬…

信道編碼技術介紹

信息與通信系統中的編碼有4 種形式&#xff1a;信源編碼、信道編碼、密碼編碼和多址編碼。 其中信道編碼的作用是對信源經過壓縮后的數據加一定數量受到控制的冗余&#xff0c;使得數據在傳輸中或接收中發生的差錯可以被糾正或被發現&#xff0c;從而可以正確恢復出原始數據信息…

線性回歸策略

一種基于ATR(平均真實范圍)、線性回歸和布林帶的交易策略。以下是對該策略的全面總結和分析: 交易邏輯思路 1. 過濾條件: - 集合競價過濾:在每個交易日的開盤階段,過濾掉集合競價產生的異常數據。 - 價格異常過濾:排除當天開盤價與最高價或最低價相同的情況,這…

WordPress Relevanssi插件時間型SQL注入漏洞(CVE-2025-4396)

免責聲明 本文檔所述漏洞詳情及復現方法僅限用于合法授權的安全研究和學術教育用途。任何個人或組織不得利用本文內容從事未經許可的滲透測試、網絡攻擊或其他違法行為。使用者應確保其行為符合相關法律法規,并取得目標系統的明確授權。 對于因不當使用本文信息而造成的任何直…

支持selenium的chrome driver更新到136.0.7103.94

最近chrome釋放新版本&#xff1a;136.0.7103.94 如果運行selenium自動化測試出現以下問題&#xff0c;是需要升級chromedriver才可以解決的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only su…

附加:TCP如何保障數據傳輸

附加&#xff1a;TCP如何保障數據傳輸 LS-NET-012-TCP的交互過程詳解 TCP 如何保障數據傳輸 TCP&#xff08;Transmission Control Protocol&#xff0c;傳輸控制協議&#xff09;是互聯網核心協議之一&#xff0c;負責在IP網絡上提供可靠的、面向連接的數據傳輸服務。它位于T…

Unity 批量將圖片從默認類型改為Sprite類型

先將該腳本放到Editor目錄下 如何使用:選中目錄,然后點擊Tool里面的批量修改按鈕 using System; using UnityEngine; using UnityEditor; using System.IO; using System.Linq;/// <summary> /// 此工具可以批量將圖片類型修改為精靈 /// </summary> public clas…

2025認證杯數學建模C題思路+代碼+模型:化工廠生產流程的預測和控制

2025認證杯數學建模C題思路代碼模型&#xff0c;詳細內容見文末名片 在化工廠的生產流程中&#xff0c;往往涉及到多個反應釜、管道和儲罐等設備。在 流水線上也有每個位置的溫度、壓力、流量等諸多參數。只有參數處于正常范 圍時&#xff0c;最終的產物才是合格的。這些參數…

Rust 學習筆記:關于 HashMap 的練習題

Rust 學習筆記&#xff1a;關于 HashMap 的練習題 Rust 學習筆記&#xff1a;關于 HashMap 的練習題以下代碼能否通過編譯&#xff1f;若能&#xff0c;輸出是&#xff1f;以下代碼能否通過編譯&#xff1f;若能&#xff0c;輸出是&#xff1f; Rust 學習筆記&#xff1a;關于 …

Vue-事件修飾符

事件修飾符 prevent &#xff08;阻止默認事件&#xff09; 超鏈接 點擊事件 代碼 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>事件修飾符</title><!-- 引入Vue --><script …

LeetCode --- 156雙周賽

題目列表 3541. 找到頻率最高的元音和輔音 3542. 將所有元素變為 0 的最少操作次數 3543. K 條邊路徑的最大邊權和 3544. 子樹反轉和 一、找到頻率最高的元音和輔音 分別統計元音和輔音的出現次數最大值&#xff0c;然后相加即可&#xff0c;代碼如下 // C class Solution {…

告別 pip:使用 uv 加速你的 Python 包管理

使用 uv:更快的 Python 包管理工具 隨著 Python 生態的演進,包管理工具也在不斷升級迭代。uv 是 Astral(同樣維護 ruff 的團隊)推出的下一代 Python 包與項目管理器,主打 單一可執行文件、極致性能,可在多數場景下取代 pip、pip-tools、pipx 與 virtualenv 等傳統工具,…

MATLAB學習筆記(七):MATLAB建模城市的雨季防洪排污的問題

使用 MATLAB 對城市雨季防洪排污問題進行建模與仿真&#xff0c;需要結合數學模型、工程經驗和 MATLAB 的數值計算、數據可視化及優化工具。以下是詳細的步驟指南&#xff0c;包含實際案例和代碼示例&#xff1a; 一、問題分析與建模框架 1. 問題拆解 ? 核心目標&#xff1a; …

以項目的方式學QT開發C++(二)——超詳細講解(120000多字詳細講解,涵蓋qt大量知識)逐步更新!

API 描述 函數原型 參數說明 push_back() 在 list 尾部 添加一個元素 void push_back(const T& value); value &#xff1a;要添 加到尾部的元 素 這個示例演示了如何創建 std::list 容器&#xff0c;并對其進行插入、刪除和迭代操作。在實際應用中&am…

08 web 自動化之 PO 設計模式詳解

文章目錄 一、什么是 POM二、如何基于 POM 進行自動化框架架構&#xff1f;1、base 層封裝2、pageobjects 層封裝3、TestCases 層封裝 三、元素和方法分離&數據分離1、哪些部分可以進行分離2、示例代碼 四、總結 一、什么是 POM POM page object model 頁面對象模型 WEB 自…

將 JSON 批量轉換為 XML:深度解析與完整實現指南

在數據科學與機器學習項目中&#xff0c;數據預處理始終扮演著不可或缺的角色。尤其當你面對多類別圖像標注任務&#xff0c;而標注數據卻是以 JSON 形式存在&#xff0c;而目標檢測模型卻偏好 VOC 格式的 XML 時&#xff0c;這個轉換過程就變得極為關鍵。 本文將帶你深入解讀…

AlphaEvolve:基于Gemini的算法發現與優化綜合報告

引言 ? 本報告分析Google DeepMind于2025年5月14日正式發布的AlphaEvolve技術。? AlphaEvolve是一種由Gemini大型語言模型驅動的進化式編碼代理&#xff0c;專注于通用算法的發現和優化。? 報告深入探討AlphaEvolve的技術原理、實際應用及其對未來AI和算法研究的潛在影響。…