1. 程式人生 > >自定義銷售屬性的展示和資料儲存解決方案

自定義銷售屬性的展示和資料儲存解決方案

我的資料表設計如下 由 Product表, SellProperty表和SKU表三張表來支援該功能. 表結構如下:
CREATE TABLE `purchaser_product` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `product_code` varchar(45) DEFAULT NULL COMMENT '商品編碼',
  `product_name` varchar(45) NOT NULL COMMENT '商品名稱',
  `price` decimal(12,2) DEFAULT NULL COMMENT '價格',
  `unit` int(11) NOT NULL COMMENT '單位-個,件等',
  `category_id` bigint(20) NOT NULL,
  `top_category_id` bigint(20) NOT NULL,
  `description` text COMMENT '商品描述',
  `create_time` datetime NOT NULL,
  `creator_name` varchar(45) NOT NULL,
  `update_time` datetime DEFAULT NULL,
  `updator_name` varchar(45) DEFAULT NULL,
  `delete_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否刪除',
  `on_shelf_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '上下架狀態',
  `brand` varchar(45) DEFAULT NULL COMMENT '商品品牌',
  `model` varchar(45) DEFAULT NULL COMMENT '商品型號',
  `vendor_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
CREATE TABLE `purchaser_product_sell_property` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `product_id` bigint(20) DEFAULT NULL,
  `property_name` varchar(45) DEFAULT NULL,
  `order_num` int(11) DEFAULT NULL,
  `creator_name` varchar(45) DEFAULT NULL,
  `creator_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

CREATE TABLE `purchaser_sku` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `product_id` bigint(20) NOT NULL,
  `sell_property_name_struct` varchar(45) DEFAULT NULL COMMENT '銷售屬性名的結構,從第一級到最後,以逗號分隔',
  `price` decimal(12,2) NOT NULL,
  `product_code` varchar(45) NOT NULL,
  `sell_property_value_struct` varchar(45) DEFAULT NULL COMMENT '銷售屬性值的結構,從第一級到最後,以逗號分隔',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8;

首先最複雜的就是增加屬性,會變化表格. 我抽象了一個JS物件,有兩個主要方法: addProperty(property) // 新增屬性 addPropertyValue(property,propertyValue) //新增屬性值
var propertyMap = {
                propertyList:[],
                total:0,
                propertyObj:{},
                validProperties:[],
                deleteProperty : function(propertyName) {
                    delete this.propertyObj[propertyName];
                    removeByValue(this.propertyList,propertyName);
                    this.show();
                },
                hasValue : function() {
                    var hasValue = false;
                    $.each(this.propertyObj,function(i,n){
                        hasValue = n.length > 0;
                    });
                    return hasValue;
                },
                propertyHasValue : function(property) {
                    return this.propertyObj[property] == null ? true:(this.propertyObj[property].length>0);
                },
                addProperty : function(propertyName) {
                    this.propertyList.push(propertyName);
                    this.propertyObj[propertyName] = [];
                    var tpl = document.getElementById("property_row_tpl").innerHTML;
                    var html = juicer(tpl,{property:propertyName});
                    $("#property_area").append(html);

                },
                addValue : function(propertyName,value) {
                    if (contains(this.propertyObj[propertyName],value) ) {
                        layer.msg("屬性值已經存在",{icon: 5,time: 1000});
                        return;
                    }
                    this.propertyObj[propertyName].push(value);
                    var tpl = document.getElementById("property_value_tpl").innerHTML;
                    var html = juicer(tpl,{propertyValue:value,propertyName:propertyName});
                    $("#" + propertyName + "_value_display_area").append(html);
                    this.show();
                },
                deleteValue : function(propertyName,value) {
                    removeByValue(this.propertyObj[propertyName],value);
                    this.show();
                },
                show : function() {
                    //沒有屬性,直接返回
                    if (this.propertyList == null || this.propertyList.length <= 0) {
                        $("#tablearea").html("");
                        return;
                    }

                    var propertySize = this.propertyList.length;//總共有多少個屬性

                    var validProperty = null;
                    var last = null;
                    var validPropertyList = [];
                    var totalTR = 1;
                    for (var i = propertySize - 1; i >= 0; i--) {
                        if (this.propertyObj[this.propertyList[i]].length > 0) {
                            validProperty = {propertyValues:[],index:0,pre:null,next:null,nextLoop:1};
                            //如果屬性對應的屬性值列表有值,說明此屬性有效
                            validProperty.index = i + 1;
                            validProperty.propertyValues = this.propertyObj[this.propertyList[i]];
                            if (last != null) {
                                last.pre = validProperty;
                            }
                            validProperty.next = last;
                            validProperty.name = this.propertyList[i];
                            last = validProperty;
                            validPropertyList.unshift(validProperty);
                            totalTR = totalTR * validProperty.propertyValues.length;
                        }
                    }
                    // 沒有有效屬性,也就是所有屬性沒有屬性值,直接返回
                    if (validPropertyList == null || validPropertyList.length <= 0) {
                        $("#tablearea").html("");
//                        var defaultTable = document.getElementById("default_sku_tpl").innerHTML;
//                        $("#tablearea").html(defaultTable);
                        return;
                    }
                    this.validProperties = validPropertyList;
                    for (var i = 0; i < validPropertyList.length; i++) { //計算每一個屬性的所有下級屬性長度乘積的結果,用來表示,下級一共多少行.
                        var nextLoop = 1;
                        var nextNode = validPropertyList[i].next;
                        while (nextNode != null) {
                            nextLoop = nextLoop * nextNode.propertyValues.length;
                            nextNode = nextNode.next;
                        }
                        validPropertyList[i].nextLoop = nextLoop;
                    }

                    var totalTD = validPropertyList.length; // 每行有幾個TD
                    var tableContent = '';
                    for (var i = 1; i <= totalTR; i++) { //需要有多少行
                        var tr = '<tr>';
                            for (var j = 1; j <= totalTD; j++) {
                                var currentProperty = validPropertyList[j - 1];
                                if (j == totalTD) {
                                    var index = parseInt((i - 1)%currentProperty.propertyValues.length);
                                    var propertyValueStruct = loadPropertyValues(currentProperty, i);
                                    var propertyStruct = loadProperty(currentProperty);
                                    console.log(propertyStruct);
                                    var id = i + "-" + j;
                                    tr +=  "<td>"+currentProperty.propertyValues[index]+"</td>";
                                    tr +=  "<td style='display:none'><input type='text' class='form-control product_code_class' placeholder='填寫商品編碼' id='productcode_"+id+"'  propertystruct='"+propertyValueStruct+"' property='"+propertyStruct+"'></td>";
                                    tr +=  "<td><input type='text' value='' class='touchspin' id='price_"+id+"'></td>";
                                    break;
                                }
                                var isFirst = false;
                                if (currentProperty.nextLoop == 1) {
                                    isFirst = ( i % currentProperty.nextLoop == 0);
                                } else {
                                    isFirst = (i % currentProperty.nextLoop == 1);
                                }
                                if (isFirst) {
                                    var index = parseInt(((i - 1)/currentProperty.nextLoop)%currentProperty.propertyValues.length);
                                    tr +=  "<td rowspan='"+ currentProperty.nextLoop +"'>"+currentProperty.propertyValues[index]+"</td>";
                                }
                            }
                        tr += "</tr>";
                        tableContent += tr;
                    }
                    var tpl = document.getElementById("table_tpl").innerHTML;
                    var html = juicer(tpl,{list:validPropertyList});
                    html = html.replace("######",tableContent);
                    $("#tablearea").html(html);
                    $(".touchspin").TouchSpin({
                        min: 0,
                        max: 100000,
                        step: 0.1,
                        decimals: 2,
                        prefix: '$'
                    });
                }

            };