This commit is contained in:
@@ -1,37 +0,0 @@
|
|||||||
package com.example.building.controller;
|
|
||||||
|
|
||||||
import com.example.building.common.Result;
|
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import com.example.building.service.CategoryAttributeService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 种类属性控制器
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/category-attributes")
|
|
||||||
public class CategoryAttributeController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CategoryAttributeService categoryAttributeService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取种类的属性列表
|
|
||||||
*/
|
|
||||||
@GetMapping("/category/{categoryId}")
|
|
||||||
public Result<List<CategoryAttribute>> getByCategoryId(@PathVariable String categoryId) {
|
|
||||||
return Result.success(categoryAttributeService.getByCategoryId(categoryId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存种类属性
|
|
||||||
*/
|
|
||||||
@PostMapping("/category/{categoryId}")
|
|
||||||
public Result<Void> saveAttributes(@PathVariable String categoryId, @RequestBody List<CategoryAttribute> attrs) {
|
|
||||||
categoryAttributeService.saveAttributes(categoryId, attrs);
|
|
||||||
return Result.success();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,11 +3,8 @@ package com.example.building.controller;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.example.building.common.Result;
|
import com.example.building.common.Result;
|
||||||
import com.example.building.entity.Category;
|
import com.example.building.entity.Category;
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import com.example.building.entity.Product;
|
import com.example.building.entity.Product;
|
||||||
import com.example.building.service.ProductService;
|
import com.example.building.service.ProductService;
|
||||||
import com.example.building.service.CategoryAttributeService;
|
|
||||||
import com.example.building.service.ProductAttributeService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -25,12 +22,6 @@ public class ProductController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ProductService productService;
|
private ProductService productService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CategoryAttributeService categoryAttributeService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProductAttributeService productAttributeService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取分类列表
|
* 获取分类列表
|
||||||
*/
|
*/
|
||||||
@@ -105,15 +96,7 @@ public class ProductController {
|
|||||||
if (!"admin".equals(role)) {
|
if (!"admin".equals(role)) {
|
||||||
return Result.error("只有管理员可以操作");
|
return Result.error("只有管理员可以操作");
|
||||||
}
|
}
|
||||||
Product created = productService.createProduct(product);
|
return Result.success(productService.createProduct(product));
|
||||||
// 如果有属性,一并保存
|
|
||||||
if (product.getAttributes() != null && !product.getAttributes().isEmpty()) {
|
|
||||||
productAttributeService.saveProductAttributes(
|
|
||||||
created.getProductId(),
|
|
||||||
created.getCategoryId(),
|
|
||||||
product.getAttributes());
|
|
||||||
}
|
|
||||||
return Result.success(created);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,54 +131,4 @@ public class ProductController {
|
|||||||
public Result<List<Map<String, Object>>> getStockAlerts() {
|
public Result<List<Map<String, Object>>> getStockAlerts() {
|
||||||
return Result.success(productService.getStockAlerts());
|
return Result.success(productService.getStockAlerts());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ============ 属性相关 ============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取种类的属性定义
|
|
||||||
*/
|
|
||||||
@GetMapping("/categories/{categoryId}/attributes")
|
|
||||||
public Result<List> getCategoryAttributes(@PathVariable String categoryId) {
|
|
||||||
return Result.success(categoryAttributeService.getByCategoryId(categoryId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存种类的属性定义
|
|
||||||
*/
|
|
||||||
@PostMapping("/categories/{categoryId}/attributes")
|
|
||||||
public Result<Void> saveCategoryAttributes(
|
|
||||||
@PathVariable String categoryId,
|
|
||||||
@RequestBody List<CategoryAttribute> attrs,
|
|
||||||
@RequestHeader(value = "X-User-Role", required = false) String role) {
|
|
||||||
if (!"admin".equals(role)) {
|
|
||||||
return Result.error("只有管理员可以操作");
|
|
||||||
}
|
|
||||||
categoryAttributeService.saveAttributes(categoryId, attrs);
|
|
||||||
return Result.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品的属性值
|
|
||||||
*/
|
|
||||||
@GetMapping("/{productId}/attributes")
|
|
||||||
public Result<List> getProductAttributes(@PathVariable String productId) {
|
|
||||||
return Result.success(productAttributeService.getByProductId(productId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存商品的属性值
|
|
||||||
*/
|
|
||||||
@PostMapping("/{productId}/attributes")
|
|
||||||
public Result<Void> saveProductAttributes(
|
|
||||||
@PathVariable String productId,
|
|
||||||
@RequestBody Map<String, Object> body,
|
|
||||||
@RequestHeader(value = "X-User-Role", required = false) String role) {
|
|
||||||
if (!"admin".equals(role)) {
|
|
||||||
return Result.error("只有管理员可以操作");
|
|
||||||
}
|
|
||||||
String categoryId = (String) body.get("categoryId");
|
|
||||||
List<Map<String, Object>> attrs = (List<Map<String, Object>>) body.get("attributes");
|
|
||||||
productAttributeService.saveProductAttributes(productId, categoryId, attrs);
|
|
||||||
return Result.success();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package com.example.building.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 种类属性定义实体
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@TableName("category_attributes")
|
|
||||||
public class CategoryAttribute {
|
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
|
||||||
private String attrId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 种类ID
|
|
||||||
*/
|
|
||||||
private String categoryId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 属性名称
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 属性类型: number=数字, text=文本, formula=公式
|
|
||||||
*/
|
|
||||||
private String attrType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单位
|
|
||||||
*/
|
|
||||||
private String unit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公式表达式(如:length*width)
|
|
||||||
*/
|
|
||||||
private String formula;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
private Integer sortOrder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否必填
|
|
||||||
*/
|
|
||||||
private Integer required;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private LocalDateTime createdAt;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
private LocalDateTime updatedAt;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.example.building.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品属性值实体
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@TableName("product_attributes")
|
|
||||||
public class ProductAttribute {
|
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品ID
|
|
||||||
*/
|
|
||||||
private String productId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 属性定义ID
|
|
||||||
*/
|
|
||||||
private String attrId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 属性名称(冗余)
|
|
||||||
*/
|
|
||||||
private String attrName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 属性值
|
|
||||||
*/
|
|
||||||
private String attrValue;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private LocalDateTime createdAt;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.example.building.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface CategoryAttributeMapper extends BaseMapper<CategoryAttribute> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.example.building.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.example.building.entity.ProductAttribute;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface ProductAttributeMapper extends BaseMapper<ProductAttribute> {
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package com.example.building.service;
|
|
||||||
|
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 种类属性服务接口
|
|
||||||
*/
|
|
||||||
public interface CategoryAttributeService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取种类的所有属性
|
|
||||||
*/
|
|
||||||
List<CategoryAttribute> getByCategoryId(String categoryId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存属性
|
|
||||||
*/
|
|
||||||
void saveAttributes(String categoryId, List<CategoryAttribute> attrs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除种类的所有属性
|
|
||||||
*/
|
|
||||||
void deleteByCategoryId(String categoryId);
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.example.building.service;
|
|
||||||
|
|
||||||
import com.example.building.entity.ProductAttribute;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品属性服务接口
|
|
||||||
*/
|
|
||||||
public interface ProductAttributeService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品的属性值
|
|
||||||
*/
|
|
||||||
List<ProductAttribute> getByProductId(String productId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存商品属性值(自动计算公式属性)
|
|
||||||
* @param productId 商品ID
|
|
||||||
* @param categoryId 种类ID(用于获取公式定义)
|
|
||||||
* @param attrs 属性列表
|
|
||||||
*/
|
|
||||||
void saveProductAttributes(String productId, String categoryId, List<Map<String, Object>> attrs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除商品的所有属性
|
|
||||||
*/
|
|
||||||
void deleteByProductId(String productId);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.example.building.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import com.example.building.mapper.CategoryAttributeMapper;
|
|
||||||
import com.example.building.service.CategoryAttributeService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 种类属性服务实现
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class CategoryAttributeServiceImpl implements CategoryAttributeService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CategoryAttributeMapper categoryAttributeMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CategoryAttribute> getByCategoryId(String categoryId) {
|
|
||||||
return categoryAttributeMapper.selectList(new LambdaQueryWrapper<CategoryAttribute>()
|
|
||||||
.eq(CategoryAttribute::getCategoryId, categoryId)
|
|
||||||
.orderByAsc(CategoryAttribute::getSortOrder));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void saveAttributes(String categoryId, List<CategoryAttribute> attrs) {
|
|
||||||
System.out.println("=== saveAttributes called ===");
|
|
||||||
System.out.println("categoryId: " + categoryId);
|
|
||||||
System.out.println("attrs size: " + (attrs != null ? attrs.size() : 0));
|
|
||||||
|
|
||||||
// 删除旧属性
|
|
||||||
categoryAttributeMapper.delete(new LambdaQueryWrapper<CategoryAttribute>()
|
|
||||||
.eq(CategoryAttribute::getCategoryId, categoryId));
|
|
||||||
|
|
||||||
// 保存新属性
|
|
||||||
if (attrs != null && !attrs.isEmpty()) {
|
|
||||||
for (int i = 0; i < attrs.size(); i++) {
|
|
||||||
CategoryAttribute attr = attrs.get(i);
|
|
||||||
attr.setAttrId(UUID.randomUUID().toString());
|
|
||||||
attr.setCategoryId(categoryId);
|
|
||||||
attr.setSortOrder(i);
|
|
||||||
|
|
||||||
System.out.println(" attr: " + attr.getName() + ", type=" + attr.getAttrType() + ", unit=" + attr.getUnit());
|
|
||||||
categoryAttributeMapper.insert(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("=== saveAttributes done ===");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void deleteByCategoryId(String categoryId) {
|
|
||||||
categoryAttributeMapper.delete(new LambdaQueryWrapper<CategoryAttribute>()
|
|
||||||
.eq(CategoryAttribute::getCategoryId, categoryId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
package com.example.building.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.example.building.entity.CategoryAttribute;
|
|
||||||
import com.example.building.entity.ProductAttribute;
|
|
||||||
import com.example.building.mapper.CategoryAttributeMapper;
|
|
||||||
import com.example.building.mapper.ProductAttributeMapper;
|
|
||||||
import com.example.building.service.ProductAttributeService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品属性服务实现
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class ProductAttributeServiceImpl implements ProductAttributeService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProductAttributeMapper productAttributeMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CategoryAttributeMapper categoryAttributeMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ProductAttribute> getByProductId(String productId) {
|
|
||||||
return productAttributeMapper.selectList(new LambdaQueryWrapper<ProductAttribute>()
|
|
||||||
.eq(ProductAttribute::getProductId, productId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void saveProductAttributes(String productId, String categoryId, List<Map<String, Object>> attrs) {
|
|
||||||
// 获取种类的属性定义(包括公式)
|
|
||||||
List<CategoryAttribute> categoryAttrs = categoryAttributeMapper.selectList(
|
|
||||||
new LambdaQueryWrapper<CategoryAttribute>()
|
|
||||||
.eq(CategoryAttribute::getCategoryId, categoryId)
|
|
||||||
.orderByAsc(CategoryAttribute::getSortOrder));
|
|
||||||
|
|
||||||
// 构建属性名->属性定义的映射
|
|
||||||
Map<String, CategoryAttribute> attrDefMap = new HashMap<>();
|
|
||||||
for (CategoryAttribute ca : categoryAttrs) {
|
|
||||||
attrDefMap.put(ca.getName(), ca);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先把输入的属性保存到 Map 中(用于公式计算)
|
|
||||||
Map<String, Double> attrValues = new HashMap<>();
|
|
||||||
List<ProductAttribute> toSave = new ArrayList<>();
|
|
||||||
|
|
||||||
// 第一遍:保存所有普通属性
|
|
||||||
for (Map<String, Object> attr : attrs) {
|
|
||||||
String attrName = (String) attr.get("attrName");
|
|
||||||
String attrValue = String.valueOf(attr.get("attrValue"));
|
|
||||||
|
|
||||||
// 尝试转换为数字
|
|
||||||
try {
|
|
||||||
attrValues.put(attrName, Double.parseDouble(attrValue));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// 非数字类型不做计算
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductAttribute pa = new ProductAttribute();
|
|
||||||
pa.setId(UUID.randomUUID().toString());
|
|
||||||
pa.setProductId(productId);
|
|
||||||
pa.setAttrId((String) attr.get("attrId"));
|
|
||||||
pa.setAttrName(attrName);
|
|
||||||
pa.setAttrValue(attrValue);
|
|
||||||
toSave.add(pa);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第二遍:处理公式属性
|
|
||||||
for (CategoryAttribute ca : categoryAttrs) {
|
|
||||||
if ("formula".equals(ca.getAttrType()) && ca.getFormula() != null && !ca.getFormula().isEmpty()) {
|
|
||||||
String formula = ca.getFormula();
|
|
||||||
try {
|
|
||||||
double result = evaluateFormula(formula, attrValues);
|
|
||||||
// 保留两位小数
|
|
||||||
result = Math.round(result * 100.0) / 100.0;
|
|
||||||
|
|
||||||
ProductAttribute pa = new ProductAttribute();
|
|
||||||
pa.setId(UUID.randomUUID().toString());
|
|
||||||
pa.setProductId(productId);
|
|
||||||
pa.setAttrId(ca.getAttrId());
|
|
||||||
pa.setAttrName(ca.getName());
|
|
||||||
pa.setAttrValue(String.valueOf(result));
|
|
||||||
toSave.add(pa);
|
|
||||||
|
|
||||||
System.out.println("公式计算: " + formula + " = " + result);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("公式计算失败: " + formula + ", error: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除旧属性
|
|
||||||
productAttributeMapper.delete(new LambdaQueryWrapper<ProductAttribute>()
|
|
||||||
.eq(ProductAttribute::getProductId, productId));
|
|
||||||
|
|
||||||
// 保存新属性
|
|
||||||
for (ProductAttribute pa : toSave) {
|
|
||||||
productAttributeMapper.insert(pa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析并计算公式
|
|
||||||
* 支持四则运算 + - * / 和括号 ()
|
|
||||||
* 变量名用实际值替换
|
|
||||||
*/
|
|
||||||
private double evaluateFormula(String formula, Map<String, Double> variables) {
|
|
||||||
// 替换变量为数值
|
|
||||||
String expr = formula;
|
|
||||||
Pattern pattern = Pattern.compile("[a-zA-Z_]+");
|
|
||||||
Matcher matcher = pattern.matcher(formula);
|
|
||||||
while (matcher.find()) {
|
|
||||||
String varName = matcher.group();
|
|
||||||
if (variables.containsKey(varName)) {
|
|
||||||
expr = expr.replace(varName, String.valueOf(variables.get(varName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 JavaScript 引擎计算表达式
|
|
||||||
return evalExpression(expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 简单的表达式计算器(支持 + - * / 和括号)
|
|
||||||
*/
|
|
||||||
private double evalExpression(String expr) {
|
|
||||||
// 去除空格
|
|
||||||
expr = expr.replace(" ", "");
|
|
||||||
|
|
||||||
return parseExpression(expr, new int[]{0});
|
|
||||||
}
|
|
||||||
|
|
||||||
private double parseExpression(String expr, int[] pos) {
|
|
||||||
double result = parseTerm(expr, pos);
|
|
||||||
|
|
||||||
while (pos[0] < expr.length()) {
|
|
||||||
char op = expr.charAt(pos[0]);
|
|
||||||
if (op != '+' && op != '-') break;
|
|
||||||
pos[0]++;
|
|
||||||
double term = parseTerm(expr, pos);
|
|
||||||
if (op == '+') {
|
|
||||||
result += term;
|
|
||||||
} else {
|
|
||||||
result -= term;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double parseTerm(String expr, int[] pos) {
|
|
||||||
double result = parseFactor(expr, pos);
|
|
||||||
|
|
||||||
while (pos[0] < expr.length()) {
|
|
||||||
char op = expr.charAt(pos[0]);
|
|
||||||
if (op != '*' && op != '/') break;
|
|
||||||
pos[0]++;
|
|
||||||
double factor = parseFactor(expr, pos);
|
|
||||||
if (op == '*') {
|
|
||||||
result *= factor;
|
|
||||||
} else {
|
|
||||||
if (factor != 0) {
|
|
||||||
result /= factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double parseFactor(String expr, int[] pos) {
|
|
||||||
// 处理括号
|
|
||||||
if (pos[0] < expr.length() && expr.charAt(pos[0]) == '(') {
|
|
||||||
pos[0]++; // 跳过 (
|
|
||||||
double result = parseExpression(expr, pos);
|
|
||||||
if (pos[0] < expr.length() && expr.charAt(pos[0]) == ')') {
|
|
||||||
pos[0]++; // 跳过 )
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理负数
|
|
||||||
boolean negative = false;
|
|
||||||
if (pos[0] < expr.length() && expr.charAt(pos[0]) == '-') {
|
|
||||||
negative = true;
|
|
||||||
pos[0]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析数字
|
|
||||||
double result = 0;
|
|
||||||
while (pos[0] < expr.length()) {
|
|
||||||
char c = expr.charAt(pos[0]);
|
|
||||||
if ((c >= '0' && c <= '9') || c == '.') {
|
|
||||||
result = result * 10 + (c - '0');
|
|
||||||
pos[0]++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return negative ? -result : result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void deleteByProductId(String productId) {
|
|
||||||
productAttributeMapper.delete(new LambdaQueryWrapper<ProductAttribute>()
|
|
||||||
.eq(ProductAttribute::getProductId, productId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
-- 种类属性定义表
|
|
||||||
CREATE TABLE IF NOT EXISTS category_attributes (
|
|
||||||
attr_id VARCHAR(36) PRIMARY KEY,
|
|
||||||
category_id VARCHAR(36) NOT NULL,
|
|
||||||
name VARCHAR(50) NOT NULL,
|
|
||||||
attr_type VARCHAR(20) DEFAULT 'number',
|
|
||||||
unit VARCHAR(20),
|
|
||||||
formula VARCHAR(200),
|
|
||||||
sort_order INTEGER DEFAULT 0,
|
|
||||||
required INTEGER DEFAULT 0,
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 商品属性值表
|
|
||||||
CREATE TABLE IF NOT EXISTS product_attributes (
|
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
|
||||||
product_id VARCHAR(36) NOT NULL,
|
|
||||||
attr_id VARCHAR(36) NOT NULL,
|
|
||||||
attr_name VARCHAR(50),
|
|
||||||
attr_value VARCHAR(200),
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (attr_id) REFERENCES category_attributes(attr_id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 商品表增加默认单位字段
|
|
||||||
ALTER TABLE products ADD COLUMN default_unit VARCHAR(20);
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- 删除种类属性相关表和字段(回滚 V7)
|
||||||
|
-- 删除商品属性值表
|
||||||
|
DROP TABLE IF EXISTS product_attributes;
|
||||||
|
|
||||||
|
-- 删除种类属性定义表
|
||||||
|
DROP TABLE IF EXISTS category_attributes;
|
||||||
|
|
||||||
|
-- 删除商品表的 default_unit 字段
|
||||||
|
ALTER TABLE products DROP COLUMN IF EXISTS default_unit;
|
||||||
Reference in New Issue
Block a user