NopCommerce定做系列(3)- 地址修改

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编程者。

 

二:添加配置

在 商城配置-> 设置管理-> 客户设置 中,客户表单字段 以及 地址表单字段,添加相对应设置。

NopCommerce定做系列(3)- 地址修改

联动还是需要的。

在 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里,其实很多地方都是值得参考的,比如使用缓存、计划任务等,都是可以照葫芦画瓢的。

谢谢支持!!!