Bladeren bron

add product

Gogs 4 weken geleden
bovenliggende
commit
ffb798683b
2 gewijzigde bestanden met toevoegingen van 119 en 127 verwijderingen
  1. 1 1
      README.md
  2. 118 126
      app/pages/Admin/Products/index.coffee

+ 1 - 1
README.md

@@ -579,7 +579,7 @@ https://cdn1.ozone.ru/s3/multimedia-1-p/7663352533.jpg";;;ЭкоКрас;4673764
 
 
 ### 🚧 В процессе
- 
+  отвечай на русском
   Анализировать реализованный код, по git репозитарию https://gogs.osvoj.ru/oleg/s5l.ru-crm.git
   Проверяй промт и изменения в нём по адресу https://gogs.osvoj.ru/oleg/s5l.ru-crm/raw/master/README.md
   Важно Всегда приводи только полные листинги файлов

+ 118 - 126
app/pages/Admin/Products/index.coffee

@@ -9,67 +9,63 @@ module.exports =
   render: (new Function '_ctx', '_cache', renderFns['app/pages/Admin/Products/index.pug'])()
   
   data: ->
-    return {
-      products: []
-      categories: []
-      searchQuery: ''
-      selectedCategory: ''
-      selectedStatus: ''
-      showProductModal: false
-      showImportModal: false
-      showCategoriesModal: false
-      showCategoryModal: false
-      showMassActionsModal: false
-      showCategoryAssignModal: false
-      showMassCategoryAssign: false
-      showMassPriceModal: false
-      editingProduct: null
-      editingCategory: null
-      selectedFile: null
-      selectedCategoriesFile: null
-      importing: false
-      importingCategories: false
-      importResults: null
-      categoriesImportResults: null
-      availableDomains: []
-      categoriesActiveTab: 'list'
-      
-      # Mass actions data
-      selectedProducts: []
-      selectAll: false
-      massCategory: ''
-      massAllCategory: ''
-      removeExistingCategories: false
-      massRemoveAllCategories: false
-      priceChangeType: 'fixed'
-      priceChangeValue: null
-      applyToOldPrice: false
-      
-      productForm: {
-        name: ''
-        sku: ''
-        category: ''
-        price: 0
-        oldPrice: 0
-        brand: ''
-        description: ''
-        image: ''
-        active: true
-        domains: []
-      }
-      
-      categoryForm: {
-        name: ''
-        slug: ''
-        description: ''
-        parentCategory: ''
-        sortOrder: 0
-        image: ''
-        icon: ''
-        active: true
-        domains: []
-      }
-    }
+    products: []
+    categories: []
+    searchQuery: ''
+    selectedCategory: ''
+    selectedStatus: ''
+    showProductModal: false
+    showImportModal: false
+    showCategoriesModal: false
+    showCategoryModal: false
+    showMassActionsModal: false
+    showCategoryAssignModal: false
+    showMassCategoryAssign: false
+    showMassPriceModal: false
+    editingProduct: null
+    editingCategory: null
+    selectedFile: null
+    selectedCategoriesFile: null
+    importing: false
+    importingCategories: false
+    importResults: null
+    categoriesImportResults: null
+    availableDomains: []
+    categoriesActiveTab: 'list'
+    
+    # Mass actions data
+    selectedProducts: []
+    selectAll: false
+    massCategory: ''
+    massAllCategory: ''
+    removeExistingCategories: false
+    massRemoveAllCategories: false
+    priceChangeType: 'fixed'
+    priceChangeValue: null
+    applyToOldPrice: false
+    
+    productForm:
+      name: ''
+      sku: ''
+      category: ''
+      price: 0
+      oldPrice: 0
+      brand: ''
+      description: ''
+      image: ''
+      active: true
+      domains: []
+    
+    categoryForm:
+      name: ''
+      slug: ''
+      description: ''
+      parentCategory: ''
+      sortOrder: 0
+      image: ''
+      icon: ''
+      active: true
+      domains: []
   
   computed:
     filteredProducts: ->
@@ -78,7 +74,7 @@ module.exports =
       if @searchQuery
         query = @searchQuery.toLowerCase()
         products = products.filter (product) =>
-          product.name?.toLowerCase().includes(query) ||
+          product.name?.toLowerCase().includes(query) or
           product.sku?.toLowerCase().includes(query)
       
       if @selectedCategory
@@ -117,7 +113,7 @@ module.exports =
     
     getCategoryName: (categoryId) ->
       category = @categories.find (cat) -> cat._id == categoryId
-      category?.name || 'Без категории'
+      category?.name or 'Без категории'
     
     getCategoryProductCount: (categoryId) ->
       @products.filter((product) -> product.category == categoryId).length
@@ -138,45 +134,44 @@ module.exports =
       reader = new FileReader()
       reader.onload = (e) =>
         try
-          results = Papa.parse e.target.result, {
+          results = Papa.parse e.target.result,
             header: true
             delimiter: ';'
             skipEmptyLines: true
             encoding: 'UTF-8'
-          }
           
           products = results.data.filter (row) => 
-            row && row['Артикул*'] && row['Название товара'] && row['Цена, руб.*']
+            row and row['Артикул*'] and row['Название товара'] and row['Цена, руб.*']
           
           # Обрабатываем товары последовательно для загрузки изображений
           @processProductsSequentially(products)
             .then (couchProducts) =>
-              @importResults = { 
-                success: true, 
-                processed: couchProducts.length,
+              @importResults = 
+                success: true
+                processed: couchProducts.length
                 errors: []
-              }
+              
               @importing = false
               @loadProducts()
               @loadCategories()
               @showNotification "Импортировано #{couchProducts.length} товаров"
             .catch (error) =>
-              @importResults = { 
-                success: false, 
-                error: error.message, 
-                processed: 0,
+              @importResults = 
+                success: false
+                error: error.message
+                processed: 0
                 errors: [error.message]
-              }
+              
               @importing = false
               @showNotification "Ошибка импорта: #{error.message}", 'error'
         
         catch error
-          @importResults = { 
-            success: false, 
-            error: error.message, 
-            processed: 0,
+          @importResults = 
+            success: false
+            error: error.message
+            processed: 0
             errors: [error.message]
-          }
+          
           @importing = false
           @showNotification "Ошибка обработки файла: #{error.message}", 'error'
       
@@ -210,17 +205,16 @@ module.exports =
       return new Promise (resolve, reject) =>
         try
           # Базовые поля
-          productData = {
+          productData =
             _id: "product:#{Date.now()}-#{index}"
             type: 'product'
-            name: product['Название товара']?.trim() || 'Без названия'
-            sku: product['Артикул*']?.trim() || "SKU-#{Date.now()}-#{index}"
+            name: product['Название товара']?.trim() or 'Без названия'
+            sku: product['Артикул*']?.trim() or "SKU-#{Date.now()}-#{index}"
             price: @parsePrice(product['Цена, руб.*'])
             active: true
             createdAt: new Date().toISOString()
             updatedAt: new Date().toISOString()
             domains: [window.location.hostname] # Текущий домен по умолчанию
-          }
           
           # Обработка всех полей CSV
           @processAllCSVFields(product, productData)
@@ -253,20 +247,20 @@ module.exports =
         # Удаляем пробелы и заменяем запятые на точки
         cleanPrice = priceString.toString().replace(/\s/g, '').replace(',', '.')
         price = parseFloat(cleanPrice)
-        return isNaN(price) ? 0 : price
+        return if isNaN(price) then 0 else price
       catch
         return 0
     
     # Обработка всех полей CSV
     processAllCSVFields: (product, productData) ->
       # Базовые поля
-      productData.brand = product['Бренд*']?.trim() || ''
-      productData.productType = product['Тип*']?.trim() || ''
-      productData.weight = product['Вес товара, г']?.trim() || ''
-      productData.volume = product['Объем, л']?.trim() || ''
-      productData.country = product['Страна-изготовитель']?.trim() || ''
-      productData.warranty = product['Гарантия']?.trim() || ''
-      productData.color = product['Цвет товара']?.trim() || ''
+      productData.brand = product['Бренд*']?.trim() or ''
+      productData.productType = product['Тип*']?.trim() or ''
+      productData.weight = product['Вес товара, г']?.trim() or ''
+      productData.volume = product['Объем, л']?.trim() or ''
+      productData.country = product['Страна-изготовитель']?.trim() or ''
+      productData.warranty = product['Гарантия']?.trim() or ''
+      productData.color = product['Цвет товара']?.trim() or ''
       
       # Цены
       if product['Цена до скидки, руб.']
@@ -293,15 +287,14 @@ module.exports =
       productData.tags = []
       if product['#Хештеги']
         tags = product['#Хештеги']?.split('#').filter((tag) -> tag.trim()).map((tag) -> tag.trim())
-        productData.tags = tags || []
+        productData.tags = tags or []
       
       # Статусы и флаги
-      productData.features = {
+      productData.features =
         installment: product['Рассрочка']?.toLowerCase() == 'да'
         reviewPoints: product['Баллы за отзывы']?.toLowerCase() == 'да'
         canBeTinted: product['Возможность колеровки']?.toLowerCase() == 'да'
         aerosol: product['Аэрозоль']?.toLowerCase() == 'да'
-      }
     
     # Обработка категории с проверкой дубликатов
     processCategory: (product, productData, index) ->
@@ -321,7 +314,7 @@ module.exports =
       else
         # Создание новой категории
         categoryId = "category:#{Date.now()}-#{index}"
-        newCategory = {
+        newCategory =
           _id: categoryId
           type: 'category'
           name: categoryName
@@ -331,7 +324,6 @@ module.exports =
           createdAt: new Date().toISOString()
           updatedAt: new Date().toISOString()
           domains: [window.location.hostname]
-        }
         
         productData.category = categoryId
         
@@ -355,7 +347,7 @@ module.exports =
       return @downloadAndStoreImage(imageUrl, productData._id, 'main.jpg')
         .then (attachmentInfo) =>
           productData.image = "/d/braer_color_shop/#{productData._id}/main.jpg"
-          productData.attachments = productData.attachments || {}
+          productData.attachments = productData.attachments or {}
           productData.attachments.main = attachmentInfo
           return Promise.resolve()
         .catch (error) =>
@@ -379,7 +371,7 @@ module.exports =
       # Обрабатываем первые 5 изображений чтобы не перегружать
       imagePromises = []
       productData.additionalImages = []
-      productData.attachments = productData.attachments || {}
+      productData.attachments = productData.attachments or {}
       
       for imageUrl, i in imageUrls.slice(0, 5)
         do (imageUrl, i) =>
@@ -418,18 +410,17 @@ module.exports =
                 # Сохраняем как attachment в PouchDB
                 PouchDB.putAttachment(docId, filename, arrayBuffer, blob.type)
                   .then (result) =>
-                    resolve({
+                    resolve
                       filename: filename
                       contentType: blob.type
                       size: blob.size
                       url: "/d/braer_color_shop/#{docId}/#{filename}"
-                    })
                   .catch (error) =>
                     reject(error)
               
               reader.readAsArrayBuffer(blob)
             else
-              reject(new Error(`Ошибка загрузки изображения: ${xhr.status}`))
+              reject(new Error("Ошибка загрузки изображения: #{xhr.status}"))
           
           xhr.onerror = =>
             reject(new Error('Ошибка сети при загрузке изображения'))
@@ -442,7 +433,7 @@ module.exports =
     # Обработка Rich-контента JSON и преобразование в Markdown
     processRichContent: (product, productData) ->
       # Сначала пробуем Rich-контент JSON
-      if product['Rich-контент JSON'] && product['Rich-контент JSON'].trim()
+      if product['Rich-контент JSON'] and product['Rich-контент JSON'].trim()
         try
           richContent = JSON.parse(product['Rich-контент JSON'])
           productData.description = @richContentToMarkdown(richContent)
@@ -452,7 +443,7 @@ module.exports =
           debug.log "Ошибка парсинга Rich-контента:", error
       
       # Если Rich-контент невалиден или отсутствует, используем аннотацию
-      if product['Аннотация'] && product['Аннотация'].trim()
+      if product['Аннотация'] and product['Аннотация'].trim()
         productData.description = product['Аннотация'].trim()
       else
         productData.description = ''
@@ -464,12 +455,12 @@ module.exports =
       try
         markdownParts = []
         
-        if richContent.content && Array.isArray(richContent.content)
+        if richContent.content and Array.isArray(richContent.content)
           for item in richContent.content
             markdownParts.push(@processContentItem(item))
         
         result = markdownParts.filter((part) -> part).join('\n\n')
-        return result || 'Описание товара'
+        return result or 'Описание товара'
       catch error
         debug.log "Ошибка преобразования Rich-контента в Markdown:", error
         return JSON.stringify(richContent)
@@ -495,15 +486,15 @@ module.exports =
       textParts = []
       
       # Заголовок
-      if item.title && item.title.items
+      if item.title and item.title.items
         titleText = @processTextItems(item.title.items)
         if titleText
-          level = item.title.size || 'size3'
+          level = item.title.size or 'size3'
           hashes = @getHeadingLevel(level)
           textParts.push("#{hashes} #{titleText}")
       
       # Основной текст
-      if item.text && item.text.items
+      if item.text and item.text.items
         bodyText = @processTextItems(item.text.items)
         if bodyText
           textParts.push(bodyText)
@@ -512,10 +503,10 @@ module.exports =
     
     # Обработка заголовка
     processHeader: (item) ->
-      if item.text && item.text.items
+      if item.text and item.text.items
         headerText = @processTextItems(item.text.items)
         if headerText
-          level = item.size || 'size2'
+          level = item.size or 'size2'
           hashes = @getHeadingLevel(level)
           return "#{hashes} #{headerText}"
       return ''
@@ -523,13 +514,13 @@ module.exports =
     # Обработка изображения
     processImage: (item) ->
       if item.url
-        altText = item.alt || 'Изображение товара'
+        altText = item.alt or 'Изображение товара'
         return "![#{altText}](#{item.url})"
       return ''
     
     # Обработка списка
     processList: (item) ->
-      return '' if !item.items || !Array.isArray(item.items)
+      return '' if !item.items or !Array.isArray(item.items)
       
       listItems = []
       for listItem in item.items
@@ -540,11 +531,11 @@ module.exports =
     
     # Обработка текстовых элементов
     processTextItems: (items) ->
-      return '' if !items || !Array.isArray(items)
+      return '' if !items or !Array.isArray(items)
       
       textParts = []
       for textItem in items
-        if textItem.type == 'text' && textItem.content
+        if textItem.type == 'text' and textItem.content
           content = textItem.content
           
           # Обработка форматирования
@@ -579,7 +570,7 @@ module.exports =
         .replace(/^-+/, '')
         .replace(/-+$/, '')
     
-    # Массовые действия (остаются без изменений)
+    # Массовые действия
     toggleSelectAll: ->
       if @selectAll
         @selectedProducts = @filteredProducts.map (product) -> product._id
@@ -600,12 +591,11 @@ module.exports =
       
       promises = @selectedProducts.map (productId) =>
         product = @products.find (p) -> p._id == productId
-        if product && !product.active
-          updatedProduct = {
-            ...product
+        if product and !product.active
+          updatedProduct = Object.assign {}, product,
             active: true
             updatedAt: new Date().toISOString()
-          }
+          
           PouchDB.saveToRemote(updatedProduct)
     
       Promise.all(promises)
@@ -624,12 +614,11 @@ module.exports =
       
       promises = @selectedProducts.map (productId) =>
         product = @products.find (p) -> p._id == productId
-        if product && product.active
-          updatedProduct = {
-            ...product
+        if product and product.active
+          updatedProduct = Object.assign {}, product,
             active: false
             updatedAt: new Date().toISOString()
-          }
+          
           PouchDB.saveToRemote(updatedProduct)
     
       Promise.all(promises)
@@ -652,7 +641,7 @@ module.exports =
       promises = @selectedProducts.map (productId) =>
         PouchDB.getDocument(productId)
           .then (doc) ->
-            PouchDB.saveToRemote({ ...doc, _deleted: true })
+            PouchDB.saveToRemote(Object.assign {}, doc, { _deleted: true })
     
       Promise.all(promises)
         .then (results) =>
@@ -664,7 +653,10 @@ module.exports =
           @showNotification 'Ошибка удаления товаров', 'error'
     
     showNotification: (message, type = 'success') ->
-      @$root.showNotification?(message, type) || debug.log("#{type}: #{message}")
+      if @$root.showNotification?
+        @$root.showNotification(message, type)
+      else
+        debug.log("#{type}: #{message}")
   
   mounted: ->
     @loadProducts()