在2.3中完成依賴注入後,這次主要實現欄目的添加功能。按照前面思路欄目有三種類型,常規欄目即可以添加子欄目也可以選擇是否添加內容,內容又可以分文章或其他類型,所以還要添加一個模塊功能。這次主要實現欄目的添加,附帶實現模塊列表功能,並將業務邏輯層的功能都實現了異步方法。
先來個完成後的界面吧。
.net Core中異步方法很簡單,只需要Task、async、await三個關鍵字就行。比如要實現統計記錄數異步方法,只要給方法添加關鍵字async,然後返回Task類型,並在方法中使用await調用異步方法就可以。
public async Task<int> CountAsync(Expression<Func<T, bool>> predicate) { return await _dbContext.Set<T>().CountAsync(predicate); }
一般在異步方法中也是調用異步方法,如果調用同步方法,如果直接調用同步方法也沒問題,但是編譯器會顯示警告,看著警告煩可以Task.FromResult,像下面這樣子。
public virtual async Task<IQueryable<T>> FindListAsync() { IQueryable<T> result = _dbContext.Set<T>(); return await Task.FromResult(result); }
基本內容都差不多,下面直接貼代碼。
在Ninesky.InterfaceBase中打開InterfaceBaseService文件。添加接口異步的方法,結果如下:
using Ninesky.Models; using System; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; namespace Ninesky.InterfaceBase { /// <summary> /// 服務基礎接口 /// </summary> public interface InterfaceBaseService<T> where T:class { /// <summary> /// 添加 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> int Add(T entity, bool isSave = true); /// <summary> /// 添加 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> Task<int> AddAsync(T entity, bool isSave = true); /// <summary> /// 添加[批量] /// </summary> /// <param name="entities">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數</returns> int AddRange(T[] entities, bool isSave = true); /// <summary> /// 添加[批量] /// </summary> /// <param name="entities">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> Task<int> AddRangeAsync(T[] entities, bool isSave = true); /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>記錄數</returns> int Count(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>記錄數</returns> Task<int> CountAsync(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢是否存在 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>是否存在</returns> bool Exists(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢是否存在 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>是否存在</returns> Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate); /// <summary> /// 查找 /// </summary> /// <param name="Id">主鍵</param> /// <returns></returns> T Find(int Id); /// <summary> /// 查找 /// </summary> /// <param name="Id">主鍵</param> /// <returns></returns> Task<T> FindAsync(int Id); /// <summary> /// 查找 /// </summary> /// <param name="keyValues">主鍵</param> /// <returns></returns> T Find(object[] keyValues); /// <summary> /// 查找 /// </summary> /// <param name="keyValues">主鍵</param> /// <returns></returns> Task<T> FindAsync(object[] keyValues); /// <summary> /// 查找 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns></returns> T Find(Expression<Func<T, bool>> predicate); /// <summary> /// 查找 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns></returns> Task<T> FindAsync(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢 /// </summary> /// <returns>實體列表</returns> IQueryable<T> FindList(); /// <summary> /// 查詢 /// </summary> /// <returns>實體列表</returns> Task<IQueryable<T>> FindListAsync(); /// <summary> /// 查詢 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> IQueryable<T> FindList(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> Task<IQueryable<T>> FindListAsync(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢 /// </summary> /// <param name="number">返回記錄數</param> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> IQueryable<T> FindList(int number, Expression<Func<T, bool>> predicate); /// <summary> /// 查詢 /// </summary> /// <param name="number">返回記錄數</param> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> Task<IQueryable<T>> FindListAsync(int number, Expression<Func<T, bool>> predicate); /// <summary> /// 查詢 /// </summary> /// <param name="number">顯示數量[小於等於0-不啟用]</param> /// <typeparam name="TKey">排序字段</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">正序</param> /// <returns></returns> IQueryable<T> FindList<TKey>(int number, Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc); /// <summary> /// 查詢 /// </summary> /// <param name="number">顯示數量[小於等於0-不啟用]</param> /// <typeparam name="TKey">排序字段</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">正序</param> /// <returns></returns> Task<IQueryable<T>> FindListAsync<TKey>(int number, Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc); /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="paging">分頁數據</param> /// <returns></returns> Paging<T> FindList<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, Paging<T> paging); /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="paging">分頁數據</param> /// <returns></returns> Task<Paging<T>> FindListAsync<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, Paging<T> paging); /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁記錄數</param> /// <returns></returns> Paging<T> FindList<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, int pageIndex, int pageSize); /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁記錄數</param> /// <returns></returns> Task<Paging<T>> FindListAsync<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, int pageIndex, int pageSize); /// <summary> /// 刪除 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否刪除成功[isSave=true時有效]</returns> bool Remove(T entity, bool isSave = true); /// <summary> /// 刪除 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否刪除成功[isSave=true時有效]</returns> Task<bool> RemoveAsync(T entity, bool isSave = true); /// <summary> /// 刪除[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>成功刪除的記錄數[isSave=true時有效]</returns> int RemoveRange(T[] entities, bool isSave = true); /// <summary> /// 刪除[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>成功刪除的記錄數[isSave=true時有效]</returns> Task<int> RemoveRangeAsync(T[] entities, bool isSave = true); /// <summary> /// 保存數據 /// </summary> /// <returns>更改的記錄數</returns> int SaveChanges(); /// <summary> /// 保存數據 /// </summary> /// <returns>更改的記錄數</returns> Task<int> SaveChangesAsync(); /// <summary> /// 更新 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否保存成功[isSave=true時有效]</returns> bool Update(T entity, bool isSave = true); /// <summary> /// 更新 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否保存成功[isSave=true時有效]</returns> Task<bool> UpdateAsync(T entity, bool isSave = true); /// <summary> /// 更新[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>更新成功的記錄數[isSave=true時有效]</returns> int UpdateRange(T[] entities, bool isSave = true); /// <summary> /// 更新[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>更新成功的記錄數[isSave=true時有效]</returns> Task<int> UpdateRangeAsync(T[] entities, bool isSave = true); } }
在Ninesky.Base中打開BaseService 添加異步接口的實現,代碼如下
using Microsoft.EntityFrameworkCore; using Ninesky.InterfaceBase; using Ninesky.Models; using System; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; namespace Ninesky.Base { /// <summary> /// 服務基類 /// </summary> public class BaseService<T>:InterfaceBaseService<T> where T:class { protected DbContext _dbContext; public BaseService(DbContext dbContext) { _dbContext = dbContext; } /// <summary> /// 添加 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> public virtual int Add(T entity, bool isSave = true) { _dbContext.Set<T>().Add(entity); if (isSave) return _dbContext.SaveChanges(); else return 0; } /// <summary> /// 添加 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> public virtual async Task<int> AddAsync(T entity, bool isSave = true) { await _dbContext.Set<T>().AddAsync(entity); if (isSave) return await _dbContext.SaveChangesAsync(); else return 0; } /// <summary> /// 添加[批量] /// </summary> /// <param name="entities">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> public virtual int AddRange(T[] entities, bool isSave = true) { _dbContext.Set<T>().AddRange(entities); if (isSave) return _dbContext.SaveChanges(); else return 0; } /// <summary> /// 添加[批量] /// </summary> /// <param name="entities">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>添加的記錄數[isSave=true時有效]</returns> public virtual async Task<int> AddRangeAsync(T[] entities, bool isSave = true) { await _dbContext.Set<T>().AddRangeAsync(entities); if (isSave) return await _dbContext.SaveChangesAsync(); else return 0; } /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>記錄數</returns> public virtual int Count(Expression<Func<T, bool>> predicate) { return _dbContext.Set<T>().Count(predicate); } /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>記錄數</returns> public virtual async Task<int> CountAsync(Expression<Func<T, bool>> predicate) { return await _dbContext.Set<T>().CountAsync(predicate); } /// <summary> /// 查詢是否存在 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>是否存在</returns> public virtual bool Exists(Expression<Func<T, bool>> predicate) { return _dbContext.Set<T>().Any(predicate); } /// <summary> /// 查詢是否存在 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>是否存在</returns> public virtual async Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate) { return await _dbContext.Set<T>().AnyAsync(predicate); } /// <summary> /// 查找 /// </summary> /// <param name="Id">主鍵</param> /// <returns></returns> public virtual T Find(int Id) { return _dbContext.Set<T>().Find(Id); } /// <summary> /// 查找 /// </summary> /// <param name="Id">主鍵</param> /// <returns></returns> public virtual async Task<T> FindAsync(int Id) { return await _dbContext.Set<T>().FindAsync(Id); } /// <summary> /// 查找 /// </summary> /// <param name="keyValues">主鍵</param> /// <returns></returns> public virtual T Find(object[] keyValues) { return _dbContext.Set<T>().Find(keyValues); } /// <summary> /// 查找 /// </summary> /// <param name="keyValues">主鍵</param> /// <returns></returns> public virtual async Task<T> FindAsync(object[] keyValues) { return await _dbContext.Set<T>().FindAsync(keyValues); } public virtual T Find(Expression<Func<T, bool>> predicate) { return _dbContext.Set<T>().SingleOrDefault(predicate); } /// <summary> /// 查找 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns></returns> public virtual async Task<T> FindAsync(Expression<Func<T, bool>> predicate) { return await _dbContext.Set<T>().SingleOrDefaultAsync(predicate); } /// <summary> /// 查詢 /// </summary> /// <returns></returns> public virtual IQueryable<T> FindList() { return _dbContext.Set<T>(); } /// <summary> /// 查詢 /// </summary> /// <returns>實體列表</returns> public virtual async Task<IQueryable<T>> FindListAsync() { IQueryable<T> result = _dbContext.Set<T>(); return await Task.FromResult(result); } /// <summary> /// 查詢 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> public virtual IQueryable<T> FindList(Expression<Func<T, bool>> predicate) { return _dbContext.Set<T>().Where(predicate); } /// <summary> /// 查詢 /// </summary> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> public virtual async Task<IQueryable<T>> FindListAsync(Expression<Func<T, bool>> predicate) { return await Task.FromResult(FindList(predicate)); } /// <summary> /// 查詢 /// </summary> /// <param name="number">返回記錄數</param> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> public virtual IQueryable<T> FindList(int number, Expression<Func<T, bool>> predicate) { var entityList = _dbContext.Set<T>().Where(predicate); if (number > 0) return entityList.Take(number); else return entityList; } /// <summary> /// 查詢 /// </summary> /// <param name="number">返回記錄數</param> /// <param name="predicate">查詢條件</param> /// <returns>實體列表</returns> public virtual async Task<IQueryable<T>> FindListAsync(int number, Expression<Func<T, bool>> predicate) { return await Task.FromResult(FindList(number, predicate)); } /// <summary> /// 查詢 /// </summary> /// <param name="number">顯示數量[小於等於0-不啟用]</param> /// <typeparam name="TKey">排序字段</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">正序</param> /// <returns></returns> public virtual IQueryable<T> FindList<TKey>(int number, Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc) { var entityList = _dbContext.Set<T>().Where(predicate); if (isAsc) entityList = entityList.OrderBy(keySelector); else entityList.OrderByDescending(keySelector); if (number > 0) return entityList.Take(number); else return entityList; } /// <summary> /// 查詢 /// </summary> /// <param name="number">顯示數量[小於等於0-不啟用]</param> /// <typeparam name="TKey">排序字段</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">正序</param> /// <returns></returns> public virtual async Task<IQueryable<T>> FindListAsync<TKey>(int number, Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc) { var entityList = _dbContext.Set<T>().Where(predicate); if (isAsc) entityList = entityList.OrderBy(keySelector); else entityList.OrderByDescending(keySelector); if (number > 0) entityList = entityList.Take(number); return await Task.FromResult(entityList); } /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="paging">分頁數據</param> /// <returns></returns> public virtual Paging<T> FindList<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, Paging<T> paging) { var entityList = _dbContext.Set<T>().Where(predicate); paging.Total = entityList.Count(); if (isAsc) entityList = entityList.OrderBy(keySelector); else entityList.OrderByDescending(keySelector); paging.Entities = entityList.Skip((paging.PageIndex - 1) * paging.PageSize).Take(paging.PageSize).ToList(); return paging; } /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="paging">分頁數據</param> /// <returns></returns> public virtual async Task<Paging<T>> FindListAsync<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, Paging<T> paging) { var entityList = _dbContext.Set<T>().Where(predicate); paging.Total = await entityList.CountAsync(); if (isAsc) entityList = entityList.OrderBy(keySelector); else entityList.OrderByDescending(keySelector); paging.Entities = await entityList.Skip((paging.PageIndex - 1) * paging.PageSize).Take(paging.PageSize).ToListAsync(); return paging; } /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁記錄數</param> /// <returns></returns> public virtual Paging<T> FindList<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, int pageIndex, int pageSize) { Paging<T> paging = new Paging<T> { PageIndex = pageIndex, PageSize = pageSize }; return FindList(predicate, keySelector, isAsc, paging); } /// <summary> /// 查詢[分頁] /// </summary> /// <typeparam name="TKey">排序屬性</typeparam> /// <param name="predicate">查詢條件</param> /// <param name="keySelector">排序</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁記錄數</param> /// <returns></returns> public virtual async Task<Paging<T>> FindListAsync<TKey>(Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> keySelector, bool isAsc, int pageIndex, int pageSize) { Paging<T> paging = new Paging<T> { PageIndex = pageIndex, PageSize = pageSize }; return await FindListAsync(predicate, keySelector, isAsc, paging); } /// <summary> /// 刪除 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否刪除成功[isSave=true時有效]</returns> public virtual bool Remove(T entity, bool isSave = true) { _dbContext.Set<T>().Remove(entity); if (isSave) return _dbContext.SaveChanges() > 0; else return false; } /// <summary> /// 刪除 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否刪除成功[isSave=true時有效]</returns> public virtual async Task<bool> RemoveAsync(T entity, bool isSave = true) { _dbContext.Set<T>().Remove(entity); if (isSave) return await _dbContext.SaveChangesAsync() > 0; else return false; } /// <summary> /// 刪除[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>成功刪除的記錄數</returns> public virtual int RemoveRange(T[] entities, bool isSave = true) { _dbContext.Set<T>().RemoveRange(entities); if (isSave) return _dbContext.SaveChanges(); else return 0; } /// <summary> /// 刪除[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>成功刪除的記錄數[isSave=true時有效]</returns> public virtual async Task<int> RemoveRangeAsync(T[] entities, bool isSave = true) { _dbContext.Set<T>().RemoveRange(entities); if (isSave) return await _dbContext.SaveChangesAsync(); else return 0; } /// <summary> /// 保存數據 /// </summary> /// <returns>更改的記錄數</returns> public virtual int SaveChanges() { return _dbContext.SaveChanges(); } /// <summary> /// 保存數據 /// </summary> /// <returns>更改的記錄數</returns> public virtual async Task<int> SaveChangesAsync() { return await _dbContext.SaveChangesAsync(); } /// <summary> /// 更新 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否保存成功</returns> public virtual bool Update(T entity, bool isSave = true) { _dbContext.Set<T>().Update(entity); if (isSave) return _dbContext.SaveChanges() > 0; else return false; } /// <summary> /// 更新 /// </summary> /// <param name="entity">實體</param> /// <param name="isSave">是否立即保存</param> /// <returns>是否保存成功[isSave=true時有效]</returns> public async Task<bool> UpdateAsync(T entity, bool isSave = true) { _dbContext.Set<T>().Update(entity); if (isSave) return await _dbContext.SaveChangesAsync() > 0; else return false; } /// <summary> /// 更新[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>更新成功的記錄數</returns> public virtual int UpdateRange(T[] entities, bool isSave = true) { _dbContext.Set<T>().UpdateRange(entities); if (isSave) return _dbContext.SaveChanges(); else return 0; } /// <summary> /// 更新[批量] /// </summary> /// <param name="entities">實體數組</param> /// <param name="isSave">是否立即保存</param> /// <returns>更新成功的記錄數[isSave=true時有效]</returns> public virtual async Task<int> UpdateRangeAsync(T[] entities, bool isSave = true) { _dbContext.Set<T>().UpdateRange(entities); if (isSave) return await _dbContext.SaveChangesAsync(); else return 0; } } }
按照設想模塊應該可以包含文章模塊、咨詢模塊、產品模塊、圖片模塊等,這裡先實現文章模塊。由於模塊功能是系統預先寫好的功能,所以模塊不用添加、修改、刪除等功能,只需要顯示和啟用(禁用)就好了。
在Ninesky.Models中添加Module類
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 模塊模型 /// </summary> public class Module { [Key] public int ModuleId { get; set; } /// <summary> /// 模塊名稱 /// </summary> [Required(ErrorMessage = "{0}必填")] [StringLength(50)] [Display(Name = "模塊名稱")] public string Name { get; set; } /// <summary> /// 模塊控制器 /// </summary> [StringLength(50)] [Display(Name = "模塊控制器")] public string Controller { get; set; } /// <summary> /// 模塊說明 /// </summary> [DataType(DataType.MultilineText)] [StringLength(1000)] [Display(Name = "模塊說明")] public string Description { get; set; } /// <summary> /// 是否啟用 /// </summary> [Required(ErrorMessage = "{0}必填")] [Display(Name = "啟用")] public bool Enabled { get; set; } /// <summary> /// 排序 /// </summary> public virtual List<ModuleOrder> ModuleOrders { get; set; } } }
類有個導航屬性ModuleOrders類型是ModuleOrder的列表。這個表示模塊支持的排序類型,在添加欄目的時候選擇排序類型,在前台欄目顯示內容列表的時候按功能進行排序。代碼如下:
using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 模塊排序類型 /// </summary> public class ModuleOrder { [Key] public int ModuleOrderId { get; set; } /// <summary> /// 模塊ID /// </summary> [Required] [Display(Name = "模塊ID")] public int ModuleId { get; set; } /// <summary> /// 名稱 /// </summary> [Required] [StringLength(50)] [Display(Name = "名稱")] public string Name { get; set; } /// <summary> /// 值 /// </summary> [Required] [Display(Name = "值")] public int Order { get; set; } /// <summary> /// 模塊 /// </summary> public virtual Module Module { get; set; } } }
在Ninesky.InterfaceBase添加模塊的接口Ninesky.InterfaceBase,繼承自InterfaceBaseService<Module>,並添加兩個新的方法。查找模塊列表和查找模塊支持的排序列表
using Ninesky.Models; using System.Linq; using System.Threading.Tasks; namespace Ninesky.InterfaceBase { public interface InterfaceModuleService:InterfaceBaseService<Module> { /// <summary> /// 查找 /// </summary> /// <param name="enable">啟用</param> /// <returns></returns> Task<IQueryable<Module>> FindListAsync(bool? enable); /// <summary> /// 查找排序列表 /// </summary> /// <param name="moduleId">模塊ID</param> /// <returns></returns> Task<IQueryable<ModuleOrder>> FindOrderListAsync(int moduleId); } }
using Microsoft.EntityFrameworkCore; using Ninesky.InterfaceBase; using Ninesky.Models; using System.Linq; using System.Threading.Tasks; namespace Ninesky.Base { public class ModuleService:BaseService<Module>,InterfaceModuleService { public ModuleService(DbContext dbContext) : base(dbContext) { } public override Module Find(int Id) { return _dbContext.Set<Module>().Include(m => m.ModuleOrders).SingleOrDefault(m => m.ModuleId == Id); } /// <summary> /// 查找 /// </summary> /// <param name="enable">啟用</param> /// <returns></returns> public async Task<IQueryable<Module>> FindListAsync(bool? enable) { if (enable == null) return await FindListAsync(); else return await FindListAsync(m => m.Enabled == enable); } /// <summary> /// 查找排序列表 /// </summary> /// <param name="moduleId">模塊ID</param> /// <returns></returns> public async Task<IQueryable<ModuleOrder>> FindOrderListAsync(int moduleId) { return await Task.FromResult(_dbContext.Set<ModuleOrder>().Where(mo => mo.ModuleId == moduleId)); } } }
在Ninesky.Web.Areas.System.Controllers中添加模塊控制器ModuleController,控制器有一個幾個功能
Enable方法返回操作結果時,考慮到不光要返回是否操作成功,可能還要返回消息字符串,所以專門寫個類型統一返回ajax操作的結果。把類型命名為JsonResponse,放到Ninesky.Web.Models下,代碼如下圖:
namespace Ninesky.Web.Models { /// <summary> /// 返回Json數據類型 /// </summary> public class JsonResponse { /// <summary> /// 操作是否成功 /// </summary> public bool succeed { get; set; } /// <summary> /// 操作結果詳細代碼【必要時】 /// </summary> public int code { get; set; } /// <summary> /// 操作結果消息 /// </summary> public string message { get; set; } /// <summary> /// 操作產生的數據【必要時】 /// </summary> public dynamic Data { get; set; } public JsonResponse() { succeed = false; message = "未知錯誤"; } } }
整個控制器代碼如下:
using Microsoft.AspNetCore.Mvc; using Ninesky.InterfaceBase; using Ninesky.Web.Models; using System.Linq; using System.Threading.Tasks; namespace Ninesky.Web.Areas.System.Controllers { [Area("System")] public class ModuleController : Controller { private InterfaceModuleService _moduleService; public ModuleController(InterfaceModuleService moduleService) { _moduleService = moduleService; } /// <summary> /// 詳細 /// </summary> /// <param name="id">模塊ID</param> /// <returns></returns> public async Task<IActionResult> Details(int id) { return View(await _moduleService.FindAsync(id)); } [HttpPost] public async Task<IActionResult> Enable (int id, bool enabled) { JsonResponse jsonResponse = new JsonResponse(); var module = await _moduleService.FindAsync(id); if(module == null) { jsonResponse.succeed = false; jsonResponse.message = "模塊不存在"; } else { module.Enabled = enabled; if(await _moduleService.UpdateAsync(module)) { jsonResponse.succeed = true; jsonResponse.message = "模塊已" + (enabled ? "啟用" : "禁用"); } else { jsonResponse.succeed = false; jsonResponse.message = "保存數據失敗"; } } return Json(jsonResponse); } public IActionResult Index() { return View(); } /// <summary> /// 模塊列表 /// </summary> /// <returns></returns> public async Task<IActionResult> List() { return Json((await _moduleService.FindListAsync()).ToList()); } /// <summary> /// 排序列表 /// </summary> /// <param name="id">模塊Id</param> /// <returns></returns> public async Task<IActionResult> OrderList(int id) { return Json((await _moduleService.FindOrderListAsync(id)).ToList()); } } }
在控制器代碼中可以看出只有兩個action返回了視圖,一個是Index,另一個是Details。
模塊首頁視圖
在控制器中index沒有像視圖提供數據,在視圖中通過ajax方式加載。在視圖中使用bootstrapTable組件來顯示視圖列表。改組件可以在項目的依賴項->Bower【右鍵】->管理Bower程序包中搜索bootstrap-Table,並安裝。
視圖代碼:
@{ ViewData["Title"] = "模塊管理"; } <ol class="breadcrumb"> <li><span class="fa fa-home"></span> <a asp-controller="Home" asp-action="Index">首頁</a></li> <li><a asp-controller="System" asp-action="Index">系統配置</a></li> <li class="active">模塊管理</li> </ol> <table id="moduletable"></table> @section aside{ @Html.Partial("SystemAside") } @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script type="text/javascript"> $(document).ready(function () { $('#moduletable').bootstrapTable({ url: '@Url.Action("List")', columns: [{ field: 'moduleId', title: '序號' }, { field: 'name', title: '名稱', formatter: function (value, row, index) { return '<a href="@Url.Action("Details")/' + row.moduleId + '">' + value + '</a>'; } }, { field: 'controller', title: '控制器' }, { field: 'description', title: '說明' }, { field: 'enabled', title: '狀態', formatter:function(value,row,index) { return value ? '<i class="fa fa-check" aria-hidden="true"></i>' : '<i class="fa fa-ban" aria-hidden="true"></i>'; } }] }); }); </script> }
完成的效果圖
詳細信息視圖
Details中使用了tabs,一個標簽顯示基本信息,另一個標簽顯示排序列表。基本信息的啟用屬性使用checkbox,點擊可以啟用/禁用模塊。排序列表繼續使用bootstrapTable組件顯示列表。
@model Ninesky.Models.Module @{ ViewData["Title"] = Model.Name; } <ol class="breadcrumb"> <li><span class="fa fa-home"></span> <a asp-controller="Home" asp-action="Index">首頁</a></li> <li><a asp-controller="System" asp-action="Index">系統配置</a></li> <li><a asp-controller="Module" asp-action="Index">模塊管理</a></li> <li class="active">@Model.Name</li> </ol> @section aside{ @Html.Partial("SystemAside") } <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#base" role="tab" data-toggle="tab">基本信息</a></li> <li role="presentation"><a href="#order" role="tab" data-toggle="tab">排序方式</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="base"> <input type="hidden" asp-for="ModuleId" /> <dl class="dl-horizontal"> <dt> <label asp-for="Name"></label> </dt> <dd> @Html.DisplayFor(model => model.Name) </dd> <dt> <label asp-for="Controller"></label> </dt> <dd> @Html.DisplayFor(model => model.Controller) </dd> <dt> <label asp-for="Description"></label> </dt> <dd> @Html.DisplayFor(model => model.Description) </dd> <dt> <label asp-for="Enabled"></label> </dt> <dd> <input type="checkbox" asp-for="Enabled" /> </dd> </dl> </div> <div role="tabpanel" class="tab-pane" id="order"><table id="moduleordertable"></table></div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script type="text/javascript"> $(document).ready(function () { $('#moduleordertable').bootstrapTable({ url: '@Url.Action("OrderList",new{ id=Model.ModuleId})', columns: [{ field: 'moduleOrderId', title: '序號' }, { field: 'name', title: '名稱', }, { field: 'order', title: '值' }] }); $('#Enabled').click(function () { $.post('@Url.Action("Enable", "Module")', { id: $('#ModuleId').val(), enabled: $('#Enabled').prop('checked') }, function (response) { if(response.succeed) { BootstrapDialog.alert({ title:'消息', message: response.message, buttonLabel: '確定' }); } }, 'json'); }); }); </script> }
界面顯示如下:
通常會用樹形菜單的形式顯示欄目結構,需要添加欄目的樹形菜單數據,需要添加一個方法,另外顯示子欄目也需要添加一個方法。
在欄目接口中添加方法。
using Ninesky.Models; using System.Linq; using System.Threading.Tasks; namespace Ninesky.InterfaceBase { /// <summary> /// 欄目服務接口 /// </summary> public interface InterfaceCategoryService:InterfaceBaseService<Category> { /// <summary> /// 查找樹形菜單 /// </summary> /// <param name="categoryType">欄目類型,可以為空</param> /// <returns></returns> Task<IQueryable<Category>> FindTreeAsync(CategoryType? categoryType); /// <summary> /// 查找子欄目 /// </summary> /// <param name="id">欄目ID</param> /// <returns></returns> IQueryable<Category> FindChildren(int id); /// <summary> /// 查找子欄目 /// </summary> /// <param name="id">欄目ID</param> /// <returns></returns> Task<IQueryable<Category>> FindChildrenAsync(int id); } }
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ninesky.Models; using Ninesky.InterfaceBase; namespace Ninesky.Base { /// <summary> /// 欄目服務類 /// </summary> public class CategoryService:BaseService<Category>,InterfaceCategoryService { public CategoryService(DbContext dbContext):base(dbContext) { } /// <summary> /// 查找 /// </summary> /// <param name="Id">欄目ID</param> /// <returns></returns> public override Category Find(int Id) { return _dbContext.Set<Category>().Include("General").Include("Page").Include("Link").SingleOrDefault(c => c.CategoryId == Id); } /// <summary> /// 查找子欄目 /// </summary> /// <param name="id">欄目ID</param> /// <returns></returns> public IQueryable<Category> FindChildren(int id) { return FindList(0, c => c.ParentId == id, c => c.Order, true); } /// <summary> /// 查找子欄目 /// </summary> /// <param name="id">欄目ID</param> /// <returns></returns> public async Task<IQueryable<Category>> FindChildrenAsync(int id) { return await FindListAsync(0, c => c.ParentId == id, c => c.Order, true); } /// <summary> /// 查找樹形菜單 /// </summary> /// <param name="categoryType">欄目類型,可以為空</param> /// <returns></returns> public async Task<IQueryable<Category>> FindTreeAsync(CategoryType? categoryType) { var categories = await FindListAsync(); //根據欄目類型分類處理 switch (categoryType) { case null: break; case CategoryType.General: categories = categories.Where(c => c.Type == categoryType); break; //默認-Page或Link類型 default: //Id數組-含本欄目及父欄目 List<int> idArray = new List<int>(); //查找欄目id及父欄目路徑 var categoryArray = categories.Where(c => c.Type == categoryType).Select(c => new { CategoryId = c.CategoryId, ParentPath = c.ParentPath }); if(categoryArray != null) { //添加欄目ID到 idArray.AddRange(categoryArray.Select(c => c.CategoryId)); foreach (var parentPath in categoryArray.Select(c=>c.ParentPath)) { var parentIdArray = parentPath.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parentIdArray != null) { int parseId = 0; foreach(var parentId in parentIdArray) { if (int.TryParse(parentId, out parseId)) idArray.Add(parseId); } } } } categories = categories.Where(c => idArray.Contains(c.CategoryId)); break; } return categories.OrderBy(c => c.ParentPath).ThenBy(C => C.Order); } } }
欄目控制器有一下幾個action
在顯示樹形菜單時使用的ztree組件,是一個功能非常強大的國產組件,需要的朋友可以去看看http://www.treejs.cn/v3/api.php
控制器中只有Add方法麻煩一點,添加時需要對其父欄目和導航屬性進行判斷和處理。代碼如下:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Ninesky.InterfaceBase; using Ninesky.Models; using Ninesky.Web.Models; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Ninesky.Web.Areas.System.Controllers { /// <summary> /// 欄目控制器 /// </summary> [Area("System")] public class CategoryController : Controller { private InterfaceCategoryService _categoryService; public CategoryController(InterfaceCategoryService categoryService) { _categoryService = categoryService; } public async Task<IActionResult> Add([FromServices]InterfaceModuleService moduleService, CategoryType? categoryType) { var modules = await moduleService.FindListAsync(true); var modeleArry = modules.Select(m => new SelectListItem { Text = m.Name, Value = m.ModuleId.ToString() }).ToList(); modeleArry.Insert(0, new SelectListItem() { Text = "無", Value = "0", Selected = true }); ViewData["Modules"] = modeleArry; return View(new Category() { Type = CategoryType.General, ParentId = 0, View="Index", Order = 0, Target = LinkTarget._self, General = new CategoryGeneral() { ContentView = "Index" } }); } [HttpPost] public async Task<IActionResult> Add([FromServices]InterfaceModuleService moduleService,Category category) { if(ModelState.IsValid) { //檢查父欄目 if (category.ParentId > 0) { var parentCategory = await _categoryService.FindAsync(category.ParentId); if (parentCategory == null) ModelState.AddModelError("ParentId", "父欄目不存在"); else if (parentCategory.Type != CategoryType.General) ModelState.AddModelError("ParentId", "父欄目不能添加子欄目"); else category.ParentPath = parentCategory.ParentPath + "," + parentCategory.CategoryId; } else category.ParentPath = "0"; //檢查欄目類型 switch (category.Type) { case CategoryType.General: if (category.General == null) ModelState.AddModelError("General.Type", "請填寫常規欄目內容"); else { if (category.General.ModuleId > 0) { if (string.IsNullOrEmpty(category.General.ContentView)) ModelState.AddModelError("General.ContentView", "請填寫欄目視圖"); if (category.General.ContentOrder == null) ModelState.AddModelError("General.ContentOrder", "請選擇內容排序方式"); } else { if (category.Page != null) category.Page = null; if (category.Link != null) category.Link = null; } } break; case CategoryType.Page: //檢查 if (category.Page == null) ModelState.AddModelError("General.Type", "請填寫單頁欄目內容"); else { if (string.IsNullOrEmpty(category.Page.Content)) ModelState.AddModelError("Page.Content", "請輸入單頁欄目內容"); else { if (category.General != null) category.General = null; if (category.Link != null) category.Link = null; } } break; case CategoryType.Link: //檢查 if (category.Link == null) ModelState.AddModelError("General.Type", "請填寫連接欄目內容"); else { if (string.IsNullOrEmpty(category.Link.Url)) ModelState.AddModelError("Link.Url", "請選擇輸入鏈接地址"); else { if (category.General != null) category.General = null; if (category.General != null) category.General = null; } } break; } //保存到數據庫 if(ModelState.IsValid) { if (await _categoryService.AddAsync(category) > 0) return View("AddSucceed", category); else ModelState.AddModelError("", "保存數據失敗"); } } var modules = await moduleService.FindListAsync(true); var modeleArry = modules.Select(m => new SelectListItem { Text = m.Name, Value = m.ModuleId.ToString() }).ToList(); modeleArry.Insert(0, new SelectListItem() { Text = "無", Value = "0", Selected = true }); ViewData["Modules"] = modeleArry; return View(category); } /// <summary> /// 欄目首頁 /// </summary> /// <returns></returns> public IActionResult Index() { return View("Index"); } /// <summary> /// 父欄目樹 /// </summary> /// <returns></returns> public async Task<IActionResult> ParentTree() { var categories = await _categoryService.FindTreeAsync(CategoryType.General); return Json(categories.Select(c => new zTreeNode { id = c.CategoryId, name = c.Name, pId = c.ParentId, iconSkin="fa fa-folder" })); } /// <summary> /// 欄目樹 /// </summary> /// <returns></returns> public async Task<IActionResult> Tree() { List<zTreeNode> nodes; var categories = await _categoryService.FindTreeAsync(null); if (categories != null) { nodes = new List<zTreeNode>(categories.Count()); foreach(var category in categories) { var node = new zTreeNode() { id = category.CategoryId, pId= category.ParentId, name = category.Name, url = Url.Action("Details", "Category", new { id = category.CategoryId }) }; switch(category.Type) { case CategoryType.General: node.iconSkin = "fa fa-folder"; node.iconOpen = "fa fa-folder-open"; node.iconClose = "fa fa-folder"; break; case CategoryType.Page: node.iconSkin = "fa fa-file"; break; case CategoryType.Link: node.iconSkin = "fa fa-link"; break; } nodes.Add(node); } } else nodes = new List<zTreeNode>(); return Json(nodes); } } }
左側導航欄視圖
視圖名Aside,視圖中采用ztree加載欄目樹
<div class="panel panel-default"> <div class="panel-heading"> <h5 class="panel-title"><span class="fa fa-list"></span> 欄目列表</h5> </div> <div class="panel-body"> <ul id="categoryTree" data-url="@Url.Action("Tree", "Category")" class="ztree"></ul> </div> </div>
添加欄目視圖
html、js都混在一起了代碼很亂,湊活看吧。
@model Ninesky.Models.Category @{ ViewData["Title"] = "添加欄目"; } <ol class="breadcrumb"> <li><span class="fa fa-home"></span> <a asp-controller="Home" asp-action="Index">首頁</a></li> <li><a asp-controller="Category" asp-action="Index">欄目管理</a></li> <li class="active">添加常規欄目</li> </ol> <div class="panel panel-default"> <div class="panel-body"> <form asp-action="Add"> <div class="form-horizontal"> <div asp-validation-summary="All" class="text-danger"></div> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#base" role="tab" data-toggle="tab">基本信息</a></li> <li role="presentation"><a href="#general" role="tab" data-toggle="tab">常規欄目</a></li> <li role="presentation"><a href="#page" role="tab" data-toggle="tab">單頁欄目</a></li> <li role="presentation"><a href="#link" role="tab" data-toggle="tab">鏈接欄目</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="base"> <div class="form-group"> <label asp-for="ParentId" class="col-md-2 control-label"></label> <div class="col-md-10"> <div class="input-group" > <input id="ParentId-text" type="text" class="form-control" readonly value="無" /> <ul id="ParentId-dropdown" class="dropdown-menu dropdown-menu-left ztree"></ul> <div class="input-group-btn"> <button id="ParentId-btn" type="button" class="btn btn-default"><span class="caret"></span></button> </div> <input asp-for="ParentId" class="form-control" /> </div> <span asp-validation-for="ParentId" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="Type" class="col-md-2 control-label"></label> <div class="col-md-10"> <select asp-for="Type" asp-items="Html.GetEnumSelectList<Ninesky.Models.CategoryType>()" class="selectpicker form-control" data-></select> <span asp-validation-for="Type" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="Name" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="Name" class="form-control" /> <span asp-validation-for="Name" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="View" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="View" class="form-control" /> <span asp-validation-for="View" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="Order" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="Order" class="form-control" /> <span asp-validation-for="Order" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="Target" class="col-md-2 control-label"></label> <div class="col-md-10"> <select asp-for="Target" asp-items="Html.GetEnumSelectList<Ninesky.Models.LinkTarget>()" class="selectpicker form-control" data-></select> <span asp-validation-for="Target" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="Description" class="col-md-2 control-label"></label> <div class="col-md-10"> <textarea asp-for="Description" class="form-control"></textarea> <span asp-validation-for="Description" class="text-danger"></span> </div> </div> </div> <div role="tabpanel" class="tab-pane" id="general"> <div class="form-group"> <label asp-for="General.ModuleId" class="col-md-2 control-label"></label> <div class="col-md-10"> <select asp-for="General.ModuleId" asp-items="@ViewData["Modules"] as List<SelectListItem>" class="selectpicker form-control" data-></select> <span asp-validation-for="General.ModuleId" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="General.ContentView" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="General.ContentView" class="form-control" /> <span asp-validation-for="General.ContentView" class="text-danger"></span> </div> </div> <div class="form-group"> <label asp-for="General.ContentOrder" class="col-md-2 control-label"></label> <div class="col-md-10"> <select asp-for="General.ContentOrder" class="form-control"></select> <span asp-validation-for="General.ContentOrder" class="text-danger"></span> </div> </div> </div> <div role="tabpanel" class="tab-pane" id="page"> <div class="form-group"> <label asp-for="Page.Content" class="control-label"></label> <textarea asp-for="Page.Content" ></textarea> <span asp-validation-for="Page.Content" class="text-danger"></span> </div> </div> <div role="tabpanel" class="tab-pane" id="link"> <div class="form-group"> <label asp-for="Link.Url" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="Link.Url" class="form-control" /> <span asp-validation-for="Link.Url" class="text-danger"></span> </div> </div> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="添加" class="btn btn-default" /> </div> </div> </div> </form> </div> </div> @section aside{ @Html.Partial("Aside") } @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script src="~/lib/ueditor/ueditor.config.js"></script> <script src="~/lib/ueditor/ueditor.all.min.js"></script> <script type="text/javascript"> var dropdownCategoryTree; var setting = { data: { simpleData: { enable: true, idKey: "id", pIdKey: "pId", rootPId: 0 } }, async: { enable: true, url: "@Url.Action("ParentTree", "Category")" }, callback: { onClick: function (event, treeId, treeNode) { $("#ParentId").val(treeNode.id); $("#ParentId-text").val(treeNode.name); $("#ParentId-dropdown").hide(); } } }; function toggleContent() { if ($("#General_ModuleId").selectpicker('val') == "") { $("#General_ContentOrder").empty(); } else { $.post("@Url.Action("OrderList","Module")", { id: $('#General_ModuleId').val() }, function (data) { if (data != undefined) { $.each(data, function (ndex, element) { $("#General_ContentOrder").append("<option value='" + element.order + "'>" + element.name + "</option>"); }) } }, 'json'); } } // zTree 的參數配置,深入使用請參考 API 文檔(setting 配置詳解) $(document).ready(function () { dropdownCategoryTree = $.fn.zTree.init($("#ParentId-dropdown"), setting); dropdownCategoryTree.addNodes(null, { id: 0, name: "無" }); $("#ParentId-text").click(function () { $("#ParentId-dropdown").show(); }); $("#ParentId-btn").click(function () { $("#ParentId-dropdown").show(); }); toggleContent(); $('#General_ModuleId').on('changed.bs.select', function (e) { toggleContent(); }); //富文本編輯器 var ue = UE.getEditor('Page_Content'); }); </script> }
添加成功的視圖
@model Ninesky.Models.Category @{ ViewData["Title"] = "添加欄目"; } <ol class="breadcrumb"> <li><span class="fa fa-home"></span> <a asp-controller="Home" asp-action="Index">首頁</a></li> <li><a asp-controller="Category" asp-action="Index">欄目管理</a></li> <li class="active">添加欄目</li> </ol> <div class="alert alert-success fade in" role="alert"> <h4><i class="fa fa-check"></i> 添加成功 </h4> <p>您已成功添加欄目【@Model.Name】</p> <p> <a href="@Url.Action("Add")" class="btn btn-default">添加欄目</a> <a href="@Url.Action("Details","Category",new {id=Model.CategoryId })" class="btn btn-default">修改欄目</a> </p> </div> @section aside{ @Html.Partial("Aside") }
文章發布地址:http://www.ninesky.cn
http://mzwhj.cnblogs.com/
代碼包下載:Ninesky2.4.rar
返回目錄