在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
返回目錄