删除种类属性相关代码,回滚V7并创建V8
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Agent
2026-03-31 13:44:57 +00:00
parent 75e996aa30
commit 7fbb95542a
12 changed files with 11 additions and 584 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}