# Текущая задача проанализируй и доработай модуль: app/shared/AppLink Сейчас он не работат, его задача дать универсальную обёртку как для внутренних ссылок так и для внешних # файл с правилами https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/README.md # применяй правила: ## оформление ссылок a(href="[ссылка]") - не правильно router-link(to="[ссылка]") - не правильно app-link(to="[ссылка]") - правильно (должен быть подключен компанент: 'app-link': require 'app/shared/AppLink') ## Корневой каталог и мета данные Важно: мета данные добавляются через app/temp.coffe базовым тегоьм для vuejs является body, app/index.pug начинается с div, теги html, head, body ЗАПРЕЩЕНО использовать. ### пример кода app/temp.coffee ``` # обязательно подключение глобальных массивов globalThis.renderFns = require 'pug.json' globalThis.stylFns = require 'styl.json' # подключение мета информации (строго в данном фиде) document.head.insertAdjacentHTML 'beforeend','' document.head.insertAdjacentHTML 'beforeend','' document.head.insertAdjacentHTML('beforeend',' Кохи Борбад - Концертный зал Душанбе') # Настройка tailwind tailwind.config = require 'tailwind.config.js' # подключение основных стилей ## tailwind document.head.insertAdjacentHTML('beforeend','') ## базовой стиль приложения document.head.insertAdjacentHTML('beforeend','') # Маршруты routes = [ { path: '/', component: require 'app/pages/Home' } { path: '/events', component: require 'app/pages/Events' } { path: '/about', component: require 'app/pages/About' } { path: '/contacts', component: require 'app/pages/Contacts' } ] # Глобальное определение vuejs приложения app = Vue.createApp name: 'app' data: ()-> return { appState: events: [] featuredEvents: [] sliderEvents: [] loading: true error: null modalState: #управление модальными окнами isVisible: false component: null props: {} couchDBService: new CouchDBService() } beforeMount: ()-> debug.log "start beforeMount" # определение контекста vuejs приложения как глобальной переменной _ globalThis._ = @ # все глобальные переменные необходимые для работы определяем в data # и получаем доступ через _.* render: (new Function '_ctx', '_cache', renderFns['app/temp.pug'])() mounted: ->{} methods: {} components: 'themetoggle': require 'app/shared/ThemeToggle' 'multilevelmenu': require 'app/shared/MultiLevelMenu' 'imageslider': require 'app/shared/ImageSlider' app.use(VueRouter.createRouter({ routes: routes history: VueRouter.createWebHistory() scrollBehavior: (to, from, savedPosition) -> if savedPosition return savedPosition else return { x: 0, y: 0 } })) # подключаем в body ОБЯЗАТЕЛЬНО!!! app.mount('body') ``` ### Привер кода index.coffee для компанентов/страниц ``` # Важно загрузка стилей компонента/страницы document.head.insertAdjacentHTML('beforeend','') module.exports = name: 'BlogPage' # ВАЖНО загрузка шаблона через рендер функцию render: (new Function '_ctx', '_cache', renderFns['app/pages/Blog/index.pug'])() data: -> posts: [] loading: true error: null beforeMount: -> @loadBlogPosts() methods: loadBlogPosts: -> try @loading = true @posts = await AppDB.getBlogPosts(limit: 10) @loading = false catch error @error = "Ошибка загрузки постов: "+error @loading = false ``` ## определение функций в _deing документе при обновлении документа учитывай версионность ``` # Design документ для блог постов blog_posts: version: "1.1" views: # Все опубликованные блог посты published: map: ((doc) -> if doc.type is 'blog_post' and doc.status is 'published' emit(doc.created_at, doc)).toString() ``` ## Важно сохранять для seed-events.coffee debug = require('../../../utils/coffee/debug.coffee').default ## определение шаблонов для слотов template(#body) - не правильно template(v-slot:body) - не правильно template([body]) - правильно ## async в методах async loadData: -> - не правильно loadData: -> - правильно ## Радота с кодом всегда приводи полный листинг файлов при форматировании кода для отделения логических блоков используй 4 пробела (" ") следи за строгим соблюдением синтаксиса используемых языков (coffeescript, pug, stylus) в pug не используй многострочные вычисляемые атрибуты ``` :class="{ 'bg-blue-50 dark:bg-blue-900 text-blue-600 dark:text-blue-400': currentLanguage === language.code, 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700': currentLanguage !== language.code }" ``` - не правильно ``` :class="{'bg-blue-50 dark:bg-blue-900 text-blue-600 dark:text-blue-400': currentLanguage === language.code, 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700': currentLanguage !== language.code }" ``` - правильно ## работа с консолью и текстовыми константами/переменными используй конкатенацию (СТРОГО! ВАЖНО!) используй для вывода в консоль debug.log console.log "переменная temp = #{temp}" - не правильно debug.log "переменная temp = "+temp - правильно shareUrl = "https://twitter.com/intent/tweet?text=#{text}" - не правильно shareUrl = "https://twitter.com/intent/tweet?text="+text - правильно "#{@baseUrl}/#{@dbName}/_all_docs?include_docs=true" - не правильно @baseUrl+"/"+@dbName+"/_all_docs?include_docs=true" - правильно ## Цвета и управление темами во всех *.styl файлах используй цвета в виде переменных, определённых в файле tailwind.config.js ## Стили все глобальный настройки стилей, пиши в app/temp.styl в остальных файлах, строго стили необходимые только для данного компаонента ## Расположение статических файлов/изображений img(src="/images/hall-interior.jpg") - не правильно img(src="/assets/[domenName]/hall-interior.jpg") - правильно ## стиль написания классов .container.mx-auto.px-4 - не правильно div(class="container.mx-auto px-4") - правильно ## *не используй вызовы* Vue = require 'vue' VueRouter = require 'vue-router' * Подключение осуществлено глобально через файл doc.json ## git ВАЖНО для анализа кода бери версии файлов СТРОГО из репозитария: https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master , корневой каталог vue/ от него идут пути к файлам пример: в коде -> app/temp.coffee, в репозитарии -> vue/app/temp.coffee # Общее описание Универсаньная CMS для работы с couchdb как бекендом. CMS мультидоменная и мультиязычная. мультидоменность во все view через поле domain # общая структура проекта app/ ├── tailwind.config.js (настройка тем и Tailwind CSS) ├── temp.pug (основной layout) ├── temp.coffee (инициализация Vue и роутера) ├── temp.styl (стили которые сложно или не удобно сделать на Tailwind CSS или стили к однотипным элементам на stylus) ├── core/ - Каталог для хранения coffee файлов частей ядра системы, для улучшения чтения temp.coffee | ├── CouchdbClass.coffee | ... ├── page/ | ├── Home/ (главная страница) | | ├── index.coffee | | ├── index.pug | | ├── index.styl | ├── [другие_страницы]/ | ├── index.coffee | ├── index.pug | ├── index.styl └── shared/ ├── ThemeToggle/ | ├── index.coffee | ├── index.pug | ├── index.styl ├── MultiLevelMenu/ | ├── index.coffee | ├── index.pug | ├── index.styl ├── ImageSlider/ | ├── index.coffee | ├── index.pug | ├── index.styl ├── ModalWindow/ | ├── index.coffee | ├── index.pug | ├── index.styl ├── FormValidator/ | ├── index.coffee | ├── index.pug | ├── index.styl ├── FilterSort/ ├── index.coffee ├── index.pug ├── index.styl # Структура хранимых данных ## Описание всех хранимых объектов Базовый объект "Запись блога" (blog_post) coffee { _id: "blog_post_season_opening_2024_borbad" type: "blog_post" domain: ["borbad.s5l.ru", "global"] # определяет приоритет доменов по порядку language: ["ru", "en"] # поддерживаемые языки в порядке domain_priority title: ["Открытие нового сезона 2024", "Opening of the new season 2024"] content: ["# Добро пожаловать в новый творческий сезон!...", "# Welcome to the new creative season!..."] excerpt: ["Новый творческий сезон 2024 года в концертном зале Борбад", "A new creative season in 2024 at the Borbad Concert Hall"] seo: { description: ["Концертный зал Борбад - культурный центр Душанбе", "Borbad Concert Hall - Dushanbe Cultural Center"] keywords: [["концерты", "мероприятия", "Душанбе", "культура"], ["concerts", "events", "Dushanbe", "culture"]] title: ["Открытие нового сезона 2024 - Кохи Борбад", "Opening of the new season 2024 - Borbad Concert Hall"] } image: ["/assets/borbad.s5l.ru/posts/season-opening.jpg", "/assets/borbad.s5l.ru/posts/season-opening.jpg"] gallery: [[ "/assets/borbad.s5l.ru/gallery/post1.jpg" "/assets/borbad.s5l.ru/gallery/post2.jpg" ], [ "/assets/borbad.s5l.ru/gallery/post1.jpg" "/assets/borbad.s5l.ru/gallery/post2.jpg" ]] tags: [["новости", "сезон", "анонс"], ["news", "season", "announcement"]] category_id: "category_news_borbad" # ID конечной категории category_path: ["category_news_borbad"] # Полный путь категории author: ["Администрация Борбад", "Borbad Administration"] status: "published" # published | draft | archived featured: true reading_time: [5, 5] # Время чтения в минутах для каждого языка created_at: "2024-01-15T10:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" published_at: "2024-01-15T10:00:00.000Z" views: 156 likes: 23 shares: 45 } Наследник "Событие" (event) - расширяет blog_post coffee { _id: "event_beethoven_concert_2024_03_borbad" type: "event" # Наследует от blog_post domain: ["borbad.s5l.ru", "concert-hall.tj"] language: ["ru", "en", "tj"] title: ["Симфонический концерт: Бетховен и Чайковский", "Symphonic Concert: Beethoven and Tchaikovsky", "Консерти симфонӣ: Бетховен ва Чайковский"] content: ["# Великие композиторы\n\n## Программа концерта...", "# Great Composers\n\n## Concert Program...", "# Оҳангсозони бузург\n\n## Барномаи консерт..."] excerpt: ["Симфонический концерт с произведениями Бетховена и Чайковского", "Symphonic concert with works by Beethoven and Tchaikovsky", "Консерти симфонӣ бо осори Бетховен ва Чайковский"] seo: { description: ["Симфонический концерт в зале Борбад - классическая музыка", "Symphonic concert at Borbad Hall - classical music", "Консерти симфонӣ дар ҳолли Борбад - мусиқии классикӣ"] keywords: [["концерт", "симфоническая музыка", "классика"], ["concert", "symphonic music", "classical"], ["консерт", "мусиқии симфонӣ", "классикӣ"]] } image: ["/assets/borbad.s5l.ru/events/beethoven-concert.jpg", "/assets/borbad.s5l.ru/events/beethoven-concert.jpg", "/assets/borbad.s5l.ru/events/beethoven-concert.jpg"] gallery: [[ "/assets/borbad.s5l.ru/gallery/concert1.jpg" "/assets/borbad.s5l.ru/gallery/concert2.jpg" ], [ "/assets/borbad.s5l.ru/gallery/concert1.jpg" "/assets/borbad.s5l.ru/gallery/concert2.jpg" ], [ "/assets/borbad.s5l.ru/gallery/concert1.jpg" "/assets/borbad.s5l.ru/gallery/concert2.jpg" ]] tags: [["концерт", "симфоническая музыка", "классика"], ["concert", "symphonic music", "classical"], ["консерт", "мусиқии симфонӣ", "классикӣ"]] category_id: "category_classical_music_concerts_events_borbad" category_path: ["category_events_borbad", "category_concerts_events_borbad", "category_classical_music_concerts_events_borbad"] author: ["Симфонический оркестр Борбад", "Borbad Symphony Orchestra", "Оркестри симфонии Борбад"] status: "published" featured: true # Дополнительные поля для событий event_data: { event_date: "2024-03-20T19:00:00.000Z" # Дата и время начала end_date: "2024-03-20T21:00:00.000Z" # Дата и время окончания location: ["Большой зал", "Main Hall", "Ҳолли асосӣ"] venue_id: "venue_main_hall_borbad" address: { street: ["пр. Рудаки 22", "Rudaki Ave 22", "хиёбони Рӯдакӣ 22"] city: ["Душанбе", "Dushanbe", "Душанбе"] country: ["Таджикистан", "Tajikistan", "Тоҷикистон"] } coordinates: { lat: 38.5732 lng: 68.7734 } price: [500, 500, 500] # Цена для каждого языка currency: "TJS" available_tickets: 45 total_tickets: 300 status: "upcoming" # upcoming | ongoing | completed | cancelled registration_required: true max_attendees: 300 age_restriction: ["6+", "6+", "6+"] organizer: ["Симфонический оркестр Борбад", "Borbad Symphony Orchestra", "Оркестри симфонии Борбад"] performers: [["Фаррух Саидов (дирижер)", "Солисты оркестра"], ["Farrukh Saidov (conductor)", "Orchestra soloists"], ["Фаррух Саидов (дирижёр)", "Солистони оркестр"]] duration: 120 # Продолжительность в минутах } created_at: "2024-01-15T10:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" published_at: "2024-01-15T10:00:00.000Z" views: 289 } Наследник "Товар" (product) - расширяет blog_post coffee { _id: "product_tshirt_logo_2024_borbad" type: "product" # Наследует от blog_post domain: ["shop.borbad.s5l.ru", "borbad.s5l.ru"] language: ["ru", "en"] title: ["Футболка с логотипом Борбад", "Borbad Logo T-shirt"] content: ["## Качественная хлопковая футболка\n\nРазмеры: S, M, L, XL...", "## High-quality cotton t-shirt\n\nSizes: S, M, L, XL..."] excerpt: ["Фирменная футболка концертного зала с логотипом", "Official concert hall t-shirt with logo"] seo: { description: ["Футболка с логотипом концертного зала Борбад - сувениры", "T-shirt with Borbad concert hall logo - souvenirs"] keywords: [["футболка", "сувениры", "мерч"], ["t-shirt", "souvenirs", "merch"]] } image: ["/assets/borbad.s5l.ru/products/tshirt.jpg", "/assets/borbad.s5l.ru/products/tshirt.jpg"] gallery: [[ "/assets/borbad.s5l.ru/products/tshirt-front.jpg" "/assets/borbad.s5l.ru/products/tshirt-back.jpg" ], [ "/assets/borbad.s5l.ru/products/tshirt-front.jpg" "/assets/borbad.s5l.ru/products/tshirt-back.jpg" ]] tags: [["одежда", "сувениры", "мерч"], ["clothing", "souvenirs", "merch"]] category_id: "category_souvenirs_borbad" category_path: ["category_shop_borbad", "category_souvenirs_borbad"] author: ["Магазин Борбад", "Borbad Shop"] status: "published" featured: true # Дополнительные поля для товаров product_data: { price: [250, 250] # Цена для каждого языка currency: "TJS" compare_price: [350, 350] # Старая цена sku: "TSH-BRB-001" inventory: 50 status: "available" # available | out_of_stock | discontinued attributes: { sizes: [["S", "M", "L", "XL"], ["S", "M", "L", "XL"]] colors: [["белый", "черный", "красный"], ["white", "black", "red"]] material: [["100% хлопок"], ["100% cotton"]] brand: [["Борбад"], ["Borbad"]] } weight: 0.3 # Вес в кг dimensions: { length: 70 width: 50 height: 5 } shipping: { free_shipping: [false, false] shipping_cost: [50, 50] } variants: [ # Варианты товара { sku: "TSH-BRB-001-W" attributes: { size: "S", color: "белый" } price: [250, 250] inventory: 15 } ] } created_at: "2024-01-15T10:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" published_at: "2024-01-15T10:00:00.000Z" views: 134 } Наследник "Слайдер" (slide) - расширяет blog_post coffee { _id: "slide_01_borbad" type: "slide" # Наследует от blog_post domain: ["borbad.s5l.ru", "concert-hall.tj"] language: ["ru", "en"] title: ["Добро пожаловать в Кохи Борбад", "Welcome to Borbad Concert Hall"] content: ["## Современный концертный зал в сердце Душанбе\n\nМесто, где встречаются искусство и культура", "## Modern concert hall in the heart of Dushanbe\n\nA place where art and culture meet"] excerpt: ["Концертный зал Борбад - культурный центр Душанбе", "Borbad Concert Hall - Dushanbe Cultural Center"] seo: { description: ["Концертный зал Борбад в Душанбе", "Borbad Concert Hall in Dushanbe"] } image: ["/assets/borbad.s5l.ru/sliders/main-hall.jpg", "/assets/borbad.s5l.ru/sliders/main-hall.jpg"] gallery: [[], []] # Для слайдера обычно не используется tags: [["слайдер", "главная"], ["slider", "main"]] category_id: "category_sliders_borbad" category_path: ["category_sliders_borbad"] author: ["Администрация Борбад", "Borbad Administration"] status: "published" featured: false # Дополнительные поля для слайдеров slide_data: { order: 1 active: true button_text: ["Узнать больше", "Learn More"] button_link: ["/about", "/about"] button_style: "primary" # primary | secondary | outline text_color: ["#ffffff", "#ffffff"] text_position: ["center", "center"] # left | center | right overlay: [true, true] overlay_opacity: [0.4, 0.4] mobile_image: ["/assets/borbad.s5l.ru/sliders/main-hall-mobile.jpg", "/assets/borbad.s5l.ru/sliders/main-hall-mobile.jpg"] start_date: "2024-01-01T00:00:00.000Z" # Дата начала показа end_date: "2024-12-31T23:59:59.000Z" # Дата окончания показа target_audience: [["all"], ["all"]] # all | registered | specific } created_at: "2024-01-01T00:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" published_at: "2024-01-01T00:00:00.000Z" views: 0 # Для слайдеров обычно не отслеживается } Категория (category) - иерархическая структура coffee { _id: "category_classical_music_concerts_events_borbad" type: "category" domain: ["borbad.s5l.ru", "concert-hall.tj"] language: ["ru", "en", "tj"] name: ["Классическая музыка", "Classical Music", "Мусиқии классикӣ"] slug: ["classical-music", "classical-music", "musiqii-klasikī"] description: ["Симфонические концерты и классические произведения", "Symphonic concerts and classical works", "Консертҳои симфонӣ ва осори классикӣ"] image: ["/assets/borbad.s5l.ru/categories/classical-music.jpg", "/assets/borbad.s5l.ru/categories/classical-music.jpg", "/assets/borbad.s5l.ru/categories/classical-music.jpg"] icon: ["classical", "classical", "classical"] parent_id: "category_concerts_events_borbad" parent_path: ["category_events_borbad", "category_concerts_events_borbad"] level: 2 order: 1 children_count: 0 meta_title: ["Классическая музыка - Кохи Борбад", "Classical Music - Borbad Concert Hall", "Мусиқии классикӣ - Ҳолли Борбад"] meta_description: ["Симфонические концерты и классические произведения", "Symphonic concerts and classical works", "Консертҳои симфонӣ ва осори классикӣ"] active: true featured: true show_in_menu: true menu_order: 1 color: ["#3B82F6", "#3B82F6", "#3B82F6"] created_at: "2024-01-15T10:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" } Настройки домена (domain_settings) coffee { _id: "domain_settings_borbad_s5l_ru" type: "domain_settings" domain: "borbad.s5l.ru" # Уникальный домен name: ["Кохи Борбад - Концертный зал Душанбе", "Borbad Concert Hall - Dushanbe"] description: ["Официальный сайт концертного зала Борбад", "Official website of Borbad Concert Hall"] active: true priority: 1 theme: "borbad" languages: ["ru", "en", "tj"] # Поддерживаемые языки default_language: "ru" timezone: "Asia/Dushanbe" currency: "TJS" settings: { seo: { title_template: ["{page} - Кохи Борбад", "{page} - Borbad Concert Hall"] description: ["Концертный зал Борбад - культурный центр Душанбе", "Borbad Concert Hall - Dushanbe Cultural Center"] keywords: [["концерты", "мероприятия", "Душанбе", "культура"], ["concerts", "events", "Dushanbe", "culture"]] } social: { facebook: "https://facebook.com/borbad" instagram: "https://instagram.com/borbad" twitter: "https://twitter.com/borbad" } contact: { address: ["г. Душанбе, пр. Рудаки 22", "Rudaki Ave 22, Dushanbe"] phone: ["+992 37 123-45-67", "+992 37 123-45-67"] email: ["info@borbad.s5l.ru", "info@borbad.s5l.ru"] } features: { online_booking: true multi_language: true ecommerce: true } } created_at: "2024-01-15T10:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" } Пользователь (user) coffee { _id: "user_admin_main" type: "user" domain: "global" # Глобальный пользователь email: "admin@borbad.s5l.ru" name: ["Администратор Борбад", "Borbad Administrator"] role: "admin" active: true permissions: ["read", "write", "delete", "admin"] profile: { avatar: ["/assets/borbad.s5l.ru/avatars/admin.jpg", "/assets/borbad.s5l.ru/avatars/admin.jpg"] phone: ["+992 37 123-45-67", "+992 37 123-45-67"] position: ["Системный администратор", "System Administrator"] bio: ["Ответственный за техническую часть сайта", "Responsible for the technical part of the site"] } preferences: { language: "ru" notifications: true theme: "dark" timezone: "Asia/Dushanbe" } security: { last_password_change: "2024-01-01T00:00:00.000Z" two_factor_enabled: true login_attempts: 0 } domains_access: ["borbad.s5l.ru", "concert-hall.tj"] created_at: "2024-01-01T00:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" last_login: "2024-01-15T09:30:00.000Z" } Заказ (order) coffee { _id: "order_2024_001_borbad" type: "order" domain: "shop.borbad.s5l.ru" language: ["ru", "en"] user_id: "user_customer_ivanov" status: "completed" total: 1500 currency: "TJS" items: [ { product_id: "event_ticket_1" name: ["Билет на симфонический концерт", "Ticket for symphonic concert"] quantity: 2 price: 500 total: 1000 type: "ticket" } { product_id: "product_tshirt_logo_2024_borbad" name: ["Футболка с логотипом", "Logo t-shirt"] quantity: 1 price: 500 total: 500 type: "product" } ] customer_info: { name: ["Иван Иванов", "Ivan Ivanov"] email: "ivan@example.com" phone: ["+992 123-45-67", "+992 123-45-67"] } payment_info: { method: "card" transaction_id: "txn_123456" status: "paid" amount: 1500 currency: "TJS" payment_date: "2024-01-15T14:00:00.000Z" } shipping_info: { method: "pickup" address: null tracking_number: null } metadata: { ip_address: "192.168.1.100" user_agent: "Mozilla/5.0..." source: "website" } created_at: "2024-01-15T13:45:00.000Z" updated_at: "2024-01-15T14:00:00.000Z" } Настройка (setting) coffee { _id: "setting_seo_title_borbad_s5l_ru" type: "setting" domain: "borbad.s5l.ru" language: ["ru", "en"] key: "seo_title" value: ["Кохи Борбад - Концертный зал Душанбе", "Borbad Concert Hall - Dushanbe"] value_type: "string" # string | number | boolean | object | array is_global: false description: ["Заголовок сайта для SEO", "Site title for SEO"] category: "seo" group: "site_settings" editable: true created_at: "2024-01-01T00:00:00.000Z" updated_at: "2024-01-15T10:00:00.000Z" } Аудит (audit_log) coffee { _id: "audit_2024_001" type: "audit_log" domain: "global" user_id: "user_admin_main" action: "create" resource_type: "blog_post" resource_id: "blog_post_season_opening_2024_borbad" description: ["Создана новая запись блога 'Открытие нового сезона 2024'", "Created new blog post 'Opening of the new season 2024'"] ip_address: "192.168.1.1" user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" language: "ru" metadata: { old_value: null new_value: { title: ["Открытие нового сезона 2024", "Opening of the new season 2024"] status: "published" } changes: ["title", "status"] } created_at: "2024-01-15T10:00:00.000Z" } ## _desing документ для работы с данными https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/scripts/design-documents.coffee