PageSourceSearch

https://www.linyangpvc.com/assets/js/design-box.js

js linyangpvc.com collected 2026-10-04 04:54:10 UTC 51,612 bytes, 1,167 lines download raw bytes

1import { PostMessages } from './messages.js'
2import { UnitTranslateConfig } from '../../config/unit.js'
3import help from '../../config/help.js'
4import hooks from '../../src/hooks/index.js'
5import configTitleObj from '../../dist/template/config-data.js'
6const newConfigTitleObj = {
7  ...configTitleObj,
8  'module-subscriptions-1': '邮件订阅',
9  'module-subscriptions-2': '邮件订阅',
10  'b2b-product_detail-module-1': '产品主图',
11  'b2b-product_detail-module-2': '产品主图',
12  'b2b2c-product_detail-module-1': '产品主图',
13  'module-b2c-detail-album-3': '产品主图',
14  'module-b2c-detail-album-4': '产品主图',
15  'module-b2c-detail-album-5': '产品主图',
16  'module-b2c-detail-album-6': '产品主图',
17  'product-detail': "产品主图",
18  'header-nav': "导航",
19  'header-cart': '购物车',
20  'header-search': '搜索',
21  'header-login': '用户',
22  'logo': 'logo',
23  'module-b2c-activity-product-1-unit-3': '活动产品',
24  'module-b2c-activity-product-2-unit-3': '活动产品',
25  'module-b2c-activity-product-3-unit-4': '活动产品',
26  'module-b2c-activity-product-4-unit-3': '活动产品',
27  'module-b2c-activity-product-5-unit-4': '活动产品',
28  'module-b2c-activity-product-6-unit-1': '活动产品',
29  'module-b2c-activity-product-7-unit-3': '活动产品',
30  'module-b2c-activity-product-8-unit-4': '活动产品',
31  'module-b2c-activity-product-9-unit-1': '活动产品',
32  'module-b2c-activity-product-10-unit-1': '活动产品',
33  'module-b2c-activity-product-11-unit-1': '活动产品',
34  'module-b2c-activity-product-12-unit-1': '活动产品',
35  'module-subscriptions-1-unit-2': '邮件订阅',
36  'module-subscriptions-2-unit-2': '邮件订阅',
37  'module-b2c-related-product-1-unit-2': '邮件订阅',
38  'module-pop-up-1-unit-3': '弹窗效果',
39  'module-b2c-related-product-1-unit-2': '关联产品',
40  'module-b2c-might-like-1-unit-2': '猜你喜欢',
41  'b2b2c-config-module-2': '面包屑',
42  'b2b2c-config-module-3': '页脚',
43  'b2b2c-config-module-4': '版权',
44  'b2b-config-module-1': '导航',
45  'b2b-config-module-2': '面包屑',
46  'b2b-config-module-3': '页脚',
47  'b2b-config-module-4': '版权',
48  'b2c-config-block-breadcrumb': '面包屑',
49  'b2c-config-block-footer': '页脚',
50  'b2c-config-block-copyright': '版权',
51  'b2b2c-config-block-header-module-3': '导航',
52  'b2b2c-config-block-header-module-1': '导航',
53  'b2b2c-config-block-header-module-2': '导航',
54  'b2b-config-block-header-module-3': '功能',
55  'b2b-config-block-header-module-1': '导航',
56  'b2b-config-module-2': '面包屑',
57  'b2b-config-module-3': '页脚',
58  'b2b-config-module-4': '版权',
59  'b2c-config-block-header-module-1': '导航',
60  'b2c-config-block-header-module-2': '导航',
61  'b2c-config-block-header-module-3': '导航',
62  'b2c-config-block-breadcrumb-module-1': '面包屑',
63  'b2c-config-block-footer-module-1': '页脚',
64  'b2c-config-block-copyright-module-1': '版权',
65
66  'module-article-4': '新闻资讯',
67  'module-inquiry-1-unit-3': '询盘表单',
68  'module-inquiry-2-unit-3': '询盘表单',
69  'module-tabs-1-grid-1-cell-1-unit-1': '选项卡',
70  'module-b2c-product-7-unit-3': '侧边栏',
71  'module-b2c-activity-product-9-unit-3': '侧边栏',
72  'module-product-7-unit-3': '侧边栏',
73  'module-activity-product-9-unit-3': '侧边栏',
74  'module-b2c-product-1-unit-3': '普通产品',
75  'module-b2c-product-2-unit-3': '普通产品',
76  'module-b2c-product-3-unit-3': '普通产品',
77  'module-b2c-product-4-unit-3': '普通产品',
78  'module-b2c-product-5-unit-1': '普通产品',
79  'module-b2c-product-5-unit-2': '普通产品',
80  'module-b2c-product-5-unit-3': '普通产品',
81  'module-b2c-product-5-unit-4': '普通产品',
82  'module-b2c-product-5-unit-5': '普通产品',
83  'module-b2c-product-6-unit-1': '普通产品',
84  'module-b2c-product-6-unit-2': '普通产品',
85  'module-b2c-product-7-unit-1': '普通产品',
86  'module-b2c-product-8-unit-1': '普通产品',
87  'module-b2c-product-9-unit-1': '普通产品',
88  'module-b2c-product-10-unit-1': '普通产品',
89  'module-product-1-unit-3': '普通产品',
90  'module-product-2-unit-3': '普通产品',
91  'module-product-3-unit-3': '普通产品',
92  'module-product-4-unit-3': '普通产品',
93  'module-product-5-unit-1': '普通产品',
94  'module-product-5-unit-2': '普通产品',
95  'module-product-5-unit-3': '普通产品',
96  'module-product-5-unit-4': '普通产品',
97  'module-product-5-unit-5': '普通产品',
98  'module-product-6-unit-1': '普通产品',
99  'module-product-6-unit-2': '普通产品',
100  'module-product-7-unit-1': '普通产品',
101  'module-product-8-unit-1': '普通产品',
102  'module-product-9-unit-1': '普通产品',
103  'module-product-10-unit-1': '普通产品',
104  'module-team-1-unit-3': '文章列表',
105  'module-team-2-unit-3': '文章列表',
106  'module-team-3-unit-3': '文章列表',
107  'module-team-4-unit-3': '文章列表',
108  'module-team-5-unit-5': '文章列表',
109  'module-case-1-unit-3': '文章列表',
110  'module-case-1-unit-4': '文章列表',
111  'module-case-1-unit-5': '文章列表',
112  'module-case-2-unit-3': '文章列表',
113  'module-case-3-unit-3': '文章列表',
114  'module-case-3-unit-4': '文章列表',
115  'module-case-4-unit-3': '文章列表',
116  'module-article-6-unit-3': '文章列表',
117  'module-article-6-unit-4': '文章列表',
118  'module-article-2-unit-3': '文章列表',
119  'module-article-3-unit-3': '文章列表',
120  'module-article-5-unit-4': '文章列表',
121  'module-article-1-unit-3': '文章列表',
122  'base-article_list-unit-3': '文章列表',
123  'module-article-list-1-unit-3': '文章列表',
124  'module-article-list-2-unit-1': '文章列表',
125  'base-article_list-module-1': '文章列表',
126  'base-video_list-module-1': '视频列表',
127  'base-video_detail-module-1': '视频详情',
128  'base-article_detail-module-1': '文章详情',
129  'base-video_detail-unit-1': '封面视频',
130  'base-video_detail-unit-6': '视频内容',
131  'base-video_detail-unit-9': '询盘表单',
132  'base-article_detail-unit-2': '详情-副标题',
133  'base-article_detail-unit-4': '详情-简介',
134  'base-article_detail-unit-5': '封面视频',
135  'base-article_detail-unit-11': '询盘表单',
136  'b2b2c-product_detail-unit-15': '询盘表单',
137  'b2b2c-product_detail-module-2': '产品详情',
138  'b2c-product_detail-module-2': '产品详情',
139  'b2b-product_detail-module-2': '产品详情',
140  'b2b2c-product_detail-module-3': '询盘表单',
141  'b2b-product_detail-module-3': '询盘表单',
142  'b2b2c-product_detail-module-4': '关联产品',
143  'b2b-product_detail-module-4': '关联产品',
144  'b2c-product_detail-module-4': '关联产品',
145  'b2b2c-product_detail-unit-17': '关联产品',
146  'b2c-product_detail-unit-17': '关联产品',
147  'b2b-product_list-unit-5': '侧边栏',
148  'b2b2c-product_list-unit-5': '侧边栏',
149  'b2b-product_list-module-1': '产品列表',
150  'b2c-product_list-module-1': '产品列表',
151  'b2b2c-product_list-module-1': '产品列表',
152  'b2b-product_list-unit-7': '询盘表单',
153  'b2b-product_list-unit-3': '普通产品',
154  'b2c-product_list-unit-3': '普通产品',
155  'b2b2c-product_list-unit-3': '普通产品',
156  'base-download_list-module-1': '下载列表',
157
158  'b2b2c-index-module-1': 'banner',
159  'b2b2c-index-module-2': '图文列表',
160  'b2b2c-index-module-3': '图文列表',
161  'b2b2c-index-module-4': '图文列表',
162  'b2b2c-index-module-5': '图文列表',
163  'b2b2c-index-module-6': '询盘表单',
164  'b2b2c-more_best_selle-module-1': '图文列表',
165  'b2b2c-more_new_products-module-1': '图文列表',
166  'b2b2c-more_recommend-module-1': '图文列表',
167  'b2b2c-product_discount_list-module-1': '图文列表',
168  'b2b-about_us-module-1': '图文',
169  'b2b-about_us-module-2': '图文列表',
170  'b2b-about_us-module-3': '图文列表',
171  'b2b-about_us-module-4': '询盘表单',
172  'b2b-contact_us-module-1': '图文列表',
173  'b2b-contact_us-module-2': '询盘表单',
174  'b2b-customized_service-module-1': '图文',
175  'b2b-customized_service-module-2': '图文列表',
176  'b2b-customized_service-module-3': '图文列表',
177  'b2b-customized_service-module-4': '询盘表单',
178  'b2b-index-module-1': 'banner',
179  'b2b-index-module-2': '图文列表',
180  'b2b-index-module-3': '图文',
181  'b2b-index-module-4': '图文列表',
182  'b2b-index-module-5': '图文',
183  'b2b-index-module-6': '图文列表',
184  'b2b-index-module-7': '图文列表',
185  'b2b-index-module-8': '询盘表单',
186  'b2c-index-module-1': 'banner',
187  'b2c-index-module-2': '图文列表',
188  'b2c-index-module-3': '图文列表',
189  'b2c-index-module-4': '图文',
190  'b2c-index-module-5': '图文列表',
191  'b2c-index-module-6': '图文列表',
192  'b2c-index-module-7': '图文列表',
193  'b2c-index-module-8': '询盘表单',
194  'b2c-index-module-9': '图文列表',
195  'b2c-more_best_selle-module-1': '图文列表',
196  'b2c-more_new_products-module-1': '图文列表',
197  'b2c-more_recommend-module-1': '图文列表',
198  'b2c-product_coupon-module-1': '优惠活动',
199  'b2c-product_coupon-module-2': '图文列表',
200  'b2c-product_detail-module-1': '产品详情',
201  'b2c-reduction_detail-module-1': '满减',
202  'b2c-reduction_detail-module-2': '图文列表',
203  'base-400-module-1': '图文',
204  'base-404-module-1': '图文',
205  'base-404-module-2': '图文列表',
206  'base-affiliate2-module-1': '分销产品',
207  'base-affiliate-module-1': '分销产品',
208  'base-ai_article_detail-module-1': '文章详情',
209  'base-ai_article_detail-module-2': '文章详情',
210  'base-ai_article_detail_2-module-1': '文章详情',
211  'base-ai_article_detail_3-module-1': '文章详情',
212  'base-ai_product_detail-module-1': '产品详情',
213  'base-ai_product_detail-module-2': '产品详情',
214  'base-ai_product_detail-module-3': '产品详情',
215  'base-ai_product_detail-module-4': '询盘表单',
216  'base-ai_product_detail_2-module-1': '产品详情',
217  'base-ai_product_detail_2-module-2': '产品详情',
218  'base-ai_product_detail_2-module-3': '产品详情',
219  'base-ai_product_detail_2-module-4': '询盘表单',
220  'base-cart-module-1': '购物车',
221  'base-checkout-module-1': '购物车',
222  'base-complete-module-1': '购物完成',
223  'base-doc_detail-module-1': '政策条款',
224  'base-due-module-1': '图文',
225  'base-findpwd-module-1': '找回密码',
226  'base-inquire_fail-module-1': '图文',
227  'base-inquire_form-module-1': '询盘表单',
228  'base-inquire_success-module-1': '询盘成功',
229  'base-landing_page-module-1': '图文',
230  'base-login-module-1': '用户登录',
231  'base-more_best_selle-module-1': '图文列表',
232  'base-more_coupon-module-1': '图文列表',
233  'base-more_new_products-module-1': '图文列表',
234  'base-more_recommend-module-1': '图文列表',
235  'base-multi_language-module-1': '多国语言',
236  'base-polymerize_article_detail-module-1': '文章详情',
237  'base-polymerize_article_detail-module-2': '文章详情',
238  'base-polymerize_article_detail_2-module-1': '文章详情',
239  'base-polymerize_article_detail_2-module-2': '文章详情',
240  'base-polymerize_article_list-module-1': '图文列表',
241  'base-polymerize_multiple_detail-module-1': '询盘表单',
242  'base-polymerize_multiple_detail-module-2': '聚合页详情',
243  'base-polymerize_multiple_detail_2-module-1': '询盘表单',
244  'base-polymerize_multiple_detail_2-module-2': '聚合页详情',
245  'base-polymerize_product_detail-module-1': '询盘表单',
246  'base-polymerize_product_detail-module-2': '聚合页详情',
247  'base-polymerize_product_list-module-1': '图文列表',
248  'base-polymerize_tag_detail-module-1': '图文列表',
249  'base-polymerize_tag_detail-module-3': '聚合页详情',
250  'base-polymerize_tag_detail-module-4': '询盘表单',
251  'base-product_detail-module-1': '产品详情',
252  'base-product_detail-module-2': '产品详情',
253  'base-product_detail-module-3': '询盘表单',
254  'base-product_detail-module-4': '图文列表',
255  'base-product_list-module-1': '图文列表',
256  'base-product_lives-module-1': '视频聚合页',
257  'base-register-module-1': '用户登录',
258  'base-search-module-1': '面包屑',
259  'base-search-module-2': '搜索',
260  'base-sitemap-module-1': '询盘表单',
261  'base-third_authorize-module-1': '第三方登录',
262  'base-updating-module-1': '图文',
263  'base-user-module-1': '用户',
264  'module-b2c-detail-album-2': '产品主图',
265  'module-b2c-products-new-1': '图文列表',
266  'module-hello-world-1': 'hello-world',
267  'module-inquiry-3': '询盘表单',
268  'module-inquiry-4': '询盘表单',
269  'module-inquiry-5': '询盘表单',
270  'module-inquiry-6': '询盘表单',
271  'module-inquiry-7': '询盘表单',
272  'module-irregular-1': '图文列表',
273  'module-might-4': '图文列表',
274  'module-might-5': '图文列表',
275  'module-sort-1': '排序',
276  'module-video-1': '图文列表',
277
278  'form': '询盘表单',
279  'list': ' 图文列表',
280  'video-list': ' 视频列表',
281  'social-list': ' 社媒',
282  'map': ' 地图',
283  'text': ' 文本',
284  'page-desc': ' 页面描述',
285  'page-title': ' 页面标题',
286  'image': ' 图片',
287  'button': ' 按钮',
288  'swiper': ' 轮播图',
289  'pagination': ' 列表页-分页',
290  'faq': ' 常见问题',
291  'video-popup': ' 视频弹框',
292  'list_sort': ' 侧边栏',
293  'attr-search': ' 属性搜索',
294  'resize': ' 对切(图文列表组件9)',
295  'list-nav': ' 栏目列表'
296}
297const packageConfig = {
298  block: { name: 'block', title: '板块', has_around: 1, has_add: 0, action_list: ['setting', 'line', 'hide', 'show-pc', 'show-pad', 'show-phone', 'clear-style'], next: 'module', rgb: '220,53,69' },
299  module: { name: 'module', title: '模块', has_around: 1, has_add: 1, action_list: ['setting', 'collect', 'copy', 'delete', 'moveUp', 'moveDown', 'mark', 'line', 'hide', 'show-pc', 'show-pad', 'show-phone', 'clear-style'], next: 'grid', rgb: '0,123,255' },
300  grid: { name: 'grid', title: '布局', has_around: 1, has_add: 1, action_list: ['setting', 'copy', 'delete', 'moveUp', 'moveDown', 'mark', 'line', 'hide', 'show-pc', 'show-pad', 'show-phone', 'clear-style'], next: 'cell', rgb: '23,162,184' },
301  cell: { name: 'cell', title: '单元格', has_around: 1, has_add: 1, action_list: ['setting', 'copy', 'delete', 'moveUp', 'moveDown', 'mark', 'line', 'hide', 'show-pc', 'show-pad', 'show-phone', 'clear-style'], next: 'unit', rgb: '233, 196, 106' },
302  unit: { name: 'unit', title: '组件', has_around: 1, has_add: 1, action_list: ['setting', 'copy', 'delete', 'moveUp', 'moveDown', 'generate', 'mark', 'line', 'hide', 'help', 'show-pc', 'show-pad', 'show-phone', 'clear-style'], next: '', rgb: '52,58,64' }
303}
304
305const actionConfig = {
306  add: { title: '添加', icon: 'icon-action-add', fun_name: 'addPackage' },
307  setting: { title: '设置', icon: 'icon-action-setting', fun_name: 'editPackage' },
308  collect: { title: '收藏', icon: 'icon-shoucang', fun_name: 'collectPackage' },
309  copy: { title: '复制', icon: 'icon-fuzhi', fun_name: 'copyPackage' },
310  // replace: { title: '替换', icon: 'icon-action-copy', fun_name: 'replacePackage' },
311  delete: { title: '删除', icon: 'icon-action-delete', fun_name: 'deletePackage' },
312  moveUp: { title: '上移', icon: 'icon-action-top-arrow-bold', fun_name: 'moveUpPackage' },
313  moveDown: { title: '下移', icon: 'icon-action-bottom-arrow-bold', fun_name: 'moveDownPackage' },
314  generate: { title: '全能AI内容助理-小鱼', icon: 'icon-xiaoyuAI', fun_name: 'generatePackage' },
315  'clear-style': { title: '清除旧站搬迁的样式', icon: 'icon-clear', fun_name: 'clearStyle' },
316  mark: { title: '标记', icon: 'icon-base-code', fun_name: 'markPackage' },
317  line: { title: '', icon: 'icon-line', fun_name: 'line' },
318  hide: { title: '隐藏', icon: 'icon-base-eye-ban', fun_name: 'show' },
319  help: { title: '帮助', icon: 'icon-wenhao', fun_name: 'showHelp' },
320  'show-pc': { title: '显示在电脑端', icon: 'icon-client-desktop', fun_name: 'hidePc' },
321  'show-pad': { title: '显示在平板端', icon: 'icon-client-pad', fun_name: 'hidePad' },
322  'show-phone': { title: '显示在手机端', icon: 'icon-client-phone', fun_name: 'hidePhone' },
323}
324
325const tinymceOption = {
326  toolbar: false,
327  menubar: false,
328  inline: true,
329  verify_html: false,
330  plugins: 'charmap link image quickbars lineheight fontweight code lists',
331  preview_styles: false,
332  quickbars_selection_toolbar: '',
333  quickbars_insert_toolbar: '',
334  fontsize_formats: '25% 50% 75% 85% 90% 100% 125% 150% 175% 200%',
335  relative_urls: false,
336  remove_script_host: true,
337  document_base_url: ''
338}
339
340export default class DesignBox {
341
342  constructor(packageItem) {
343    this.getInsideData = null
344    this.getInsideData = () => {
345      const resData = {}
346      //当前节点数据
347      resData.packageItem = packageItem
348      //当前自己的节点
349      resData.$selfDoc = document.getElementById(resData.packageItem.attr_id)
350      return resData
351    }
352    this.init()
353  }
354
355  async init() {
356    // if (Utilts.ins().getParamsByUrl('language_code') === 'en') {
357    //   /** 初始化装修 */
358    //   this.initDesignBox()
359    // }
360    this.initDesignBox()
361    /** 注册移动事件装修 */
362    this._onMouseover()
363    /** 初始化富文本 */
364    /** 设置列表里面的html可以编辑 */
365    this._htmlEdit()
366  }
367
368  /**
369 * 初始化装修
370 */
371  initDesignBox() {
372    /** 渲染design-box */
373    this._renderBox()
374    /** 内容为空时显示添加按钮 */
375    this._showAddBtn()
376  }
377
378  /** checkBlank */
379  checkBlank() {
380    let { packageItem, $selfDoc } = this.getInsideData()
381    if (packageItem.children.length) $selfDoc.classList.remove('blank-package')
382    else $selfDoc.classList.add('blank-package')
383    const popUpModule = $selfDoc.querySelectorAll('.all-pop-up_module')
384    if (window.app.info.page.page_type === 'all_pop_up' && !popUpModule.length && packageItem.dir === 'block') {
385      $selfDoc.classList.add('blank-package')
386    }
387    if (window.app.info.page.page_type === 'all_pop_up' && popUpModule.length) {
388      popUpModule.forEach((val, index) => {
389        val.previousElementSibling.innerHTML = `弹窗${index + 1}`
390      })
391    }
392  }
393
394  /** 渲染design-box */
395  _renderBox() {
396    let { $selfDoc } = this.getInsideData()
397    if (!$selfDoc) return
398    // 非首页的头部底部不可编辑
399    if (window.app.info.page.page_type !== 'all_pop_up' && DesignBox.checkCannotDesign($selfDoc)) {
400      if ($selfDoc.getAttribute('package-item') === 'block') $selfDoc.classList.add('only-home-design')
401      else return
402    }
403    const thisPackageDir = $selfDoc.getAttribute('package-item')
404    const thisConfig = packageConfig[thisPackageDir]
405    //是否有旧的design-box
406    let $designBox = $selfDoc.querySelector(':scope > .design-box')
407    const isHaveDesignBox = $designBox !== null
408    // 没有创建design-box
409    if (!isHaveDesignBox) {
410      $designBox = document.createElement('div')
411      $designBox.style = `--rgb:${thisConfig.rgb}`
412      $designBox.className = 'design-box'
413    }
414    // 渲染design-box
415    const initIconHtml = this._initIconsHtml(thisConfig) //在上角按钮
416    const initAroundHtml = this._initAroundHtml(thisConfig) //生成四周边框的html
417    const initAddHtml = this._initAddHtml(thisConfig) //生成添加按钮的html
418    $designBox.innerHTML = `${initIconHtml}${initAroundHtml}${initAddHtml}`
419    //没有旧的design--box添加有,则不添加
420    if (!isHaveDesignBox) {
421      $selfDoc.insertBefore($designBox, $selfDoc.children[0])
422    }
423    /** 注册详情监听事件 */
424    this._onOperationEvent($designBox)
425  }
426  /** 设置icons的定位 */
427  setIconsPosition($designBox) {
428    if (!$designBox) return
429    const $icons = $designBox.querySelector('.setting')
430    const $ul = $icons.querySelector('.d-flex')
431    const $addBtnList = $designBox.querySelectorAll('.add-btn')
432    const distant = $icons.getBoundingClientRect().x + $ul.offsetWidth
433    if (distant > document.body.offsetWidth) $ul.classList.add('icon-to-right')
434    else $ul.classList.remove('icon-to-right')
435    $addBtnList.forEach(item => {
436      const btnDistant = $icons.getBoundingClientRect().x + item.offsetWidth
437      if (btnDistant > document.body.offsetWidth) item.classList.add('button-to-right')
438      else item.classList.remove('button-to-right')
439    })
440    // 超出 overflow: hidden 父元素边界,调整位置
441    const $parentEl = Utilts.ins().findParentElement($ul, (el) => {
442      const computedStyle = window.getComputedStyle(el);
443      if (['hidden', 'clip'].includes(computedStyle.overflow)) {
444        return true
445      }
446    })
447    if ($parentEl) {
448      if ($ul.getBoundingClientRect().y - $parentEl.getBoundingClientRect().y > 40) {
449        $ul.classList.remove('icon-to-inner')
450      } else if ($ul.getBoundingClientRect().y < $parentEl.getBoundingClientRect().y){
451        $ul.classList.add('icon-to-inner')
452      }
453      $addBtnList.forEach($addBtn => {
454        if (($addBtn.getBoundingClientRect().y + $addBtn.offsetHeight) - ($parentEl.getBoundingClientRect().y + $parentEl.offsetHeight) < -20) {
455          $addBtn.classList.remove('btn-to-inner')
456        } else if (($addBtn.getBoundingClientRect().y + $addBtn.offsetHeight - 2) > ($parentEl.getBoundingClientRect().y + $parentEl.offsetHeight)) {
457          $addBtn.classList.add('btn-to-inner')
458        }
459      })
460    }
461    // cell的添加按钮重叠,调整位置
462    if ($addBtnList[0]?.getAttribute('data-target') === 'cell') {
463      let count = 0
464      const $parentCell = Utilts.ins().findParentElement($addBtnList[0], (el) => {
465        if (el.getAttribute('package-item') === 'cell') {
466          if (count) return true
467          count++
468        }
469      })
470      if ($parentCell) {
471        const $parentCellAddBtn = $parentCell.querySelector('.add-btn')
472        if (Math.abs($addBtnList[0].getBoundingClientRect().y - $parentCellAddBtn.getBoundingClientRect().y) < 40) {
473          const computedStyle = window.getComputedStyle($addBtnList[0]);
474          $addBtnList[0].style.bottom = parseFloat(computedStyle.bottom) + 40 + 'px'
475        }
476      }
477    }
478  }
479  /**注册装修移动事件 */
480  _onMouseover() {
481    const { $selfDoc } = this.getInsideData()
482    if (!$selfDoc) return
483    $selfDoc.addEventListener('mouseover', (event) => {
484      event.preventDefault()
485      event.stopPropagation()
486      this.setIconsPosition($selfDoc.querySelector(':scope > .design-box'))
487      // 如果当前有正在修改的弹出框,不做下面的事
488      // 删除所有父类的clsss不显示装修
489      // 不能用全局的$allItem 会出现,使用旧的item项,所有会有BUG
490      document.querySelectorAll('[package-item]').forEach(item => {
491        item.classList.remove('active', 'setting-active')
492      })
493      //当前的显示装修
494      $selfDoc.classList.add('active')
495      const parentList = Utilts.ins().getParentsByAttr($selfDoc, 'package-item')
496      parentList.forEach(p => {
497        p.classList.add('setting-active')
498        this.setIconsPosition(p.querySelector(':scope > .design-box'))
499      })
500    }, false)
501    $selfDoc.addEventListener('click', (event) => {
502      event.stopPropagation()
503      event.preventDefault()
504    })
505  }
506
507  /**
508   * 重新注册详情监听事件,
509   * 因为是html事件只能调用全局所以改成属性,
510   * 所以再重新注册
511   */
512  _onOperationEvent($designBox) {
513    $designBox.querySelectorAll('[data-click]').forEach(p => {
514      p.addEventListener('click', () => {
515        const funcName = p.getAttribute('data-click')
516        const target = p.getAttribute('data-target') || ''
517        const action = p.getAttribute('data-action') || ''
518        const from = p.getAttribute('data-from') || ''
519        const originAttrId = p.getAttribute('data-origin-attr-id') || ''
520        window.ctx.state.addPackageState = { thisDesignBox: this, from, originAttrId }
521        const packages = window.design.packages
522        switch (action) {
523          case 'moduleToGrid': {
524            window.ctx.state.addPackageState.action = 'moduleToGrid'
525            const checkGrid = (element) => element.getAttribute('package-item') === 'grid'
526            let $grid = p
527            if (!checkGrid(p)) {
528              $grid = Utilts.ins().findParentElement(p, checkGrid)
529              window.ctx.state.addPackageState.thisDesignBox = packages[$grid.id].designBox
530            }
531            const $module = Utilts.ins().findParentElement($grid, (element) => element.getAttribute('package-item') === 'module')
532            if ($module && PostMessages.ins()[funcName]) {
533              PostMessages.ins()[funcName](packages[$module.id].designBox, target)
534            }
535            break;
536          }
537          case 'unitToGrid': {
538            window.ctx.state.addPackageState.action = 'unitToGrid'
539
540            const $grid = Utilts.ins().findParentElement(p, (element) => element.getAttribute('package-item') === 'grid')
541            if ($grid && PostMessages.ins()[funcName]) {
542
543              window.ctx.state.addPackageState.thisDesignBox = packages[$grid.id].designBox
544              PostMessages.ins()[funcName](packages[$grid.id].designBox, target)
545            }
546            break;
547          }
548          default:
549            if (PostMessages.ins()[funcName]) PostMessages.ins()[funcName](this, target)
550            break;
551        }
552
553      }, false)
554    })
555  }
556
557  /** 初始化组件的html编辑 */
558  _htmlEdit() {
559    // 组件的html编辑
560    let { $selfDoc } = this.getInsideData()
561    $selfDoc.querySelectorAll('[_html]')
562      .forEach((thisHtmlDom) => {
563        // if (thisHtmlDom.getAttribute('contenteditable')) {
564        //   return
565        // }
566        const sign = thisHtmlDom.getAttribute('_html')
567        // 没有sign或是非首页的头部底版权部,不可编辑,删掉_html属性
568        if (!sign || DesignBox.checkCannotDesign(thisHtmlDom)) {
569          if (thisHtmlDom.removeAttribute) thisHtmlDom.removeAttribute('_html')
570          return
571        }
572        // 失去焦点后保存一下
573        thisHtmlDom.setAttribute('contenteditable', true)
574        this._htmlEditEvent(sign, thisHtmlDom)
575      })
576  }
577
578  _htmlEditEvent(sign, thisDom) {
579    if (!thisDom) { return }
580    let { packageItem } = this.getInsideData()
581    thisDom.addEventListener('blur', event => {
582      // 冒泡
583      event.stopPropagation()
584      // 不是组件就不需要继续了
585      if (packageItem.dir !== 'unit') return
586      // 获取html内容,包括标签
587      const html = thisDom.innerHTML
588      // 匹配修改项并更新,返回是否修改
589      let isChange = this.mapEditDataHtml(packageItem.content.data, sign, html)
590      /** 提交到装修修改页面中的Html */
591      if (isChange) {
592        PostMessages.ins().modifyUnitHtml(packageItem)
593        // 计算长度,超了就提示,但还是要保存,不能随便自动还原或截断,需要手动处理
594        if (thisDom.innerHTML.length >= 65535) new Message().error('内容超过限制,将无法保存')
595        else new Message().success('修改成功,保存后生效')
596      } else {
597        // new Message().info('无修改')
598      }
599    })
600  }
601  /**
602   * 因为只能拿到sign,所以匹配一下是哪个sign,找到了就替换,并且更新组件
603   * @param {*} items
604   * @param {*} htmlSign
605   * @param {*} htmlValue
606   * @returns true 有修改
607   * @returns false 无修改
608   */
609  mapEditDataHtml(items, htmlSign, htmlValue) {
610    let isChange = false
611    items.forEach(item => {
612      const titleEditState = this.mapEditAttrHtml(item, htmlSign, htmlValue, 'title')
613      const subtitleEditState = this.mapEditAttrHtml(item, htmlSign, htmlValue, 'subtitle')
614      const descriptionEditState = this.mapEditAttrHtml(item, htmlSign, htmlValue, 'description')
615      const tabEditState = this.mapEditAttrHtml(item, htmlSign, htmlValue, 'tab')
616      if (titleEditState === 2 || subtitleEditState === 2 || descriptionEditState === 2 || tabEditState === 2) isChange = true
617    })
618    return isChange
619  }
620  /**
621   * 因为只能拿到sign,所以匹配一下是哪个sign,找到了就替换,并且更新组件
622   * @param {*} item
623   * @param {*} htmlSign
624   * @param {*} htmlValue
625   * @param {*} attrName
626   * @returns 0 不匹配
627   * @returns 1 无修改
628   * @returns 2 修改成功
629   */
630  mapEditAttrHtml(item, htmlSign, htmlValue, attrName) {
631    const trueSign = item[`${attrName}_sign`]
632    const trueValue = item[attrName]
633    if (trueSign !== htmlSign) return 0
634    if (trueValue === htmlValue) return 1
635    else {
636      item[attrName] = htmlValue
637      return 2
638    }
639  }
640
641  /**生成左上角按钮的html */
642  _initIconsHtml(thisConfig) {
643    let html = `<div class="setting hover icons">`
644    if (thisConfig.action_list.length > 0) {
645      const { packageItem, $selfDoc } = this.getInsideData()
646      const unitName = UnitTranslateConfig[packageItem.type] || packageItem.type || ''
647      html += `<ul class="d-flex" ${this._getModuleTitle(thisConfig)}>`
648      // console.log('packageItem', packageItem);
649      let moduleName = ''
650      if (packageItem.dir === 'module') moduleName = newConfigTitleObj[packageItem.code] || '自定义'
651      // if (packageItem.dir === 'unit') moduleName = newConfigTitleObj[packageItem.code] || newConfigTitleObj[packageItem.type] || '自定义'
652      if (packageItem.dir === 'unit') moduleName = UnitTranslateConfig[packageItem.type] || newConfigTitleObj[packageItem.type] || newConfigTitleObj[packageItem.code] || '自定义'
653      if (packageItem.dir === 'module' || packageItem.dir === 'unit') html += `<li class="title-box">${moduleName}</li>`
654      if (packageItem.transfer) {
655        if (!thisConfig.action_list.includes('clear-style')) thisConfig.action_list.push('clear-style')
656      } else {
657        thisConfig.action_list = thisConfig.action_list.filter(val => val !== 'clear-style')
658      }
659      thisConfig.action_list.forEach(item => {
660        const thisActionConfig = actionConfig[item]
661        let icon = thisActionConfig.icon
662
663        let title = thisActionConfig.title + unitName + thisConfig.title
664        if (item === 'generate' || item === 'mark') {
665
666          if (
667            (packageItem['dir'] === 'unit' && !packageItem['type']) ||
668            (packageItem['dir'] === 'unit' && !['video-popup', 'text', 'list', 'image', 'product-list', 'faq'].includes(packageItem['type'])) ||
669            (item === 'mark' && window.ctx.state.site.client_id !== 10)
670          ) {
671            return
672          }
673          if (item === 'mark') {
674            if (Object.keys(packageItem['generate_config']).length) {
675              icon = 'icon-base-code generate_marked'
676            }
677          }
678          title = thisActionConfig.title
679          if (packageItem['type'] === 'image') title = 'AI生成'
680        } else if (item === 'collect') {
681          if (!$selfDoc.getAttribute('is-collected')) {
682            icon = 'icon-shoucang-empty'
683          }
684        }
685        if (item === 'copy') {
686          // if (['grid', 'cell', 'unit'].includes(packageItem.dir)) {
687          //   let tabs = Utilts.ins().findNode(packageItem, (node) => node.type === 'tabs')
688          //   if (tabs) return
689          // }
690          let column_tabs = Utilts.ins().findNode(packageItem, (node) => node.type === 'column-tabs')
691          if (column_tabs) return
692        }
693        if (!(item === 'help' && !(packageItem.type in help))) {
694          let newTitle = thisActionConfig.title
695          if (item === 'generate') newTitle = 'AI生成'
696          if (item.includes('show-p')) newTitle = '可见'
697          if (item === 'clear-style') newTitle = '清除样式'
698          if (item === 'help') newTitle = ''
699          if (item === 'setting' && packageItem.dir === 'block' && packageItem.type === 'header') newTitle = '导航设置'
700          if (item === 'setting' && packageItem.dir === 'unit' && packageItem.type === 'logo') newTitle = 'logo设置'
701          html += `<li data-click="${thisActionConfig.fun_name}" title="${title}" data-toggle="tooltip" data-placement="top">
702          <i class="iconfont ${icon}"></i>
703          <span class="icon-title">${newTitle}</span>
704        </li>`
705        }
706      })
707      html += `</ul>`
708    }
709    html += `</div>`
710    return html
711  }
712  /**生成四周边框的html */
713  _initAroundHtml(thisConfig) {
714    if (!thisConfig.has_around) { return '' }
715    const { $selfDoc } = this.getInsideData()
716
717    // 获取间距
718    const mt = $selfDoc.style['margin-top'] || '0px'
719    const mr = $selfDoc.style['margin-right'] || '0px'
720    const mb = $selfDoc.style['margin-bottom'] || '0px'
721    const ml = $selfDoc.style['margin-left'] || '0px'
722    const pt = $selfDoc.style['padding-top'] || '0px'
723    const pr = $selfDoc.style['padding-right'] || '0px'
724    const pb = $selfDoc.style['padding-bottom'] || '0px'
725    const pl = $selfDoc.style['padding-left'] || '0px'
726    return `
727      <div class="hover around">
728        <ul class="around-y around-top">
729          <li class="spacing margin" style="--s:${mt}"></li>
730          <li class="spacing padding" style="--s:${pt}"></li>
731          <li class="size height"></li>
732        </ul>
733        <ul class="around-x around-right">
734          <li class="spacing margin" style="--s:${mr}"></li>
735          <li class="spacing padding" style="--s:${pr}"></li>
736          <li class="size width"></li>
737        </ul>
738        <ul class="around-y around-bottom">
739          <li class="spacing margin" style="--s:${mb}"></li>
740          <li class="spacing padding" style="--s:${pb}"></li>
741          <li class="size height"></li>
742        </ul>
743        <ul class="around-x around-left">
744          <li class="spacing margin" style="--s:${ml}"></li>
745          <li class="spacing padding" style="--s:${pl}"></li>
746          <li class="size width"></li>
747        </ul>
748      </div>
749      `
750  }
751  /**生成添加按钮的html */
752  _initAddHtml(thisConfig) {
753    let resHtml = ''
754    let { packageItem, $selfDoc } = this.getInsideData()
755    let hookKey = packageItem.dir === 'unit' ? packageItem.type : packageItem.dir
756    let hasAdd = thisConfig.has_add && hooks[hookKey]?.designBoxConfig['add'] !== 'hide'
757    if (hasAdd) {
758      resHtml += `
759        <button
760          data-click="${actionConfig.add.fun_name}"
761          class="hover setting add-btn"
762          title="添加${thisConfig.title}"
763          type="submit"
764          data-toggle="tooltip"
765          data-placement="bottom"
766          data-target="${thisConfig.name}"
767        ><span class="icon-box">+</span><span class="name-box">添加${thisConfig.title}</span></button>`
768    }
769    if (thisConfig.next) {
770      const nextConfig = packageConfig[thisConfig.next]
771      resHtml += `
772        <div class="blank-package__box" data-title="添加${nextConfig.title}" style="${'--rgb:' + nextConfig.rgb}">
773          <div class="blank-package__box-inner">
774            <div class="blank-package__content">
775              <div class="blank-package__btn-box">
776                <button
777                  data-click="${actionConfig.add.fun_name}"
778                  data-target="${thisConfig.next}"
779                  class="setting add-btn"
780                  title="添加${nextConfig.title}"
781                  type="submit"
782                  data-toggle="tooltip"
783                  data-placement="bottom"
784                ></button>
785                <p>添加${nextConfig.title}</p>
786              </div>
787            </div>
788          </div>
789        </div>
790      `
791    }
792    if (packageItem.dir === 'grid' && packageItem.tab_key) {
793      const otherConfig = packageConfig['module']
794      resHtml += `
795        <button
796          style="left: 75%;--rgb:${otherConfig.rgb};"
797          data-click="${actionConfig.add.fun_name}"
798          class="hover setting add-btn"
799          title="关联${otherConfig.title}"
800          type="submit"
801          data-toggle="tooltip"
802          data-placement="bottom"
803          data-target="${otherConfig.name}"
804          data-action="moduleToGrid"
805          data-from="tabs"
806          data-origin-attr-id="${packageItem.attr_id}"
807        ></button>`
808    }
809    if (packageItem.type === 'tabs') {
810      // const nextConfig = packageConfig['grid']
811      /**
812       <div class="blank-package__btn-box">
813              <button
814                data-click="${actionConfig.add.fun_name}"
815                class="setting add-btn"
816                data-target="${nextConfig.name}"
817                title="添加${nextConfig.title}"
818                type="submit"
819                data-toggle="tooltip"
820                data-placement="bottom"
821                data-action="unitToGrid"
822                data-from="tabs"
823              ></button>
824              <p>添加${nextConfig.title}</p>
825            </div>
826       */
827      const otherConfig = packageConfig['module']
828      resHtml += `
829        <div class="blank-package__box" data-title="关联${otherConfig.title}" style="${'--rgb:' + otherConfig.rgb}">
830          <div class="blank-package__box-inner">
831            <div class="blank-package__content">
832              <div class="blank-package__btn-box">
833                <button
834                  data-click="${actionConfig.add.fun_name}"
835                  class="setting add-btn"
836                  data-target="${otherConfig.name}"
837                  title="关联${otherConfig.title}"
838                  type="submit"
839                  data-toggle="tooltip"
840                  data-placement="bottom"
841                  data-action="moduleToGrid"
842                  data-from="tabs"
843                  data-origin-attr-id="${packageItem.attr_id}"
844                ></button>
845                <p>关联${otherConfig.title}</p>
846              </div>
847            </div>
848          </div>
849        </div>
850      `
851    }
852    return resHtml
853  }
854  /**
855  * 判断组件为空的情况下 显示添加按钮为正中间
856  */
857  _showAddBtn() {
858    //当前自己的package-group节点
859    let { $selfDoc, packageItem } = this.getInsideData()
860    const $selfGroup = $selfDoc.querySelectorAll('[package-group]')
861    const popUpModule = $selfDoc.querySelectorAll('[package-item="module"][code="module-pop-up-1"]')
862    $selfGroup.forEach(item => {
863      if (item.children.length === 0) {
864        item.parentNode.classList.add('blank-package')
865        if (item.getAttribute === 'unit') {
866          item.parentNode.parentNode.parentNode.classList.add('show_add-btn')
867        }
868      } else {
869        item.parentNode.classList.remove('blank-package')
870        if (item.getAttribute === 'unit') {
871          setTimeout(() => {
872            const parent = Utilts.getParentsByAttr(item, '[package-item="grid"]')
873            let isUnit = true
874            const $unitGroup = parent.querySelectorAll('[package-group="unit"]')
875            $unitGroup.forEach(
876              (pItem) => { if (pItem.childNodes.length === 0) isUnit = false })
877            if (isUnit) {
878              parent.forEach(ppItem => ppItem.classList.remove('show_add-btn'))
879            }
880          }, 300);
881        }
882        if (window.app.info.page.page_type === 'all_pop_up' && !popUpModule.length && packageItem.dir === 'block') {
883          item.parentNode.classList.add('blank-package')
884        }
885      }
886    })
887  }
888
889  _getModuleTitle(thisConfig) {
890    let { packageItem } = this.getInsideData()
891    if (thisConfig.name === 'module' && packageItem.name) return `title = ${packageItem.name}`
892    return ''
893  }
894
895  /**
896  * 初始化富文本,静态方法,性能好点,只调用一次
897  * @param type =1 初始化,0各种操作
898  */
899  static async initTinyMce(attr_id,packages) {
900    await new Load('/assets/plugins/tinymce/tinymce.js')
901    // tinymce.remove(`#${attr_id} [_html][tinymce]`)
902    tinymceOption.document_base_url = `https://${window.app.info.site.site_domain}`
903    tinymce.remove(`#${attr_id} [_html][tinymce]`);
904    tinymce.init({
905      ...tinymceOption,
906      selector: `#${attr_id} [_html][tinymce]`,
907      language:'zh_CN',
908      quickbars_selection_toolbar: 'undo redo | fontweight italic underline strikethrough | formatselect fontsizeselect lineheight | alignleft aligncenter alignright al
908ignjustify | bullist numlist | outdent indent | forecolor backcolor removeformat | pagebreak | charmap | image link code | xyaiMenu',
909      quickbars_insert_toolbar: 'pagebreak | charmap | image quicktable',
910      setup: function (editor) {
911        editor.ui.registry.addIcon('xiaoyuai', `<svg t="1700114644609" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10004" width="18" height="18"><path d="M634.571245 772.507235h-67.882244c-238.098795 0-298.937344-164.231235-298.937344-304.192744l5.839333-193.427899 194.084824-10.948749c155.143774-4.343004 295.616224 71.67781 293.316987 296.638107v67.444294c0 53.539383 32.846247 96.896429 86.349134 96.896429h160.581652c0-79.086464 0.547437-136.238934 0.547437-211.675815C1008.653503 229.814242 786.247915 0 512.018248 0S15.419488 229.814242 15.419488 513.350346s222.332597 510.649654 496.59876 510.649654h229.522275V858.746881c0-59.086749-47.882529-86.239646-106.969278-86.239646z" fill="#287dff" p-id="10005"></path><path d="M392.786371 379.885095m-42.700121 0a42.700121 42.700121 0 1 0 85.400242 0 42.700121 42.700121 0 1 0-85.400242 0Z" fill="#287dff" p-id="10006"></path><path d="M774.532754 765.719011h66.750873a166.347993 166.347993 0 0 1 166.347993 166.347993v90.071709h-66.86036A166.347993 166.347993 0 0 1 774.532754 855.790719v-90.071708z" fill="#287dff" p-id="10007"></path></svg>`)
912        editor.ui.registry.addMenuButton('xyaiMenu', {
913          text: '小鱼AI',
914          icon: "xiaoyuai",
915          onSetup: function () {
916            const tinymceMaskEle = document.createElement('div')
917            tinymceMaskEle.classList.add('tinymce-mask-box')
918            tinymceMaskEle.innerHTML = '<span class="loading"></span><span>生成期间请勿进行任何操作,请耐心等待,小鱼AI即将生成完毕。</span>'
919            tinymceMaskEle.style.display = 'none'
920            document.querySelector('.tox-pop').appendChild(tinymceMaskEle)
921          },
922          fetch: function (callback) {
923            const getContentWithScene = (params, editor) => {
924              document.querySelector('.tox-toolbar').style.pointerEvents = "none"
925              document.querySelector('.tinymce-mask-box').style.display = 'flex'
926              let requestParams = {
927                site_id:window.ctx.state.site.site_id,
928                scene: params['scene'],
929                content: Utilts.ins().getEditorRangeText(editor),
930                module:2
931              }
932              if (params.tone) requestParams.tone = params.tone
933              if (params.target_group) requestParams.target_group = params.target_group
934              PostMessages.ins().getExternalContent(requestParams, editor.id, params['method'])
935            }
936            var items = [
937              {
938                type: 'menuitem',
939                text: '内容补充',
940                disabled: true,
941                onSetup: function () {
942                  setTimeout(() => {
943                    const aria_owns = document.querySelector('.tox-toolbar .tox-toolbar__group:last-child .tox-tbtn').getAttribute('aria-owns')
944                    document.querySelector(`#${aria_owns}`).classList.add('customize-menu-list')
945                  }, 0);
946                }
947              },
948              {
949                type: 'menuitem',
950                text: '继续写',
951                onAction: () => {
952                  // 插入选中内容
953                  getContentWithScene({ scene: 1, method: 'insert' }, editor)
954                }
955              },
956              {
957                type: 'menuitem',
958                text: '长度调整',
959                disabled: true
960              },
961              {
962                type: 'menuitem',
963                text: '缩短',
964                onAction: function () {
965                  // 覆盖选中内容
966                  getContentWithScene({ scene: 2, method: 'replace' }, editor)
967                }
968              },
969              {
970                type: 'menuitem',
971                text: '加长',
972                onAction: function () {
973                  // 覆盖选中内容
974                  getContentWithScene({ scene: 3, method: 'replace' }, editor)
975                }
976              },
977              {
978                type: 'menuitem',
979                text: '风格调整',
980                disabled: true
981              },
982              {
983                type: 'nestedmenuitem',
984                text: '改变语气',
985                getSubmenuItems: function () {
986                  return [
987                    {
988                      type: 'menuitem',
989                      text: '专业',
990                      onAction: function () {
991                        getContentWithScene({ scene: 7, tone: 1, method: 'replace' }, editor)
992                      }
993                    },
994                    {
995                      type: 'menuitem',
996                      text: '随意',
997                      onAction: function () {
998                        getContentWithScene({ scene: 7, tone: 2, method: 'replace' }, editor)
999                      }
1000                    },
1001                    {
1002                      type: 'menuitem',
1003                      text: '简洁',
1004                      onAction: function () {
1005                        getContentWithScene({ scene: 7, tone: 3, method: 'replace' }, editor)
1006                      }
1007                    },
1008                    {
1009                      type: 'menuitem',
1010                      text: '自信',
1011                      onAction: function () {
1012                        getContentWithScene({ scene: 7, tone: 4, method: 'replace' }, editor)
1013                      }
1014                    },
1015                    {
1016                      type: 'menuitem',
1017                      text: '友好',
1018                      onAction: function () {
1019                        getContentWithScene({ scene: 7, tone: 5, method: 'replace' }, editor)
1020                      }
1021                    },
1022                    {
1023                      type: 'menuitem',
1024                      text: '严肃',
1025                      onAction: function () {
1026                        getContentWithScene({ scene: 7, tone: 6, method: 'replace' }, editor)
1027                      }
1028                    }
1029                  ];
1030                }
1031              },
1032              {
1033                type: 'nestedmenuitem',
1034                text: '面向群体',
1035                getSubmenuItems: function () {
1036                  return [
1037                    {
1038                      type: 'menuitem',
1039                      text: '面向B端采购商',
1040                      onAction: function () {
1041                        getContentWithScene({ scene: 8, target_group: 1, method: 'replace' }, editor)
1042                      }
1043                    },
1044                    {
1045                      type: 'menuitem',
1046                      text: '面向C端消费者',
1047                      onAction: function () {
1048                        getContentWithScene({ scene: 8, target_group: 2, method: 'replace' }, editor)
1049                      }
1050                    }
1051                  ];
1052                }
1053              },
1054              {
1055                type: 'menuitem',
1056                text: '优化调整',
1057                disabled: true
1058              },
1059              {
1060                type: 'menuitem',
1061                text: '语法拼写纠正',
1062                onAction: function () {
1063                  getContentWithScene({ scene: 9, method: 'replace' }, editor)
1064                }
1065              },
1066            ];
1067            callback(items);
1068          }
1069        });
1070      },
1071    })
1072    const tinymceDomtextAll = document.querySelectorAll('[editor_btn]');
1073    if(+tinymceDomtextAll.length){
1074      tinymceDomtextAll.forEach(((e,i)=>{
1075          e.setAttribute('id','editor_btn'+i)
1076          var thisId = e.getAttribute('id');
1077          let option = {}
1078          option.inline = false;
1079          option.menubar = false;
1080          option.branding = false;
1081          option.height = '600px';
1082          option.paste_data_images = false;
1083          tinymce.remove(`#${e.getAttribute('id')}`);
1084          tinymce.init({
1085            selector:`#${thisId}`,
1086            language:'zh_CN',
1087            fontsize_formats: "8pt 10pt 12pt 14pt 16pt 18pt 20pt 24pt 36pt",
1088            toolbar: 'code undo redo | formatpainter casechange blocks | bold italic underline strikethrough backcolor forecolor | ' +
1089            'formatselect fontsizeselect lineheight | ' +
1090            'alignleft aligncenter alignright alignjustify | ' +
1091            'bullist numlist checklist outdent indent | removeformat | image link table backlight',
1092            plugins: 'paste  charmap link image quickbars lineheight table code lists',
1093            ...option,
1094            quickbars_insert_toolbar: 'quicktable',
1095            setup: function () {
1096            },
1097            init_instance_callback(editor){
1098              editor.on('input', (e) => {
1099              });
1100              editor.on('blur', (e) => {
1101                var content = tinyMCE.activeEditor.getContent();
1102                var editorParents = Utilts.ins().getParents(editor.iframeElement.parentNode,{className:'unit-custom_editor'});
1103                var unitParents =  editorParents[0].parentNode;
1104                var id = unitParents.getAttribute('id')
1105                if(+Object.keys(packages).length){
1106                  var keys = Object.keys(packages).filter(a=>a==id);
1107                  packages[keys[0]].content.data[0].description =  content
1108                }
1109              });
1110              editor.on('paste', (e) => {
1111                  //var content = tinyMCE.activeEditor.getContent();
1112              });
1113              editor.on('ExecCommand', (e) => {
1114                  //var content = tinyMCE.activeEditor.getContent();
1115              });
1116            }
1117          })
1118      }))
1119    }
1120    window.dispatchEvent(new CustomEvent('designAfterInitTinyMce'))
1121  }
1122
1123  // _htmlEditEvent(sign, thisDom) {
1124  //   if (!thisDom) { return }
1125  //   let { packageItem } = this.getInsideData()
1126  //   thisDom.addEventListener('blur', event => {
1127  //     // 冒泡
1128  //     event.stopPropagation()
1129  //     // 不是组件就不需要继续了
1130  //     if (packageItem.dir !== 'unit') return
1131  //     // 获取html内容,包括标签
1132  //     const html = thisDom.innerHTML
1133  //     // 匹配修改项并更新,返回是否修改
1134  //     let isChange = this.mapEditDataHtml(packageItem.content.data, sign, html)
1135  //     /** 提交到装修修改页面中的Html */
1136  //     if (isChange) {
1137  //       PostMessages.ins().modifyUnitHtml(packageItem)
1138  //       // 计算长度,超了就提示,但还是要保存,不能随便自动还原或截断,需要手动处理
1139  //       if (thisDom.innerHTML.length >= 65535) new Message().error('内容超过限制,将无法保存')
1140  //       else new Message().success('修改成功,保存后生效')
1141  //     } else {
1142  //       // new Message().info('无修改')
1143  //     }
1144  //   })
1145  // }
1146  /**
1147  * 判断是否不能装修(针对非首页的头部、底部、版权)
1148  */
1149  static checkCannotDesign(dom) {
1150    if (!dom) return
1151    const noDesignList = ['header', 'footer', 'copyright']
1152    let block = dom
1153    if (dom.getAttribute('package-item') !== 'block') {
1154      const paramsDom = Utilts.ins().getParentsByAttr(dom, 'package-item', 'block')
1155      block = paramsDom[0]
1156    }
1157    if (!block) return
1158    const blockType = block.getAttribute('package-type')
1159    // 如果是底部的友情链接不能编辑
1160    if (blockType === 'copyright') {
1161      const links = Utilts.ins().getParentsByAttr(dom, 'package-type', 'list')
1162      if (links.length > 0) { return true }
1163    }
1164    const allow = (window.location.pathname !== '/' && window.location.pathname !== '/all-pop-up.html') && noDesignList.includes(blockType)
1165    return allow
1166  }
1167}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.