最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于NetCorePal Cloud Framework的DDD架構(gòu)管理系統(tǒng)實(shí)踐指南

 更新時(shí)間:2026年05月22日 08:54:27   作者:紅泥巴煮雪  
前段時(shí)間在做一個(gè)管理系統(tǒng)的項(xiàng)目,想嘗試一下DDD架構(gòu)在實(shí)際項(xiàng)目中的應(yīng)用,今天就想和大家分享一下這個(gè)項(xiàng)目的架構(gòu)設(shè)計(jì)和技術(shù)選型,希望能給正在做類似項(xiàng)目的朋友一些參考

前段時(shí)間在做一個(gè)管理系統(tǒng)的項(xiàng)目,想嘗試一下DDD架構(gòu)在實(shí)際項(xiàng)目中的應(yīng)用。經(jīng)過(guò)一番調(diào)研,最終選擇了NetCorePal Cloud Framework作為基礎(chǔ)框架,結(jié)合.NET 10和Vue 3搭建了一套完整的前后端分離架構(gòu)。今天就想和大家分享一下這個(gè)項(xiàng)目的架構(gòu)設(shè)計(jì)和技術(shù)選型,希望能給正在做類似項(xiàng)目的朋友一些參考。

項(xiàng)目源碼地址:https://github.com/zhouda1fu/Ncp.Admin

項(xiàng)目概述

這個(gè)項(xiàng)目是一個(gè)典型的企業(yè)級(jí)管理系統(tǒng),包含了用戶、角色、部門等基礎(chǔ)功能模塊。在技術(shù)選型上,采用了目前比較主流的技術(shù)棧:

后端方面,使用.NET 10作為主要框架,配合EF Core做數(shù)據(jù)訪問(wèn),F(xiàn)astEndpoints替代傳統(tǒng)的Controller,MediatR實(shí)現(xiàn)CQRS模式。數(shù)據(jù)存儲(chǔ)支持MySQL、PostgreSQL和SQL Server,消息隊(duì)列選擇了RabbitMQ(通過(guò)CAP框架集成),緩存用Redis,還集成了.NET Aspire來(lái)做云原生的基礎(chǔ)設(shè)施管理。

前端部分基于Vben Admin,這是一個(gè)非常優(yōu)秀的Vue 3 + TypeScript + Vite的管理后臺(tái)模板,UI組件用的是Ant Design Vue,整體體驗(yàn)不錯(cuò)。

架構(gòu)設(shè)計(jì)

分層架構(gòu)

整個(gè)項(xiàng)目采用了經(jīng)典的三層架構(gòu),這個(gè)結(jié)構(gòu)應(yīng)該很多做DDD的朋友都比較熟悉。三層之間的依賴關(guān)系是單向的:Web層依賴Infrastructure層,Infrastructure層依賴Domain層,Domain層作為核心,不依賴任何其他層。

Ncp.Admin
├── Domain(領(lǐng)域?qū)樱?
│   ├── AggregatesModel(聚合模型)
│   └── DomainEvents(領(lǐng)域事件)
├── Infrastructure(基礎(chǔ)設(shè)施層)
│   ├── EntityConfigurations(實(shí)體配置)
│   └── Repositories(倉(cāng)儲(chǔ)實(shí)現(xiàn))
└── Web(表現(xiàn)層)
    ├── Application(應(yīng)用服務(wù)層)
    │   ├── Commands(命令)
    │   ├── Queries(查詢)
    │   └── DomainEventHandlers(領(lǐng)域事件處理器)
    └── Endpoints(API端點(diǎn))

這種分層的好處是職責(zé)清晰,Domain層只關(guān)注業(yè)務(wù)邏輯,Infrastructure層負(fù)責(zé)技術(shù)實(shí)現(xiàn),Web層處理HTTP請(qǐng)求和響應(yīng)。

核心設(shè)計(jì)模式

1. 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)

在這個(gè)項(xiàng)目中,DDD主要體現(xiàn)在聚合根的設(shè)計(jì)上。每個(gè)聚合根都有自己的業(yè)務(wù)邊界,狀態(tài)只能通過(guò)業(yè)務(wù)方法來(lái)修改。就拿部門這個(gè)聚合根來(lái)說(shuō)吧:

/// <summary>
/// 部門ID(強(qiáng)類型ID)
/// </summary>
public partial record DeptId : IInt64StronglyTypedId;
/// <summary>
/// 部門聚合根
/// </summary>
public class Dept : Entity<DeptId>, IAggregateRoot
{
    public string Name { get; private set; } = string.Empty;
    public string Remark { get; private set; } = string.Empty;
    public DeptId ParentId { get; private set; } = default!;
    public int Status { get; private set; } = 1;
    protected Dept() { }
    // 業(yè)務(wù)方法:更新部門信息
    public void UpdateInfo(string name, string remark, DeptId parentId, int status)
    {
        Name = name;
        Remark = remark;
        ParentId = parentId;
        Status = status;
        UpdateTime = new UpdateTime(DateTimeOffset.UtcNow);
        // 發(fā)布領(lǐng)域事件
        AddDomainEvent(new DeptInfoChangedDomainEvent(this));
    }
    // 軟刪除
    public void SoftDelete()
    {
        if (IsDeleted)
        {
            throw new KnownException("部門已經(jīng)被刪除");
        }
        IsDeleted = true;
        UpdateTime = new UpdateTime(DateTimeOffset.UtcNow);
    }
}

這里有幾個(gè)設(shè)計(jì)點(diǎn)我覺得值得說(shuō)一下。首先是強(qiáng)類型ID,比如DeptId,這樣可以避免把部門ID和用戶ID搞混,編譯器就能幫你檢查出來(lái)。其次是屬性都用private set,外面不能直接修改,必須通過(guò)業(yè)務(wù)方法,這樣就保證了業(yè)務(wù)規(guī)則的一致性。另外,當(dāng)部門信息變更時(shí)會(huì)發(fā)布領(lǐng)域事件,這樣可以通知其他需要同步更新的地方,比如用戶表中的部門名稱。

2. CQRS模式(命令查詢職責(zé)分離)

CQRS在這個(gè)項(xiàng)目中主要體現(xiàn)在讀寫分離上。寫操作通過(guò)命令(Command)來(lái)處理,讀操作通過(guò)查詢(Query)來(lái)處理。這樣做的好處是職責(zé)清晰,而且可以針對(duì)不同的場(chǎng)景做優(yōu)化。

寫操作這邊,命令的定義很簡(jiǎn)單,就是一個(gè)record。每個(gè)命令都有對(duì)應(yīng)的驗(yàn)證器和處理器??匆粋€(gè)創(chuàng)建部門的例子:

/// <summary>
/// 創(chuàng)建部門命令
/// </summary>
public record CreateDeptCommand(string Name, string Remark, DeptId? ParentId, int Status) 
    : ICommand<DeptId>;
/// <summary>
/// 命令驗(yàn)證器
/// </summary>
public class CreateDeptCommandValidator : AbstractValidator<CreateDeptCommand>
{
    public CreateDeptCommandValidator(DeptQuery deptQuery)
    {
        RuleFor(d => d.Name).NotEmpty().WithMessage("部門名稱不能為空");
        RuleFor(d => d.Name)
            .MustAsync(async (n, ct) => !await deptQuery.DoesDeptExist(n, ct))
            .WithMessage(d => $"該部門已存在,Name={d.Name}");
        RuleFor(d => d.Status).InclusiveBetween(0, 1).WithMessage("狀態(tài)值必須為0或1");
    }
}
/// <summary>
/// 命令處理器
/// </summary>
public class CreateDeptCommandHandler(IDeptRepository deptRepository) 
    : ICommandHandler<CreateDeptCommand, DeptId>
{
    public async Task<DeptId> Handle(CreateDeptCommand request, CancellationToken cancellationToken)
    {
        var parentId = request.ParentId ?? new DeptId(0);
        var dept = new Dept(request.Name, request.Remark, parentId, request.Status);
        await deptRepository.AddAsync(dept, cancellationToken);
        // 注意:不需要手動(dòng)調(diào)用SaveChanges,框架會(huì)自動(dòng)處理
        return dept.Id;
    }
}

驗(yàn)證器這里用了FluentValidation,支持同步和異步驗(yàn)證。比如檢查部門名稱是否已存在這種需要查數(shù)據(jù)庫(kù)的驗(yàn)證,就可以用異步的MustAsync。

讀操作這邊,直接使用DbContext,而且可以用投影來(lái)優(yōu)化性能。比如獲取部門樹的時(shí)候,只選擇需要的字段:

/// <summary>
/// 部門查詢服務(wù)
/// </summary>
public class DeptQuery(ApplicationDbContext applicationDbContext) : IQuery
{
    private DbSet<Dept> DeptSet { get; } = applicationDbContext.Depts;
    /// <summary>
    /// 獲取部門樹(使用投影優(yōu)化性能)
    /// </summary>
    public async Task<IEnumerable<DeptTreeDto>> GetDeptTreeAsync(
        bool includeInactive = false, 
        CancellationToken cancellationToken = default)
    {
        // 使用投影只選擇需要的字段,減少內(nèi)存占用
        var allDepts = await DeptSet.AsNoTracking()
            .WhereIf(!includeInactive, d => d.Status != 0)
            .Select(d => new DeptTreeNode
            {
                Id = d.Id,
                Name = d.Name,
                Remark = d.Remark,
                ParentId = d.ParentId,
                Status = d.Status,
                CreatedAt = d.CreatedAt
            })
            .ToListAsync(cancellationToken);
        // 在內(nèi)存中構(gòu)建樹形結(jié)構(gòu)
        return BuildTreeStructure(allDepts);
    }
}

這樣讀寫分離的好處是,查詢這邊可以針對(duì)不同的查詢場(chǎng)景做優(yōu)化,比如用投影減少內(nèi)存占用,或者將來(lái)可以加緩存、用讀庫(kù)等,而不會(huì)影響寫操作的邏輯。

3. 事件驅(qū)動(dòng)架構(gòu)

事件驅(qū)動(dòng)這塊,項(xiàng)目實(shí)現(xiàn)了領(lǐng)域事件和集成事件兩種機(jī)制。領(lǐng)域事件主要用于聚合內(nèi)部的同步操作,集成事件用于跨服務(wù)通信。

比如說(shuō),當(dāng)部門信息變更的時(shí)候,需要同步更新用戶表中的部門名稱。這個(gè)過(guò)程就可以通過(guò)領(lǐng)域事件來(lái)實(shí)現(xiàn):

/// <summary>
/// 部門信息變更領(lǐng)域事件
/// </summary>
public record DeptInfoChangedDomainEvent(Dept Dept) : IDomainEvent;

然后在事件處理器中處理這個(gè)邏輯:

/// <summary>
/// 部門信息變更領(lǐng)域事件處理器 - 用于更新用戶部門名稱
/// </summary>
public class DeptInfoChangedDomainEventHandlerForUpdateUserDeptName(
    IMediator mediator, 
    UserQuery userQuery) 
    : IDomainEventHandler<DeptInfoChangedDomainEvent>
{
    public async Task Handle(DeptInfoChangedDomainEvent domainEvent, CancellationToken cancellationToken)
    {
        var dept = domainEvent.Dept;
        var deptId = dept.Id;
        var newDeptName = dept.Name;
        // 查詢所有屬于該部門的用戶ID
        var userIds = await userQuery.GetUserIdsByDeptIdAsync(deptId, cancellationToken);
        // 通過(guò)Command更新每個(gè)用戶的部門名稱(而不是直接操作數(shù)據(jù)庫(kù))
        foreach (var userId in userIds)
        {
            var command = new UpdateUserDeptNameCommand(userId, newDeptName);
            await mediator.Send(command, cancellationToken);
        }
    }
}

這樣設(shè)計(jì)的好處是,部門聚合和用戶聚合之間沒有直接依賴,通過(guò)事件來(lái)通信。如果將來(lái)需要增加新的業(yè)務(wù)邏輯,比如部門變更時(shí)要發(fā)送通知,只需要再加一個(gè)事件處理器就行了,不需要改現(xiàn)有的代碼。

4. FastEndpoints輕量級(jí)API框架

在API設(shè)計(jì)這塊,項(xiàng)目選擇了FastEndpoints而不是傳統(tǒng)的Controller。主要是覺得FastEndpoints的代碼更簡(jiǎn)潔,性能也更好。一個(gè)端點(diǎn)就是一個(gè)類,職責(zé)清晰。

看一個(gè)創(chuàng)建部門的例子:

/// <summary>
/// 創(chuàng)建部門的API端點(diǎn)
/// </summary>
[Tags("Depts")]
public class CreateDeptEndpoint(IMediator mediator) 
    : Endpoint<CreateDeptRequest, ResponseData<CreateDeptResponse>>
{
    public override void Configure()
    {
        Post("/api/admin/dept");
        AuthSchemes(JwtBearerDefaults.AuthenticationScheme);
        Permissions(PermissionCodes.AllApiAccess, PermissionCodes.DeptCreate);
    }
    public override async Task HandleAsync(CreateDeptRequest req, CancellationToken ct)
    {
        var cmd = new CreateDeptCommand(req.Name, req.Remark, req.ParentId, req.Status);
        var deptId = await mediator.Send(cmd, ct);
        var response = new CreateDeptResponse(deptId, req.Name, req.Remark);
        await Send.OkAsync(response.AsResponseData(), cancellation: ct);
    }
}

代碼很簡(jiǎn)潔,一個(gè)類就把路由、認(rèn)證、權(quán)限都配置好了。請(qǐng)求和響應(yīng)都是強(qiáng)類型的,類型安全有保障。而且測(cè)試起來(lái)也很方便,不需要啟動(dòng)HTTP服務(wù)器,直接測(cè)端點(diǎn)就行了。

幾個(gè)核心特性

1. 強(qiáng)類型ID

這個(gè)項(xiàng)目里所有聚合根都用強(qiáng)類型ID,而不是直接用longint。比如部門ID是DeptId,用戶ID是UserId。這樣做的好處是編譯器能幫你檢查類型錯(cuò)誤,不會(huì)把部門ID和用戶ID搞混。

使用起來(lái)也很簡(jiǎn)單:

// 定義強(qiáng)類型ID
public partial record DeptId : IInt64StronglyTypedId;
// 使用強(qiáng)類型ID
var deptId = new DeptId(123);
var parentId = request.ParentId ?? new DeptId(0);

框架會(huì)自動(dòng)處理序列化和類型轉(zhuǎn)換,用起來(lái)很順手。

2. 倉(cāng)儲(chǔ)模式

倉(cāng)儲(chǔ)這塊,寫操作通過(guò)倉(cāng)儲(chǔ)來(lái)處理,查詢操作直接使用DbContext。倉(cāng)儲(chǔ)的實(shí)現(xiàn)很簡(jiǎn)單:

/// <summary>
/// 部門倉(cāng)儲(chǔ)接口
/// </summary>
public interface IDeptRepository : IRepository<Dept, DeptId> { }
/// <summary>
/// 部門倉(cāng)儲(chǔ)實(shí)現(xiàn)
/// </summary>
public class DeptRepository(ApplicationDbContext context) 
    : RepositoryBase<Dept, DeptId, ApplicationDbContext>(context), 
      IDeptRepository { }

框架會(huì)自動(dòng)管理事務(wù)和SaveChanges,命令處理器里不需要手動(dòng)調(diào)用,這樣代碼更簡(jiǎn)潔,也不容易出錯(cuò)。

3. 驗(yàn)證機(jī)制

驗(yàn)證用的是FluentValidation,支持同步和異步驗(yàn)證。比如創(chuàng)建部門的時(shí)候,需要檢查部門名稱是否已存在,就可以用異步驗(yàn)證:

public class CreateDeptCommandValidator : AbstractValidator<CreateDeptCommand>
{
    public CreateDeptCommandValidator(DeptQuery deptQuery)
    {
        RuleFor(d => d.Name).NotEmpty().WithMessage("部門名稱不能為空");
        // 異步驗(yàn)證:檢查部門名稱是否已存在
        RuleFor(d => d.Name)
            .MustAsync(async (n, ct) => !await deptQuery.DoesDeptExist(n, ct))
            .WithMessage(d => $"該部門已存在,Name={d.Name}");
    }
}

4. 異常處理

業(yè)務(wù)異常用KnownException來(lái)處理,框架會(huì)自動(dòng)轉(zhuǎn)換成合適的HTTP狀態(tài)碼。比如在聚合根里:

// 在聚合根中
public void SoftDelete()
{
    if (IsDeleted)
    {
        throw new KnownException("部門已經(jīng)被刪除");
    }
    // ...
}
// 在命令處理器中
var dept = await deptRepository.GetAsync(request.DeptId, cancellationToken) 
    ?? throw new KnownException($"未找到部門,DeptId = {request.DeptId}");

這樣前端收到的錯(cuò)誤信息就很清晰,不需要再做額外的轉(zhuǎn)換。

測(cè)試策略

測(cè)試這塊,項(xiàng)目用的是xUnit,集成測(cè)試用了Aspire來(lái)自動(dòng)管理測(cè)試環(huán)境。這樣做的好處是不用手動(dòng)搭建測(cè)試數(shù)據(jù)庫(kù)、Redis這些基礎(chǔ)設(shè)施,Aspire會(huì)自動(dòng)啟動(dòng)和管理。

看一個(gè)部門創(chuàng)建接口的測(cè)試?yán)樱?/p>

[Collection(WebAppTestCollection.Name)]
public class DeptTests(WebAppFixture app) : AuthenticatedTestBase<WebAppFixture>(app)
{
    [Fact]
    public async Task CreateDept_WithValidData_ShouldSucceed()
    {
        // Arrange
        var client = await GetAuthenticatedClientAsync();
        var deptName = $"測(cè)試部門_{Guid.NewGuid():N}";
        try
        {
            // Act
            var request = new CreateDeptRequest(deptName, "測(cè)試備注", null, 1);
            var (response, result) = await client.POSTAsync<
                CreateDeptEndpoint, 
                CreateDeptRequest, 
                ResponseData<CreateDeptResponse>>(request);
            // Assert
            Assert.True(response.IsSuccessStatusCode);
            Assert.NotNull(result?.Data);
            Assert.Equal(deptName, result.Data.Name);
        }
        finally
        {
            await CleanupTestDataAsync();
        }
    }
}

這種測(cè)試方式很接近真實(shí)的場(chǎng)景,測(cè)試的是完整的HTTP請(qǐng)求流程,而且會(huì)自動(dòng)清理測(cè)試數(shù)據(jù),保證測(cè)試之間的獨(dú)立性。另外還支持身份認(rèn)證測(cè)試,可以模擬登錄用戶的各種操作。

前端架構(gòu)

前端用的是Vben Admin這個(gè)模板,這是一個(gè)基于Vue 3的管理后臺(tái)框架。技術(shù)棧也比較主流:Vue 3 Composition API、TypeScript、Vite、Ant Design Vue,狀態(tài)管理用Pinia,路由用Vue Router。

Vben Admin這個(gè)框架做得很完善,開箱即用的功能很多。比如權(quán)限控制,支持路由權(quán)限和按鈕權(quán)限,用起來(lái)很方便。還有國(guó)際化支持,可以多語(yǔ)言切換。主題和布局也可以定制,基本的管理后臺(tái)需求都能滿足。

最重要的是類型安全,前后端都用了TypeScript,接口定義好之后,類型檢查能幫你發(fā)現(xiàn)很多問(wèn)題。

開發(fā)規(guī)范

為了讓代碼質(zhì)量更統(tǒng)一,項(xiàng)目里制定了一些開發(fā)規(guī)范。比如文件的組織方式:

  • 聚合根放在 Domain/AggregatesModel/{AggregateName}Aggregate/
  • 領(lǐng)域事件放在 Domain/DomainEvents/
  • 倉(cāng)儲(chǔ)放在 Infrastructure/Repositories/
  • 命令放在 Web/Application/Commands/{Module}Commands/
  • 查詢放在 Web/Application/Queries/
  • 端點(diǎn)放在 Web/Endpoints/{Module}Endpoints/

還有一些強(qiáng)制性的要求,比如所有聚合根都用強(qiáng)類型ID,而且不手動(dòng)賦值ID,依賴EF的值生成器。所有命令都要有對(duì)應(yīng)的驗(yàn)證器。領(lǐng)域事件要在聚合發(fā)生改變時(shí)發(fā)布。命令處理器不能調(diào)用SaveChanges,框架會(huì)自動(dòng)處理。倉(cāng)儲(chǔ)必須用異步方法。業(yè)務(wù)異常用KnownException處理。

另外,項(xiàng)目還提供了很多代碼片段,可以快速生成常用代碼。比如ncpcmd可以生成命令及其驗(yàn)證器和處理器,ncpar可以生成聚合根,ncprepo可以生成倉(cāng)儲(chǔ)接口和實(shí)現(xiàn),epp可以生成FastEndpoint的完整實(shí)現(xiàn)。這樣開發(fā)效率會(huì)高不少。

云原生支持

項(xiàng)目集成了.NET Aspire,這個(gè)功能真的很方便。啟動(dòng)開發(fā)環(huán)境只需要運(yùn)行AppHost項(xiàng)目,Aspire會(huì)自動(dòng)管理所有依賴服務(wù),不需要手動(dòng)啟動(dòng)數(shù)據(jù)庫(kù)、Redis、RabbitMQ這些。

# 僅需確保Docker環(huán)境運(yùn)行
docker version
# 直接運(yùn)行AppHost項(xiàng)目,Aspire會(huì)自動(dòng)管理所有依賴服務(wù)
cd src/Ncp.Admin.AppHost
dotnet run

Aspire會(huì)自動(dòng)啟動(dòng)和管理數(shù)據(jù)庫(kù)容器(MySQL、PostgreSQL等)、消息隊(duì)列容器(RabbitMQ等)、Redis容器,還會(huì)提供統(tǒng)一的Aspire Dashboard界面,可以查看所有服務(wù)的狀態(tài)。服務(wù)之間的連接字符串也會(huì)自動(dòng)配置,省了很多麻煩。

代碼分析可視化

框架還提供了代碼流分析和可視化功能,這個(gè)對(duì)理解架構(gòu)很有幫助。可以通過(guò)命令行工具生成HTML文件:

# 安裝全局工具
dotnet tool install -g NetCorePal.Extensions.CodeAnalysis.Tools
# 生成可視化文件
cd src/Ncp.Admin.Web
netcorepal-codeanalysis generate --output architecture.html

BASH 復(fù)制 全屏

支持生成架構(gòu)流程圖、命令鏈路圖、事件流程圖、類圖等,可以直觀地看到代碼之間的關(guān)系和數(shù)據(jù)流向。

總結(jié)

這個(gè)項(xiàng)目算是一個(gè)DDD架構(gòu)的實(shí)踐案例,展示了如何在.NET 10生態(tài)中應(yīng)用DDD、CQRS、事件驅(qū)動(dòng)這些架構(gòu)思想。整體架構(gòu)清晰,職責(zé)分明,代碼組織得也比較規(guī)范。

技術(shù)棧上,后端用.NET 10 + EF Core + FastEndpoints + MediatR,前端用Vue 3 + TypeScript + Vite,都是目前比較主流的技術(shù)。開發(fā)體驗(yàn)上,有代碼片段、自動(dòng)化工具,還有完善的開發(fā)規(guī)范,開發(fā)效率還可以。

可維護(hù)性這塊,代碼分層清晰,測(cè)試支持也比較完善,還有代碼可視化工具,方便新人理解架構(gòu)。云原生支持也很到位,Aspire讓基礎(chǔ)設(shè)施管理變得簡(jiǎn)單。

如果你也在做類似的管理系統(tǒng),或者想了解DDD在實(shí)際項(xiàng)目中的應(yīng)用,可以看看這個(gè)項(xiàng)目的代碼,應(yīng)該能有一些參考價(jià)值。項(xiàng)目地址在https://github.com/zhouda1fu/Ncp.Admin,歡迎交流討論。

參考資料

最后附上一些相關(guān)的參考資料,有興趣的朋友可以深入了解一下:

項(xiàng)目源碼地址:https://github.com/zhouda1fu/Ncp.Admin

到此這篇關(guān)于基于NetCorePal Cloud Framework的DDD架構(gòu)管理系統(tǒng)實(shí)踐指南的文章就介紹到這了,更多相關(guān)NetCorePal Cloud Framework內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

临猗县| 曲靖市| 佛山市| 循化| 清新县| 密云县| 牡丹江市| 通渭县| 苏尼特右旗| 华蓥市| 班玛县| 图木舒克市| 福建省| 乳山市| 建平县| 东乡族自治县| 霍城县| 沾益县| 东至县| 江西省| 宁远县| 内江市| 广饶县| 正镶白旗| 抚顺县| 绵竹市| 南通市| 桐梓县| 连云港市| 景东| 武功县| 邵东县| 宜川县| 武川县| 南部县| 南开区| 武义县| 红安县| 晋宁县| 若羌县| 姜堰市|