Gogs 3 tygodni temu
rodzic
commit
1ca2b7776f
2 zmienionych plików z 480 dodań i 100 usunięć
  1. 171 4
      README.md
  2. 309 96
      scripts/design-documents.coffee

+ 171 - 4
README.md

@@ -1,6 +1,8 @@
 # Текущая ззадача
-доработай design-documents.coffee, отслеживая его версию. с учетом изменений в правилах, допиши недостающие описания типов документов, добавь документ я настройками домена.
-Добавь в документы, мульти доменое использование. 
+доработай design-documents.coffee, добавь мультиязычность в документы, и обнови описание всех хранимых объектов.
+
+# файл с правилами
+https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/README.md
 
 # применяй правила:
 
@@ -117,6 +119,7 @@ module.exports =
 ```
 
 ## определение функций в _deing документе
+при обновлении документа учитывай версионность
 ```
     # Design документ для блог постов
     blog_posts:
@@ -180,8 +183,12 @@ https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master
 , корневой каталог vue/
 от него идут пути к файлам пример: в коде -> app/temp.coffee, в репозитарии -> vue/app/temp.coffee
 
-## файл с правилами
-https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/README.md
+
+# Общее описание
+Универсаньная CMS для работы с couchdb как бекендом.
+CMS мультидоменная и мультиязычная.
+мультидоменность во все view через поле domain
+
 
 # общая структура проекта
 app/
@@ -281,5 +288,165 @@ coffee
     created_at: ISOString
     updated_at: ISOString
 }
+
+## Пример документа настроек домена
+domainSettingsExample =
+    _id: "domain_settings_borbad_s5l_ru"
+    type: "domain_settings"
+    domain: "borbad.s5l.ru"
+    name: "Кохи Борбад - Концертный зал Душанбе"
+    description: "Официальный сайт концертного зала Борбад"
+    active: true
+    priority: 1
+    theme: "borbad"
+    languages: ["ru", "en", "tj"]
+    default_language: "ru"
+    timezone: "Asia/Dushanbe"
+    currency: "TJS"
+    settings:
+        seo:
+            title_template: "{page} - Кохи Борбад"
+            description: "Концертный зал Борбад - культурный центр Душанбе"
+            keywords: ["концерты", "мероприятия", "Душанбе", "культура"]
+        social:
+            facebook: "https://facebook.com/borbad"
+            instagram: "https://instagram.com/borbad"
+            twitter: "https://twitter.com/borbad"
+        contact:
+            address: "г. Душанбе, пр. Рудаки 22"
+            phone: "+992 37 123-45-67"
+            email: "info@borbad.s5l.ru"
+    created_at: new Date().toISOString()
+    updated_at: new Date().toISOString()
+## Пример документа страницы
+pageExample =
+    _id: "page_about_borbad"
+    type: "page"
+    domain: "borbad.s5l.ru"
+    title: "О нас - Кохи Борбад"
+    slug: "about"
+    content: "# О концертном зале Борбад\n\nИстория и описание нашего зала..."
+    excerpt: "Информация о концертном зале Борбад в Душанбе"
+    image: "/assets/borbad.s5l.ru/about.jpg"
+    meta_title: "О нас - Концертный зал Борбад"
+    meta_description: "Узнайте больше о концертном зале Борбад в Душанбе"
+    status: "published"
+    order: 2
+    template: "default"
+    created_at: new Date().toISOString()
+    updated_at: new Date().toISOString()
+
+## Пример документа меню
+menuExample =
+    _id: "menu_main_borbad"
+    type: "menu"
+    domain: "borbad.s5l.ru"
+    name: "Главное меню"
+    location: "header"
+    active: true
+    items: [
+        {
+            title: "Главная"
+            url: "/"
+            order: 1
+            target: "_self"
+        }
+        {
+            title: "Мероприятия"
+            url: "/events"
+            order: 2
+            target: "_self"
+        }
+        {
+            title: "О нас"
+            url: "/about"
+            order: 3
+            target: "_self"
+        }
+        {
+            title: "Контакты"
+            url: "/contacts"
+            order: 4
+            target: "_self"
+        }
+    ]
+    created_at: new Date().toISOString()
+    updated_at: new Date().toISOString()
+
+## Пример документа пользователя
+userExample =
+    _id: "user_admin_1"
+    type: "user"
+    email: "admin@borbad.s5l.ru"
+    name: "Администратор"
+    role: "admin"
+    active: true
+    permissions: [
+        "read"
+        "write"
+        "delete"
+        "admin"
+    ]
+    profile:
+        avatar: "/assets/borbad.s5l.ru/avatars/admin.jpg"
+        phone: "+992 37 123-45-67"
+        position: "Системный администратор"
+    settings:
+        language: "ru"
+        notifications: true
+    created_at: new Date().toISOString()
+    updated_at: new Date().toISOString()
+    last_login: new Date().toISOString()
+
+## Пример документа заказа
+orderExample =
+    _id: "order_2024_001"
+    type: "order"
+    domain: "borbad.s5l.ru"
+    user_id: "user_customer_1"
+    status: "completed"
+    total: 1500
+    currency: "TJS"
+    items: [
+        {
+            product_id: "event_ticket_1"
+            name: "Билет на симфонический концерт"
+            quantity: 2
+            price: 500
+            total: 1000
+        }
+        {
+            product_id: "product_1"
+            name: "Футболка с логотипом"
+            quantity: 1
+            price: 500
+            total: 500
+        }
+    ]
+    customer_info:
+        name: "Иван Иванов"
+        email: "ivan@example.com"
+        phone: "+992 123-45-67"
+    payment_info:
+        method: "card"
+        transaction_id: "txn_123456"
+        status: "paid"
+    created_at: new Date().toISOString()
+    updated_at: new Date().toISOString()
+
+## Пример документа аудита
+auditExample =
+    _id: "audit_2024_001"
+    type: "audit_log"
+    user_id: "user_admin_1"
+    action: "create"
+    resource_type: "blog_post"
+    resource_id: "blog_post_1"
+    description: "Создана новая запись блога"
+    ip_address: "192.168.1.1"
+    user_agent: "Mozilla/5.0..."
+    created_at: new Date().toISOString()
+
+
 ## _desing документ для работы с данными
 https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/scripts/design-documents.coffee

+ 309 - 96
scripts/design-documents.coffee

@@ -1,161 +1,318 @@
-# Design документы для CouchDB
+# Design документы для CouchDB с поддержкой мультидоменности
 
 module.exports =
-    # Design документ для блог постов
+    # Design документ для настроек доменов
+    domains:
+        version: "2.0"
+        views:
+            # Все настройки доменов
+            all_domains:
+                map: ((doc) ->
+                    if doc.type is 'domain_settings'
+                        emit(doc.domain, doc)
+                ).toString()
+            
+            # Активные домены
+            active_domains:
+                map: ((doc) ->
+                    if doc.type is 'domain_settings' and doc.active is true
+                        emit(doc.domain, doc)
+                ).toString()
+            
+            # Домены по приоритету
+            by_priority:
+                map: ((doc) ->
+                    if doc.type is 'domain_settings' and doc.active is true
+                        emit(doc.priority or 0, doc)
+                ).toString()
+
+    # Design документ для блог постов с мультидоменностью
     blog_posts:
-        version: "1.1"
+        version: "2.0"
         views:
-            # Все опубликованные блог посты
+            # Все опубликованные блог посты с фильтром по домену
             published:
                 map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
-                        emit(doc.created_at, doc)).toString()
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.created_at], doc)
+                ).toString()
             
-            # Блог посты по тегам
+            # Блог посты по тегам с фильтром по домену
             by_tag:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published' and doc.tags
+                        domain = doc.domain or 'default'
                         for tag in doc.tags
-                            emit([tag, doc.created_at], doc)
+                            emit([domain, tag, doc.created_at], doc)
+                ).toString()
             
-            # Блог посты по автору
+            # Блог посты по автору с фильтром по домену
             by_author:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
-                        emit([doc.author, doc.created_at], doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.author, doc.created_at], doc)
+                ).toString()
             
-            # Поиск по заголовку и содержанию
+            # Поиск по заголовку и содержанию с фильтром по домену
             search:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
-                        # Индексируем заголовок и содержание для поиска
+                        domain = doc.domain or 'default'
                         text = (doc.title + " " + doc.content + " " + doc.excerpt).toLowerCase()
                         words = text.split(/\W+/).filter (word) -> word.length > 2
                         
                         for word in words
-                            emit(word, {
+                            emit([domain, word], {
                                 _id: doc._id
                                 title: doc.title
                                 excerpt: doc.excerpt
                                 created_at: doc.created_at
+                                domain: doc.domain
                             })
+                ).toString()
 
-    # Design документ для мероприятий
+    # Design документ для мероприятий с мультидоменностью
     events:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Все мероприятия по дате
+            # Все мероприятия по дате с фильтром по домену
             by_date:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event'
-                        emit(doc.event_date, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.event_date], doc)
+                ).toString()
             
-            # Предстоящие мероприятия
+            # Предстоящие мероприятия с фильтром по домену
             upcoming:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event' and doc.status is 'upcoming'
-                        emit(doc.event_date, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.event_date], doc)
+                ).toString()
             
-            # Активные мероприятия
+            # Активные мероприятия с фильтром по домену
             ongoing:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event' and doc.status is 'ongoing'
-                        emit(doc.event_date, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.event_date], doc)
+                ).toString()
             
-            # Мероприятия по тегам
+            # Мероприятия по тегам с фильтром по домену
             by_tag:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event' and doc.tags
+                        domain = doc.domain or 'default'
                         for tag in doc.tags
-                            emit([tag, doc.event_date], doc)
+                            emit([domain, tag, doc.event_date], doc)
+                ).toString()
             
-            # Мероприятия по местоположению
+            # Мероприятия по местоположению с фильтром по домену
             by_location:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event'
-                        emit([doc.location, doc.event_date], doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.location, doc.event_date], doc)
+                ).toString()
 
-    # Design документ для слайдов
+    # Design документ для слайдов с мультидоменностью
     slides:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Активные слайды по порядку
+            # Активные слайды по порядку с фильтром по домену
             active_ordered:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'slide' and doc.active is true
-                        emit(doc.order, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.order], doc)
+                ).toString()
 
-    # Design документ для товаров
+    # Design документ для товаров с мультидоменностью
     products:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Все доступные товары
+            # Все доступные товары с фильтром по домену
             available:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
-                        emit(doc.created_at, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.created_at], doc)
+                ).toString()
             
-            # Товары по категориям
+            # Товары по категориям с фильтром по домену
             by_category:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
-                        emit([doc.category, doc.created_at], doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.category, doc.created_at], doc)
+                ).toString()
             
-            # Товары по тегам
+            # Товары по тегам с фильтром по домену
             by_tag:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'product' and doc.tags
+                        domain = doc.domain or 'default'
                         for tag in doc.tags
-                            emit([tag, doc.created_at], doc)
+                            emit([domain, tag, doc.created_at], doc)
+                ).toString()
             
-            # Товары по цене
+            # Товары по цене с фильтром по домену
             by_price:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
-                        emit(doc.price, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.price], doc)
+                ).toString()
 
-    # Design документ для категорий и тем
+    # Design документ для категорий и тем с мультидоменностью
     categories_themes:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Все категории по порядку
+            # Все категории по порядку с фильтром по домену
             categories_ordered:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'category'
-                        emit(doc.order, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.order], doc)
+                ).toString()
             
-            # Категории по родителю (для иерархии)
+            # Категории по родителю с фильтром по домену
             categories_by_parent:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'category'
+                        domain = doc.domain or 'default'
                         parent = doc.parent or 'root'
-                        emit([parent, doc.order], doc)
+                        emit([domain, parent, doc.order], doc)
+                ).toString()
             
-            # Все темы
+            # Все темы с фильтром по домену
             themes:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'theme'
-                        emit(doc.name, doc)
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.name], doc)
+                ).toString()
+
+    # Design документ для страниц с мультидоменностью
+    pages:
+        version: "2.0"
+        views:
+            # Все страницы по slug с фильтром по домену
+            by_slug:
+                map: ((doc) ->
+                    if doc.type is 'page'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.slug], doc)
+                ).toString()
+            
+            # Опубликованные страницы с фильтром по домену
+            published:
+                map: ((doc) ->
+                    if doc.type is 'page' and doc.status is 'published'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.order or 0], doc)
+                ).toString()
+
+    # Design документ для меню с мультидоменностью
+    menus:
+        version: "2.0"
+        views:
+            # Меню по локации с фильтром по домену
+            by_location:
+                map: ((doc) ->
+                    if doc.type is 'menu'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.location], doc)
+                ).toString()
+            
+            # Активные меню с фильтром по домену
+            active:
+                map: ((doc) ->
+                    if doc.type is 'menu' and doc.active is true
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.location], doc)
+                ).toString()
+
+    # Design документ для настроек с мультидоменностью
+    settings:
+        version: "2.0"
+        views:
+            # Настройки по ключу с фильтром по домену
+            by_key:
+                map: ((doc) ->
+                    if doc.type is 'setting'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.key], doc)
+                ).toString()
 
-    # Design документ для глобального поиска
+    # Design документ для пользователей
+    users:
+        version: "2.0"
+        views:
+            # Пользователи по email
+            by_email:
+                map: ((doc) ->
+                    if doc.type is 'user'
+                        emit(doc.email, doc)
+                ).toString()
+            
+            # Пользователи по роли
+            by_role:
+                map: ((doc) ->
+                    if doc.type is 'user'
+                        emit(doc.role, doc)
+                ).toString()
+            
+            # Активные пользователи
+            active:
+                map: ((doc) ->
+                    if doc.type is 'user' and doc.active is true
+                        emit(doc.email, doc)
+                ).toString()
+
+    # Design документ для заказов с мультидоменностью
+    orders:
+        version: "2.0"
+        views:
+            # Заказы по статусу с фильтром по домену
+            by_status:
+                map: ((doc) ->
+                    if doc.type is 'order'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.status, doc.created_at], doc)
+                ).toString()
+            
+            # Заказы по пользователю с фильтром по домену
+            by_user:
+                map: ((doc) ->
+                    if doc.type is 'order'
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.user_id, doc.created_at], doc)
+                ).toString()
+
+    # Design документ для глобального поиска с мультидоменностью
     global_search:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Глобальный поиск по всем типам документов
+            # Глобальный поиск по всем типам документов с фильтром по домену
             all_content:
-                map: (doc) ->
-                    # Индексируем различные типы документов для поиска
+                map: ((doc) ->
                     searchFields = {}
+                    domain = doc.domain or 'default'
                     
                     switch doc.type
                         when 'blog_post'
-                            searchFields =
-                                title: doc.title
-                                content: doc.content
-                                excerpt: doc.excerpt
-                                author: doc.author
-                                tags: doc.tags
-                                type: 'blog_post'
+                            if doc.status is 'published'
+                                searchFields =
+                                    title: doc.title
+                                    content: doc.content
+                                    excerpt: doc.excerpt
+                                    author: doc.author
+                                    tags: doc.tags
+                                    type: 'blog_post'
                         
                         when 'event'
                             searchFields =
@@ -166,19 +323,27 @@ module.exports =
                                 type: 'event'
                         
                         when 'product'
-                            searchFields =
-                                title: doc.title
-                                content: doc.content
-                                excerpt: doc.excerpt
-                                category: doc.category
-                                tags: doc.tags
-                                type: 'product'
+                            if doc.status is 'available'
+                                searchFields =
+                                    title: doc.title
+                                    content: doc.content
+                                    excerpt: doc.excerpt
+                                    category: doc.category
+                                    tags: doc.tags
+                                    type: 'product'
                         
                         when 'category', 'theme'
                             searchFields =
                                 name: doc.name
                                 description: doc.description
                                 type: doc.type
+                        
+                        when 'page'
+                            if doc.status is 'published'
+                                searchFields =
+                                    title: doc.title
+                                    content: doc.content
+                                    type: 'page'
                     
                     # Создаем поисковый индекс
                     if searchFields.title
@@ -198,37 +363,85 @@ module.exports =
                         words = text.split(/\W+/).filter (word) -> word.length > 2
                         
                         for word in words
-                            emit(word, {
+                            emit([domain, word], {
                                 _id: doc._id
                                 type: searchFields.type
                                 title: searchFields.title
                                 excerpt: searchFields.excerpt
                                 created_at: doc.created_at
+                                domain: domain
                             })
+                ).toString()
 
-    # Design документ для статистики
+    # Design документ для статистики с мультидоменностью
     statistics:
-        version: "1.0"
+        version: "2.0"
         views:
-            # Статистика по типам документов
+            # Статистика по типам документов с фильтром по домену
             by_type:
-                map: (doc) ->
-                    emit(doc.type, 1)
-                reduce: (keys, values) ->
+                map: ((doc) ->
+                    domain = doc.domain or 'default'
+                    emit([domain, doc.type], 1)
+                ).toString()
+                reduce: ((keys, values) ->
                     sum values
+                ).toString()
             
-            # Статистика просмотров блог постов
+            # Статистика просмотров блог постов с фильтром по домену
             blog_views:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'blog_post'
-                        emit(doc._id, doc.views or 0)
-                reduce: (keys, values) ->
+                        domain = doc.domain or 'default'
+                        emit([domain, doc._id], doc.views or 0)
+                ).toString()
+                reduce: ((keys, values) ->
                     sum values
+                ).toString()
             
-            # Статистика мероприятий по статусу
+            # Статистика мероприятий по статусу с фильтром по домену
             events_by_status:
-                map: (doc) ->
+                map: ((doc) ->
                     if doc.type is 'event'
-                        emit(doc.status, 1)
-                reduce: (keys, values) ->
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.status], 1)
+                ).toString()
+                reduce: ((keys, values) ->
+                    sum values
+                ).toString()
+            
+            # Статистика продаж товаров с фильтром по домену
+            product_sales:
+                map: ((doc) ->
+                    if doc.type is 'order' and doc.items
+                        domain = doc.domain or 'default'
+                        for item in doc.items
+                            emit([domain, item.product_id], item.quantity)
+                ).toString()
+                reduce: ((keys, values) ->
                     sum values
+                ).toString()
+
+    # Design документ для ревизий и аудита
+    audit:
+        version: "2.0"
+        views:
+            # Логи изменений по дате
+            by_date:
+                map: ((doc) ->
+                    if doc.type is 'audit_log'
+                        emit(doc.created_at, doc)
+                ).toString()
+            
+            # Логи по пользователю
+            by_user:
+                map: ((doc) ->
+                    if doc.type is 'audit_log'
+                        emit([doc.user_id, doc.created_at], doc)
+                ).toString()
+            
+            # Логи по действию
+            by_action:
+                map: ((doc) ->
+                    if doc.type is 'audit_log'
+                        emit([doc.action, doc.created_at], doc)
+                ).toString()