|
@@ -0,0 +1,311 @@
|
|
|
+/**
|
|
|
+ * NewSearchproduct.js - Enhanced product search functionality
|
|
|
+ *
|
|
|
+ * This script handles the product search and specification management
|
|
|
+ * for the country price management interface.
|
|
|
+ */
|
|
|
+
|
|
|
+// Make sure jQuery is available before initializing
|
|
|
+(function($) {
|
|
|
+ // Run when document is ready
|
|
|
+ $(document).ready(function() {
|
|
|
+ // Initialize the product specification search functionality
|
|
|
+ initProductSearch();
|
|
|
+
|
|
|
+ // Ensure search input is enabled on page load
|
|
|
+ $('#specificationSearch').prop('disabled', false);
|
|
|
+
|
|
|
+ // Add form validation for price fields
|
|
|
+ $('form[name="form1"]').on('submit', function(e) {
|
|
|
+ var hasError = false;
|
|
|
+ var firstErrorField = null;
|
|
|
+
|
|
|
+ // Check country name and area code fields
|
|
|
+ var $countryName = $('#countryName');
|
|
|
+ var $countryCode = $('#countryCode');
|
|
|
+
|
|
|
+ // Validate country name
|
|
|
+ if ($countryName.val().trim() === '') {
|
|
|
+ hasError = true;
|
|
|
+ $countryName.css('border-color', 'red');
|
|
|
+
|
|
|
+ if (!firstErrorField) {
|
|
|
+ firstErrorField = $countryName;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Show inline error
|
|
|
+ if ($countryName.next('.field-error').length === 0) {
|
|
|
+ $countryName.after('<div class="field-error" style="color:red;font-size:12px;margin-top:5px;">国家名称不能为空</div>');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $countryName.css('border-color', '');
|
|
|
+ $countryName.next('.field-error').remove();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate area code
|
|
|
+ if ($countryCode.val().trim() === '') {
|
|
|
+ hasError = true;
|
|
|
+ $countryCode.css('border-color', 'red');
|
|
|
+
|
|
|
+ if (!firstErrorField) {
|
|
|
+ firstErrorField = $countryCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Show inline error
|
|
|
+ if ($countryCode.next('.field-error').length === 0) {
|
|
|
+ $countryCode.after('<div class="field-error" style="color:red;font-size:12px;margin-top:5px;">区号不能为空</div>');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $countryCode.css('border-color', '');
|
|
|
+ $countryCode.next('.field-error').remove();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check all price fields
|
|
|
+ $('input[name="spec_price[]"]').each(function() {
|
|
|
+ var price = $(this).val().trim();
|
|
|
+ if (price === '' || price === '0' || parseFloat(price) <= 0) {
|
|
|
+ hasError = true;
|
|
|
+ $(this).css('border-color', 'red');
|
|
|
+
|
|
|
+ // Store reference to first error field for scrolling
|
|
|
+ if (!firstErrorField) {
|
|
|
+ firstErrorField = $(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Find product and spec name for error message
|
|
|
+ var $specItem = $(this).closest('.specitem');
|
|
|
+ var productName = $specItem.prevAll('.product-header').first().text().trim();
|
|
|
+ var specName = $specItem.find('.spec-name').text().trim();
|
|
|
+
|
|
|
+ // Show inline error under the field
|
|
|
+ var $errorMsg = $('<div class="price-error" style="color:red;font-size:12px;margin-top:5px;">售价不能为0或空白</div>');
|
|
|
+ $specItem.find('.price-error').remove();
|
|
|
+ $(this).after($errorMsg);
|
|
|
+ } else {
|
|
|
+ $(this).css('border-color', '');
|
|
|
+ $(this).next('.price-error').remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (hasError) {
|
|
|
+ e.preventDefault();
|
|
|
+
|
|
|
+ // Create appropriate error message
|
|
|
+ var errorMessage = '错误:';
|
|
|
+ if ($countryName.val().trim() === '' || $countryCode.val().trim() === '') {
|
|
|
+ errorMessage += '国家名称和区号不能为空!';
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if there are price errors
|
|
|
+ var hasPriceErrors = false;
|
|
|
+ $('input[name="spec_price[]"]').each(function() {
|
|
|
+ var price = $(this).val().trim();
|
|
|
+ if (price === '' || price === '0' || parseFloat(price) <= 0) {
|
|
|
+ hasPriceErrors = true;
|
|
|
+ return false; // Break the loop
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (hasPriceErrors) {
|
|
|
+ if (errorMessage !== '错误:') {
|
|
|
+ errorMessage += '\n\n';
|
|
|
+ }
|
|
|
+ errorMessage += '部分产品规格的售价为0或空白,请检查并填写所有售价!';
|
|
|
+ }
|
|
|
+
|
|
|
+ alert(errorMessage);
|
|
|
+
|
|
|
+ // Scroll to first error field
|
|
|
+ if (firstErrorField) {
|
|
|
+ $('html, body').animate({
|
|
|
+ scrollTop: firstErrorField.offset().top - 100
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Initialize the product search functionality
|
|
|
+ */
|
|
|
+ function initProductSearch() {
|
|
|
+ var $searchInput = $('#specificationSearch');
|
|
|
+ var $resultsList = $('#specificationlist');
|
|
|
+ var searchTimeout;
|
|
|
+
|
|
|
+ // Product search input keyup event with debounce
|
|
|
+ $searchInput.on('keyup', function() {
|
|
|
+ var keyword = $(this).val().trim();
|
|
|
+
|
|
|
+ // Clear previous timeout to implement debounce
|
|
|
+ clearTimeout(searchTimeout);
|
|
|
+
|
|
|
+ // Hide results and return if search term is too short
|
|
|
+ if (keyword.length < 2) {
|
|
|
+ $resultsList.find('ul').empty();
|
|
|
+ $resultsList.hide();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set a timeout to prevent too many requests
|
|
|
+ searchTimeout = setTimeout(function() {
|
|
|
+ // Show loading indicator
|
|
|
+ $resultsList.find('ul').html('<li class="search-loading">正在搜索产品...</li>');
|
|
|
+ $resultsList.show();
|
|
|
+
|
|
|
+ // Make AJAX request to search products
|
|
|
+ $.ajax({
|
|
|
+ url: 'ajax_search_products_for_spec.php',
|
|
|
+ type: 'POST',
|
|
|
+ data: {keyword: keyword},
|
|
|
+ dataType: 'html',
|
|
|
+ success: function(data) {
|
|
|
+ // Check for session errors in the response
|
|
|
+ if (data.indexOf('session') !== -1 && data.indexOf('Notice') !== -1) {
|
|
|
+ console.warn("Session notice detected in response. This may be harmless.");
|
|
|
+ }
|
|
|
+
|
|
|
+ $resultsList.find('ul').html(data);
|
|
|
+
|
|
|
+ // Show or hide results based on content
|
|
|
+ if ($resultsList.find('ul li').length > 0) {
|
|
|
+ $resultsList.show();
|
|
|
+ } else {
|
|
|
+ $resultsList.hide();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ error: function(xhr, status, error) {
|
|
|
+ console.error("Search error:", error);
|
|
|
+ $resultsList.find('ul').html('<li class="search-error">搜索失败,请重试</li>');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, 300); // 300ms debounce
|
|
|
+ });
|
|
|
+
|
|
|
+ // Show search results when input is focused (if results exist and search term is valid)
|
|
|
+ $searchInput.on('focus', function() {
|
|
|
+ var keyword = $(this).val().trim();
|
|
|
+ if (keyword.length >= 2 && $resultsList.find('ul li').length > 0) {
|
|
|
+ $resultsList.show();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Handle product selection from search results
|
|
|
+ $(document).on('click', '#specificationlist ul li', function() {
|
|
|
+ if ($(this).hasClass('search-loading') || $(this).hasClass('search-error')) {
|
|
|
+ return; // Don't process clicks on loading or error messages
|
|
|
+ }
|
|
|
+
|
|
|
+ var $this = $(this);
|
|
|
+ var productId = $this.data('product-id');
|
|
|
+
|
|
|
+ // Skip if no product ID was found
|
|
|
+ if (!productId) {
|
|
|
+ console.error("No product ID found");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var productName = $this.data('product-name');
|
|
|
+ var categoryName = $this.data('category-name');
|
|
|
+ var productUnit = $this.data('unit');
|
|
|
+
|
|
|
+ // Check if product is already added
|
|
|
+ if ($('.specifications .product-header:contains("' + productName + '")').length > 0) {
|
|
|
+ alert('该产品已添加!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Hide results and show loading state
|
|
|
+ $resultsList.hide();
|
|
|
+ $searchInput.val('正在加载产品规格...').prop('disabled', true);
|
|
|
+
|
|
|
+ // Fetch product specifications
|
|
|
+ $.ajax({
|
|
|
+ url: 'ajax_get_product_specifications.php',
|
|
|
+ type: 'POST',
|
|
|
+ data: {product_id: productId},
|
|
|
+ dataType: 'html',
|
|
|
+ success: function(data) {
|
|
|
+ // Check for session errors in the response
|
|
|
+ if (data.indexOf('session') !== -1 && data.indexOf('Notice') !== -1) {
|
|
|
+ console.warn("Session notice detected in response. This may be harmless.");
|
|
|
+ // Try to extract the actual content after the notice
|
|
|
+ data = data.substring(data.indexOf('</p>') + 4);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if we received an error message about no specifications
|
|
|
+ if (data.indexOf('没有规格信息') !== -1) {
|
|
|
+ alert('该产品没有规格信息,请先在产品管理中添加规格');
|
|
|
+ $searchInput.val('').prop('disabled', false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create product header
|
|
|
+ var categoryDisplay = categoryName ? ' <span class="category-tag">(' + categoryName + ')</span>' : '';
|
|
|
+ var productHeader = $('<div class="product-header">' + productName + categoryDisplay + '</div>');
|
|
|
+
|
|
|
+ // Append product header and specifications
|
|
|
+ $('.specifications').append(productHeader);
|
|
|
+ $('.specifications').append(data);
|
|
|
+
|
|
|
+ // Make sure price fields are empty and don't have placeholders
|
|
|
+ var $lastHeader = $('.specifications .product-header:last');
|
|
|
+ $lastHeader.nextUntil('.product-header', '.specitem').find('input[name="spec_price[]"]').attr('placeholder', '').val('');
|
|
|
+
|
|
|
+ // Reset search input
|
|
|
+ $searchInput.val('').prop('disabled', false);
|
|
|
+ },
|
|
|
+ error: function(xhr, status, error) {
|
|
|
+ console.error("Error loading specifications:", error);
|
|
|
+ alert('加载产品规格失败,请重试');
|
|
|
+ $searchInput.val('').prop('disabled', false);
|
|
|
+ },
|
|
|
+ complete: function() {
|
|
|
+ // Always make sure search input is re-enabled
|
|
|
+ setTimeout(function() {
|
|
|
+ $searchInput.prop('disabled', false);
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // Delete specification when delete button is clicked
|
|
|
+ $(document).on('click', '.specdelete', function() {
|
|
|
+ // if (!confirm('确定要删除此规格吗?')) {
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+
|
|
|
+ var $specItem = $(this).closest('.specitem');
|
|
|
+ var $productHeader = $specItem.prevAll('.product-header').first();
|
|
|
+
|
|
|
+ // Remove specification item
|
|
|
+ $specItem.fadeOut(200, function() {
|
|
|
+ $(this).remove();
|
|
|
+
|
|
|
+ // Check if there are any specifications left for this product
|
|
|
+ var hasSpecs = false;
|
|
|
+ $productHeader.nextUntil('.product-header', '.specitem').each(function() {
|
|
|
+ hasSpecs = true;
|
|
|
+ return false; // Break the loop
|
|
|
+ });
|
|
|
+
|
|
|
+ // If no specifications left, remove product header
|
|
|
+ if (!hasSpecs) {
|
|
|
+ $productHeader.fadeOut(200, function() {
|
|
|
+ $(this).remove();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // Hide search results when clicking outside
|
|
|
+ $(document).on('click', function(e) {
|
|
|
+ if (!$(e.target).closest('#specificationSearch, #specificationlist').length) {
|
|
|
+ $resultsList.hide();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+})(jQuery);
|