Browse Source

change: 产品搜索页面

kindring 2 years ago
parent
commit
1d556c3e1e

+ 4 - 4
map/adminSideBar.js

@@ -53,12 +53,12 @@ export const adminMenus = [
       {
         key: 'searchPages',
         title: '文章中心',
-        path: '/manger/product'
+        path: '/manger/news'
       },
       {
-        key: 'searchSolution',
-        title: '新闻中心',
-        path: '/manger/product'
+        key: 'addPage',
+        title: '新增文章',
+        path: '/manger/news/add'
       },
       {
         key: 'productType',

+ 1 - 0
nuxt.config.js

@@ -60,6 +60,7 @@ export default {
     ],
     plugins: [
       "@plugins/svg-icon.js",
+      { src: "@plugins/ckeditor.js", mode: "client" ,ssr: false}
       // {src: '~/plugins/vue-pdf.js', ssr: false}
     ],
     // api中间件

+ 2 - 0
package.json

@@ -9,6 +9,8 @@
     "generate": "nuxt generate"
   },
   "dependencies": {
+    "@ckeditor/ckeditor5-build-classic": "^39.0.0",
+    "@ckeditor/ckeditor5-vue2": "^3.0.1",
     "@nuxtjs/axios": "^5.12.2",
     "ant-design-vue": "^1.6.5",
     "body-parser": "^1.20.2",

+ 51 - 0
pages/manger/news/add.vue

@@ -0,0 +1,51 @@
+<script>
+// import editor from "@ckeditor/ckeditor5-build-classic";
+// import "@ckeditor/ckeditor5-build-classic/build/translations/ja.js";
+// import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
+
+// Vue.use( CKEditor );
+import RoundedTitle from "../../../components/public/roundedTitle.vue";
+
+let ClassicEditor;
+if (process.client) {
+  ClassicEditor = require('@ckeditor/ckeditor5-build-classic')
+}
+
+export default {
+  name: "add",
+  components: {
+    RoundedTitle
+    // Use the <ckeditor> component in this view.
+
+  },
+  data(){
+    return {
+      editor: ClassicEditor,
+      editorData: '<p>文章内容</p>',
+      editorConfig: {
+        language: "zh-cn"
+      }
+    }
+  }
+}
+</script>
+
+<template>
+<div class="w-full p-2">
+  <rounded-title class="text-xl">
+    <span>新增文章</span>
+    <a href="/manger/news"
+       class="px-10 h-full ml-5 rounded bg-blue-400 text-white cursor-pointer
+        hover:text-orange-500 ">文章中心</a>
+  </rounded-title>
+  <div class="page-content-box w-full mt-2 p-0.5  rounded bg-white">
+    <ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
+  </div>
+</div>
+</template>
+
+<style scoped>
+.page-content-box{
+  min-height: 500px;
+}
+</style>

+ 71 - 15
pages/manger/news/index.vue

@@ -33,6 +33,11 @@ const newsColumns = [
     width: '20%',
     scopedSlots: {customRender: 'image'},
   },
+  {
+    title: "文章作者",
+    dataIndex: 'source',
+    width: '10%',
+  },
   {
     title: "操作",
     scopedSlots: {customRender: 'operation'},
@@ -45,9 +50,19 @@ export default {
   computed: {
     // 产品类型数据
     newsTypes(){
-      let arr = this.$store.getters.allNewsTypes;
-      // 添加 all
-      arr.unshift({text: '全部', key: 'all' });
+      let arr = [];
+      if (this.form.pType.val === dbField_esm.db_base.newsType.all){
+        arr = this.$store.getters.allNewsTypes;
+      }else if (this.form.pType.val === dbField_esm.db_base.newsType.news){
+        arr = this.$store.getters.newsTypes;
+      }else if (this.form.pType.val === dbField_esm.db_base.newsType.solution){
+        arr = this.$store.getters.solutionTypes;
+      }
+      if (arr[0].key !== 'all'){
+        // 添加 all
+        arr.unshift({text: '全部', key: 'all' });
+      }
+
       return arr;
     },
   },
@@ -61,13 +76,15 @@ export default {
       total: 0,
       form: {
         pType: {
-          val: '',
-          oldVal: '',
-          init: '',
+          val: dbField_esm.db_base.newsType.all,
+          oldVal: dbField_esm.db_base.newsType.all,
+          init: dbField_esm.db_base.newsType.all,
           msg: '',
           state: 0,
           options: [
-
+            {text: '全部', key: dbField_esm.db_base.newsType.all},
+            {text: '新闻', key: dbField_esm.db_base.newsType.news},
+            {text: '解决方案', key: dbField_esm.db_base.newsType.solution},
           ]
         },
         key: {
@@ -95,8 +112,8 @@ export default {
       key: '',
       type: 'all'
     };
-    console.log('搜索产品数据');
-    let [err,res] = await handle(axios.get(baseUrl + apiMap.searchProduct.path,{params: searchParam}));
+    console.log('搜索文章数据');
+    let [err,res] = await handle(axios.get(baseUrl + apiMap.searchAllNews.path,{params: searchParam}));
     if(err){
       console.error(err);
       return {};
@@ -136,7 +153,7 @@ export default {
     // 搜索
     async searchExecute(params = {}){
       let err,res;
-      let url = apiMap.searchNews.path;
+      let url = apiMap.searchAllNews.path;
       console.log(params);
       // 如果没有传入参数,则使用表单数据
       if(isEmpty(params.key)){
@@ -145,6 +162,9 @@ export default {
       if(isEmpty(params.type)){
         params.type = this.form.type.oldVal;
       }
+      if(isEmpty(params.pType)){
+        params.pType = this.form.pType.oldVal;
+      }
       params.p = this.page;
       params.l = this.pageSize;
       console.log(`搜索产品数据:${JSON.stringify(params)}`);
@@ -159,6 +179,7 @@ export default {
         console.log(`搜索成功`)
         this.form.key.oldVal = params.key;
         this.form.type.oldVal = params.type;
+        this.form.pType.oldVal = params.pType;
         if (params.p === 1){
           this.$message.success('搜索成功');
           this.total = result.total;
@@ -192,8 +213,33 @@ export default {
       this.searchExecute({
         key: this.form.key.val,
         type: this.form.type.val,
+        pType: this.form.pType.val
       });
     },
+    onPTypeChange(){
+      console.log('文章主类型改变');
+      console.log(this.newsTypes);
+      this.form.type.val = this.newsTypes[0].key;
+      this.form.type.oldVal = this.newsTypes[0].key;
+      this.form.type.init = this.newsTypes[0].key;
+      this.form.type.options = this.newsTypes;
+      this.$nextTick(()=>{
+        // this.form.type.val = this.newsTypes[0].key;
+        // this.form.type.oldVal = this.newsTypes[0].key;
+        // this.form.type.init = this.newsTypes[0].key;
+        // this.form.type.options = this.newsTypes;
+        this.searchExecute({
+          pType: this.form.pType.val
+        });
+      })
+    },
+    onTypeChange(){
+      this.$nextTick(()=>{
+        this.searchExecute({
+          type: this.form.type.val
+        });
+      })
+    },
     refreshHandel(){
       this.page = 1;
       this.searchExecute();
@@ -202,6 +248,10 @@ export default {
       let type = this.newsTypes.find(item=>item.key === key);
       return type ? type.text : '';
     },
+    getTypeText(key){
+      let type = this.form.type.options.find(item=>item.key === key);
+      return type ? type.text : key;
+    }
 
   }
 }
@@ -218,10 +268,16 @@ export default {
       <div class="w-full flex h-14 items-center justify-between border-b">
 
         <div class="flex">
+<!--          文章主分类-->
+          <a-radio-group class="flex flex-shrink-0  items-center" v-model="form.pType.val" @change="onPTypeChange">
+            <a-radio-button class="" :value="item.key" v-for="item in form.pType.options" :key="item.key">{{item.text}}</a-radio-button>
+          </a-radio-group>
+
           <table-select
-            class="w-48 mx-3"
+            class="w-48 !mx-3 flex-shrink-0"
             :options="form.type.options"
             v-model="form.type.val"
+            @change="onTypeChange"
           />
           <a-input-search class="!ml-2 w-64" type="text" allow-clear placeholder="产品关键字"
                           @search="onSearchHandle"
@@ -242,8 +298,8 @@ export default {
           :pagination="false"
           :data-source="dataList"
         >
-          <template slot="proType" slot-scope="text">
-            <span>{{getProTypeText(text)}}</span>
+          <template slot="newsType" slot-scope="text">
+            <span>{{getTypeText(text)}}</span>
           </template>
 
           <template slot="image" slot-scope="text,record">
@@ -258,11 +314,11 @@ export default {
           </template>
           <template class="flex justify-center" slot="operation" slot-scope="text,record">
             <a-button  type="primary">
-              <a :href="`/manger/product/info?id=${record.id}`">产品详情</a>
+              <a :href="`/manger/product/info?id=${record.id}`">文章详情</a>
             </a-button>
 
             <a-button class="mx-3" type="primary">
-              <a :href="`/manger/product/edit?id=${record.id}`">编辑产品</a>
+              <a :href="`/manger/product/edit?id=${record.id}`">编辑文章</a>
             </a-button>
 
           </template>

+ 18 - 0
pages/manger/news/info.vue

@@ -0,0 +1,18 @@
+<script>
+export default {
+  name: "newsInfo",
+  data(){
+    return {}
+  }
+}
+</script>
+
+<template>
+  <div class="w-full">
+
+  </div>
+</template>
+
+<style scoped>
+
+</style>

+ 1 - 1
pages/manger/product/index.vue

@@ -209,7 +209,7 @@ export default {
 
         <div class="flex">
           <table-select
-            class="w-48 mx-3"
+            class="w-48 !mx-3 flex-shrink-0"
             :options="form.type.options"
             v-model="form.type.val"
           />

+ 4 - 0
plugins/ckeditor.js

@@ -0,0 +1,4 @@
+
+import Vue from 'vue'
+import CKEditor from '@ckeditor/ckeditor5-vue2'
+Vue.use(CKEditor)

+ 4 - 1
server/control/c_news.js

@@ -5,6 +5,7 @@ const log = require("../logger").logger("c_solution","info");
 
 const d_news = require("../database/d_news");
 const d_product = require("../database/d_product");
+const {filePathToUrl} = require("../tools/filePathTool");
 
 async function addReadNum(newId){
   let [err,res] = await handle(d_news.addReadNum(newId));
@@ -26,12 +27,14 @@ async function searchNewsByMini(type, key, p, l){
     _params.key = key
   }
 
+
   return await searchHandle(
     '搜索文章失败',
     d_news.searchAllNewsMini,
     _params,
     p,
-    l);
+    l,
+  );
 }
 
 module.exports = {

+ 50 - 15
server/control/c_solution.js

@@ -2,7 +2,10 @@ const {searchHandle} = require('../tools/searchSql');
 const {handle} = require('../tools/handle_cjs');
 const d_solution = require("../database/d_solution");
 const codeMap = require("../map/rcodeMap");
-const {isEmpty} = require("../tools/typeTool_cjs");
+const {isEmpty, toNumber} = require("../tools/typeTool_cjs");
+const {filePathToUrl} = require("../tools/filePathTool");
+const {newsType} = require("../../map/newMap");
+const dbField = require("../map/dbField");
 const log = require("../logger").logger("c_solution","info")
 
 /**
@@ -64,7 +67,16 @@ async function searchSolution(type, key, p, l)
     d_solution.searchSolution,
     _params,
     p,
-    l);
+    l,
+    (item)=>{
+      if(item.coverPath){
+        item.coverPath = filePathToUrl(item.coverType,item.coverPath);
+      }else{
+        item.coverPath = '';
+      }
+
+      return item;
+    });
 }
 
 async function searchNews(type, key, p, l)
@@ -87,36 +99,59 @@ async function searchNews(type, key, p, l)
     d_solution.searchSolution,
     _params,
     p,
-    l);
+    l,
+    (item)=>{
+      if(item.coverPath){
+        item.coverPath = filePathToUrl(item.coverType,item.coverPath);
+      }else{
+        item.coverPath = '';
+      }
+
+      return item;
+    }
+  );
 }
 
 async function searchAllNews(pType,type, key, p, l){
   p = p || 1;
   l = l || 10;
   let _params = { }
-  if(pType !== 'all'){
-    _params.pType = type;
-  }
+
   if(type !== 'all'){
     _params.type = type;
   }
   if(key){
     _params.key = key
   }
-
-  if(isEmpty(_params)){
-    return [
-      {
-        eCode:codeMap.NotParam,
-        eMsg:`搜索文章参数异常`
-      },null]
+  pType = toNumber(pType);
+  if(pType === dbField.db_base.newsType.news){
+    log.info(`新闻 未知${pType}`);
+    _params.parentType = dbField.db_base.newsType.news;
+  }else if(pType === dbField.db_base.newsType.solution){
+    log.info(`解决方案 未知${pType}`);
+    _params.parentType = dbField.db_base.newsType.solution;
+  }else{
+    // 不区分主类别
+    log.info(`pType 未知${pType} ${typeof pType}}`);
   }
+
+
   return await searchHandle(
     '搜索文章失败',
     d_solution.searchSolution,
     _params,
     p,
-    l);
+    l,
+    (item)=>{
+      if(item.coverPath){
+        item.coverPath = filePathToUrl(item.coverType,item.coverPath);
+      }else{
+        item.coverPath = '';
+      }
+
+      return item;
+    }
+  );
 }
 
 module.exports = {
@@ -124,6 +159,6 @@ module.exports = {
   searchSolution,
   searchNews,
   searchAllNews,
-  getSolutionInfo
+  getSolutionInfo,
 }
 

+ 1 - 1
server/database/d_base.js

@@ -38,7 +38,7 @@ function getCarouselById(id){
                 hfy_files as f
             WHERE
                 c.fileId = f.fileId
-                c.id = ?
+                and c.id = ?
             `;
   let values = [id];
   return mysql.pq(sql,values);

+ 25 - 16
server/database/d_solution.js

@@ -31,24 +31,32 @@ function searchSolution(type='array',searchParam,page,limit){
   let sql;
   let values = [];
   if(type === 'count'){
-    sql = `select count(*) as total `;
+    sql = `
+      select
+        count(*) as total
+      FROM hfy_news AS news
+          INNER JOIN hfy_news_type AS n_type
+          ON news.type_id = n_type.type_id`;
   }else{
-    sql = `select
-    news.id,
-    news.remark,
-    news.title as name,
-    news.image,
-    news.source,
-    news.sourceType,
-    n_type.type_key
+    sql = `
+      SELECT
+        news.id,
+        news.remark,
+        news.title,
+        news.title as name,
+        news.image,
+        news.coverId,
+        f.filePath as coverPath,
+        f.fileType as coverType,
+        news.source,
+        news.sourceType,
+        n_type.type_key
+      FROM hfy_news AS news
+        LEFT JOIN hfy_files as f ON news.coverId = f.fileId
+        INNER JOIN hfy_news_type AS n_type ON news.type_id = n_type.type_id
     `;
   }
-  sql += `
-   from
-   hfy_news as news ,
-   hfy_news_type as n_type
-  `
-  sql += ` where news.type_id = n_type.type_id`
+  sql += ` where 1=1 `
   if(searchParam.parentType) {
     sql += ` and n_type.parent_type = ?`
     values.push(searchParam.parentType);
@@ -62,6 +70,8 @@ function searchSolution(type='array',searchParam,page,limit){
     sql += ` and n_type.type_key = ?`
     values.push(searchParam.type)
   }
+  // console.log(sql);
+  // console.log(values);
   return searchSql(mysql.pq,type,sql,values,limit,page);
 }
 
@@ -82,5 +92,4 @@ module.exports = {
   loadSolution,
   searchSolution,
   getSolutionInfo
-
 }

+ 1 - 2
server/router/r_news.js

@@ -39,10 +39,9 @@ router.get(
       let err, result;
       let {key, l, p, type ,pType} = req.query;
       type = type || 'all';
-      pType = pType || 'all';
       l = typeTool.toNumber(l);
       p = typeTool.toNumber(p);
-      log.info(`page=${p},limit=${l}`);
+      log.info(`key=${key} pTYpe=${pType}  page=${p},limit=${l}`);
       [err, result] = await c_solution.searchAllNews(pType, type, key, p, l);
       if(err){
         return controlError(res, err, null);}

+ 17 - 10
server/tools/searchSql.js

@@ -13,15 +13,18 @@ function limitSql (limit = 20,page = 1){
   return {sql,values}
 }
 /**
-* 封装搜索数据库字段
-* @param errorText
-* @param dbFn
-* @param _params
-* @param page
-* @param limit
-* @returns {Promise<[err,{arr, total: number, limit, page}]>}
-*/
-async function searchHandle(errorText,dbFn,_params,page,limit){
+ * 封装搜索数据库字段
+ * @param errorText
+ * @param dbFn
+ * @param _params
+ * @param page
+ * @param limit
+ * @param listChangeHandle [function] map中的每一项的处理函数
+ * @returns {Promise<[err,{arr, total: number, limit, page}]>}
+ */
+async function searchHandle(errorText,dbFn,_params,page,limit ,
+                            listChangeHandle = null
+){
     let err,response,arrPromise,countPromise;
     limit = toNumber(limit);
     page = toNumber(page);
@@ -41,8 +44,12 @@ async function searchHandle(errorText,dbFn,_params,page,limit){
           null
         ]
     }
+    let arr = response[0];
+    if(listChangeHandle){
+        arr = arr.map(listChangeHandle)
+    }
     let  result = {
-        arr: response[0],
+        arr: arr,
         limit: limit,
         page: page,
         total: 0

+ 332 - 8
yarn.lock

@@ -1053,6 +1053,294 @@
     "@babel/helper-validator-identifier" "^7.22.5"
     to-fast-properties "^2.0.0"
 
+"@ckeditor/ckeditor5-adapter-ckfinder@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-39.0.0.tgz#0f7f8c58f1c55a39c222c611f048327bf2efa59f"
+  integrity sha512-b4gp7Gpzmss4axZfLHuzLsEywSsWhpxVy/VZSWfIt3VEsgk3y0VxhRk+lk5A4Hos94OH9U/HAz58Jg1in9XDgQ==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-autoformat@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-39.0.0.tgz#db031af970055fc7d28247900b10264f8e692e38"
+  integrity sha512-0HZ1G/x1SOd0P0VWvN84uURCjE80sFx57gLDmbG0B4jT/ahdBQWbuyB5jie048pyHZiM1HQqf3d3IGmOHqSKyg==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-basic-styles@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-39.0.0.tgz#1ccc9819bff55f66511f73a639dd5a7049245c4f"
+  integrity sha512-k50IZgZA+WOv3ZXudQ4/e7WRkySRridMcjoNZzmIPWptG8Z/lr9CakxxBxZ7qWSbQikTXBc+RBstfl9yb5PXdQ==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-block-quote@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-39.0.0.tgz#574c5fd35584c9260fe52a9e4b8c787cfe2b3a7d"
+  integrity sha512-1rvrS7RPx9KDxdA5UhAytNXvlVCl4ESxTuqO4kfVHKiSkrOPFlYL/eOixhPN7Q2Zp5fW9qu3JaE0TD6bsHh8og==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-build-classic@^39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-39.0.0.tgz#c322bdb12a4cdbdf4b093549221770bad67f6516"
+  integrity sha512-p+W/Wn/EnKuxniTbZbIL9EPeptIBKCEULuJZI5w5Nuz9r86VO+ZvC3dkat6MuHcyN1Lg6kjoDQE2lP/UTQNoPA==
+  dependencies:
+    "@ckeditor/ckeditor5-adapter-ckfinder" "39.0.0"
+    "@ckeditor/ckeditor5-autoformat" "39.0.0"
+    "@ckeditor/ckeditor5-basic-styles" "39.0.0"
+    "@ckeditor/ckeditor5-block-quote" "39.0.0"
+    "@ckeditor/ckeditor5-ckbox" "39.0.0"
+    "@ckeditor/ckeditor5-ckfinder" "39.0.0"
+    "@ckeditor/ckeditor5-cloud-services" "39.0.0"
+    "@ckeditor/ckeditor5-easy-image" "39.0.0"
+    "@ckeditor/ckeditor5-editor-classic" "39.0.0"
+    "@ckeditor/ckeditor5-essentials" "39.0.0"
+    "@ckeditor/ckeditor5-heading" "39.0.0"
+    "@ckeditor/ckeditor5-image" "39.0.0"
+    "@ckeditor/ckeditor5-indent" "39.0.0"
+    "@ckeditor/ckeditor5-link" "39.0.0"
+    "@ckeditor/ckeditor5-list" "39.0.0"
+    "@ckeditor/ckeditor5-media-embed" "39.0.0"
+    "@ckeditor/ckeditor5-paragraph" "39.0.0"
+    "@ckeditor/ckeditor5-paste-from-office" "39.0.0"
+    "@ckeditor/ckeditor5-table" "39.0.0"
+    "@ckeditor/ckeditor5-typing" "39.0.0"
+
+"@ckeditor/ckeditor5-ckbox@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-39.0.0.tgz#02baf50bffa69148d220ad82e7d2d5a074e4473a"
+  integrity sha512-dhdqkW6rR8yZq3o1VswWgZ1UAMpR4hhxyQ2iP9x27ZYzsHZbgpgfLVyi/RmMdR81FQriDqqBXjnhIeJV3VHGkA==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-ckfinder@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-39.0.0.tgz#28847a5ba6d3681b84ff97937c0c40225a2b6c94"
+  integrity sha512-UazQdHwfrjB1dX4NrxariTbocuKVyHM+Sgxdc3sRgBlBkHU8H1ER0UtZ3c6Y3BupJp8xeScY3l1HdZqhLikBNg==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-clipboard@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-39.0.0.tgz#e200bf4c4dc4a607aa2e035eb80f85be6745d8a3"
+  integrity sha512-6IufwrghR7nuoghxRdFx1r4CTHjxza+SfdSjP35G9BpTpS3vVt2MlJMUVppzVRRuBrF8bReG8jlhNugH/h5Qdg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    "@ckeditor/ckeditor5-widget" "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-cloud-services@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-39.0.0.tgz#6046bba4f624d89b6aa9b26dd0f3bbcc10423bcc"
+  integrity sha512-33ChRrRNxU1K/IKQoDT52GptigA1JudvWSIKzvcqYXCJHAqMeTVMcE9fx+i922SprSBIREDXmfpr9QaJ1zY8Ow==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-core@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-39.0.0.tgz#0dc6959da012dc95eca785b1419df280b26b2b1a"
+  integrity sha512-hBsXCsUu6IrH3++SNZlk2MNRgw/l4swulGeL65zUfT6Us+UN1XcuKT4hSBZW8kSGJjdhaVyn8qU8gVgUfaCCyw==
+  dependencies:
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-easy-image@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-39.0.0.tgz#99c8e88fb81679c88e26db6dec6c0a15abe4f0d8"
+  integrity sha512-hfsUoRSwD82ESkCGiHOcn3Gx029wALBz99BtVVGNORc4estdDtQShCo9ujNvQ7RvxrruVHRG4vH0U9toO7tBsw==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-editor-classic@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-39.0.0.tgz#4f06daac7ce5a3aa8263c4ae57ad4ede50dd5451"
+  integrity sha512-5U8RWvnlh00X8AgT93io9eFhemPrsRbGfh4MT6ZzUotaidyYEZmB/doDCN9ZEeZQsJFefptxnz0GRQYTHIS34A==
+  dependencies:
+    ckeditor5 "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-engine@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-39.0.0.tgz#041fecf609cbe6514719a7caa4fced5b1a4717be"
+  integrity sha512-eXWkMU7TJH6CziO+maIO/lRdCFgsiy2ZB2nw07JeTCQAYZuMpc0JOn4HOYwiouxf2Sbl9k+GfMiin8fr60WHRw==
+  dependencies:
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-enter@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-39.0.0.tgz#7a0f5aaabc7fca44d862d0944371f1bd081849e1"
+  integrity sha512-Fm6fCQO7Xt1UBKuTWG785XueeYAsEriyx/pL0LM7PofUkwL9Iu1EbxQWw1bzm7DXB6tIaaX3JqPWP6OTAQpS2Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+
+"@ckeditor/ckeditor5-essentials@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-39.0.0.tgz#0fae0a33cc14b6e7cb993413e174a16ce798724e"
+  integrity sha512-axwvWUqbqBpE6FGl+sDRSyDlrZV2AHXyGBca1zzpgvJPoD8gpenwhhFyySc6QwGKCxx+d0k9XTkflW89HCuTLw==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-heading@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-39.0.0.tgz#581c9aa618c2dad002f055c4a22c407dbb1d61c6"
+  integrity sha512-Or6UEmCHTgX9qXorK/I3m1ZGa2f31uPSKZgYL+l3DHLHar23TvWX0CstJso9R9lIMqe/TmKdlHsk2XtkE9VsIw==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-image@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-image/-/ckeditor5-image-39.0.0.tgz#72e26661431202774da3a2c40a5850c50fd84e20"
+  integrity sha512-wAd16v9p+G6iQiyjoIBiyJ8BITpdok7RUoxJgN6C2p7pJ/yx8I7Ks8p5oYD88XiG6OudBmoMAo28YfNxc7n22g==
+  dependencies:
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    ckeditor5 "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-indent@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-39.0.0.tgz#8f5d9514a0081053aaf7856f6a00359ccbdfb664"
+  integrity sha512-N+UNo0ncxpJCDn04TSz4Epk7f5gZpTEAt3/U4kaTT8e9pUEud4gI3FIr4zEaHIC8EWh9Ul4QbZgCBhKLC9m74Q==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-link@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-link/-/ckeditor5-link-39.0.0.tgz#44fd98509134b925efacd2659f6a9eff54e82876"
+  integrity sha512-GIDgNxmirFiLkIqaPtNGWxU2s9Eduhq3oPTa68Ck6jmEsGmMW6i+dhPdrqrv21kz3Xp3xPEnFs1ymQwv9cjgnw==
+  dependencies:
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    ckeditor5 "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-list@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-list/-/ckeditor5-list-39.0.0.tgz#ce6bb87f9bc519c78c7c51a914bd1641206188ac"
+  integrity sha512-+h/dMR1YhxRTCyMfodkYV0jkRupBu32JX7POWnaC2+Tbmpdrh1eY3osCEQueQe74h+wkSkaIR1f3ja/+srQJVw==
+  dependencies:
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-media-embed@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-39.0.0.tgz#64f74e152d6980e5d3e3f2ccb79f1cd443529038"
+  integrity sha512-hNpXliLQfin4Lp3akmAeuMKqgzt6ivcO9t8oYJQGI/qZcgcECn9rXkF7o2ukNSQPs0TA6t+qKojIYXZVepNcmg==
+  dependencies:
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-paragraph@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-39.0.0.tgz#551a12a74cf1bca4ba26e90f4f6fbe53345cdf72"
+  integrity sha512-Ubk/L0VZ+UQ5HN451iO1Itmf2Leb/M9X3V3RwI4+90Ir4hhaHsWFkARRyxavB2gdJFfGJqXy+lNepYQkbtI0lg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+
+"@ckeditor/ckeditor5-paste-from-office@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-39.0.0.tgz#cb9a041899a5931a926c4cd8889f5da647ac2f4d"
+  integrity sha512-f1Ul7KWsqjPWKnokyWQLtgimgePeGkq37/zoJVgEZ+DjP/mqzKvkoEDYtSkG3eAGwXk89TgRdQ5HajQjRkdwhQ==
+  dependencies:
+    ckeditor5 "39.0.0"
+
+"@ckeditor/ckeditor5-select-all@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-39.0.0.tgz#e51c39c4ff24d2070c4be5a966fa570c2b8f1a04"
+  integrity sha512-2Ec9a6K36SaZZ4/8FpVY/SMNEDCyaJe1uRn7C0VK3s2D1OT7pK4N27U2CpizKSrJoeAM4tcTRcHSarEeTNnWHA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+
+"@ckeditor/ckeditor5-table@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-table/-/ckeditor5-table-39.0.0.tgz#789f2f61ead92f39acaf2fd9831d4b5214643633"
+  integrity sha512-VXEvxEklAyjaBf8+YVI9j1ibBhW/dd7HWMjvlMXnYnwZGgbqwCDsGoxh2ED31MFQQEz94ir5WxTZxNVs4BexUw==
+  dependencies:
+    ckeditor5 "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-typing@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-39.0.0.tgz#dafa22de749cc96790bd1e218dc3b6872540a154"
+  integrity sha512-aIIkezuZPxlLPwDxcSe1Lm3M8K0J/vJViig1Fa4Olrt9R0Zf0SbpHLos27v/2WdM2pWCGnNFVD87pyNhlUUwhg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-ui@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-39.0.0.tgz#e59d0fae0dc8d5487622579a30ee72289dd1ff5a"
+  integrity sha512-gE5Voy6wLm+JwDZ7DaM0PZcdlVq3isSF7JIPLJUiCMJahnUd//Bev8BnKI1JemeYwLZI/WvIYfbIC+kBk93iPg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    color-convert "2.0.1"
+    color-parse "1.4.2"
+    lodash-es "4.17.21"
+    vanilla-colorful "0.7.2"
+
+"@ckeditor/ckeditor5-undo@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-39.0.0.tgz#18422bce81c39e8e3fbdff9f4a00ce75008710c6"
+  integrity sha512-YXfcshGfM+ycBlProgCshe//affNmmxXo344oN6ML4Q+ktOmOkPKehC6ZqTYN6FNfZJqpb3Rmf+Zw/YJ05SAWw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+
+"@ckeditor/ckeditor5-upload@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-39.0.0.tgz#f4629a2ff0d80fcea5698a1d6f0c09d36611f168"
+  integrity sha512-X/v18Xzr0c8QBJyOc6eAKaKwk+Pp89Uu/r9MqUI0UwXCzjhO7LaYX2f0a7I0cdQGhGE1J0lzLrGC7yLA6vvs7Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+
+"@ckeditor/ckeditor5-utils@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-39.0.0.tgz#b07327fd25d073e2fb9c56edbd3a8d109eb284e0"
+  integrity sha512-UweuJZh3N0LpTpWbF0mYNqTYr8kMOHJQs2aWFV6QkXkNtkRQccqv9IPpogdXkvjJ1sWfNjRTT0iWlE2zWyhqkg==
+  dependencies:
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-vue2@^3.0.1":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-vue2/-/ckeditor5-vue2-3.0.1.tgz#302e5773b31f1455973806d5c6002dd1b3db70ee"
+  integrity sha512-vS9ffP3rOFgM8oeG9XVFD+UtcYAhkgFDfBHjswJuCgUM0Iw8uqLlCiDPbs4PeJsend8GcmmtNeFdcQaSPkOtpw==
+
+"@ckeditor/ckeditor5-watchdog@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-39.0.0.tgz#1be0d443ffa9f6a6042c56828d2c8525fd2f80e0"
+  integrity sha512-u+2YTzHWxXoD6IWV/3pkMlq655OOvuevMnIwpFa4CGf53YnHsbwxNrlH2PgQ0kdF6CoD0xePbQgjyMvEHDcRHg==
+  dependencies:
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-widget@39.0.0":
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-39.0.0.tgz#96ed430b129cbfa9539156bc4242232b0a047019"
+  integrity sha512-/mrJVmlw7seLyhkmHXHzbbpsmttlZkh4rzWNx2Mgmhl17J3QLoUpI+QzWlgeP6ViHoDVwTEMZUsWZyLg5Z5ReA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-enter" "39.0.0"
+    "@ckeditor/ckeditor5-typing" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    lodash-es "4.17.21"
+
 "@csstools/cascade-layer-name-parser@^1.0.3":
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.3.tgz#7f049a670c1e071102243ab6c392174844ca6cd7"
@@ -3108,6 +3396,25 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
+ckeditor5@39.0.0:
+  version "39.0.0"
+  resolved "https://registry.yarnpkg.com/ckeditor5/-/ckeditor5-39.0.0.tgz#7a46bbb90a83d341d866c4f80298448925f9e870"
+  integrity sha512-YrSaW5qp1rpqWKG+id6/mW3I4tikcVJ4hwJI23xHPwnD24sFMKqBS77jS8gAM3rPbuABl6ATWCsK7+XddAMbeA==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "39.0.0"
+    "@ckeditor/ckeditor5-core" "39.0.0"
+    "@ckeditor/ckeditor5-engine" "39.0.0"
+    "@ckeditor/ckeditor5-enter" "39.0.0"
+    "@ckeditor/ckeditor5-paragraph" "39.0.0"
+    "@ckeditor/ckeditor5-select-all" "39.0.0"
+    "@ckeditor/ckeditor5-typing" "39.0.0"
+    "@ckeditor/ckeditor5-ui" "39.0.0"
+    "@ckeditor/ckeditor5-undo" "39.0.0"
+    "@ckeditor/ckeditor5-upload" "39.0.0"
+    "@ckeditor/ckeditor5-utils" "39.0.0"
+    "@ckeditor/ckeditor5-watchdog" "39.0.0"
+    "@ckeditor/ckeditor5-widget" "39.0.0"
+
 class-utils@^0.3.5:
   version "0.3.6"
   resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
@@ -3187,6 +3494,13 @@ collection-visit@^1.0.0:
     map-visit "^1.0.0"
     object-visit "^1.0.0"
 
+color-convert@2.0.1, color-convert@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
 color-convert@^1.9.0:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -3194,23 +3508,23 @@ color-convert@^1.9.0:
   dependencies:
     color-name "1.1.3"
 
-color-convert@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
-  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
-  dependencies:
-    color-name "~1.1.4"
-
 color-name@1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
   integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
 
-color-name@~1.1.4:
+color-name@^1.0.0, color-name@~1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
+color-parse@1.4.2:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.4.2.tgz#78651f5d34df1a57f997643d86f7f87268ad4eb5"
+  integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==
+  dependencies:
+    color-name "^1.0.0"
+
 colord@^2.9.1:
   version "2.9.3"
   resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
@@ -6000,6 +6314,11 @@ locate-path@^5.0.0:
   dependencies:
     p-locate "^4.1.0"
 
+lodash-es@4.17.21:
+  version "4.17.21"
+  resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
 lodash._reinterpolate@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -9857,6 +10176,11 @@ utils-merge@1.0.1:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
 
+vanilla-colorful@0.7.2:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz#3fb1f4b9f15b797e20fd1ce8e0364f33b073f4a2"
+  integrity sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==
+
 vary@^1.1.2, vary@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"