NopCommerce 3.4省市联动
做法有两种,一种是在StateProvince表里面加个字段,另一种是新建两个表,用来存市、县的数据,表结构完全按照StateProvince走就好了。我这里用的是第二种做法,菜鸟一枚,代码写的比较烂,哪里写的不好欢迎提出来以便我提高自己。
第一步:去数据库,新建两个表,表我就不给了,直接给对应的Model
1 using System.Collections.Generic; 2 using Nop.Core.Domain.Localization; 3 4 namespace Nop.Core.Domain.Directory 5 { 6 /// <summary> 7 /// Represents a state/province 8 /// </summary> 9 public partial class City : BaseEntity, ILocalizedEntity 10 { 11 private ICollection<County> _counties; 12 /// <summary> 13 /// Gets or sets the country identifier 14 /// </summary> 15 public int StateProvinceId { get; set; } 16 17 /// <summary> 18 /// Gets or sets the name 19 /// </summary> 20 public string Name { get; set; } 21 22 /// <summary> 23 /// Gets or sets the abbreviation 24 /// </summary> 25 public string Abbreviation { get; set; } 26 27 /// <summary> 28 /// Gets or sets a value indicating whether the entity is published 29 /// </summary> 30 public bool Published { get; set; } 31 32 /// <summary> 33 /// Gets or sets the display order 34 /// </summary> 35 public int DisplayOrder { get; set; } 36 37 /// <summary> 38 /// Gets or sets the country 39 /// </summary> 40 public virtual StateProvince StateProvince { get; set; } 41 public virtual ICollection<County> Countys 42 { 43 get { return _counties ?? (_counties = new List<County>()); } 44 protected set { _counties = value; } 45 } 46 } 47 48 }
1 using Nop.Core.Domain.Localization; 2 3 namespace Nop.Core.Domain.Directory 4 { 5 /// <summary> 6 /// Represents a state/province 7 /// </summary> 8 public partial class County : BaseEntity, ILocalizedEntity 9 { 10 /// <summary> 11 /// Gets or sets the country identifier 12 /// </summary> 13 public int CityId { get; set; } 14 15 /// <summary> 16 /// Gets or sets the name 17 /// </summary> 18 public string Name { get; set; } 19 20 /// <summary> 21 /// Gets or sets the abbreviation 22 /// </summary> 23 public string Abbreviation { get; set; } 24 25 /// <summary> 26 /// Gets or sets a value indicating whether the entity is published 27 /// </summary> 28 public bool Published { get; set; } 29 30 /// <summary> 31 /// Gets or sets the display order 32 /// </summary> 33 public int DisplayOrder { get; set; } 34 35 /// <summary> 36 /// Gets or sets the country 37 /// </summary> 38 public virtual City City { get; set; } 39 } 40 41 }
当然,还需要修改StateProvince的Model
1 using System.Collections.Generic; 2 using Nop.Core.Domain.Localization; 3 4 namespace Nop.Core.Domain.Directory 5 { 6 /// <summary> 7 /// Represents a state/province 8 /// </summary> 9 public partial class StateProvince : BaseEntity, ILocalizedEntity 10 { 11 private ICollection<City> _cities; 12 /// <summary> 13 /// Gets or sets the country identifier 14 /// </summary> 15 public int CountryId { get; set; } 16 17 /// <summary> 18 /// Gets or sets the name 19 /// </summary> 20 public string Name { get; set; } 21 22 /// <summary> 23 /// Gets or sets the abbreviation 24 /// </summary> 25 public string Abbreviation { get; set; } 26 27 /// <summary> 28 /// Gets or sets a value indicating whether the entity is published 29 /// </summary> 30 public bool Published { get; set; } 31 32 /// <summary> 33 /// Gets or sets the display order 34 /// </summary> 35 public int DisplayOrder { get; set; } 36 37 /// <summary> 38 /// Gets or sets the country 39 /// </summary> 40 public virtual Country Country { get; set; } 41 public virtual ICollection<City> Citys 42 { 43 get { return _cities ?? (_cities = new List<City>()); } 44 protected set { _cities = value; } 45 } 46 } 47 48 }
第二步:去Service层去做Crud,县、市的基本是一样的,我就只列出来一个。另外一个照着写就完了。
先定义接口:
1 using System.Collections.Generic; 2 using Nop.Core.Domain.Directory; 3 4 namespace Nop.Services.Directory 5 { 6 public interface ICityService 7 { 8 void DeleteCity(City city); 9 City GetCityById(int cityId); 10 City GetByAbbreviation(string abbreviation); 11 IList<City> GetCityByStateProvinceId(int stateProvinceId, bool showHidden = false); 12 void InsertCity(City city); 13 void UpdateCity(City city); 14 } 15 }
去实现接口:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using Nop.Core.Caching; 5 using Nop.Core.Data; 6 using Nop.Core.Domain.Directory; 7 using Nop.Services.Events; 8 9 namespace Nop.Services.Directory 10 { 11 public partial class CityService:ICityService 12 { 13 #region Constants 14 15 /// <summary> 16 /// Key for caching 17 /// </summary> 18 /// <remarks> 19 /// {1} : country ID 20 /// </remarks> 21 private const string CITYS_ALL_KEY = "Nop.city.all-{0}"; 22 /// <summary> 23 /// Key pattern to clear cache 24 /// </summary> 25 private const string CITYS_PATTERN_KEY = "Nop.city."; 26 27 #endregion 28 29 #region Fields 30 31 private readonly IRepository<City> _cityRepository; 32 private readonly IEventPublisher _eventPublisher; 33 private readonly ICacheManager _cacheManager; 34 35 #endregion 36 37 #region Ctor 38 39 /// <summary> 40 /// Ctor 41 /// </summary> 42 /// <param name="cacheManager">Cache manager</param> 43 /// <param name="stateProvinceRepository">State/province repository</param> 44 /// <param name="eventPublisher">Event published</param> 45 public CityService(ICacheManager cacheManager, 46 IRepository<City> cityRepository, 47 IEventPublisher eventPublisher) 48 { 49 _cacheManager = cacheManager; 50 _cityRepository = cityRepository; 51 _eventPublisher = eventPublisher; 52 } 53 54 #endregion 55 public void DeleteCity(City city) 56 { 57 if(city==null) 58 throw new ArgumentNullException("city"); 59 _cityRepository.Delete(city); 60 _cacheManager.RemoveByPattern(CITYS_PATTERN_KEY); 61 _eventPublisher.EntityDeleted(city); 62 } 63 64 public City GetCityById(int cityId) 65 { 66 if (cityId == 0) 67 { 68 return null; 69 } 70 return _cityRepository.GetById(cityId); 71 } 72 73 public City GetByAbbreviation(string abbreviation) 74 { 75 var query = from sp in _cityRepository.Table 76 where sp.Abbreviation == abbreviation 77 select sp; 78 var city = query.FirstOrDefault(); 79 return city; 80 } 81 82 public IList<City> GetCityByStateProvinceId(int stateProvinceId, bool showHidden = false) 83 { 84 string key = string.Format(CITYS_ALL_KEY, stateProvinceId); 85 return _cacheManager.Get(key, () => 86 { 87 var query= from sp in _cityRepository.Table 88 orderby sp.DisplayOrder 89 where sp.StateProvinceId == stateProvinceId && 90 (showHidden || sp.Published) 91 select sp; 92 var city = query.ToList(); 93 return city; 94 }); 95 } 96 97 public void InsertCity(City city) 98 { 99 if (city == null) 100 throw new ArgumentNullException("city"); 101 102 _cityRepository.Insert(city); 103 104 _cacheManager.RemoveByPattern(CITYS_PATTERN_KEY); 105 106 //event notification 107 _eventPublisher.EntityInserted(city); 108 } 109 110 public void UpdateCity(City city) 111 { 112 if (city == null) 113 throw new ArgumentNullException("city"); 114 115 _cityRepository.Update(city); 116 117 _cacheManager.RemoveByPattern(CITYS_PATTERN_KEY); 118 119 //event notification 120 _eventPublisher.EntityUpdated(city); 121 } 122 } 123 }
这是市的,县的照着这个写就完了。注意缓存那块也一定要给把那个Key给改了,不然会重名的。
第三步:去Nop.Web.Framework把刚写的这些Service注入。
1 builder.RegisterType<CityService>().As<ICityService>().SingleInstance(); 2 builder.RegisterType<CountyService>().As<ICountyService>().SingleInstance();
第三步:修改他转换po和vo的方法,我这个做的是国内的电子商务网站,所以,国家那里我直接就写死了,而且在后续的界面中,我也直接把国家给干掉了。
1 public static void PrepareModel(this AddressModel model, 2 Address address, bool excludeProperties, 3 AddressSettings addressSettings, 4 ILocalizationService localizationService = null, 5 IStateProvinceService stateProvinceService = null, 6 #region yunchen.bai 7 ICityService cityService=null, 8 ICountyService countyService=null , 9 #endregion 10 Func<IList<Country>> loadCountries = null, 11 bool prePopulateWithCustomerFields = false, 12 Customer customer = null 13 14 ) 15 { 16 if (model == null) 17 throw new ArgumentNullException("model"); 18 19 if (addressSettings == null) 20 throw new ArgumentNullException("addressSettings"); 21 22 if (!excludeProperties && address != null) 23 { 24 model.Id = address.Id; 25 model.FirstName = address.FirstName; 26 model.LastName = address.LastName; 27 model.Email = address.Email; 28 model.Company = address.Company; 29 model.CountryId = address.CountryId; 30 model.CountryName = address.Country != null 31 ? address.Country.GetLocalized(x => x.Name) 32 : null; 33 model.StateProvinceId = address.StateProvinceId; 34 model.StateProvinceName = address.StateProvince != null 35 ? address.StateProvince.GetLocalized(x => x.Name) 36 : null; 37 model.City = address.City; 38 model.Address1 = address.Address1; 39 model.Address2 = address.Address2; 40 model.ZipPostalCode = address.ZipPostalCode; 41 model.PhoneNumber = address.PhoneNumber; 42 model.FaxNumber = address.FaxNumber; 43 } 44 45 if (address == null && prePopulateWithCustomerFields) 46 { 47 if (customer == null) 48 throw new Exception("Customer cannot be null when prepopulating an address"); 49 model.Email = customer.Email; 50 model.FirstName = customer.GetAttribute<string>(SystemCustomerAttributeNames.FirstName); 51 model.LastName = customer.GetAttribute<string>(SystemCustomerAttributeNames.LastName); 52 model.Company = customer.GetAttribute<string>(SystemCustomerAttributeNames.Company); 53 model.Address1 = customer.GetAttribute<string>(SystemCustomerAttributeNames.StreetAddress); 54 model.Address2 = customer.GetAttribute<string>(SystemCustomerAttributeNames.StreetAddress2); 55 model.ZipPostalCode = customer.GetAttribute<string>(SystemCustomerAttributeNames.ZipPostalCode); 56 model.City = customer.GetAttribute<string>(SystemCustomerAttributeNames.City); 57 //ignore country and state for prepopulation. it can cause some issues when posting pack with errors, etc 58 //model.CountryId = customer.GetAttribute<int>(SystemCustomerAttributeNames.CountryId); 59 //model.StateProvinceId = customer.GetAttribute<int>(SystemCustomerAttributeNames.StateProvinceId); 60 model.PhoneNumber = customer.GetAttribute<string>(SystemCustomerAttributeNames.Phone); 61 model.FaxNumber = customer.GetAttribute<string>(SystemCustomerAttributeNames.Fax); 62 } 63 64 //countries and states 65 if (addressSettings.CountryEnabled && loadCountries != null) 66 { 67 if (localizationService == null) 68 throw new ArgumentNullException("localizationService"); 69 70 model.AvailableCountries.Add(new SelectListItem() { Text = localizationService.GetResource("Address.SelectCountry"), Value = "0" }); 71 foreach (var c in loadCountries()) 72 { 73 model.AvailableCountries.Add(new SelectListItem() 74 { 75 Text = c.GetLocalized(x => x.Name), 76 Value = c.Id.ToString(), 77 Selected = c.Id == model.CountryId 78 }); 79 } 80 model.CountryId = 21; 81 if (address != null) 82 { 83 model.CountyId = address.CountyId; 84 model.CityId = address.CityId; 85 } 86 if (addressSettings.StateProvinceEnabled) 87 { 88 //states 89 if (stateProvinceService == null) 90 throw new ArgumentNullException("stateProvinceService"); 91 92 var states = stateProvinceService 93 .GetStateProvincesByCountryId(21)//这块直接给写死成中国 94 .ToList(); 95 if (states.Count > 0) 96 { 97 foreach (var s in states) 98 { 99 model.AvailableStates.Add(new SelectListItem() 100 { 101 Text = s.GetLocalized(x => x.Name), 102 Value = s.Id.ToString(), 103 Selected = (s.Id == model.StateProvinceId) 104 }); 105 } 106 } 107 else 108 { 109 model.AvailableStates.Add(new SelectListItem() 110 { 111 Text = localizationService.GetResource("Address.OtherNonUS"), 112 Value = "0" 113 }); 114 } 115 #region yunchen.bai 2014.10.27 116 if (cityService == null) 117 throw new ArgumentNullException("cityService"); 118 var firstProvince = stateProvinceService.GetStateProvincesByCountryId(21).FirstOrDefault() ?? 119 new StateProvince(); 120 var citys = 121 cityService.GetCityByStateProvinceId(model.StateProvinceId != null 122 ? model.StateProvinceId.Value 123 : firstProvince.Id).ToList(); 124 var firstCity = cityService.GetCityByStateProvinceId(firstProvince.Id).FirstOrDefault() ?? 125 new City(); 126 if (citys.Count > 0) 127 { 128 foreach (var c in citys) 129 { 130 model.AvailableCity.Add(new SelectListItem() 131 { 132 Text = c.GetLocalized(x=>x.Name), 133 Value = c.Id.ToString(), 134 Selected = (c.Id==model.CityId) 135 }); 136 } 137 } 138 else 139 { 140 model.AvailableCity.Add(new SelectListItem() 141 { 142 Text = localizationService.GetResource("Address.OtherNonUS"), 143 Value = "0" 144 }); 145 } 146 if(countyService==null) 147 throw new ArgumentNullException("countyService"); 148 var counties = countyService.GetCountyByCityId(model.CityId.HasValue?model.CityId.Value:firstCity.Id); 149 if (counties.Count > 0) 150 { 151 foreach (var county in counties) 152 { 153 model.AvailableCounty.Add(new SelectListItem() 154 { 155 Text = county.GetLocalized(x=>x.Name), 156 Value = county.Id.ToString(), 157 Selected = (county.Id==model.CityId) 158 }); 159 } 160 } 161 else 162 { 163 model.AvailableCity.Add(new SelectListItem() 164 { 165 Text = localizationService.GetResource("Address.OtherNonUS"), 166 Value = "0" 167 }); 168 } 169 170 #endregion 171 172 173 } 174 }
未完待续.....
西安.NET俱乐部群