]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Создание правки по вики
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 11 Feb 2025 11:20:29 +0000 (14:20 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 11 Feb 2025 11:20:29 +0000 (14:20 +0300)
erp24/config/web.php
erp24/controllers/WikiController.php
erp24/records/WikiCategory.php
erp24/views/wiki/_form.php
erp24/views/wiki/index.php
erp24/views/wiki/tree.php [new file with mode: 0644]
erp24/views/wiki/view.php

index c0b65feefacbf491c81cd85122cc2a0b6695a686..c6c3a0fc86916405ce718ab4f9a02344d98846c1 100644 (file)
@@ -41,8 +41,8 @@ $config = [
         ],
         'queue' => [
             'class' => Queue::class,
-            // 'dsn' => 'amqp://admin:3qqHK2MRgGgxUdVT61@rabbitmq-yii_erp24:5672',
-            'dsn' => 'amqp://admin:3qqHK2MRgGgxUdVT61@localhost:5672',
+            'dsn' => 'amqp://admin:3qqHK2MRgGgxUdVT61@rabbitmq-yii_erp24:5672',
+           // 'dsn' => 'amqp://admin:3qqHK2MRgGgxUdVT61@localhost:5672',
             'queueName' => 'telegram-queue',
             'as log' => \yii\queue\LogBehavior::class,
             'ttr' => 300, // Время для выполнения задания
@@ -95,6 +95,7 @@ $config = [
             'enablePrettyUrl' => true,
             'showScriptName' => false,
             'rules' => [
+                'wiki/<parent_cat_slug>/<article_slug>' => 'wiki/view',
             ],
         ],
     ],
index e48902cbc207ff8d7bb014fe18439f3b77174cca..cddee509f98c29d523c6fc94e3e3139b8a169531 100644 (file)
@@ -76,6 +76,8 @@ class WikiController extends Controller
      */
     public function actionView($parent_cat_slug, $article_slug)
     {
+        $categories = WikiCategory::find()->all();
+        $tree = $this->buildTree($categories);
         $category = WikiCategory::findOne(['slug' => $parent_cat_slug]);
         if (!$category) {
             throw new NotFoundHttpException('Category not found.');
@@ -86,7 +88,7 @@ class WikiController extends Controller
             throw new NotFoundHttpException('Article not found.');
         }
 
-        return $this->render('view', ['model' => $model]);
+        return $this->render('view', ['model' => $model, 'tree' => $tree]);
     }
 
     /**
index 7601035b0a5c0005b85826e476293c85dbd054a1..3df74747d093b4699488de997e76e90940dc0b81 100644 (file)
@@ -121,4 +121,15 @@ class WikiCategory extends \yii\db\ActiveRecord
     {
         return $this->hasMany(WikiCategory::class, ['parent_id' => 'id']);
     }
+    public function getParentCategories()
+    {
+        $categories = [];
+        $category = $this;
+        while ($category !== null) {
+            array_unshift($categories, $category);
+            $category = $this->parent;
+        }
+        return $categories;
+    }
+
 }
index 15ecddf82d4bed84471b29e55bf56041482cfd28..cf965f11c6983f25a1674c5d256b53e30c40f065 100644 (file)
@@ -47,7 +47,7 @@ $categoryList = getCategoriesWithHierarchy($categories);
 
     <?= $form->field($model, 'content')->widget(CKEditor::class, [
         'options' => ['rows' => 6],
-        'uploadUrl' => '/uploads',
+        'uploadUrl' => Yii::getAlias('@uploads')
     ]) ?>
 
 
index 65bc2d1ebe7fe62a5dcbcf0086e386d0dab1f815..ed28807802144c5da3b3445d2663d624f99cd1dc 100644 (file)
@@ -14,52 +14,6 @@ use yii\grid\GridView;
 $this->title = 'Документация';
 $this->params['breadcrumbs'][] = $this->title;
 $user = Yii::$app->user->identity;
-function renderTree($tree, $level = 0)
-{
-    if (empty($tree)) {
-        return '';
-    }
-
-    $html = '<ul class="tree-level-' . $level . '">';
-    foreach ($tree as $node) {
-        $category = $node['category'];
-        $articles = $node['articles'];
-        $children = $node['children'];
-
-        // Выводим категорию
-        $html .= '<li>';
-        $html .= Html::tag('div', Html::encode($category->title), ['class' => 'category-title']);
-
-        // Выводим описание категории (если есть)
-        if (!empty($category->description)) {
-            $html .= Html::tag('div', Html::encode($category->description), ['class' => 'category-description']);
-        }
-
-
-        if (!empty($articles)) {
-            $html .= '<ul class="articles-list">';
-            foreach ($articles as $article) {
-                $articleUrl = Url::to(['view', 'parent_cat_slug' => $category->slug, 'article_slug' => $article->slug], true);
-                $html .= '<li>';
-                $html .= Html::a(Html::encode($article->title), $articleUrl, ['class' => 'article-link']);
-
-                $html .= '</li>';
-            }
-            $html .= '</ul>';
-        }
-
-        if (!empty($children)) {
-            $html .= '<ul class="subcategories visible">';
-            $html .= renderTree($children, $level + 1);
-            $html .= '</ul>';
-        }
-
-        $html .= '</li>';
-    }
-    $html .= '</ul>';
-
-    return $html;
-}
 
 ?>
 
@@ -74,10 +28,10 @@ function renderTree($tree, $level = 0)
     <!-- Вывод дерева -->
     <div class="row">
         <div class="col-3 tree-container">
-            <?= renderTree($tree); ?>
+            <?= $this->render('tree', ['tree' => $tree]) ?>
         </div>
         <div class="col-9">
-           <?= GridView::widget([
+            <?= GridView::widget([
                 'dataProvider' => $dataProvider,
                 'filterModel' => $searchModel,
                 'columns' => [
@@ -91,103 +45,101 @@ function renderTree($tree, $level = 0)
                     ],
                     ['class' => 'yii\grid\ActionColumn'],
                 ],
-            ]); ?>
+            ]) ?>
         </div>
     </div>
-</div>
-
-<!-- Стили -->
-<style>
-    .tree-container {
-        font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
-        line-height: 1.6;
-    }
-
-    .tree-level-0 {
-        margin-left: 0;
-    }
-
-    .tree-level-1 {
-        margin-left: 20px;
-    }
-
-    .tree-level-2 {
-        margin-left: 40px;
-    }
-
-    .category-title {
-        font-weight: bold;
-        cursor: pointer;
-        padding: 8px 12px;
-        background-color: #f4f4f4;
-        border-radius: 4px;
-        transition: background-color 0.3s ease;
-    }
-
-    .category-title:hover {
-        background-color: #e0e0e0;
-    }
-
-    .category-description {
-        color: #666;
-        font-size: 0.9em;
-        margin-top: 4px;
-    }
-
-    .article-link {
-        display: block;
-        padding: 6px 12px;
-        text-decoration: none;
-        color: #337ab7;
-        border-radius: 4px;
-        transition: background-color 0.3s ease, color 0.3s ease;
-    }
-
-    .article-link:hover {
-        background-color: #e0e0e0;
-        color: #23527c;
-    }
 
-    .article-description {
-        color: #666;
-        font-size: 0.9em;
-        margin-top: 4px;
-    }
-
-    .subcategories {
-        list-style-type: none;
-        padding-left: 20px;
-        transition: max-height 0.3s ease;
-        overflow: hidden;
-    }
-
-    .subcategories.hidden {
-        max-height: 0;
-    }
-
-    .subcategories.visible {
-        margin-bottom: 20px;
-    }
 
+    <style>
+        .tree-container {
+            font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
+            line-height: 1.6;
+        }
+        .tree-level-0 {
+            margin-left: 0;
+        }
+        .tree-level-1 {
+            margin-left: 20px;
+        }
+        .tree-level-2 {
+            margin-left: 40px;
+        }
+        /* Категории */
+        .category-title {
+            font-weight: bold;
+            cursor: pointer;
+            padding: 8px 12px;
+            background-color: #f4f4f4;
+            border-radius: 4px;
+            transition: background-color 0.3s ease;
+        }
+        .category-title:hover {
+            background-color: #e0e0e0;
+        }
 
-</style>
+        /* Стрелочка */
+        .category-title.toggleable svg {
+            margin-left: 8px;
+            transition: transform 0.3s ease;
+            transform: rotate(0deg);
+        }
+        .category-title.toggleable.open svg {
+            transform: rotate(90deg);
+        }
 
-<!-- JavaScript для раскрывающегося дерева -->
-<script>
-    document.addEventListener('DOMContentLoaded', function () {
-        const categoryTitles = document.querySelectorAll('.category-title');
-        categoryTitles.forEach(title => {
-            title.addEventListener('click', function () {
-                const parentLi = this.closest('li');
-                const subcategories = parentLi.querySelector('.subcategories');
+        /* Скрытые подкатегории и статьи */
+        .subcategories.hidden {
+            display: none;
+        }
+        .subcategories.visible {
+            display: block;
+        }
 
-                if (subcategories) {
-                    subcategories.classList.toggle('visible');
-                    subcategories.classList.toggle('hidden');
-                }
+        /* Статьи */
+        .articles-list {
+            list-style-type: none;
+            padding-left: 20px;
+        }
+        .article-link {
+            display: block;
+            padding: 6px 12px;
+            text-decoration: none;
+            color: #337ab7;
+            border-radius: 4px;
+            transition: background-color 0.3s ease, color 0.3s ease;
+        }
+        .article-link:hover {
+            background-color: #e0e0e0;
+            color: #23527c;
+        }
+        .article-description {
+            color: #666;
+            font-size: 0.9em;
+            margin-top: 4px;
+        }
+    </style>
+    <script>
+        function copyToClipboard(text) {
+            navigator.clipboard.writeText(text).then(function() {
+                alert('Ссылка скопирована: ' + text);
+            }, function(err) {
+                console.error('Ошибка копирования: ', err);
+            });
+        }
+        document.addEventListener('DOMContentLoaded', function () {
+            const categoryTitles = document.querySelectorAll('.category-title.toggleable');
+            categoryTitles.forEach(title => {
+                title.addEventListener('click', function () {
+                    const parentLi = this.closest('li');
+                    const subcategories = parentLi.querySelector('.subcategories');
+
+                    if (subcategories) {
+                        subcategories.classList.toggle('visible');
+                        subcategories.classList.toggle('hidden');
+                        this.classList.toggle('open');
+                    }
+                });
             });
         });
-    });
-</script>
-
+    </script>
 
diff --git a/erp24/views/wiki/tree.php b/erp24/views/wiki/tree.php
new file mode 100644 (file)
index 0000000..b7b4bcd
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+use yii\helpers\Html;
+use yii\helpers\Url;
+
+/** @var array $tree */
+/** @var int $level */
+
+if (!isset($level)) {
+    $level = 0;
+}
+if (empty($tree)) {
+    return '';
+}
+?>
+
+<ul class="tree-level-<?= $level ?>">
+    <?php foreach ($tree as $node): ?>
+        <?php
+        $category = $node['category'];
+        $articles = $node['articles'];
+        $children = $node['children'];
+        $hasContent = !empty($articles) || !empty($children);
+        ?>
+        <li>
+            <!-- Категория с кнопкой раскрытия/сворачивания -->
+            <div
+                    class="category-title open <?= $hasContent ? 'toggleable' : '' ?>"
+                    data-has-content="<?= $hasContent ? 'true' : 'false' ?>"
+            >
+                <?= Html::encode($category->title) ?>
+                <?php if ($hasContent): ?>
+                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
+                        <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"/>
+                    </svg>
+                <?php endif; ?>
+            </div>
+
+
+            <?php if (!empty($category->description)): ?>
+                <div class="category-description"><?= Html::encode($category->description) ?></div>
+            <?php endif; ?>
+
+            <?php if ($hasContent): ?>
+                <ul class="subcategories visible">
+                    <!-- Статьи -->
+                    <?php if (!empty($articles)): ?>
+                        <ul class="articles-list">
+                            <?php foreach ($articles as $article): ?>
+                                <li>
+                                    <?= Html::a(Html::encode($article->title), Url::to([
+                                        'view',
+                                        'parent_cat_slug' => $category->slug,
+                                        'article_slug' => $article->slug
+                                    ], true), ['class' => 'article-link']) ?>
+                                </li>
+                            <?php endforeach; ?>
+                        </ul>
+                    <?php endif; ?>
+
+                    <!-- Подкатегории -->
+                    <?php if (!empty($children)): ?>
+                        <?= $this->render('tree', ['tree' => $children, 'level' => $level + 1]) ?>
+                    <?php endif; ?>
+                </ul>
+            <?php endif; ?>
+        </li>
+    <?php endforeach; ?>
+</ul>
index 844b23b01e8840a32c1d8004a41a1f4538f05747..6f59abeddbd99147c78bb5d874570c41829e2105 100644 (file)
@@ -3,13 +3,15 @@
 use yii\helpers\Html;
 use yii\helpers\Url;
 use yii\web\YiiAsset;
-use yii\widgets\DetailView;
+
 use yii\web\View;
 use yii\bootstrap5\Button;
 use yii\bootstrap5\Alert;
 
 /** @var View $this */
 /** @var yii_app\records\WikiArticle $model */
+/** @var array $tree */
+
 
 $this->title = $model->title;
 $this->params['breadcrumbs'][] = ['label' => 'Wiki Articles', 'url' => ['index']];
@@ -19,47 +21,127 @@ $articleUrl = Url::to(['view', 'parent_cat_slug' => $model->category->slug, 'art
 YiiAsset::register($this);
 ?>
 
-<div class="wiki-article-view p-4 bg-white rounded shadow-sm">
-    <div class="d-flex justify-content-between align-items-center mb-3">
-        <h1 class="mb-0">
-            <?= Html::encode($this->title) ?>
-            <button class="btn btn-outline-secondary btn-sm" onclick="copyToClipboard('<?= $articleUrl ?>')">
-                <svg  id="Layer_1" xmlns="http://www.w3.org/2000/svg"
-                      xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-                      viewBox="0 0 115.77 122.88" style="enable-background:new 0 0 115.77 122.88" xml:space="preserve">
+<div class="wiki-article-view p-4 ">
+    <?= Html::a('Назад', ['index'], ['class' => 'btn btn-secondary mb-4']) ?>
+    <div class="row">
+        <div class="col-3 tree-container">
+            <?= $this->render('tree', ['tree' => $tree]) ?>
+        </div>
+        <div class="col-9">
+            <div class="d-flex justify-content-between align-items-center mb-3">
+                <h1 class="mb-0">
+                    <?= Html::encode($this->title) ?>
+                    <button class="btn btn-outline-secondary btn-sm" onclick="copyToClipboard('<?= $articleUrl ?>')">
+                        <svg  id="Layer_1" xmlns="http://www.w3.org/2000/svg"
+                              xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+                              viewBox="0 0 115.77 122.88" style="enable-background:new 0 0 115.77 122.88" xml:space="preserve">
                     <style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style>
-                    <g><path class="st0" d="M89.62,13.96v7.73h12.19h0.01v0.02c3.85,0.01,7.34,1.57,9.86,
+                            <g><path class="st0" d="M89.62,13.96v7.73h12.19h0.01v0.02c3.85,0.01,7.34,1.57,9.86,
                     4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02v0.02 v73.27v0.01h-0.02c-0.01,3.84-1.57,
                     7.33-4.1,9.86c-2.51,2.5-5.98,4.06-9.82,4.07v0.02h-0.02h-61.7H40.1v-0.02
                     c-3.84-0.01-7.34-1.57-9.86-4.1c-2.5-2.51-4.06-5.98-4.07-9.82h-0.02v-0.02V92.51H13.96h-0.01v-0.02c-3.84-0.01-7.34-1.57-9.86-4.1 c-2.5-2.51-4.06-5.98-4.07-9.82H0v-0.02V13.96v-0.01h0.02c0.01-3.85,1.58-7.34,4.1-9.86c2.51-2.5,5.98-4.06,9.82-4.07V0h0.02h61.7 h0.01v0.02c3.85,0.01,7.34,1.57,9.86,4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02V13.96L89.62,13.96z M79.04,21.69v-7.73v-0.02h0.02 c0-0.91-0.39-1.75-1.01-2.37c-0.61-0.61-1.46-1-2.37-1v0.02h-0.01h-61.7h-0.02v-0.02c-0.91,0-1.75,0.39-2.37,1.01 c-0.61,0.61-1,1.46-1,2.37h0.02v0.01v64.59v0.02h-0.02c0,0.91,0.39,1.75,1.01,2.37c0.61,0.61,1.46,1,2.37,1v-0.02h0.01h12.19V35.65 v-0.01h0.02c0.01-3.85,1.58-7.34,4.1-9.86c2.51-2.5,5.98-4.06,9.82-4.07v-0.02h0.02H79.04L79.04,21.69z M105.18,108.92V35.65v-0.02 h0.02c0-0.91-0.39-1.75-1.01-2.37c-0.61-0.61-1.46-1-2.37-1v0.02h-0.01h-61.7h-0.02v-0.02c-0.91,0-1.75,0.39-2.37,1.01 c-0.61,0.61-1,1.46-1,2.37h0.02v0.01v73.27v0.02h-0.02c0,0.91,0.39,1.75,1.01,2.37c0.61,0.61,1.46,1,2.37,1v-0.02h0.01h61.7h0.02 v0.02c0.91,0,1.75-0.39,2.37-1.01c0.61-0.61,1-1.46,1-2.37h-0.02V108.92L105.18,108.92z"/>
-                    </g></svg>
-            </button>
-        </h1>
-        <?= Html::a('Назад', ['index'], ['class' => 'btn btn-secondary']) ?>
-    </div>
+                            </g></svg>
+                    </button>
+                </h1>
 
-    <div class="text-muted mb-3">
-        <strong>Автор:</strong> <?= Html::encode($model->created_by) ?> |
-        <strong>Дата создания:</strong> <?= date('d.m.Y H:i', strtotime($model->created_at)) ?>
-    </div>
+            </div>
+
+            <div class="text-muted mb-3">
+                <strong>Автор:</strong> <?= Html::encode($model->created_by) ?> |
+                <strong>Дата создания:</strong> <?= date('d.m.Y H:i', strtotime($model->created_at)) ?>
+            </div>
+
+            <div class="article-content border p-3 rounded bg-light">
+                <?= nl2br($model->content) ?>
+            </div>
+            <?php if ($user->group_id  == 81) : ?>
+                <div class="mt-4">
+                    <?= Html::a('Редактировать', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
+                    <?= Html::a('Удалить', ['delete', 'id' => $model->id], [
+                        'class' => 'btn btn-danger',
+                        'data' => [
+                            'confirm' => 'Вы уверены, что хотите удалить статью?',
+                            'method' => 'post',
+                        ],
+                    ]) ?>
+                </div>
+            <?php endif; ?>
+
+        </div>
 
-    <div class="article-content border p-3 rounded bg-light">
-        <?= nl2br($model->content) ?>
-    </div>
-    <?php if ($user->group_id  == 81) : ?>
-    <div class="mt-4">
-        <?= Html::a('Редактировать', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
-        <?= Html::a('Удалить', ['delete', 'id' => $model->id], [
-            'class' => 'btn btn-danger',
-            'data' => [
-                'confirm' => 'Вы уверены, что хотите удалить статью?',
-                'method' => 'post',
-            ],
-        ]) ?>
     </div>
-    <?php endif; ?>
+
+
 </div>
 
+<style>
+    .tree-container {
+        font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
+        line-height: 1.6;
+    }
+    .tree-level-0 {
+        margin-left: 0;
+    }
+    .tree-level-1 {
+        margin-left: 20px;
+    }
+    .tree-level-2 {
+        margin-left: 40px;
+    }
+    /* Категории */
+    .category-title {
+        font-weight: bold;
+        cursor: pointer;
+        padding: 8px 12px;
+        background-color: #f4f4f4;
+        border-radius: 4px;
+        transition: background-color 0.3s ease;
+    }
+    .category-title:hover {
+        background-color: #e0e0e0;
+    }
+
+    /* Стрелочка */
+    .category-title.toggleable svg {
+        margin-left: 8px;
+        transition: transform 0.3s ease;
+        transform: rotate(0deg);
+    }
+    .category-title.toggleable.open svg {
+        transform: rotate(90deg);
+    }
+
+    /* Скрытые подкатегории и статьи */
+    .subcategories.hidden {
+        display: none;
+    }
+    .subcategories.visible {
+        display: block;
+    }
+
+    /* Статьи */
+    .articles-list {
+        list-style-type: none;
+        padding-left: 20px;
+    }
+    .article-link {
+        display: block;
+        padding: 6px 12px;
+        text-decoration: none;
+        color: #337ab7;
+        border-radius: 4px;
+        transition: background-color 0.3s ease, color 0.3s ease;
+    }
+    .article-link:hover {
+        background-color: #e0e0e0;
+        color: #23527c;
+    }
+    .article-description {
+        color: #666;
+        font-size: 0.9em;
+        margin-top: 4px;
+    }
+</style>
 <script>
     function copyToClipboard(text) {
         navigator.clipboard.writeText(text).then(function() {
@@ -68,4 +150,19 @@ YiiAsset::register($this);
             console.error('Ошибка копирования: ', err);
         });
     }
+    document.addEventListener('DOMContentLoaded', function () {
+        const categoryTitles = document.querySelectorAll('.category-title.toggleable');
+        categoryTitles.forEach(title => {
+            title.addEventListener('click', function () {
+                const parentLi = this.closest('li');
+                const subcategories = parentLi.querySelector('.subcategories');
+
+                if (subcategories) {
+                    subcategories.classList.toggle('visible');
+                    subcategories.classList.toggle('hidden');
+                    this.classList.toggle('open');
+                }
+            });
+        });
+    });
 </script>