diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteCraftController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteCraftController.java index e8e7fc0..fdf64cd 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteCraftController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteCraftController.java @@ -1,9 +1,15 @@ package com.ruoyi.system.controller; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.system.domain.QuoteType; +import com.ruoyi.system.domain.ServiceCate; +import com.ruoyi.system.service.IQuoteTypeService; import com.ruoyi.system.service.IServiceGoodsService; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +43,8 @@ public class QuoteCraftController extends BaseController @Autowired private IQuoteCraftService quoteCraftService; - + @Autowired + private IQuoteTypeService quoteTypeService; @Autowired private IServiceGoodsService serviceGoodsService; @@ -62,6 +69,40 @@ public class QuoteCraftController extends BaseController return getDataTable(list); } + + /** + * 获取工艺分类下拉list用来进行多选 + */ + @PreAuthorize("@ss.hasPermi('system:ServiceGoods:query')") + @PostMapping(value = "/selectQuoteTypeList") + public AjaxResult selectQuoteTypeList() + { + + QuoteType quoteType = new QuoteType(); + + List quoteTypeList = quoteTypeService.selectQuoteTypeList(quoteType); + return success(quoteType); + } + +// /** +// * 获取工艺分类下拉list用来进行多选 +// */ +// @PreAuthorize("@ss.hasPermi('system:ServiceGoods:query')") +// @PostMapping(value = "/selectQuoteTypeList") +// public AjaxResult selectQuoteTypeList(@RequestBody ArrayList ids) +// { +// System.out.println("&&&&&&&&&&&&&&&"+ids); +// QuoteType quoteType = new QuoteType(); +//// if(ids!=null){ +//// List idslist = Arrays.asList( +//// +//// quoteType.setGoodsids(idslist); +//// } +// List quoteTypeList = quoteTypeService.selectQuoteTypeList(quoteType); +// return success(quoteTypeList); +// } + + /** * 导出项目报价--服务工艺列表 */ @@ -82,7 +123,22 @@ public class QuoteCraftController extends BaseController @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { - return success(quoteCraftService.selectQuoteCraftById(id)); + QuoteCraft quoteCraft=quoteCraftService.selectQuoteCraftById(id); + if(quoteCraft!=null){ + if (quoteCraft.getTypeId()!=null) { + String strtype = quoteCraft.getTypeId(); + List strtypeList = JSON.parseArray(strtype, String.class); + List intstrtypeList = strtypeList.stream().map(Integer::parseInt).collect(Collectors.toList()); + quoteCraft.setTypeintids(intstrtypeList); + } + if (quoteCraft.getGoodId()!=null){ + String str = quoteCraft.getGoodId(); + List stringList = JSON.parseArray(str, String.class); + List intList = stringList.stream().map(Integer::parseInt).collect(Collectors.toList()); + quoteCraft.setGoodsintids(intList); + } + } + return success(quoteCraft); } /** @@ -93,6 +149,15 @@ public class QuoteCraftController extends BaseController @PostMapping public AjaxResult add(@RequestBody QuoteCraft quoteCraft) { + if(quoteCraft.getGoodsintids().size()>0){ + List intList =quoteCraft.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteCraft.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + } return toAjax(quoteCraftService.insertQuoteCraft(quoteCraft)); } @@ -104,6 +169,15 @@ public class QuoteCraftController extends BaseController @PutMapping public AjaxResult edit(@RequestBody QuoteCraft quoteCraft) { + if(quoteCraft.getGoodsintids().size()>0){ + List intList =quoteCraft.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteCraft.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + } return toAjax(quoteCraftService.updateQuoteCraft(quoteCraft)); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialController.java index 469b7be..249cec6 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialController.java @@ -2,8 +2,10 @@ package com.ruoyi.system.controller; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; +import com.alibaba.fastjson2.JSON; import com.ruoyi.system.domain.QuoteType; import com.ruoyi.system.service.IQuoteMaterialTypeService; import com.ruoyi.system.service.IServiceGoodsService; @@ -87,7 +89,14 @@ public class QuoteMaterialController extends BaseController @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { - return success(quoteMaterialService.selectQuoteMaterialById(id)); + QuoteMaterial quoteMaterial=quoteMaterialService.selectQuoteMaterialById(id); + if (quoteMaterial.getGoodId()!=null){ + String str = quoteMaterial.getGoodId(); + List stringList = JSON.parseArray(str, String.class); + List intList = stringList.stream().map(Integer::parseInt).collect(Collectors.toList()); + quoteMaterial.setGoodsintids(intList); + } + return success(quoteMaterial); } /** @@ -98,6 +107,15 @@ public class QuoteMaterialController extends BaseController @PostMapping public AjaxResult add(@RequestBody QuoteMaterial quoteMaterial) { + if(quoteMaterial.getGoodsintids().size()>0){ + List intList =quoteMaterial.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteMaterial.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + } return toAjax(quoteMaterialService.insertQuoteMaterial(quoteMaterial)); } @@ -109,6 +127,18 @@ public class QuoteMaterialController extends BaseController @PutMapping public AjaxResult edit(@RequestBody QuoteMaterial quoteMaterial) { + if(quoteMaterial.getGoodsintids().size()>0){ + System.out.println("#########################"+quoteMaterial.getGoodsintids()); + List intList =quoteMaterial.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteMaterial.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + System.out.println("#########################"+json.replaceAll("\",\"", "\", \"")); + + } return toAjax(quoteMaterialService.updateQuoteMaterial(quoteMaterial)); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialTypeController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialTypeController.java index f0a3f87..414e454 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialTypeController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteMaterialTypeController.java @@ -2,8 +2,11 @@ package com.ruoyi.system.controller; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.system.domain.QuoteType; import com.ruoyi.system.service.IServiceGoodsService; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; @@ -79,7 +82,15 @@ public class QuoteMaterialTypeController extends BaseController @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { - return success(quoteMaterialTypeService.selectQuoteMaterialTypeById(id)); + QuoteMaterialType quoteMaterialType =quoteMaterialTypeService.selectQuoteMaterialTypeById(id); + if (quoteMaterialType.getGoodId()!=null){ + String str = quoteMaterialType.getGoodId(); + List stringList = JSON.parseArray(str, String.class); + List intList = stringList.stream().map(Integer::parseInt).collect(Collectors.toList()); + quoteMaterialType.setGoodsintids(intList); + } + + return success(quoteMaterialType); } /** @@ -90,6 +101,15 @@ public class QuoteMaterialTypeController extends BaseController @PostMapping public AjaxResult add(@RequestBody QuoteMaterialType quoteMaterialType) { + if(quoteMaterialType.getGoodsintids().size()>0){ + List intList =quoteMaterialType.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteMaterialType.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + } return toAjax(quoteMaterialTypeService.insertQuoteMaterialType(quoteMaterialType)); } @@ -101,6 +121,18 @@ public class QuoteMaterialTypeController extends BaseController @PutMapping public AjaxResult edit(@RequestBody QuoteMaterialType quoteMaterialType) { + if(quoteMaterialType.getGoodsintids().size()>0){ + System.out.println("#########################"+quoteMaterialType.getGoodsintids()); + List intList =quoteMaterialType.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteMaterialType.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + System.out.println("#########################"+json.replaceAll("\",\"", "\", \"")); + + } return toAjax(quoteMaterialTypeService.updateQuoteMaterialType(quoteMaterialType)); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteTypeController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteTypeController.java index 58fae7e..17ddbc8 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteTypeController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/QuoteTypeController.java @@ -80,6 +80,8 @@ public class QuoteTypeController extends BaseController List list = quoteTypeService.selectQuoteTypeList(quoteType); for(QuoteType quoteTypeData:list){ + System.out.println("#########################"+quoteTypeData.getGoodId()); + System.out.println("#########################"+quoteTypeData.getGoodId().replaceAll("[\\[\\]\"]", "").split(", ")); List idslist = Arrays.asList( quoteTypeData.getGoodId().replaceAll("[\\[\\]\"]", "").split(", ")); quoteTypeData.setServiceName(serviceGoodsService.selectTitlesByIds(idslist)); @@ -135,24 +137,16 @@ public class QuoteTypeController extends BaseController QuoteType quoteType = quoteTypeService.selectQuoteTypeById(id); if (quoteType.getGoodId()!=null){ - String str = "[\"45\", \"47\", \"48\", \"49\", \"5\", \"52\"]"; + String str = quoteType.getGoodId(); List stringList = JSON.parseArray(str, String.class); List intList = stringList.stream().map(Integer::parseInt).collect(Collectors.toList()); quoteType.setGoodsintids(intList); } - return success(quoteType); } -// public static void main(String[] args) { -// String str = "[\"45\", \"47\", \"48\", \"49\", \"5\", \"52\"]"; -// List stringList = JSON.parseArray(str, String.class); -// List intList = stringList.stream().map(Integer::parseInt).collect(Collectors.toList()); -// System.out.println(intList); // 输出: [45, 47, 48, 49, 5, 52] -// } - /** @@ -163,6 +157,16 @@ public class QuoteTypeController extends BaseController @PostMapping public AjaxResult add(@RequestBody QuoteType quoteType) { + + if(quoteType.getGoodsintids().size()>0){ + List intList =quoteType.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteType.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + } return toAjax(quoteTypeService.insertQuoteType(quoteType)); } @@ -174,6 +178,19 @@ public class QuoteTypeController extends BaseController @PutMapping public AjaxResult edit(@RequestBody QuoteType quoteType) { + + if(quoteType.getGoodsintids().size()>0){ + System.out.println("#########################"+quoteType.getGoodsintids()); + List intList =quoteType.getGoodsintids(); + // 先转成字符串List + List strList = intList.stream().map(String::valueOf).collect(Collectors.toList()); + // 再转成json字符串 + String json = JSON.toJSONString(strList); + quoteType.setGoodId(json.replaceAll("\",\"", "\", \"")); + //String withSpace = compact.replaceAll("\",\"", "\", \""); + System.out.println("#########################"+json.replaceAll("\",\"", "\", \"")); + + } return toAjax(quoteTypeService.updateQuoteType(quoteType)); } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteCraft.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteCraft.java index 0c1b9b4..499a3e9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteCraft.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteCraft.java @@ -2,6 +2,7 @@ package com.ruoyi.system.domain; import java.math.BigDecimal; import java.util.Date; +import java.util.List; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -45,6 +46,10 @@ public class QuoteCraft extends BaseEntity @Excel(name = "服务名称") private String ServiceName; + private List goodsintids; + + private List typeintids; + /** $column.columnComment */ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") private Date createdAt; @@ -141,6 +146,22 @@ public class QuoteCraft extends BaseEntity ServiceName = serviceName; } + public List getGoodsintids() { + return goodsintids; + } + + public void setGoodsintids(List goodsintids) { + this.goodsintids = goodsintids; + } + + public List getTypeintids() { + return typeintids; + } + + public void setTypeintids(List typeintids) { + this.typeintids = typeintids; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterial.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterial.java index adcd412..5c982ec 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterial.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterial.java @@ -2,6 +2,7 @@ package com.ruoyi.system.domain; import java.math.BigDecimal; import java.util.Date; +import java.util.List; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -69,6 +70,9 @@ public class QuoteMaterial extends BaseEntity @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") private Date updatedAt; + + private List goodsintids; + public void setId(Long id) { this.id = id; @@ -181,6 +185,14 @@ public class QuoteMaterial extends BaseEntity this.priceMax = priceMax; } + public List getGoodsintids() { + return goodsintids; + } + + public void setGoodsintids(List goodsintids) { + this.goodsintids = goodsintids; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterialType.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterialType.java index 669abac..155ead7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterialType.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/QuoteMaterialType.java @@ -1,6 +1,7 @@ package com.ruoyi.system.domain; import java.util.Date; +import java.util.List; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -48,6 +49,8 @@ public class QuoteMaterialType extends BaseEntity @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") private Date updatedAt; + private List goodsintids; + public void setId(Long id) { this.id = id; @@ -126,6 +129,14 @@ public class QuoteMaterialType extends BaseEntity this.serviceName = serviceName; } + public List getGoodsintids() { + return goodsintids; + } + + public void setGoodsintids(List goodsintids) { + this.goodsintids = goodsintids; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) diff --git a/ruoyi-ui/src/api/system/QuoteCraft.js b/ruoyi-ui/src/api/system/QuoteCraft.js index 8e242ed..e228b9c 100644 --- a/ruoyi-ui/src/api/system/QuoteCraft.js +++ b/ruoyi-ui/src/api/system/QuoteCraft.js @@ -16,6 +16,16 @@ export function getQuoteCraft(id) { method: 'get' }) } +// 查询项目报价--服务工艺详细 +export function selectQuoteTypeList(ids) { + return request({ + url: '/system/QuoteCraft/selectQuoteTypeList', + method: 'post', + data: ids + }) +} + + // 新增项目报价--服务工艺 export function addQuoteCraft(data) { diff --git a/ruoyi-ui/src/components/Sku/sku.vue b/ruoyi-ui/src/components/Sku/sku.vue index 0df4d07..ffb7d80 100644 --- a/ruoyi-ui/src/components/Sku/sku.vue +++ b/ruoyi-ui/src/components/Sku/sku.vue @@ -1,14 +1,15 @@ @@ -155,7 +155,6 @@ export default { // 2. 组装 sku // 取所有规格名 const specNames = Object.keys(attrs); - console.log(specNames,this.sku) // 每个sku对象包含所有规格名及其值、图片、价格、库存等字段 const skuList = (this.sku || []).map(row => { @@ -284,7 +283,7 @@ export default { diff --git a/ruoyi-ui/src/components/Sku/skufrom.vue b/ruoyi-ui/src/components/Sku/skufrom.vue index 7716037..e07b746 100644 --- a/ruoyi-ui/src/components/Sku/skufrom.vue +++ b/ruoyi-ui/src/components/Sku/skufrom.vue @@ -44,6 +44,7 @@ :value="item.name" style="width: 200px" clearable + @change="onAttributeNameChange(index, $event, item.name)" > @@ -81,6 +82,8 @@ v-model="scope.row.name" style="width: 150px" clearable + @focus="onAttributeNameFocus(scope)" + @blur="onAttributeNameBlur(scope.$index, $event, scope)" > @@ -104,7 +107,7 @@ - + + + +
+ + 批量设置价格 + + 批量设置库存 +
+
+
@@ -320,6 +342,9 @@ export default { skuData: [], }, batch: {}, + attributeNameMap: {}, + batchSetPrice: '', + batchSetStock: '', }; }, computed: { @@ -389,6 +414,12 @@ export default { watch: { myAttribute: { handler() { + // 保证每次 myAttribute 变化都同步 _oldName 字段 + this.myAttribute.forEach((attr, idx) => { + if (!Object.prototype.hasOwnProperty.call(attr, '_oldName')) { + this.$set(this.myAttribute[idx], '_oldName', attr.name); + } + }); if (!this.isInit) { // 更新父组件 this.$emit("update:attribute", this.emitAttribute); @@ -453,39 +484,89 @@ export default { }, mounted() { !this.async && this.init(); + // 初始化 _oldName + this.myAttribute.forEach((attr, idx) => { + this.$set(this.myAttribute[idx], '_oldName', attr.name); + }); }, methods: { delitem(row, index) { - console.log(row, index); - row.item.splice(index, 1); - // row.item[index].checked=false; - // 删除规格 + this.$confirm('确认删除该规格值吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + row.item.splice(index, 1); + this.$message({ + type: 'success', + message: '删除成功!' + }); + }).catch(() => { + this.$message({ + type: 'info', + message: '已取消删除' + }); + }); }, - delsuk(index){ - this.myAttribute.splice(index,1) + delsuk(index) { + this.$confirm('确认删除该规格吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + this.myAttribute.splice(index, 1); + this.$message({ + type: 'success', + message: '删除成功!' + }); + }).catch(() => { + this.$message({ + type: 'info', + message: '已取消删除' + }); + }); }, addlist() { - if (this.inputname) { - const flag = this.myAttribute.find((item) => { - return item.name == this.inputname; + if (!this.inputname.trim()) { + this.$message({ + type: "warning", + message: "请填写属性名称", }); - if (!flag) { - this.myAttribute.push({ name: this.inputname, item: [] }); - this.inputname = ""; - } else { - this.$message({ - type: "warning", - message: "请勿添加相同规格", - }); - } - + return; } - else{ - this.$message({ - type: "warning", - message: "请填属性名称", - }); - } + + if (this.inputname.includes(this.separator)) { + this.$message({ + type: "warning", + message: `属性名称不允许包含「${this.separator}」字符`, + }); + return; + } + + const flag = this.myAttribute.find((item) => { + return item.name === this.inputname; + }); + + if (flag) { + this.$message({ + type: "warning", + message: "请勿添加相同规格", + }); + return; + } + + this.myAttribute.push({ + name: this.inputname.trim(), + item: [], + canAddAttribute: true, + addAttribute: "", + _oldName: this.inputname.trim() + }); + this.inputname = ""; + this.$message({ + type: "success", + message: "添加成功", + }); }, init() { this.$nextTick(() => { @@ -583,13 +664,38 @@ export default { if (index !== this.attribute.length - 1) { this.combinationAttribute(index + 1, dataTemp); } else { - if (!this.isInit || this.async) { - // 将原有的 sku 数据和新的 sku 数据比较,相同的 sku 则把原有的 sku 数据覆盖到新的 sku 数据里 - for (let i = 0; i < this.form.skuData.length; i++) { - for (let j = 0; j < dataTemp.length; j++) { - if (this.form.skuData[i].sku === dataTemp[j].sku) { - dataTemp[j] = this.form.skuData[i]; + // 1. 构建老skuData的map(用老的sku字符串做key) + const oldSkuMap = {}; + this.form.skuData.forEach(row => { + oldSkuMap[row.sku] = row; + }); + // 2. 用新组合的sku去找老数据 + for (let j = 0; j < dataTemp.length; j++) { + // 先尝试用新sku找 + if (oldSkuMap[dataTemp[j].sku]) { + // 迁移所有结构字段 + this.structure.forEach((v) => { + if (!(v.type == "slot" && v.skuProperty == false)) { + dataTemp[j][v.name] = oldSkuMap[dataTemp[j].sku][v.name]; } + }); + } else { + // 尝试用"老属性名组合"找 + // 1. 拿到新组合的各个规格 + const skuArr = dataTemp[j].sku.split(this.separator); + // 2. 拿到老的属性名顺序 + const oldAttrNames = Object.keys(this.form.skuData[0] || {}).filter(k => !this.structure.some(s => s.name === k) && k !== 'sku'); + // 3. 拼成老sku + let oldSku = ''; + if (oldAttrNames.length === skuArr.length) { + oldSku = skuArr.join(this.separator); + } + if (oldSku && oldSkuMap[oldSku]) { + this.structure.forEach((v) => { + if (!(v.type == "slot" && v.skuProperty == false)) { + dataTemp[j][v.name] = oldSkuMap[oldSku][v.name]; + } + }); } } } @@ -626,7 +732,18 @@ export default { } }, onBatchSet(type) { - if (this.batch[type] != "") { + // 支持批量设置价格和库存 + if (type === 'price' && this.batchSetPrice !== '') { + this.form.skuData.forEach((v) => { + v.price = this.batchSetPrice; + }); + this.batchSetPrice = ''; + } else if (type === 'stock' && this.batchSetStock !== '') { + this.form.skuData.forEach((v) => { + v.stock = this.batchSetStock; + }); + this.batchSetStock = ''; + } else if (this.batch[type] != "") { this.form.skuData.forEach((v) => { v[type] = this.batch[type]; }); @@ -638,15 +755,52 @@ export default { // 自定义输入框验证,通过调用 structure 里的 validate 方法实现,重点是 callback 要带过去 customizeValidate(rule, value, callback) { let [model, index, name] = rule.field.split("."); + const row = this.form[model][index]; + + // 检查是否为空 + if (value === '' || value === null || value === undefined) { + callback(new Error(`${this.structure.find(s => s.name === name).label}不能为空`)); + return; + } + + // 检查数字类型 + if (name === 'price' || name === 'stock') { + if (isNaN(value) || value < 0) { + callback(new Error(`${this.structure.find(s => s.name === name).label}必须是非负数`)); + return; + } + } + + // 调用自定义验证 this.structure.forEach((v) => { - if (v.name == name) { + if (v.name === name && v.validate) { v.validate(this.form[model], index, callback); } }); + + callback(); }, // sku 表单验证 validate(callback) { this.$refs["form"].validate((valid) => { + if (!valid) { + // 查找未填写的字段,提示具体行和字段 + let errorMsg = ''; + const formItems = this.$refs.form.fields || []; + formItems.forEach(item => { + if (item.validateState === 'error') { + // skuData.0.price 解析出行号和字段 + const match = item.prop && item.prop.match(/skuData\.(\d+)\.(\w+)/); + if (match) { + const rowIdx = Number(match[1]) + 1; + const colName = this.structure.find(s => s.name === match[2]); + errorMsg += `第${rowIdx}行【${colName ? colName.label : match[2]}】未填写,`; + } + } + }); + if (!errorMsg) errorMsg = '请完整填写所有必填项!'; + this.$message.error(errorMsg.replace(/,$/, '')); + } callback(valid); }); }, @@ -674,7 +828,45 @@ export default { }, getArray(){ return this.myAttribute - } + }, + onAttributeNameChange(index, newName, oldName) { + if (!newName || newName === oldName) return; + // 1. 检查新名字是否重复 + if (this.myAttribute.some((attr, idx) => idx !== index && attr.name === newName)) { + this.$message.warning('属性名不能重复'); + this.myAttribute[index].name = oldName; + return; + } + // 2. 替换 skuData 里的 key + this.form.skuData.forEach(row => { + if (row[oldName] !== undefined) { + row[newName] = row[oldName]; + delete row[oldName]; + } + }); + // 3. 触发更新 + this.$forceUpdate(); + }, + onAttributeNameFocus(scope) { + // 记录旧名 + scope.row._oldName = scope.row.name; + }, + onAttributeNameBlur(index, event, scope) { + const newName = event.target.value.trim(); + const oldName = scope.row._oldName || ''; + if (!newName || newName === oldName) return; + // 检查新名字是否重复 + if (this.myAttribute.some((attr, idx) => idx !== index && attr.name === newName)) { + this.$message.warning('属性名不能重复'); + this.myAttribute[index].name = oldName; + return; + } + // 记录映射 + this.attributeNameMap[oldName] = newName; + this.myAttribute[index].name = newName; + this.$set(this.myAttribute[index], '_oldName', newName); + this.$forceUpdate(); + }, }, }; @@ -712,11 +904,42 @@ export default { border: 1px solid #ebeef5; border-bottom: 0; margin-bottom: 20px; + background: #fafbfc; + border-radius: 6px; + overflow: hidden; } } .sku-name { text-align: right; } + .batch-set-card { + margin: 24px 0 8px 0; + background: #f8fafd; + border-radius: 8px; + border: 1px solid #e6e8eb; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.03); + .batch-set-row { + display: flex; + align-items: center; + gap: 18px; + padding: 12px 0 4px 0; + } + .batch-input { + width: 160px; + margin-right: 0; + } + .batch-btn { + min-width: 110px; + font-weight: bold; + letter-spacing: 1px; + } + } + .sku-divider { + height: 1px; + background: #eaeaea; + margin: 18px 0 8px 0; + border-radius: 1px; + } .batch-set { width: 100%; margin-top: 5px; @@ -725,6 +948,14 @@ export default { line-height: initial; ::v-deep .el-input__inner { text-align: center; + border-radius: 4px; + background: #fff; + border: 1px solid #dcdfe6; + transition: border-color 0.2s; + &:focus { + border-color: #409eff; + box-shadow: 0 0 0 2px rgba(64,158,255,0.08); + } } ::v-deep .el-table__append-wrapper { overflow: initial; @@ -748,6 +979,39 @@ export default { content: "*"; color: #f56c6c; } + ::v-deep .el-table__body .el-table__row td:nth-child(5) { + text-align: center; + vertical-align: middle; + } + ::v-deep .el-upload { + display: flex; + justify-content: center; + align-items: center; + } + } + + .sku-check { + padding: 10px 10px 0 10px; + .el-button.el-button--mini{ + padding: 7px; + font-size: 12px; + } + .el-table, + .el-card { + font-size: 13px; + } + .el-input, + + .el-card { + margin-bottom: 8px; + border-radius: 6px; + .el-card__header, .el-card__body { + padding: 8px 12px; + } + } + .el-table__row { + height: 32px; + } } } diff --git a/ruoyi-ui/src/views/system/QuoteCraft/index.vue b/ruoyi-ui/src/views/system/QuoteCraft/index.vue index 1a77276..e23b1b2 100644 --- a/ruoyi-ui/src/views/system/QuoteCraft/index.vue +++ b/ruoyi-ui/src/views/system/QuoteCraft/index.vue @@ -11,7 +11,7 @@ /> - + - - - - + + + + + + - - + + + + - + - - - - - - - - -