diff --git a/controller/product/inventory.go b/controller/product/inventory.go
new file mode 100644
index 00000000..35475064
--- /dev/null
+++ b/controller/product/inventory.go
@@ -0,0 +1,175 @@
+package product
+
+import (
+ "fmt"
+ "strings"
+ "strconv"
+ "unicode/utf8"
+ "wemall/model"
+ "wemall/config"
+ "gopkg.in/kataras/iris.v6"
+)
+
+func combinationPropValue(productID uint, properties []model.Property) []model.Inventory {
+ var inventories []model.Inventory
+ if len(properties) == 1 {
+ for i := 0; i < len(properties[0].PropertyValues); i++ {
+ var inventory = model.Inventory{
+ ProductID : productID,
+ PropertyValues : []model.PropertyValue{
+ properties[0].PropertyValues[i],
+ },
+ }
+ inventories = append(inventories, inventory)
+ }
+ } else {
+ theInventories := combinationPropValue(productID, properties[1:])
+ property := properties[0]
+ for i := len(theInventories) - 1; i >= 0; i-- {
+ for j := 0; j < len(property.PropertyValues); j++ {
+ var inventory = model.Inventory{
+ ProductID : productID,
+ PropertyValues : theInventories[i].PropertyValues,
+ }
+ inventory.PropertyValues = append(inventory.PropertyValues, property.PropertyValues[j])
+ inventories = append(inventories, inventory)
+ }
+ theInventories = append(theInventories[:i], theInventories[i + 1:]...)
+ }
+ }
+ return inventories
+}
+
+// test 添加商品属性值
+func test(ctx *iris.Context) {
+ var productID uint
+ var propertyValue model.PropertyValue
+
+ if err := ctx.ReadJSON(&propertyValue); err != nil {
+ fmt.Println(err.Error());
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "参数无效",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ productID = propertyValue.ProductID
+ propertyValue.Name = strings.TrimSpace(propertyValue.Name)
+
+ var isErr bool
+ var errMsg = ""
+
+ if productID <= 0 {
+ isErr = true
+ errMsg = "无效的商品ID"
+ } else if utf8.RuneCountInString(propertyValue.Name) > config.ServerConfig.MaxNameLen {
+ isErr = true
+ errMsg = "名称不能超过" + strconv.Itoa(config.ServerConfig.MaxNameLen) + "个字符"
+ } else if utf8.RuneCountInString(propertyValue.Name) <= 0 {
+ isErr = true
+ errMsg = "名称不能为空"
+ }
+
+ if isErr {
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : errMsg,
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var product model.Product
+
+ if err := model.DB.First(&product, productID).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.NotFound,
+ "msg" : "错误的商品id",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ if err := model.DB.Model(&product).Related(&product.Properties).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var properties = product.Properties
+ var index = -1 //属性(新添加的属性值属于的属性)在属性数组中的索引
+ for i := 0; i < len(properties); i++ {
+ fmt.Println(123, properties[i].ID, propertyValue.PropertyID)
+ if properties[i].ID == propertyValue.PropertyID {
+ index = i
+ break;
+ }
+ }
+
+ if index < 0 {
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "错误的propertyID",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ for i := 0; i < len(properties); i++ {
+ property := properties[i]
+ if err := model.DB.Model(&property).Related(&property.PropertyValues).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+ properties[i] = property
+ }
+
+ if err := model.DB.Create(&propertyValue).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var inventories []model.Inventory
+ if len(properties) == 1 {
+ var inventory = model.Inventory{
+ ProductID : productID,
+ PropertyValues : append([]model.PropertyValue{}, propertyValue),
+ }
+ inventories = append(inventories, inventory)
+ } else if len(properties) >= 2 {
+ properties = append(properties[:index], properties[index + 1:]...)
+ inventories = combinationPropValue(productID, properties)
+ for i := 0; i < len(inventories); i++ {
+ inventories[i].PropertyValues = append(inventories[i].PropertyValues, propertyValue)
+ }
+ }
+
+ for i := 0; i < len(inventories); i++ {
+ if err := model.DB.Create(&inventories[i]).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+ }
+}
\ No newline at end of file
diff --git a/controller/product/property.go b/controller/product/property.go
new file mode 100644
index 00000000..6fb3ccc9
--- /dev/null
+++ b/controller/product/property.go
@@ -0,0 +1,182 @@
+package product
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+ "wemall/model"
+ "wemall/config"
+ "gopkg.in/kataras/iris.v6"
+)
+
+// AddProperty 添加商品属性
+func AddProperty(ctx *iris.Context) {
+ var property model.Property
+
+ if err := ctx.ReadJSON(&property); err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "参数无效",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ property.Name = strings.TrimSpace(property.Name)
+
+ var isErr bool
+ var errMsg = ""
+
+ if property.ProductID <= 0 {
+ isErr = true
+ errMsg = "无效的商品ID"
+ } else if utf8.RuneCountInString(property.Name) > config.ServerConfig.MaxNameLen {
+ isErr = true
+ errMsg = "属性名称不能超过" + strconv.Itoa(config.ServerConfig.MaxNameLen) + "个字符"
+ } else if utf8.RuneCountInString(property.Name) <= 0 {
+ isErr = true
+ errMsg = "属性名称不能为空"
+ }
+
+ if isErr {
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : errMsg,
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var product model.Product
+
+ if err := model.DB.First(&product, property.ProductID).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.NotFound,
+ "msg" : "错误的商品id",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ if err := model.DB.Create(&property).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ property.PropertyValues = []model.PropertyValue{}
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.SUCCESS,
+ "msg" : "success",
+ "data" : iris.Map{
+ "property": property,
+ },
+ })
+}
+
+// AddPropertyValue 添加商品属性值
+func AddPropertyValue(ctx *iris.Context) {
+ var productID uint
+ var propertyValue model.PropertyValue
+
+ if err := ctx.ReadJSON(&propertyValue); err != nil {
+ fmt.Println(err.Error());
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "参数无效",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ productID = propertyValue.ProductID
+ propertyValue.Name = strings.TrimSpace(propertyValue.Name)
+
+ var isErr bool
+ var errMsg = ""
+
+ if productID <= 0 {
+ isErr = true
+ errMsg = "无效的商品ID"
+ } else if utf8.RuneCountInString(propertyValue.Name) > config.ServerConfig.MaxNameLen {
+ isErr = true
+ errMsg = "名称不能超过" + strconv.Itoa(config.ServerConfig.MaxNameLen) + "个字符"
+ } else if utf8.RuneCountInString(propertyValue.Name) <= 0 {
+ isErr = true
+ errMsg = "名称不能为空"
+ }
+
+ if isErr {
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : errMsg,
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var product model.Product
+
+ if err := model.DB.First(&product, productID).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.NotFound,
+ "msg" : "错误的商品id",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ if err := model.DB.Model(&product).Related(&product.Properties).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ var properties = product.Properties
+ var index = -1 //属性(新添加的属性值属于的属性)在属性数组中的索引
+ for i := 0; i < len(properties); i++ {
+ if properties[i].ID == propertyValue.PropertyID {
+ index = i
+ break;
+ }
+ }
+
+ if index < 0 {
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "错误的propertyID",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ if err := model.DB.Create(&propertyValue).Error; err != nil {
+ fmt.Println(err.Error())
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.ERROR,
+ "msg" : "error",
+ "data" : iris.Map{},
+ })
+ return
+ }
+
+ ctx.JSON(iris.StatusOK, iris.Map{
+ "errNo" : model.ErrorCode.SUCCESS,
+ "msg" : "success",
+ "data" : iris.Map{
+ "propertyValue": propertyValue,
+ },
+ })
+}
\ No newline at end of file
diff --git a/main.go b/main.go
index 176653b1..9b4b3e0f 100644
--- a/main.go
+++ b/main.go
@@ -69,4 +69,7 @@ func main() {
})
app.Listen(":" + strconv.Itoa(config.ServerConfig.Port))
-}
\ No newline at end of file
+}
+
+
+
diff --git a/model/inventory.go b/model/inventory.go
new file mode 100644
index 00000000..4b551a46
--- /dev/null
+++ b/model/inventory.go
@@ -0,0 +1,14 @@
+package model
+
+import "time"
+
+// Inventory 商品库存
+type Inventory struct {
+ ID uint `gorm:"primary_key" json:"id"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ DeletedAt *time.Time `sql:"index" json:"deletedAt"`
+ ProductID uint `json:"productID"`
+ Count uint `json:"count"`
+ PropertyValues []PropertyValue `gorm:"many2many:inventory_property_value;ForeignKey:ID;AssociationForeignKey:ID" json:"propertyValues"`
+}
\ No newline at end of file
diff --git a/model/product.go b/model/product.go
index d3740091..765b46e3 100644
--- a/model/product.go
+++ b/model/product.go
@@ -27,39 +27,6 @@ type Product struct {
Categories []Category `gorm:"many2many:product_category;ForeignKey:ID;AssociationForeignKey:ID" json:"categories"`
}
-// Property 商品属性
-type Property struct {
- ID uint `gorm:"primary_key" json:"id"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- DeletedAt *time.Time `sql:"index" json:"deletedAt"`
- Name string `json:"name"`
- ProductID uint `json:"productID"`
- PropertyValues []PropertyValue `json:"values"`
-}
-
-// PropertyValue 商品属性值
-type PropertyValue struct {
- ID uint `gorm:"primary_key" json:"id"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- DeletedAt *time.Time `sql:"index" json:"deletedAt"`
- Name string `json:"name"`
- Note string `json:"note"`
- PropertyID uint `json:"propertyID"`
-}
-
-// Inventory 商品库存
-type Inventory struct {
- ID uint `gorm:"primary_key" json:"id"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- DeletedAt *time.Time `sql:"index" json:"deletedAt"`
- ProductID uint `json:"productID"`
- Count uint `json:"count"`
- PropertyValues []PropertyValue `gorm:"many2many:inventory_property;ForeignKey:ID;AssociationForeignKey:ID" json:"propertyValues"`
-}
-
const (
// ProductUpShelf 商品已上架
ProductUpShelf = 1
diff --git a/model/property.go b/model/property.go
new file mode 100644
index 00000000..64a6a8c3
--- /dev/null
+++ b/model/property.go
@@ -0,0 +1,26 @@
+package model
+
+import "time"
+
+// Property 商品属性
+type Property struct {
+ ID uint `gorm:"primary_key" json:"id"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ DeletedAt *time.Time `sql:"index" json:"deletedAt"`
+ Name string `json:"name"`
+ ProductID uint `json:"productID"`
+ PropertyValues []PropertyValue `json:"values"`
+}
+
+// PropertyValue 商品属性值
+type PropertyValue struct {
+ ID uint `gorm:"primary_key" json:"id"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ DeletedAt *time.Time `sql:"index" json:"deletedAt"`
+ Name string `json:"name"`
+ Note string `json:"note"`
+ ProductID uint `json:"productID"`
+ PropertyID uint `json:"propertyID"`
+}
\ No newline at end of file
diff --git a/nodejs/static/javascripts/admin/actions/product/requestSaveProperty.js b/nodejs/static/javascripts/admin/actions/product/requestSaveProperty.js
new file mode 100644
index 00000000..86a074b4
--- /dev/null
+++ b/nodejs/static/javascripts/admin/actions/product/requestSaveProperty.js
@@ -0,0 +1,32 @@
+import {
+ REQUEST_SAVE_PRODUCT_PROP,
+ REQUEST_SAVE_PRODUCT_PROP_SUCCESS,
+} from '../../constants';
+
+function receive(data) {
+ return {
+ type : REQUEST_SAVE_PRODUCT_PROP_SUCCESS,
+ property : data.property
+ };
+}
+
+export default function(data) {
+ return dispatch => {
+ var url = pageConfig.apiPath + '/admin/product/property/create';
+ var reqData = {
+ productID : data.productID,
+ name : data.name
+ };
+ return fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(reqData)
+ })
+ .then(response => response.json())
+ .then(json => dispatch(receive(json.data)));
+ };
+};
+
diff --git a/nodejs/static/javascripts/admin/actions/product/requestSavePropertyValue.js b/nodejs/static/javascripts/admin/actions/product/requestSavePropertyValue.js
new file mode 100644
index 00000000..abf6b0e5
--- /dev/null
+++ b/nodejs/static/javascripts/admin/actions/product/requestSavePropertyValue.js
@@ -0,0 +1,33 @@
+import {
+ REQUEST_SAVE_PRODUCT_PROP_VALUE,
+ REQUEST_SAVE_PRODUCT_PROP_VALUE_SUCCESS,
+} from '../../constants';
+
+function receive(data) {
+ return {
+ type : REQUEST_SAVE_PRODUCT_PROP_VALUE_SUCCESS,
+ propertyValue : data.propertyValue
+ };
+}
+
+export default function(data) {
+ return dispatch => {
+ var url = pageConfig.apiPath + '/admin/product/property/saveval';
+ var reqData = {
+ productID : data.productID,
+ name : data.name,
+ propertyID : data.propertyID
+ };
+ return fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(reqData)
+ })
+ .then(response => response.json())
+ .then(json => dispatch(receive(json.data)));
+ };
+};
+
diff --git a/nodejs/static/javascripts/admin/constants/index.js b/nodejs/static/javascripts/admin/constants/index.js
index e37dda74..b3a8e412 100644
--- a/nodejs/static/javascripts/admin/constants/index.js
+++ b/nodejs/static/javascripts/admin/constants/index.js
@@ -24,6 +24,14 @@ export const REQUEST_SAVE_PRODUCT = 'requestSaveProduct';
export const REQUEST_SAVE_PRODUCT_SUCCESS = 'requestSaveProductSuccess';
+export const REQUEST_SAVE_PRODUCT_PROP = 'requestSaveProductProp';
+
+export const REQUEST_SAVE_PRODUCT_PROP_SUCCESS = 'requestSaveProductPropSuccess';
+
+export const REQUEST_SAVE_PRODUCT_PROP_VALUE = 'requestSaveProductPropValue';
+
+export const REQUEST_SAVE_PRODUCT_PROP_VALUE_SUCCESS = 'requestSaveProductPropValueSuccess';
+
export const CHANGE_PRODUCT_STATUS = 'changeProductStatus';
export const REQUEST_CATEGORY_LIST = 'requestCategoryList';
diff --git a/nodejs/static/javascripts/admin/containers/product/EditProduct.js b/nodejs/static/javascripts/admin/containers/product/EditProduct.js
index 7ed9a95c..532f3917 100644
--- a/nodejs/static/javascripts/admin/containers/product/EditProduct.js
+++ b/nodejs/static/javascripts/admin/containers/product/EditProduct.js
@@ -21,6 +21,8 @@ import {
import requestProduct from '../../actions/product/requestProduct';
import requestSaveProduct from '../../actions/product/requestSaveProduct';
import requestCategoryList from '../../actions/category/requestCategoryList';
+import requestSaveProperty from '../../actions/product/requestSaveProperty';
+import requestSavePropertyValue from '../../actions/product/requestSavePropertyValue';
import Software from '../Software';
import utils from '../../utils';
import analyze from '../../../sdk/analyze';
@@ -48,6 +50,10 @@ class EditProduct extends Component {
this.onContentImageChange = this.onContentImageChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onPropValueVisibleChange = this.onPropValueVisibleChange.bind(this);
+ this.onPropVisibleChange = this.onPropVisibleChange.bind(this);
+ this.onPropInput = this.onPropInput.bind(this);
+ this.addProp = this.addProp.bind(this);
+ this.cancelAddProp = this.cancelAddProp.bind(this);
this.state = {
productId : this.props.routeParams.id,
@@ -69,6 +75,8 @@ class EditProduct extends Component {
inventories : [],
propValueVisibleMap : {},
propValueTemp : '',
+ propPopupVisible : false,
+ propTemp : '',
isLoading : true
};
}
@@ -114,6 +122,7 @@ class EditProduct extends Component {
if (allCategories && allCategories.length > 0) {
if (this.state.productId) {
if (product) {
+ console.log(product);
var categories = [];
for (var i = 0; i < product.categories.length; i++) {
var parentId = product.categories[i].parentId;
@@ -306,7 +315,12 @@ class EditProduct extends Component {
propValueTemp : ''
});
- message.success(propValueTemp + '添加成功! 请完善库存。');
+ const { dispatch } = this.props;
+ dispatch(requestSavePropertyValue({
+ productID : this.state.productId,
+ propertyID : propId,
+ name : propValueTemp
+ }));
}
cancelAddPropValue(propId) {
var propValueVisibleMap = this.state.propValueVisibleMap;
@@ -316,6 +330,34 @@ class EditProduct extends Component {
propValueTemp : ''
});
}
+ onPropVisibleChange(visible) {
+ this.setState({
+ propPopupVisible: visible
+ });
+ }
+ onPropInput(event) {
+ this.setState({
+ propTemp: event.target.value
+ });
+ }
+ addProp() {
+ var propTemp = this.state.propTemp;
+ this.setState({
+ propTemp : '',
+ propPopupVisible : false
+ });
+ const { dispatch } = this.props;
+ dispatch(requestSaveProperty({
+ productID : this.state.productId,
+ name : propTemp
+ }));
+ }
+ cancelAddProp() {
+ this.setState({
+ propTemp : '',
+ propPopupVisible : false
+ });
+ }
render() {
let self = this;
let { data } = this.props;
@@ -337,6 +379,8 @@ class EditProduct extends Component {
let inventories = this.state.inventories;
let propValueVisibleMap = this.state.propValueVisibleMap;
let propValueTemp = this.state.propValueTemp;
+ let propPopupVisible = this.state.propPopupVisible;
+ let propTemp = this.state.propTemp;
let TabPane = Tabs.TabPane;
@@ -514,6 +558,19 @@ class EditProduct extends Component {
);
})
}
+
+
+
+
+
+ }
+ onVisibleChange={self.onPropVisibleChange}
+ visible={propPopupVisible}
+ title={'添加属性'} trigger="click" >
+
+
+
{
inventories.map(function(inv) {
diff --git a/nodejs/static/javascripts/admin/reducers/product.js b/nodejs/static/javascripts/admin/reducers/product.js
index 7703d460..57dc3c20 100644
--- a/nodejs/static/javascripts/admin/reducers/product.js
+++ b/nodejs/static/javascripts/admin/reducers/product.js
@@ -6,7 +6,9 @@ import {
REQUEST_PRODUCT_SUCCESS,
REQUEST_CATEGORY_LIST,
REQUEST_CATEGORY_LIST_SUCCESS,
- REQUEST_SAVE_PRODUCT_SUCCESS
+ REQUEST_SAVE_PRODUCT_SUCCESS,
+ REQUEST_SAVE_PRODUCT_PROP_SUCCESS,
+ REQUEST_SAVE_PRODUCT_PROP_VALUE_SUCCESS
} from '../constants';
let initState = {
@@ -73,6 +75,29 @@ export default (state = initState, action) => {
categories: action.categories
};
}
+ case REQUEST_SAVE_PRODUCT_PROP_SUCCESS: {
+ let product = state.product;
+ let properties = product.properties.concat(action.property);
+ product.properties = properties;
+ return {
+ ...state,
+ product: product
+ };
+ }
+ case REQUEST_SAVE_PRODUCT_PROP_VALUE_SUCCESS: {
+ let product = state.product;
+ let properties = product.properties;
+ for (let i = 0; i < properties.length; i++) {
+ if (properties[i].id == action.propertyValue.propertyID) {
+ properties[i].values.push(action.propertyValue);
+ break;
+ }
+ }
+ return {
+ ...state,
+ product: product
+ };
+ }
default: {
return state
}
diff --git a/nodejs/static/styles/admin/product/editProduct.css b/nodejs/static/styles/admin/product/editProduct.css
index 3e7d5e0a..1c779ee6 100644
--- a/nodejs/static/styles/admin/product/editProduct.css
+++ b/nodejs/static/styles/admin/product/editProduct.css
@@ -56,6 +56,10 @@
color: #666;
}
+.product-prop-add label {
+ font-size: 0;
+}
+
.product-prop-value {
margin-right: 12px;
}
@@ -65,12 +69,12 @@
cursor: pointer;
}
-.product-prop-value-add-input {
+.product-prop-add-input, .product-prop-value-add-input {
width: 120px;
margin-right: 12px;
}
-.product-prop-value-add-confirm {
+.product-prop-add-confirm, .product-prop-value-add-confirm {
margin-right: 12px;
}
diff --git a/route/route.go b/route/route.go
index 3dc887c7..5e3f3231 100644
--- a/route/route.go
+++ b/route/route.go
@@ -39,11 +39,13 @@ func Route(app *iris.Framework) {
adminRouter.Post("/category/update", category.Update)
adminRouter.Post("/category/status/update", category.UpdateStatus)
- adminRouter.Get("/products", product.AdminList)
- adminRouter.Get("/product/:id", product.Info)
- adminRouter.Post("/product/create", product.Create)
- adminRouter.Post("/product/update", product.Update)
- adminRouter.Post("/product/status/update", product.UpdateStatus)
+ adminRouter.Get("/products", product.AdminList)
+ adminRouter.Get("/product/:id", product.Info)
+ adminRouter.Post("/product/create", product.Create)
+ adminRouter.Post("/product/update", product.Update)
+ adminRouter.Post("/product/status/update", product.UpdateStatus)
+ adminRouter.Post("/product/property/saveval", product.AddPropertyValue)
+ adminRouter.Post("/product/property/create", product.AddProperty)
adminRouter.Get("/order/analyze", order.Analyze)
adminRouter.Get("/order/todaycount", order.TodayCount)