NopCommerce定做系列(3)- 地址修改
Nop版本3.7。
Nop里的地址为 国家-> 省份。现在需要修改为 省份-> 城市-> 地区-> 街道。
关于直辖市的话,由于只有三级,参考淘宝,即 北京 -> 北京 -> 地区 ->街道。
一:添加表
添加城市(City)、地区(District)、街道(Street)表。
City 表结构如下,地区、街道表与 City 基本一致。可以参考 国家、省份 做法。
using System.Collections.Generic;
using Nop.Core.Domain.Localization;
namespace Nop.Core.Domain.Directory
{
/// <summary>
/// Represents a city
/// </summary>
public partial class City : BaseEntity, ILocalizedEntity
{
private ICollection<District> _districts;
/// <summary>
/// Gets or sets the StateProvince identifier
/// </summary>
public int StateProvinceId { get; set; }
/// <summary>
/// Gets or sets the name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the abbreviation
/// </summary>
public string Abbreviation { get; set; }
/// <summary>
/// Gets or sets the zip
/// </summary>
public int Zip { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the entity is published
/// </summary>
public bool Published { get; set; }
/// <summary>
/// Gets or sets the display order
/// </summary>
public int DisplayOrder { get; set; }
/// <summary>
/// Gets or sets the StateProvince
/// </summary>
public virtual StateProvince StateProvince { get; set; }
/// <summary>
/// Gets or sets the district
/// </summary>
public virtual ICollection<District> Districts
{
get { return _districts ?? (_districts = new List<District>()); }
protected set { _districts = value; }
}
}
}
实现创建完毕后,需要在Address表中添加县区、街道的关联字段。
在原Address表中,City是一个nvarchar类型字段,需删除。新增3个int类型字段,CityID,DistrictId,StreetId。
这个时候编译,会发现很多错误,是由于City字段删除的缘故,需更改的地方太多,就不贴代码了,在修改时候,正好加上 City、District、Street相应代码,这一步很花时间,耐心修改。当然,如果图省事,也可以直接用City。
关于添加一个实体的方法,请参考链接 http://www.nopchina.net/post/nopcommerce-add-table.html
控制器、实体、视图 参考 国家省份即可。
PS:我是一只光荣的面向Copy编程者。
二:添加配置
在 商城配置-> 设置管理-> 客户设置 中,客户表单字段 以及 地址表单字段,添加相对应设置。
联动还是需要的。
在 Libraries\Nop.Core\Domain\Common\AddressSetting.cs 中,添加设置字段。
/// <summary>
/// Gets or sets a value indicating whether 'City' is enabled
/// </summary>
public bool CityEnabled { get; set; }
/// <summary>
/// Gets or sets a value indicating whether 'District' is enabled
/// </summary>
public bool DistrictEnabled { get; set; }
/// <summary>
/// Gets or sets a value indicating whether 'Street' is enabled
/// </summary>
public bool StreetEnabled { get; set; }
重装即可。
在 控制器、实体、视图 中添加相应代码。依旧参考。
三:使用
后台为例,在 Nop.Admin\Views\Shared\EditorTemplates\Address.cshtml 中
@model AddressModel
@if (Model.CountryEnabled && Model.StateProvinceEnabled)
{
<script type="text/javascript">
$(document).ready(function() {
$("#@Html.FieldIdFor(model => model.CountryId)").change(function() {
CountryIsChange();
});
});
function CountryIsChange()
{
var selectedItem = $("#@Html.FieldIdFor(model => model.CountryId)").val();
var ddlStates = $("#@Html.FieldIdFor(model => model.StateProvinceId)");
$.ajax({
async: false,
cache: false,
type: "GET",
url: "@(Url.Action("GetStatesByCountryId", "Country"))",
data: { "countryId": selectedItem, "addSelectStateItem": "true" },
success: function(data) {
ddlStates.html('');
$.each(data, function(id, option) {
ddlStates.append($('<option></option>').val(option.id).html(option.name));
});
},
error: function(xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve states.');
}
});
}
</script>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled)
{
<script type="text/javascript">
$(document).ready(function () {
$("#@Html.FieldIdFor(model => model.StateProvinceId)").change(function() {
StateProvinceIsChange();
CityIsChange();
DistrictIsChange();
});
});
function StateProvinceIsChange()
{
var selectedItem = $("#@Html.FieldIdFor(model => model.StateProvinceId)").val();
var ddlCitys = $("#@Html.FieldIdFor(model => model.CityId)");
$.ajax({
async: false,
cache: false,
type: "GET",
url: "@(Url.Action("GetCitysByStateProvinceId", "Country"))",
data: { "stateProvinceId": selectedItem, "addSelectCityItem": "true" },
success: function(data) {
ddlCitys.html('');
$.each(data, function(id, option) {
ddlCitys.append($('<option></option>').val(option.id).html(option.name));
});
},
error: function(xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve citys.');
}
});
}
</script>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled && Model.DistrictEnabled)
{
<script type="text/javascript">
$(document).ready(function () {
$("#@Html.FieldIdFor(model => model.CityId)").change(function () {
CityIsChange();
DistrictIsChange();
});
});
function CityIsChange()
{
var selectedItem = $("#@Html.FieldIdFor(model => model.CityId)").val();
var ddlDistricts = $("#@Html.FieldIdFor(model => model.DistrictId)");
$.ajax({
async: false,
cache: false,
type: "GET",
url: "@(Url.Action("GetDistrictsByCityId", "Country"))",
data: { "cityId": selectedItem, "addSelectDistrictItem": "true" },
success: function(data) {
ddlDistricts.html('');
$.each(data, function(id, option) {
ddlDistricts.append($('<option></option>').val(option.id).html(option.name));
});
},
error: function(xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve district.');
}
});
}
</script>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled && Model.DistrictEnabled && Model.StreetEnabled)
{
<script type="text/javascript">
$(document).ready(function () {
$("#@Html.FieldIdFor(model => model.DistrictId)").change(function() {
DistrictIsChange();
});
});
function DistrictIsChange()
{
var selectedItem = $("#@Html.FieldIdFor(model => model.DistrictId)").val();
var ddlStreets = $("#@Html.FieldIdFor(model => model.StreetId)");
$.ajax({
async: false,
cache: false,
type: "GET",
url: "@(Url.Action("GetStreetsByDistrictId", "Country"))",
data: { "districtId": selectedItem, "addSelectStreetItem": "true" },
success: function(data) {
ddlStreets.html('');
$.each(data, function(id, option) {
ddlStreets.append($('<option></option>').val(option.id).html(option.name));
});
},
error: function(xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve street.');
}
});
}
</script>
}
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.FirstNameEnabled)
@Html.HiddenFor(model => model.FirstNameRequired)
@Html.HiddenFor(model => model.LastNameEnabled)
@Html.HiddenFor(model => model.LastNameRequired)
@Html.HiddenFor(model => model.EmailEnabled)
@Html.HiddenFor(model => model.EmailRequired)
@Html.HiddenFor(model => model.CompanyEnabled)
@Html.HiddenFor(model => model.CompanyRequired)
@Html.HiddenFor(model => model.CountryEnabled)
@Html.HiddenFor(model => model.StateProvinceEnabled)
@Html.HiddenFor(model => model.CityEnabled)
@Html.HiddenFor(model => model.CityRequired)
@Html.HiddenFor(model => model.DistrictEnabled)
@Html.HiddenFor(model => model.StreetEnabled)
@Html.HiddenFor(model => model.StreetAddressEnabled)
@Html.HiddenFor(model => model.StreetAddressRequired)
@Html.HiddenFor(model => model.StreetAddress2Enabled)
@Html.HiddenFor(model => model.StreetAddress2Required)
@Html.HiddenFor(model => model.ZipPostalCodeEnabled)
@Html.HiddenFor(model => model.ZipPostalCodeRequired)
@Html.HiddenFor(model => model.PhoneEnabled)
@Html.HiddenFor(model => model.PhoneRequired)
@Html.HiddenFor(model => model.FaxEnabled)
@Html.HiddenFor(model => model.FaxRequired)
<table class="address-block">
@if (Model.FirstNameEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.FirstName):
</td>
<td class="adminData">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</td>
</tr>
}
@*@if (Model.LastNameEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.LastName):
</td>
<td class="adminData">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</td>
</tr>
}*@
@if (Model.EmailEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.Email):
</td>
<td class="adminData">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</td>
</tr>
}
@if (Model.CompanyEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.Company):
</td>
<td class="adminData">
@Html.EditorFor(model => model.Company)
@Html.ValidationMessageFor(model => model.Company)
</td>
</tr>
}
@if (Model.CountryEnabled)
{
<tr style="display:none;">
<td class="adminTitle">
@Html.NopLabelFor(model => model.CountryId):
</td>
<td class="adminData">
@Html.DropDownListFor(model => model.CountryId, Model.AvailableCountries)
@Html.ValidationMessageFor(model => model.CountryId)
</td>
</tr>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.StateProvinceId):
</td>
<td class="adminData">
@Html.DropDownListFor(model => model.StateProvinceId, Model.AvailableStates)
@Html.ValidationMessageFor(model => model.StateProvinceId)
</td>
</tr>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.CityId):
</td>
<td class="adminData">
@Html.DropDownListFor(model => model.CityId, Model.AvailableCitys)
@Html.ValidationMessageFor(model => model.CityId)
</td>
</tr>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled && Model.DistrictEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.DistrictId):
</td>
<td class="adminData">
@Html.DropDownListFor(model => model.DistrictId, Model.AvailableDistricts)
@Html.ValidationMessageFor(model => model.DistrictId)
</td>
</tr>
}
@if (Model.CountryEnabled && Model.StateProvinceEnabled && Model.CityEnabled && Model.DistrictEnabled && Model.StreetEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.StreetId):
</td>
<td class="adminData">
@Html.DropDownListFor(model => model.StreetId, Model.AvailableStreets)
@Html.ValidationMessageFor(model => model.StreetId)
</td>
</tr>
}
@if (Model.StreetAddressEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.Address1):
</td>
<td class="adminData">
@Html.EditorFor(model => model.Address1)
@Html.ValidationMessageFor(model => model.Address1)
</td>
</tr>
}
@if (Model.StreetAddress2Enabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.Address2):
</td>
<td class="adminData">
@Html.EditorFor(model => model.Address2)
@Html.ValidationMessageFor(model => model.Address2)
</td>
</tr>
}
@if (Model.ZipPostalCodeEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.ZipPostalCode):
</td>
<td class="adminData">
@Html.EditorFor(model => model.ZipPostalCode)
@Html.ValidationMessageFor(model => model.ZipPostalCode)
</td>
</tr>
}
@if (Model.PhoneEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.PhoneNumber):
</td>
<td class="adminData">
@Html.EditorFor(model => model.PhoneNumber)
@Html.ValidationMessageFor(model => model.PhoneNumber)
</td>
</tr>
}
@if (Model.FaxEnabled)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.FaxNumber):
</td>
<td class="adminData">
@Html.EditorFor(model => model.FaxNumber)
@Html.ValidationMessageFor(model => model.FaxNumber)
</td>
</tr>
}
@if (Model.CustomAddressAttributes.Count > 0)
{
@Html.Partial("_AddressAttributes", Model.CustomAddressAttributes)
}
</table>
@if (Model.CountryId == null)
{
<script type="text/javascript">
$(function () {
$("#@Html.FieldIdFor(model => model.CountryId) option").each(function () {
if ($(this).text() == "中国")
{
$(this).attr('selected', true);
}
});
$("#@Html.FieldIdFor(model => model.CountryId)").trigger("change");
})
</script>
}
四:数据
东西都做好了,数据哪来呢? 当然是中国官方网站里找喏。http://www.mca.gov.cn/article/sj/tjbz/a/2016/201603/201604281751.html
不想自己折腾的话,就直接 下载
数据只有 省份、城市、县区 ,街道的话,淘宝有接口,可以去看看。
这里我只是简单的介绍了下怎么去修改。我自己去做的时候,有 国家 省份 参考,并没有太多难点,主要是修改的地方有点多,需要耐心的,一点点的去改动,所以我并没有写太多具体改动的地方,在不熟悉的情况下,参考是很重要的,虽然不能保证很完美,至少保证跟以前一样,不会很烂。在Nop里,其实很多地方都是值得参考的,比如使用缓存、计划任务等,都是可以照葫芦画瓢的。
谢谢支持!!!