|
@@ -28,16 +28,21 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
}
|
|
|
|
|
|
// 获取订单项信息
|
|
|
- $sql = "SELECT oi.*, p.ProductName, pc.name as category_name
|
|
|
+ $sql = "SELECT oi.*, p.ProductName, pc.name as category_name,
|
|
|
+ ps.id as product_spec_id, ps.spec_name, ps.spec_value,
|
|
|
+ oi.specification_id /* 显式获取数据库中的specification_id */
|
|
|
FROM order_items oi
|
|
|
LEFT JOIN products p ON oi.product_id = p.id
|
|
|
LEFT JOIN product_categories pc ON p.category_id = pc.id
|
|
|
+ LEFT JOIN product_specifications ps ON oi.specification_id = ps.id
|
|
|
WHERE oi.order_id = $id";
|
|
|
|
|
|
$itemsResult = mysqli_query($conn, $sql);
|
|
|
|
|
|
$orderItems = [];
|
|
|
while ($itemRow = mysqli_fetch_assoc($itemsResult)) {
|
|
|
+ // 调试输出
|
|
|
+ error_log("订单项数据: " . print_r($itemRow, true));
|
|
|
$orderItems[] = $itemRow;
|
|
|
}
|
|
|
} else {
|
|
@@ -295,11 +300,11 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
|
|
|
<div class="product-list-header" style="display: flex; background-color: #eee; padding: 8px 15px; margin-bottom: 10px; border-radius: 4px; font-weight: bold; color: #555; font-size: 13px; gap: 8px;">
|
|
|
<div style="flex: 2; min-width: 200px;">产品</div>
|
|
|
+ <div style="flex: 2; min-width: 200px;">规格</div>
|
|
|
<div style="flex: 1; min-width: 80px;">数量</div>
|
|
|
<div style="flex: 0.5; min-width: 60px;">单位</div>
|
|
|
<div style="flex: 1; min-width: 100px;">单价</div>
|
|
|
<div style="flex: 1; min-width: 100px;">总价</div>
|
|
|
- <div style="flex: 2; min-width: 200px;">备注</div>
|
|
|
</div>
|
|
|
|
|
|
<div id="product-container">
|
|
@@ -310,6 +315,8 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
<div class="row-section product-info">
|
|
|
<div class="row-section-label"><span>产品</span></div>
|
|
|
<input type="hidden" name="items[<?= $index ?>][product_id]" class="product-id-input" value="<?= $item['product_id'] ?>">
|
|
|
+ <input type="text" class="product-search" placeholder="输入产品名称搜索..." style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px; display: none;">
|
|
|
+ <div class="productlist" style="width: 100%; max-height: 200px;"><ul></ul></div>
|
|
|
<div class="selected-product-info" style="cursor: pointer;" title="点击重新选择产品">
|
|
|
<?= htmlspecialcharsFix($item['ProductName'] ?? '') ?>
|
|
|
<?php if (!empty($item['category_name'])): ?>
|
|
@@ -318,6 +325,20 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <div class="row-section product-spec">
|
|
|
+ <div class="row-section-label"><span>规格</span></div>
|
|
|
+ <input type="hidden" name="items[<?= $index ?>][spec_id]" class="spec-id-input" value="<?= $item['specification_id'] ?? 0 ?>">
|
|
|
+ <!-- 规格选择框将在加载产品时填充 -->
|
|
|
+ <select class="spec-select" name="items[<?= $index ?>][spec_select]" style="display: none;">
|
|
|
+ <option value="">请选择规格</option>
|
|
|
+ </select>
|
|
|
+ <div class="spec-info" style="cursor: pointer;" title="点击修改规格">
|
|
|
+ <?php if (!empty($item['spec_name'])): ?>
|
|
|
+ <?= htmlspecialcharsFix($item['spec_name']) ?>: <?= htmlspecialcharsFix($item['spec_value'] ?? '') ?>
|
|
|
+ <?php endif; ?>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div class="row-section product-quantity">
|
|
|
<div class="row-section-label"><span>数量</span></div>
|
|
|
<input type="number" name="items[<?= $index ?>][quantity]" value="<?= $item['quantity'] ?>" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
|
|
@@ -325,7 +346,8 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
|
|
|
<div class="row-section product-unit">
|
|
|
<div class="row-section-label"><span>单位</span></div>
|
|
|
- <input type="text" name="items[<?= $index ?>][unit]" value="<?= htmlspecialcharsFix($item['unit']) ?>" class="unit-input">
|
|
|
+ <span class="unit-label"><?= htmlspecialcharsFix($item['unit']) ?></span>
|
|
|
+ <input type="hidden" name="items[<?= $index ?>][unit]" value="<?= htmlspecialcharsFix($item['unit']) ?>" class="unit-input">
|
|
|
</div>
|
|
|
|
|
|
<div class="row-section product-price">
|
|
@@ -335,18 +357,14 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
|
|
|
<div class="row-section product-total">
|
|
|
<div class="row-section-label"><span>总价</span></div>
|
|
|
- <span class="total-price-display"><?= number_format($item['total_price'], 2) ?></span>
|
|
|
+ <span class="total-price-display" style="display: inline-block; background-color: #f0f0f0; border: 1px solid #ddd; padding: 2px 8px; min-width: 60px; text-align: right;"><?= number_format($item['total_price'], 2) ?></span>
|
|
|
<input type="hidden" name="items[<?= $index ?>][total_price]" value="<?= $item['total_price'] ?>" class="total-price-input">
|
|
|
</div>
|
|
|
|
|
|
- <div class="row-section product-notes" style="flex: 2; min-width: 200px;">
|
|
|
- <div class="row-section-label"><span>备注</span></div>
|
|
|
- <input type="text" name="items[<?= $index ?>][notes]" value="<?= htmlspecialcharsFix($item['notes']) ?>" style="width: 100%;">
|
|
|
-
|
|
|
- <!-- 保留隐藏的折扣字段以便后端兼容 -->
|
|
|
- <input type="hidden" name="items[<?= $index ?>][discount_amount]" value="0" class="discount-amount-input">
|
|
|
- <input type="hidden" name="items[<?= $index ?>][discount_percent]" value="0" class="discount-percent-input">
|
|
|
- </div>
|
|
|
+ <!-- 保留隐藏的折扣字段以便后端兼容 -->
|
|
|
+ <input type="hidden" name="items[<?= $index ?>][discount_amount]" value="0" class="discount-amount-input">
|
|
|
+ <input type="hidden" name="items[<?= $index ?>][discount_percent]" value="0" class="discount-percent-input">
|
|
|
+ <input type="hidden" name="items[<?= $index ?>][notes]" value="<?= htmlspecialcharsFix($item['notes'] ?? '') ?>">
|
|
|
</div>
|
|
|
<?php endforeach; ?>
|
|
|
<!-- 产品行将通过搜索添加 -->
|
|
@@ -394,6 +412,19 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
// 初始化无产品消息
|
|
|
updateNoProductsMessage();
|
|
|
|
|
|
+ // 初始化现有产品的规格选择
|
|
|
+ $('.product-row').each(function() {
|
|
|
+ var row = $(this);
|
|
|
+ var productId = row.find('.product-id-input').val();
|
|
|
+ var specId = row.find('.spec-id-input').val();
|
|
|
+ console.log("初始化行 - 行索引:", row.data('index'), "产品ID:", productId, "规格ID:", specId);
|
|
|
+
|
|
|
+ if (productId) {
|
|
|
+ // 加载产品规格
|
|
|
+ getProductSpecifications(productId, row);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
// 添加产品行按钮点击事件
|
|
|
$('#add-product-btn').on('click', function() {
|
|
|
addEmptyProductRow();
|
|
@@ -476,16 +507,30 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
$('.selected-customer-info').text(customerName);
|
|
|
$('.customerlist').hide();
|
|
|
});
|
|
|
+
|
|
|
+ // 产品搜索框聚焦时显示搜索提示
|
|
|
+ $(document).on('focus', '.product-search', function() {
|
|
|
+ // 隐藏所有已打开的产品搜索列表
|
|
|
+ $('.productlist').hide();
|
|
|
+
|
|
|
+ // 当前搜索框的值
|
|
|
+ var searchTerm = $(this).val().trim();
|
|
|
+ if (searchTerm.length >= 2) {
|
|
|
+ // 找到当前行的产品列表并显示
|
|
|
+ $(this).siblings('.productlist').show();
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // 单一产品搜索功能 - 使用防抖动以减少请求数量
|
|
|
- var productSearchTimeout = null;
|
|
|
- $(document).on('keyup', '#product-search-single', function() {
|
|
|
+ // 产品搜索功能 - 行内搜索
|
|
|
+ var productSearchTimeouts = {};
|
|
|
+ $(document).on('keyup', '.product-search', function() {
|
|
|
var $this = $(this);
|
|
|
+ var rowIndex = $this.closest('.product-row').data('index');
|
|
|
var searchTerm = $this.val().trim();
|
|
|
- var productList = $('#product-list-single');
|
|
|
+ var productList = $this.siblings('.productlist');
|
|
|
|
|
|
// 清除之前的超时
|
|
|
- clearTimeout(productSearchTimeout);
|
|
|
+ clearTimeout(productSearchTimeouts[rowIndex]);
|
|
|
|
|
|
// 隐藏之前的结果
|
|
|
productList.hide();
|
|
@@ -496,7 +541,7 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
}
|
|
|
|
|
|
// 设置一个300毫秒的超时,以减少请求数量
|
|
|
- productSearchTimeout = setTimeout(function() {
|
|
|
+ productSearchTimeouts[rowIndex] = setTimeout(function() {
|
|
|
$.ajax({
|
|
|
url: 'get_product_info.php',
|
|
|
type: 'GET',
|
|
@@ -523,51 +568,151 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
}, 300);
|
|
|
});
|
|
|
|
|
|
- // 点击选择产品 - 从单一搜索框
|
|
|
- $(document).on('click', '#product-list-single li', function() {
|
|
|
+ // 点击选择产品 - 行内搜索结果
|
|
|
+ $(document).on('click', '.productlist li', function() {
|
|
|
var $this = $(this);
|
|
|
var productId = $this.data('id');
|
|
|
var productName = $this.text(); // 这会包含分类名,需要清理
|
|
|
var categoryTag = $this.find('.category-tag').text();
|
|
|
+ var row = $this.closest('.product-row');
|
|
|
|
|
|
// 清理产品名称,移除分类信息
|
|
|
if (categoryTag) {
|
|
|
productName = productName.replace(categoryTag, '').trim();
|
|
|
}
|
|
|
|
|
|
- // 检查产品是否已经添加
|
|
|
- var isDuplicate = false;
|
|
|
- $('.product-id-input').each(function() {
|
|
|
- if ($(this).val() == productId) {
|
|
|
- isDuplicate = true;
|
|
|
- return false; // 跳出循环
|
|
|
- }
|
|
|
- });
|
|
|
+ // 设置产品ID和名称
|
|
|
+ row.find('.product-id-input').val(productId);
|
|
|
+ row.find('.product-search').hide();
|
|
|
|
|
|
- if (isDuplicate) {
|
|
|
- alert('该产品已添加,不能重复添加');
|
|
|
- $('#product-search-single').val('');
|
|
|
- $('#product-list-single').hide();
|
|
|
- return;
|
|
|
+ // 显示包含分类的完整产品信息
|
|
|
+ var displayName = productName;
|
|
|
+ if (categoryTag) {
|
|
|
+ displayName += ' <span class="category-tag">' + categoryTag + '</span>';
|
|
|
}
|
|
|
+ row.find('.selected-product-info').html(displayName).show();
|
|
|
|
|
|
- // 添加产品行
|
|
|
- addProductRowWithProduct(productId, productName, categoryTag);
|
|
|
+ // 隐藏产品搜索结果
|
|
|
+ row.find('.productlist').hide();
|
|
|
|
|
|
- // 清空搜索框并隐藏结果
|
|
|
- $('#product-search-single').val('');
|
|
|
- $('#product-list-single').hide();
|
|
|
+ // 获取产品规格信息
|
|
|
+ getProductSpecifications(productId, row);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 规格选择改变事件
|
|
|
+ $(document).on('change', '.spec-select', function() {
|
|
|
+ var $this = $(this);
|
|
|
+ var row = $this.closest('.product-row');
|
|
|
+ var specId = $this.val();
|
|
|
+ var specData = $this.find('option:selected').data();
|
|
|
+
|
|
|
+ if (specId) {
|
|
|
+ // 检查是否已存在相同的产品规格组合
|
|
|
+ var isDuplicate = false;
|
|
|
+ $('.spec-select').not($this).each(function() {
|
|
|
+ if ($(this).val() == specId) {
|
|
|
+ isDuplicate = true;
|
|
|
+ return false; // 跳出循环
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (isDuplicate) {
|
|
|
+ alert('该产品规格已添加,不能重复添加');
|
|
|
+ $this.val(''); // 重置选择
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置规格ID到隐藏字段
|
|
|
+ row.find('.spec-id-input').val(specId);
|
|
|
+
|
|
|
+ // 获取选中项的文本内容作为显示信息
|
|
|
+ var displayText = $this.find('option:selected').text();
|
|
|
+ row.find('.spec-info').html(displayText).show();
|
|
|
+
|
|
|
+ // 隐藏下拉框
|
|
|
+ $this.hide();
|
|
|
+
|
|
|
+ // 存储规格价格作为最低价格限制
|
|
|
+ var minPrice = specData.price || 0;
|
|
|
+ var priceInput = row.find('.price-input');
|
|
|
+ priceInput.attr('data-min-price', minPrice);
|
|
|
+ if (minPrice > 0) {
|
|
|
+ priceInput.attr('placeholder', '输入单价');
|
|
|
+ } else {
|
|
|
+ priceInput.attr('placeholder', '输入单价');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置最小订购数量
|
|
|
+ var minQty = specData.minQty || 1;
|
|
|
+ var qtyInput = row.find('.quantity-input');
|
|
|
+ if (parseInt(qtyInput.val()) < minQty) {
|
|
|
+ qtyInput.val(minQty);
|
|
|
+ }
|
|
|
+ qtyInput.attr('min', minQty);
|
|
|
+
|
|
|
+ // 重新计算总价
|
|
|
+ calculateItemTotal(row.find('.price-input')[0]);
|
|
|
+ } else {
|
|
|
+ // 清除规格相关信息
|
|
|
+ row.find('.spec-id-input').val('');
|
|
|
+ row.find('.price-input').attr('data-min-price', '0').attr('placeholder', '输入单价');
|
|
|
+ row.find('.spec-info').html('').hide();
|
|
|
+ calculateItemTotal(row.find('.price-input')[0]);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
// 点击其他地方隐藏下拉列表
|
|
|
$(document).on('click', function(e) {
|
|
|
- if (!$(e.target).closest('#product-search-single').length) {
|
|
|
- $('#product-list-single').hide();
|
|
|
+ if (!$(e.target).closest('.product-search').length && !$(e.target).closest('.productlist').length) {
|
|
|
+ $('.productlist').hide();
|
|
|
}
|
|
|
if (!$(e.target).closest('.customerinput').length) {
|
|
|
$('.customerlist').hide();
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ // 点击已选产品名显示的标签时,切换回搜索模式
|
|
|
+ $(document).on('click dblclick', '.selected-product-info', function() {
|
|
|
+ var row = $(this).closest('.product-row');
|
|
|
+ var productId = row.find('.product-id-input').val();
|
|
|
+
|
|
|
+ // 只有当已经选择了产品时才允许重新选择
|
|
|
+ if (productId) {
|
|
|
+ if (confirm('确定要重新选择产品吗?这将清除当前选择的产品及其规格信息。')) {
|
|
|
+ // 清空产品ID和选择的规格
|
|
|
+ row.find('.product-id-input').val('');
|
|
|
+ row.find('.spec-id-input').val('');
|
|
|
+
|
|
|
+ // 隐藏产品信息,显示搜索框
|
|
|
+ $(this).hide();
|
|
|
+ row.find('.product-search').val('').show();
|
|
|
+
|
|
|
+ // 隐藏并清空规格选择
|
|
|
+ row.find('.spec-select').hide().empty();
|
|
|
+ row.find('.spec-info').html('');
|
|
|
+
|
|
|
+ // 清除单位信息
|
|
|
+ row.find('.unit-input').val('');
|
|
|
+ row.find('.unit-label').text('');
|
|
|
+
|
|
|
+ // 清除价格信息并重新计算总额
|
|
|
+ row.find('.price-input').val('');
|
|
|
+ calculateItemTotal(row.find('.price-input')[0]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 点击规格信息时显示规格选择下拉框
|
|
|
+ $(document).on('click', '.spec-info', function() {
|
|
|
+ var row = $(this).closest('.product-row');
|
|
|
+ var specSelect = row.find('.spec-select');
|
|
|
+
|
|
|
+ if (specSelect.find('option').length > 1) {
|
|
|
+ // 隐藏规格信息,显示规格选择下拉框
|
|
|
+ $(this).hide();
|
|
|
+ specSelect.show().focus();
|
|
|
+ }
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
function addEmptyProductRow() {
|
|
@@ -583,6 +728,15 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
<div class="selected-product-info" style="cursor: pointer; display: none;" title="点击重新选择产品"></div>
|
|
|
</div>
|
|
|
|
|
|
+ <div class="row-section product-spec">
|
|
|
+ <div class="row-section-label"><span>规格</span></div>
|
|
|
+ <input type="hidden" name="items[${productIndex}][spec_id]" class="spec-id-input" value="">
|
|
|
+ <select class="spec-select" name="items[${productIndex}][spec_select]" style="display: none;">
|
|
|
+ <option value="">请选择规格</option>
|
|
|
+ </select>
|
|
|
+ <div class="spec-info" style="cursor: pointer;" title="点击修改规格"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div class="row-section product-quantity">
|
|
|
<div class="row-section-label"><span>数量</span></div>
|
|
|
<input type="number" name="items[${productIndex}][quantity]" value="1" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
|
|
@@ -590,7 +744,8 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
|
|
|
<div class="row-section product-unit">
|
|
|
<div class="row-section-label"><span>单位</span></div>
|
|
|
- <input type="text" name="items[${productIndex}][unit]" value="" class="unit-input">
|
|
|
+ <span class="unit-label" style="display: inline-block; padding: 2px 5px; min-width: 30px;"></span>
|
|
|
+ <input type="hidden" name="items[${productIndex}][unit]" class="unit-input" value="">
|
|
|
</div>
|
|
|
|
|
|
<div class="row-section product-price">
|
|
@@ -600,18 +755,14 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
|
|
|
<div class="row-section product-total">
|
|
|
<div class="row-section-label"><span>总价</span></div>
|
|
|
- <span class="total-price-display">0.00</span>
|
|
|
+ <span class="total-price-display" style="display: inline-block; background-color: #f0f0f0; border: 1px solid #ddd; padding: 2px 8px; min-width: 60px; text-align: right;">0.00</span>
|
|
|
<input type="hidden" name="items[${productIndex}][total_price]" value="0.00" class="total-price-input">
|
|
|
</div>
|
|
|
|
|
|
- <div class="row-section product-notes" style="flex: 2; min-width: 200px;">
|
|
|
- <div class="row-section-label"><span>备注</span></div>
|
|
|
- <input type="text" name="items[${productIndex}][notes]" value="" style="width: 100%;">
|
|
|
-
|
|
|
- <!-- 保留隐藏的折扣字段以便后端兼容 -->
|
|
|
- <input type="hidden" name="items[${productIndex}][discount_amount]" value="0" class="discount-amount-input">
|
|
|
- <input type="hidden" name="items[${productIndex}][discount_percent]" value="0" class="discount-percent-input">
|
|
|
- </div>
|
|
|
+ <!-- 保留隐藏的字段以便后端兼容 -->
|
|
|
+ <input type="hidden" name="items[${productIndex}][discount_amount]" value="0" class="discount-amount-input">
|
|
|
+ <input type="hidden" name="items[${productIndex}][discount_percent]" value="0" class="discount-percent-input">
|
|
|
+ <input type="hidden" name="items[${productIndex}][notes]" value="">
|
|
|
</div>
|
|
|
`;
|
|
|
|
|
@@ -633,10 +784,11 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
if (categoryTag) {
|
|
|
displayName += ' <span class="category-tag">' + categoryTag + '</span>';
|
|
|
}
|
|
|
- row.find('.selected-product-info').html(displayName);
|
|
|
+ row.find('.selected-product-info').html(displayName).show();
|
|
|
+ row.find('.product-search').hide();
|
|
|
|
|
|
- // 获取产品信息
|
|
|
- getProductInfo(productId, row);
|
|
|
+ // 获取产品规格信息
|
|
|
+ getProductSpecifications(productId, row);
|
|
|
|
|
|
// 更新无产品消息显示
|
|
|
updateNoProductsMessage();
|
|
@@ -656,6 +808,128 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
productIndex = $('.product-row').length;
|
|
|
}
|
|
|
|
|
|
+ function getProductSpecifications(productId, row) {
|
|
|
+ if (!productId) return;
|
|
|
+
|
|
|
+ // 获取当前选中的规格ID(如果有的话)
|
|
|
+ var currentSpecId = row.find('.spec-id-input').val();
|
|
|
+ console.log("加载规格 - 产品ID:", productId, "当前规格ID:", currentSpecId);
|
|
|
+
|
|
|
+ $.ajax({
|
|
|
+ url: 'get_product_info.php',
|
|
|
+ type: 'GET',
|
|
|
+ data: {product_id: productId},
|
|
|
+ dataType: 'json',
|
|
|
+ success: function(data) {
|
|
|
+ if (data && data.product && data.specifications) {
|
|
|
+ console.log("获取到规格数据:", data.specifications);
|
|
|
+ // 设置单位信息
|
|
|
+ if (data.product.unit) {
|
|
|
+ row.find('.unit-input').val(data.product.unit);
|
|
|
+ row.find('.unit-label').text(data.product.unit);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理规格信息
|
|
|
+ var specifications = data.specifications;
|
|
|
+ console.log("获取到的规格列表详情:", JSON.stringify(specifications)); // 打印完整的规格对象
|
|
|
+ if (specifications.length === 0) {
|
|
|
+ // 如果是编辑现有产品,不显示警告
|
|
|
+ if (!currentSpecId) {
|
|
|
+ alert('此产品没有规格信息,请添加规格后再选择');
|
|
|
+ // 重置产品选择
|
|
|
+ row.find('.product-id-input').val('');
|
|
|
+ row.find('.selected-product-info').hide();
|
|
|
+ row.find('.product-search').val('').show();
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 填充规格选择下拉框
|
|
|
+ var specSelect = row.find('.spec-select');
|
|
|
+ specSelect.empty();
|
|
|
+ specSelect.append('<option value="">请选择规格</option>');
|
|
|
+
|
|
|
+ var foundSelectedSpec = false;
|
|
|
+
|
|
|
+ $.each(specifications, function(i, spec) {
|
|
|
+ var displayText = spec.spec_name + ': ' + spec.spec_value;
|
|
|
+ if (spec.price) {
|
|
|
+ displayText += ' (¥' + spec.price + ')';
|
|
|
+ }
|
|
|
+
|
|
|
+ var option = $('<option></option>')
|
|
|
+ .attr('value', spec.id)
|
|
|
+ .text(displayText)
|
|
|
+ .data('price', spec.price)
|
|
|
+ .data('minQty', spec.min_order_quantity)
|
|
|
+ .data('code', spec.spec_code);
|
|
|
+
|
|
|
+ // 如果是当前选中的规格,设置selected属性
|
|
|
+ if (currentSpecId && parseInt(spec.id) === parseInt(currentSpecId)) {
|
|
|
+ console.log("找到匹配的规格 - 规格ID:", spec.id, "当前规格ID:", currentSpecId,
|
|
|
+ "规格名称:", spec.spec_name, "规格值:", spec.spec_value);
|
|
|
+ option.prop('selected', true);
|
|
|
+ foundSelectedSpec = true;
|
|
|
+
|
|
|
+ // 更新规格信息显示
|
|
|
+ row.find('.spec-info').html(displayText);
|
|
|
+
|
|
|
+ // 设置参考价格
|
|
|
+ var priceInput = row.find('.price-input');
|
|
|
+ priceInput.attr('data-min-price', spec.price || 0);
|
|
|
+ } else {
|
|
|
+ console.log("规格不匹配 - 规格ID:", spec.id, "当前规格ID:", currentSpecId,
|
|
|
+ "类型:", typeof spec.id, typeof currentSpecId);
|
|
|
+ }
|
|
|
+
|
|
|
+ specSelect.append(option);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 显示规格选择下拉框并隐藏spec-info
|
|
|
+ if (!currentSpecId || !foundSelectedSpec) {
|
|
|
+ // 如果没有选中规格,显示下拉框
|
|
|
+ specSelect.show();
|
|
|
+ row.find('.spec-info').hide();
|
|
|
+ } else {
|
|
|
+ // 如果已选中规格,显示规格信息
|
|
|
+ specSelect.hide();
|
|
|
+ row.find('.spec-info').show();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果在规格列表中找不到已选择的规格
|
|
|
+ if (currentSpecId && !foundSelectedSpec) {
|
|
|
+ console.log("在规格列表中找不到已选择的规格ID:", currentSpecId);
|
|
|
+ // 不清除规格ID,保留数据库中的值
|
|
|
+ // row.find('.spec-id-input').val('');
|
|
|
+
|
|
|
+ // 隐藏规格选择下拉框,保留现有规格信息
|
|
|
+ specSelect.hide();
|
|
|
+ row.find('.spec-info').show();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果是编辑现有产品,不显示警告
|
|
|
+ if (!currentSpecId) {
|
|
|
+ alert('获取产品规格失败');
|
|
|
+ // 重置产品选择
|
|
|
+ row.find('.product-id-input').val('');
|
|
|
+ row.find('.selected-product-info').hide();
|
|
|
+ row.find('.product-search').val('').show();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ error: function() {
|
|
|
+ // 如果是编辑现有产品,不显示警告
|
|
|
+ if (!currentSpecId) {
|
|
|
+ alert('获取产品规格失败,请重试');
|
|
|
+ // 重置产品选择
|
|
|
+ row.find('.product-id-input').val('');
|
|
|
+ row.find('.selected-product-info').hide();
|
|
|
+ row.find('.product-search').val('').show();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
function getProductInfo(productId, row) {
|
|
|
if (!productId) return;
|
|
|
|
|
@@ -667,6 +941,7 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
success: function(data) {
|
|
|
if (data) {
|
|
|
row.find('.unit-input').val(data.unit);
|
|
|
+ row.find('.unit-label').text(data.unit);
|
|
|
// 只有当数据库中有价格信息时才设置价格
|
|
|
if (data.price && data.price !== '0' && data.price !== '0.00') {
|
|
|
//默认不设置单价
|
|
@@ -712,23 +987,59 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
var customerId = $('#customer_id').val();
|
|
|
var customerName = $('.customer-search').val();
|
|
|
var hasProducts = false;
|
|
|
+ var allSpecsSelected = true;
|
|
|
var allPricesValid = true;
|
|
|
- var firstEmptyPriceField = null;
|
|
|
+ var allPricesHighEnough = true;
|
|
|
+ var firstInvalidField = null;
|
|
|
|
|
|
- $('.product-id-input').each(function() {
|
|
|
- if ($(this).val()) {
|
|
|
- hasProducts = true;
|
|
|
-
|
|
|
- // 检查该产品的单价是否已填写
|
|
|
- var row = $(this).closest('.product-row');
|
|
|
- var priceInput = row.find('.price-input');
|
|
|
- var priceValue = priceInput.val().trim();
|
|
|
-
|
|
|
- if (priceValue === '' || isNaN(parseFloat(priceValue))) {
|
|
|
- allPricesValid = false;
|
|
|
- if (!firstEmptyPriceField) {
|
|
|
- firstEmptyPriceField = priceInput;
|
|
|
- }
|
|
|
+ // 检查是否有产品行
|
|
|
+ if ($('.product-row').length === 0) {
|
|
|
+ alert('请至少添加一个产品');
|
|
|
+ $('#add-product-btn').focus();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $('.product-row').each(function() {
|
|
|
+ var productId = $(this).find('.product-id-input').val();
|
|
|
+ var specId = $(this).find('.spec-id-input').val();
|
|
|
+ var priceInput = $(this).find('.price-input');
|
|
|
+ var priceValue = priceInput.val().trim();
|
|
|
+ var price = parseFloat(priceValue) || 0;
|
|
|
+ var minPrice = parseFloat(priceInput.attr('data-min-price')) || 0;
|
|
|
+ var specSelect = $(this).find('.spec-select');
|
|
|
+ var productSearch = $(this).find('.product-search');
|
|
|
+
|
|
|
+ // 检查产品是否已选择
|
|
|
+ if (!productId) {
|
|
|
+ if (!firstInvalidField) {
|
|
|
+ firstInvalidField = productSearch;
|
|
|
+ }
|
|
|
+ return true; // continue
|
|
|
+ }
|
|
|
+
|
|
|
+ hasProducts = true;
|
|
|
+
|
|
|
+ // 检查规格是否已选择
|
|
|
+ if (!specId && specSelect.is(':visible')) {
|
|
|
+ allSpecsSelected = false;
|
|
|
+ if (!firstInvalidField) {
|
|
|
+ firstInvalidField = specSelect;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查单价是否有效
|
|
|
+ if (priceValue === '' || isNaN(parseFloat(priceValue))) {
|
|
|
+ allPricesValid = false;
|
|
|
+ if (!firstInvalidField) {
|
|
|
+ firstInvalidField = priceInput;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查单价是否大于等于规格价格
|
|
|
+ if (minPrice > 0 && price < minPrice) {
|
|
|
+ allPricesHighEnough = false;
|
|
|
+ if (!firstInvalidField) {
|
|
|
+ firstInvalidField = priceInput;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -739,7 +1050,7 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (!customerId || customerId <= 0) {
|
|
|
+ if (!customerId || customerId == '0') {
|
|
|
alert('请选择客户');
|
|
|
$('.customer-search').focus();
|
|
|
return false;
|
|
@@ -752,15 +1063,35 @@ if (!empty($id) && is_numeric($id)) {
|
|
|
}
|
|
|
|
|
|
if (!hasProducts) {
|
|
|
- alert('请至少添加一个产品');
|
|
|
- $('#product-search-single').focus();
|
|
|
+ alert('请至少添加一个有效的产品');
|
|
|
+ if (firstInvalidField) {
|
|
|
+ firstInvalidField.focus();
|
|
|
+ } else {
|
|
|
+ $('#add-product-btn').focus();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!allSpecsSelected) {
|
|
|
+ alert('请为所有产品选择规格');
|
|
|
+ if (firstInvalidField) {
|
|
|
+ firstInvalidField.focus();
|
|
|
+ }
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (!allPricesValid) {
|
|
|
alert('请为所有产品输入有效的单价');
|
|
|
- if (firstEmptyPriceField) {
|
|
|
- firstEmptyPriceField.focus();
|
|
|
+ if (firstInvalidField) {
|
|
|
+ firstInvalidField.focus();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!allPricesHighEnough) {
|
|
|
+ alert('单价不能低于规格设定的参考价格');
|
|
|
+ if (firstInvalidField) {
|
|
|
+ firstInvalidField.focus();
|
|
|
}
|
|
|
return false;
|
|
|
}
|