1. 程式人生 > >通用屬性系統設計與實現

通用屬性系統設計與實現

    這兩年做過不少的小型電商系統,有的賣衣服,有的賣鞋子,有的賣電器,甚至還有些賣虛擬服務的。不同商品的屬性千差萬別,為了減少以後賣xxx的電商系統的工作量,特將屬性系統做成通用版的。 設計思路如下: 1、可自定義的無限級商品類別。 2、各類別可自定義屬性,屬性的型別有:普通文字、數字、價格、單項選擇、多項選擇、日期、文字域、富文字、圖片、布林值等,新增商品時自動載入所需的元件。 3、支援公共屬性。 4、支援屬性繼承,即子類別自動繼承父類別的屬性,並支援覆蓋父類別同名屬性。 5、支援屬性值驗證,新增商品時對必填項、正則表示式進行自動驗證。 6、支援屬性分組,新增商品時屬性按照屬性分組名進行分組。 模型設計:   Classify:商品類別表 Attribute:屬性表 AttributeOption:屬性選項表,只有類別為“單項選擇”和“多項選擇”時,屬性需要設定屬性選項。 Product:商品表 ProductAttribute:商品屬性關係表 這裡只是對商品屬性進行了簡單的建模,與屬性無關的模型沒有畫出。 關鍵程式碼:
@{
    ViewBag.Title = "新增產品";
    Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
}
@section header{
    <link href="~/Content/css/dataTables.bootstrap.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css"
/> <link href="~/Content/js/plugs/webuploader/webuploader.css" rel="stylesheet" type="text/css" /> } <div class="page-container"> <div class="page-body"> <div class="row"> <div class="col-lg-12 col-sm-12 col-xs-12"> <div id="simplewizard"
class="wizard" data-target="#simplewizard-steps"> <ul class="steps"> <li data-target="#basicInfoStep" class="active"><span class="step">1</span><span class="title">基礎資訊</span> <span class="chevron"></span></li> <li data-target="#attributeStep"><span class="step">2</span><span class="title">產品屬性</span> <span class="chevron"></span></li> <li data-target="#picInfoStep"><span class="step">3</span><span class="title">產品圖片</span> <span class="chevron"></span></li> <li data-target="#confirmInfoStep"><span class="step">4</span><span class="title">確認資訊</span> <span class="chevron"></span></li> </ul> </div> <div class="step-content" id="simplewizard-steps"> <!--基礎資訊--> <div class="step-pane active" id="basicInfoStep"> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="name" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>產品名稱:</label> <div class="col-sm-6"> <input type="text" class="form-control" id="name" v-model="product.name"> </div> </div> <div class="form-group"> <label for="originPrice" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>原價:</label> <div class="col-sm-6"> <input type="text" class="form-control" id="price" v-model="product.originPrice" data-type="2"> </div> </div> <div class="form-group"> <label for="price" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>銷售價:</label> <div class="col-sm-6"> <input type="text" class="form-control" id="price" v-model="product.price" data-type="2"> </div> </div> <div class="form-group"> <label for="inventory" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>庫存:</label> <div class="col-sm-6"> <input type="text" class="form-control" id="inventory" v-model="product.inventory" data-type="2"> </div> </div> <div class="form-group"> <label for="isOnShelf" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>是否上架:</label> <div class="col-sm-6"> <select id="isOnShelf" v-model="product.isOnShelf"> <option value="false"></option> <option value="true"></option> </select> </div> </div> <div class="form-group"> <label for="classifyId" class="col-sm-2 control-label no-padding-right"><span style="color:red;">* </span>所屬分類:</label> <div class="col-sm-6"> <select id="classifyId" v-model="product.classifyId" v-on:change="classifyChange()" disabled="disabled"> <option v-for="option in classifies" v-bind:value="option.Value"> {{ option.Name }} </option> </select> </div> </div> </form> </div> <!--產品屬性--> <div class="step-pane" id="attributeStep"> <div class="row"> <div class="col-sm-12"> <div class="tabbable"> <ul class="nav nav-tabs tabs-flat"> <template v-for="(index,group) in product.groupAttributes"> <li class="tab-sky"> <a data-toggle="tab" href="#group{{index}}" aria-expanded="true"> {{group.groupName}} </a> </li> </template> </ul> <div class="tab-content tabs-flat"> <template v-for="(index,group) in product.groupAttributes"> <div id="group{{index}}" class="tab-pane" style="width:99%"> <form class="form-horizontal" role="form"> <template v-for="attribute in group.attributes"> <div class="form-group"> <label class="col-sm-2 control-label no-padding-right"><span v-if="attribute.isRequired" style="color:red;">* </span>{{attribute.name}}:</label> <div class="col-sm-6"> <!--單選--> <select v-if="attribute.attributeType==4" class="form-control" id="atrribute_{{attribute.id}}" v-model="attribute.attributeOptionId"> <option v-for="item in attribute.options" v-bind:value="item.value">{{item.name}}</option> </select> <template v-else> <!--多選--> <div v-if="attribute.attributeType==5" class="row"> <div v-for="item in attribute.options" class="col-sm-3 col-lg-2"> <div class="checkbox"> <label> <input type="checkbox" v-bind:value="item.value" v-model="attribute.attributeOptionIds"> <span class="text">{{item.name}}</span> </label> </div> </div> </div> <template v-else> <!--文字域--> <textarea v-if="attribute.attributeType==7" class="form-control" data-type="{{attribute.attributeType}}" v-model="attribute.value"></textarea> <template v-else> <!--富文字--> <script v-if="attribute.attributeType==8" id="atrribute_{{attribute.id}}" data-type="{{attribute.attributeType}}" name="content" type="text/plain"> </script> <template v-else> <!--圖片--> <template v-if="attribute.attributeType==9"> <img style="width:160px;height:90px;" id="img_{{attribute.id}}" v-bind:src="attribute.value" /> <div id="upload_{{attribute.id}}" data-type="{{attribute.attributeType}}">選擇圖片</div> </template> <input v-else type="text" class="form-control" id="atrribute_{{attribute.id}}" data-type="{{attribute.attributeType}}" v-model="attribute.value"> </template> </template> </template> </template> </div> <div class="col-sm-2" style="margin-top:7px;">{{attribute.tips}}</div> </div> </template> </form> </div> </template> </div> </div> </div> </div> </div> <!--產品圖片--> <div class="step-pane" id="picInfoStep"> <form class="form-horizontal form-bordered" role="form"> <div class="form-group"> <div id="upload_album" class="col-sm-2 control-label no-padding-right">上傳圖片</div> <div class="col-sm-6"> <div class="row"> <div class="col-sm-3" v-for="path in product.albums"> <img style="width:160px;height:90px;" id="img_album" v-bind:src="path" /> </div> </div> </div> </div> </form> </div> <!--確認資訊--> <div class="step-pane" id="confirmInfoStep"> <table class="table table-bordered table-hover"> <tbody> <tr> <td width="150px">商品名稱</td> <td>{{product.name}}</td> </tr> <tr> <td width="150px">原價</td> <td>{{product.originPrice}}</td> </tr> <tr> <td width="150px">銷售價</td> <td>{{product.price}}</td> </tr> <tr> <td width="150px">庫存</td> <td>{{product.inventory}}</td> </tr> <tr> <td width="150px">是否上架</td> <td>{{product.isOnShelf}}</td> </tr> <tr> <td width="150px">所屬城市</td> <td>{{product.regionId}}</td> </tr> <template v-for="group in product.groupAttributes"> <tr v-for="attribute in group.attributes"> <td width="150px">{{attribute.name}}</td> <td>{{{attribute.value}}}</td> </tr> </template> <tr> <td width="150px">產品圖片</td> <td> <img v-for="path in product.albums" style="width:160px;height:90px;" v-bind:src="path" /> </td> </tr> </tbody> </table> </div> </div> <div class="actions actions-footer" id="simplewizard-actions"> <div class="btn-group"> <button type="button" class="btn btn-default btn-prev"> <i class="fa fa-angle-left"></i>上一步</button> <button type="button" class="btn btn-default btn-next">下一步<i class="fa fa-angle-right"></i></button> </div> </div> </div> </div> </div> </div> @section footer{ <script src="~/Content/js/bode/bode.wizard.js" type="text/javascript"></script> <script src="~/Content/js/plugs/datetime/bootstrap-datetimepicker.min.js" type="text/javascript"></script> <script src="~/Content/js/plugs/datetime/bootstrap-datetimepicker.zh-CN.js" type="text/javascript"></script> <script src="~/Content/js/plugs/webuploader/webuploader.js" type="text/javascript"></script> <script src="~/Content/js/plugs/ueditor/ueditor.config.js" type="text/javascript"></script> <script src="~/Content/js/plugs/ueditor/ueditor.all.min.js" type="text/javascript"></script> <script src