@epxing/designer 5.3.0-beta.1 → 5.3.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/API.md +5 -4
  2. package/README.md +46 -45
  3. package/dist/src/index.js +1 -0
  4. package/dist/src/page-designer/PageConfigPreview.js +1 -0
  5. package/dist/src/page-designer/PageDesigner.js +12 -0
  6. package/dist/src/page-designer/designer.js +22 -0
  7. package/dist/src/page-designer/index.js +1 -0
  8. package/dist/src/page-designer/mixins/dragSourceMixin.js +1 -0
  9. package/dist/src/page-designer/page-variable-panel/JsonEditor.js +1 -0
  10. package/dist/src/page-designer/page-variable-panel/PageVariablePanel.js +1 -0
  11. package/dist/src/page-designer/page-variable-panel/index.js +1 -0
  12. package/dist/src/page-designer/page-variable-panel/jsonlint.js +1 -0
  13. package/dist/src/page-designer/previews/add-form/Preview.js +2 -1
  14. package/dist/src/page-designer/previews/add-form/Preview.vue.js +19 -8
  15. package/dist/src/page-designer/previews/add-form-item/Preview.js +1 -0
  16. package/dist/src/page-designer/previews/button/Preview.js +1 -0
  17. package/dist/src/page-designer/previews/card/Preview.js +1 -0
  18. package/dist/src/page-designer/previews/carousel/CarouselItemPreview.js +1 -0
  19. package/dist/src/page-designer/previews/carousel/Preview.js +1 -0
  20. package/dist/src/page-designer/previews/collapse/CollapseItemPreview.js +1 -0
  21. package/dist/src/page-designer/previews/collapse/Preview.js +1 -0
  22. package/dist/src/page-designer/previews/dropdown/Preview.js +1 -0
  23. package/dist/src/page-designer/previews/entity-list/Preview.js +1 -0
  24. package/dist/src/page-designer/previews/entity-sub-list/Preview.js +1 -0
  25. package/dist/src/page-designer/previews/entity-virtual-list/Preview.js +1 -0
  26. package/dist/src/page-designer/previews/form-field/preview/Checkbox.js +1 -0
  27. package/dist/src/page-designer/previews/form-field/preview/Date.js +1 -0
  28. package/dist/src/page-designer/previews/form-field/preview/Input.js +1 -0
  29. package/dist/src/page-designer/previews/form-field/preview/InputNumber.js +1 -0
  30. package/dist/src/page-designer/previews/form-field/preview/Object.js +1 -0
  31. package/dist/src/page-designer/previews/form-field/preview/Radio.js +1 -0
  32. package/dist/src/page-designer/previews/form-field/preview/Select.js +1 -0
  33. package/dist/src/page-designer/previews/form-field/preview/Textarea.js +1 -0
  34. package/dist/src/page-designer/previews/grid/Preview.js +1 -0
  35. package/dist/src/page-designer/previews/html/Preview.js +1 -0
  36. package/dist/src/page-designer/previews/icon/Preview.js +1 -0
  37. package/dist/src/page-designer/previews/image/Preview.js +1 -0
  38. package/dist/src/page-designer/previews/index.js +1 -0
  39. package/dist/src/page-designer/previews/layout/ColumnPreview.js +1 -0
  40. package/dist/src/page-designer/previews/layout/Preview.js +1 -0
  41. package/dist/src/page-designer/previews/num/Preview.js +1 -0
  42. package/dist/src/page-designer/previews/page-tabs/Preview.js +1 -0
  43. package/dist/src/page-designer/previews/step/Preview.js +1 -0
  44. package/dist/src/page-designer/previews/tabs/Preview.js +1 -0
  45. package/dist/src/page-designer/previews/tabs/tab-pane/Preview.js +1 -0
  46. package/dist/src/page-designer/previews/text/Preview.js +1 -0
  47. package/dist/src/page-designer/previews/text-editor/Preview.js +1 -0
  48. package/dist/src/page-designer/previews/video/Preview.js +1 -0
  49. package/dist/src/page-designer/setting-panel/Advance.js +1 -0
  50. package/dist/src/page-designer/setting-panel/CodeEditor.js +1 -0
  51. package/dist/src/page-designer/setting-panel/Property.js +1 -0
  52. package/dist/src/page-designer/setting-panel/Setting.js +47 -10
  53. package/dist/src/page-designer/setting-panel/Style.js +1 -0
  54. package/dist/src/page-designer/setting-panel/css-editor/CssEditor.js +1 -0
  55. package/dist/src/page-designer/setting-panel/css-editor/css-hint.js +1 -0
  56. package/dist/src/page-designer/setting-panel/index.js +1 -0
  57. package/dist/src/page-designer/template-attribute-panel/TemplateAttributePanel.js +1 -0
  58. package/dist/src/page-designer/template-attribute-panel/index.js +1 -0
  59. package/dist/src/page-designer/template-library/Library.js +1 -0
  60. package/dist/src/page-designer/template-library/index.js +1 -0
  61. package/dist/src/page-designer/widget-library/Base.js +1 -0
  62. package/dist/src/page-designer/widget-library/Library.js +1 -0
  63. package/dist/src/page-designer/widget-library/index.js +1 -0
  64. package/dist/src/page-designer/widget-preview/Container.js +1 -0
  65. package/dist/src/page-designer/widget-preview/DragGhost.js +1 -0
  66. package/dist/src/page-designer/widget-preview/DropZoneOverlay.js +1 -0
  67. package/dist/src/page-designer/widget-preview/HoverOverlay.js +1 -0
  68. package/dist/src/page-designer/widget-preview/Mixin.js +1 -0
  69. package/dist/src/page-designer/widget-preview/Placeholder.js +1 -0
  70. package/dist/src/page-designer/widget-preview/Preview.js +1 -0
  71. package/dist/src/page-designer/widget-preview/PreviewItem.js +1 -0
  72. package/dist/src/page-designer/widget-preview/SelectedOverlay.js +1 -0
  73. package/dist/src/page-designer/widget-preview/Template.js +1 -0
  74. package/dist/src/page-designer/widget-preview/WidgetWrapper.js +1 -0
  75. package/dist/src/page-designer/widget-preview/directive.js +1 -0
  76. package/dist/src/page-designer/widget-preview/dropPosition.js +1 -0
  77. package/dist/src/page-designer/widget-preview/index.js +1 -0
  78. package/dist/src/page-designer/widget-preview/overlayPositionMixin.js +1 -0
  79. package/dist/src/page-designer/widget-preview/resolvePreviewName.js +1 -0
  80. package/dist/src/page-designer/widget-tree/Item.js +1 -0
  81. package/dist/src/page-designer/widget-tree/Tree.js +1 -0
  82. package/dist/src/page-designer/widget-tree/index.js +1 -0
  83. package/dist/src/visual/AddForm.js +1 -0
  84. package/dist/src/visual/AddFormItem.js +1 -0
  85. package/dist/src/visual/AppIndex.js +1 -0
  86. package/dist/src/visual/ApplyForm.js +1 -0
  87. package/dist/src/visual/AttributeList.js +1 -0
  88. package/dist/src/visual/BasePage.js +1 -0
  89. package/dist/src/visual/Button.js +1 -0
  90. package/dist/src/visual/CardNum.js +1 -0
  91. package/dist/src/visual/CategoryList.js +1 -0
  92. package/dist/src/visual/Chart.js +1 -0
  93. package/dist/src/visual/ChartNew.js +1 -0
  94. package/dist/src/visual/CheckForm.js +1 -0
  95. package/dist/src/visual/ClientList.js +1 -0
  96. package/dist/src/visual/CodeManage.js +1 -0
  97. package/dist/src/visual/Component.js +1 -0
  98. package/dist/src/visual/ComponentList.js +1 -0
  99. package/dist/src/visual/Config.js +1 -0
  100. package/dist/src/visual/ConfigItem.js +1 -0
  101. package/dist/src/visual/ConfigSelectItems.js +1 -0
  102. package/dist/src/visual/CreatePage.js +1 -0
  103. package/dist/src/visual/DashboardDiv.js +1 -0
  104. package/dist/src/visual/DashboardTabs.js +1 -0
  105. package/dist/src/visual/DashboardWidget.js +1 -0
  106. package/dist/src/visual/DblogList.js +1 -0
  107. package/dist/src/visual/EntityAddPage.js +1 -0
  108. package/dist/src/visual/EntityApplyPage.js +1 -0
  109. package/dist/src/visual/EntityCardList.js +1 -0
  110. package/dist/src/visual/EntityCheckPage.js +1 -0
  111. package/dist/src/visual/EntityFindPage.js +1 -0
  112. package/dist/src/visual/EntityList.js +1 -0
  113. package/dist/src/visual/EntityListPage.js +1 -0
  114. package/dist/src/visual/EntityNoSubmitSubList.js +1 -0
  115. package/dist/src/visual/EntityRightSubList.js +1 -0
  116. package/dist/src/visual/EntitySubAdd.js +1 -0
  117. package/dist/src/visual/EntitySubGridItem.js +1 -0
  118. package/dist/src/visual/EntitySubList.js +1 -0
  119. package/dist/src/visual/EntityTreeFindPage.js +1 -0
  120. package/dist/src/visual/EntityTreeManage.js +1 -0
  121. package/dist/src/visual/EntityTreePage.js +1 -0
  122. package/dist/src/visual/ExcelPreview.js +1 -0
  123. package/dist/src/visual/FormField.js +1 -0
  124. package/dist/src/visual/HeaderNew.js +1 -0
  125. package/dist/src/visual/Html.js +1 -0
  126. package/dist/src/visual/Import.js +1 -0
  127. package/dist/src/visual/InterfaceSubList.js +1 -0
  128. package/dist/src/visual/ListFirst.js +1 -0
  129. package/dist/src/visual/MEntityAddPage.js +1 -0
  130. package/dist/src/visual/MEntityList.js +1 -0
  131. package/dist/src/visual/MEntityListPage.js +1 -0
  132. package/dist/src/visual/MEntitySubList.js +1 -0
  133. package/dist/src/visual/MetaList.js +1 -0
  134. package/dist/src/visual/ModuleIndexPage.js +1 -0
  135. package/dist/src/visual/ModuleList.js +1 -0
  136. package/dist/src/visual/NavAddForm.js +1 -0
  137. package/dist/src/visual/NavFormCatalogItem.js +1 -0
  138. package/dist/src/visual/NumItem.js +1 -0
  139. package/dist/src/visual/NumStatistic.js +1 -0
  140. package/dist/src/visual/OrgChart.js +1 -0
  141. package/dist/src/visual/PageCatalog.js +1 -0
  142. package/dist/src/visual/PageConfig.js +1 -0
  143. package/dist/src/visual/PageTabs.js +1 -0
  144. package/dist/src/visual/Progress.js +1 -0
  145. package/dist/src/visual/ProgressItem.js +1 -0
  146. package/dist/src/visual/SystemManager.js +1 -0
  147. package/dist/src/visual/Title.js +1 -0
  148. package/dist/src/visual/TodoList.js +1 -0
  149. package/dist/src/visual/UserFormItem.js +1 -0
  150. package/dist/src/visual/UserManage.js +1 -0
  151. package/dist/src/visual/chart/CircularPie.js +1 -0
  152. package/dist/src/visual/chart/Column.js +1 -0
  153. package/dist/src/visual/chart/HoriColumn.js +1 -0
  154. package/dist/src/visual/chart/Line.js +1 -0
  155. package/dist/src/visual/chart/Pie.js +1 -0
  156. package/dist/src/visual/config/Background.js +1 -0
  157. package/dist/src/visual/config/Chart.js +1 -0
  158. package/dist/src/visual/config/Checkbox.js +1 -0
  159. package/dist/src/visual/config/Color.js +1 -0
  160. package/dist/src/visual/config/DesignReport.js +1 -0
  161. package/dist/src/visual/config/Event.js +1 -0
  162. package/dist/src/visual/config/Field.js +1 -0
  163. package/dist/src/visual/config/Font.js +1 -0
  164. package/dist/src/visual/config/FormItem.js +1 -0
  165. package/dist/src/visual/config/Function.js +1 -0
  166. package/dist/src/visual/config/Html.js +1 -0
  167. package/dist/src/visual/config/Image.js +1 -0
  168. package/dist/src/visual/config/Input.js +1 -0
  169. package/dist/src/visual/config/LazyDialog.js +1 -0
  170. package/dist/src/visual/config/List.js +1 -0
  171. package/dist/src/visual/config/ListField.js +1 -0
  172. package/dist/src/visual/config/MField.js +1 -0
  173. package/dist/src/visual/config/Number.js +1 -0
  174. package/dist/src/visual/config/Object.js +1 -0
  175. package/dist/src/visual/config/Operate.js +1 -0
  176. package/dist/src/visual/config/OperateItem.js +1 -0
  177. package/dist/src/visual/config/Options.js +1 -0
  178. package/dist/src/visual/config/OrderField.js +1 -0
  179. package/dist/src/visual/config/Page.js +1 -0
  180. package/dist/src/visual/config/Params.js +1 -0
  181. package/dist/src/visual/config/Radio.js +1 -0
  182. package/dist/src/visual/config/Row.js +1 -0
  183. package/dist/src/visual/config/Scope.js +1 -0
  184. package/dist/src/visual/config/Select.js +1 -0
  185. package/dist/src/visual/config/Switch.js +1 -0
  186. package/dist/src/visual/config/Textarea.js +1 -0
  187. package/dist/src/visual/config/Tree.js +1 -0
  188. package/dist/src/visual/config/remote-cache.js +1 -0
  189. package/dist/src/visual/config/show-condition.js +1 -0
  190. package/dist/src/visual/config/variable-sources.js +1 -0
  191. package/dist/src/visual/config/wait-ref.js +1 -0
  192. package/dist/src/visual/config-page/ComponentLibrary.js +1 -0
  193. package/dist/src/visual/config-page/ComponentLibraryDialog.js +9 -2
  194. package/dist/src/visual/config-page/ComponentList.js +1 -0
  195. package/dist/src/visual/config-page/ComponentPreview.js +1 -0
  196. package/dist/src/visual/config-page/ConfigOption.js +1 -0
  197. package/dist/src/visual/config-page/ConfigPanel.js +1 -0
  198. package/dist/src/visual/config-page/Dashboard.js +1 -0
  199. package/dist/src/visual/config-page/DashboardDesign.js +1 -0
  200. package/dist/src/visual/config-page/DashboardGlobalConfig.js +1 -0
  201. package/dist/src/visual/config-page/DashboardMobile.js +2 -1
  202. package/dist/src/visual/config-page/DashboardSetting.js +1 -0
  203. package/dist/src/visual/config-page/PagePreview.js +1 -0
  204. package/dist/src/visual/config-page/StyleConfig.js +1 -0
  205. package/dist/src/visual/config-page/VisualConfigPage.js +1 -0
  206. package/dist/src/visual/config-page/dashboard-theme-setting/Background.js +1 -0
  207. package/dist/src/visual/config-page/dashboard-theme-setting/Border.js +1 -0
  208. package/dist/src/visual/config-page/dashboard-theme-setting/Font.js +1 -0
  209. package/dist/src/visual/config-page/dashboard-theme-setting/Index.js +1 -0
  210. package/dist/src/visual/config-page/dashboard-theme-setting/Shadow.js +1 -0
  211. package/dist/src/visual/config-page/index.js +1 -0
  212. package/dist/src/visual/index.js +1 -0
  213. package/dist/src/visual/mixins/innerGridMixin.js +1 -0
  214. package/dist/src/visual/search/Filter.js +1 -0
  215. package/dist/src/visual/step/Index.js +1 -0
  216. package/dist/src/visual/step/Item.js +1 -0
  217. package/dist/src/visual/widgets/CardFormItemVisual.js +1 -0
  218. package/dist/src/visual/widgets/CarouselVisual.js +1 -0
  219. package/dist/src/visual/widgets/CollapseVisual.js +1 -0
  220. package/dist/src/visual/widgets/DropdownVisual.js +1 -0
  221. package/dist/src/visual/widgets/LayoutConfig.js +1 -0
  222. package/dist/src/visual/widgets/ListVisual.js +1 -0
  223. package/dist/src/visual/widgets/MEntityListFindVisual.js +1 -0
  224. package/dist/src/visual/widgets/ProcessFormItemVisual.js +1 -0
  225. package/dist/src/visual/widgets/TabsConfig.js +1 -0
  226. package/dist/style.css +116 -112
  227. package/package.json +10 -9
  228. package/src/index.js +27 -27
  229. package/src/page-designer/PageDesigner.vue +11 -0
  230. package/src/page-designer/designer.js +1322 -1299
  231. package/src/page-designer/previews/add-form/Preview.vue +43 -44
  232. package/src/page-designer/setting-panel/Setting.vue +24 -2
  233. package/src/page-designer/widget-preview/Mixin.js +285 -285
  234. package/src/page-designer/widget-preview/Preview.vue +322 -322
  235. package/src/page-designer/widget-preview/WidgetWrapper.vue +197 -197
  236. package/src/page-designer/widget-preview/directive.js +258 -258
  237. package/src/visual/CategoryList.vue +563 -563
  238. package/src/visual/ComponentList.vue +280 -280
  239. package/src/visual/CreatePage.vue +389 -389
  240. package/src/visual/EntityCardList.vue +449 -449
  241. package/src/visual/EntityList.vue +838 -838
  242. package/src/visual/config-page/ComponentLibraryDialog.vue +7 -1
  243. package/src/visual/config-page/DashboardMobile.vue +934 -934
  244. package/src/visual/widgets/ProcessFormItemVisual.vue +58 -58
  245. package/types/index.d.ts +22 -22
  246. package/types/page-designer.d.ts +3 -3
  247. package/types/visual-component.d.ts +1 -1
  248. package/types/visual-entity-list.d.ts +1 -1
  249. package/types/visual-entity-sub-list.d.ts +1 -1
@@ -1,322 +1,322 @@
1
- <template>
2
- <div :class="['epx-page-designer-widget-preview', 'css_' + designer.page.pageId]">
3
- <div
4
- ref="rootDropZone"
5
- class="epx-page-designer-widget-preview__drop-zone"
6
- @dragenter="onRootDragEnter"
7
- @dragover.prevent="onRootDragOver"
8
- @dragleave="onRootDragLeave"
9
- @drop.prevent="onRootDrop"
10
- >
11
- <div class="epx-page-designer-widget-preview__draggable epx-page-designer-widget-preview__draggable-list el-row">
12
- <template v-for="widget in designer.widgetList" :key="widget.id">
13
- <!-- 模板 -->
14
- <template-preview
15
- v-if="widget.type === 'template'"
16
-
17
- :widget="widget"
18
- :designer="designer"
19
- :parent-widget="null"
20
- :pageRelationList="pageRelationList"
21
- ></template-preview>
22
- <!-- 普通组件 -->
23
- <component
24
- v-else
25
- :key="widget.id"
26
- :is="getWidgetName(widget)"
27
- :widget="widget"
28
- :designer="designer"
29
- :parent-widget="null"
30
- :pageRelationList="pageRelationList"
31
- v-widget-designer="{ widget, designer, parentWidget: null, templateInfo: null }"
32
- ></component>
33
- </template>
34
- <div class="epx-page-designer-widget-preview__no-widget" v-if="designer.widgetList.length===0">拖拽组件到这里</div>
35
- </div>
36
- </div>
37
- </div>
38
- </template>
39
-
40
- <script>
41
- import util from '@epxing/core/src/runtime-utils/util'
42
- import TemplatePreview from './Template'
43
- import widgetDesignerDirective from './directive'
44
- import { resolvePreviewName } from './resolvePreviewName'
45
- import { createDropCache, clearDropCache, insertIndex, insertLineRect } from './dropPosition'
46
-
47
- function appendCss (id, css) {
48
- const formatCss = css.replace(/:current/g, '.css_' + id).replace(/url\s*\(([\w+-/.\s]+)\)/g, (str, $1) => {
49
- return `url(${util.getFileUrl($1)})`
50
- })
51
- const element = document.getElementById('style_' + id)
52
- if (element) {
53
- element.textContent = formatCss
54
- } else {
55
- const style = document.createElement('style')
56
- style.id = 'style_' + id
57
- style.textContent = formatCss
58
-
59
- style.setAttribute('type', 'text/css')
60
- document.head.appendChild(style)
61
- }
62
- }
63
- function removeCss (id) {
64
- const element = document.getElementById('style_' + id)
65
- if (element) document.head.removeChild(element)
66
- }
67
- export default {
68
- name: 'epx-page-designer-widget-preview',
69
-
70
- // T33:原为 module-level `Vue.directive('widget-designer', …)`(Vue3 无全局 Vue.directive)。
71
- // 改成**局部注册** —— 最干净:不依赖 app 单例,也不会有「指令重复注册」的 dev 告警。
72
- directives: { 'widget-designer': widgetDesignerDirective },
73
-
74
- data () {
75
- return {
76
- }
77
- },
78
- components: {
79
- TemplatePreview
80
- },
81
- props: {
82
- designer: Object,
83
- pageRelationList: Array
84
- },
85
- // emits: ['widget-click', 'widget-hover'],
86
- computed: {
87
- isContainer () {
88
- return v => {
89
- const widgetInfo = this.designer.getWidgetByType(v.code) || {}
90
- return widgetInfo.CONTAINER === '1'
91
- }
92
- },
93
- widgetInfo () {
94
- return v => {
95
- return this.designer.getWidgetByType(v.code) || {}
96
- }
97
- },
98
- // 预览组件名解析统一走 resolvePreviewName(命中项有缓存)
99
- getWidgetName () {
100
- return widget => resolvePreviewName(this.designer, widget)
101
- }
102
- },
103
- watch: {
104
- 'designer.pageConfig.css' (v) {
105
- appendCss(this.designer.page.pageId, v)
106
- }
107
- },
108
- methods: {
109
- // 根画布拖拽进入:重新测量一次根列表的 children,之后的 dragover 复用缓存
110
- onRootDragEnter (e) {
111
- if (this._rootDragLeaveTimer) {
112
- clearTimeout(this._rootDragLeaveTimer)
113
- this._rootDragLeaveTimer = null
114
- }
115
- if (!this.isDraggingFromLibrary(e)) return
116
- if (!this._dropCache) this._dropCache = createDropCache()
117
- clearDropCache(this._dropCache)
118
- this.designer.setDragOverTarget({ type: 'root', widgetId: null })
119
- this.designer.setDragOverTargetElement(this.$refs.rootDropZone)
120
- // 同步到大纲树:设置根级拖拽目标
121
- this.designer.setPreviewDragTarget({ widgetId: null, position: 'root' })
122
- },
123
- // 根画布拖拽悬停:只记坐标 + 允许放置;插入位置的计算与状态更新合并到下一帧
124
- onRootDragOver (e) {
125
- if (!this.isDraggingFromLibrary(e)) return
126
- e.preventDefault()
127
- // 拖画布已有组件用 move,组件库 / 模板库用 copy(不能在 dragover 里 getData,读拖拽状态即可)
128
- e.dataTransfer.dropEffect = this.designer.dragState.dragSource === 'preview' ? 'move' : 'copy'
129
- this._dragClientX = e.clientX
130
- this._dragClientY = e.clientY
131
- if (this._dragFrame) return
132
- this._dragFrame = requestAnimationFrame(() => {
133
- this._dragFrame = null
134
- if (!this.designer.dragState.isDragging) return
135
- this.designer.updateDragGhostPosition(this._dragClientX, this._dragClientY)
136
- const listEl = this.$el.querySelector('.epx-page-designer-widget-preview__draggable')
137
- if (!this._dropCache) this._dropCache = createDropCache()
138
- const lineRect = insertLineRect(this._dropCache, listEl, this._dragClientY)
139
- if (lineRect) this.designer.setDragInsertLine(lineRect)
140
- // 同步到大纲树:更新插入位置
141
- this.designer.setPreviewDragTarget({ widgetId: null, index: insertIndex(this._dropCache, listEl, this._dragClientY), position: 'root' })
142
- })
143
- },
144
- onRootDragLeave (e) {
145
- // 使用延迟检查,避免在子元素之间移动时误判
146
- if (this._rootDragLeaveTimer) {
147
- clearTimeout(this._rootDragLeaveTimer)
148
- }
149
-
150
- this._rootDragLeaveTimer = setTimeout(() => {
151
- // 检查 relatedTarget 是否仍在根元素内
152
- if (!this.$refs.rootDropZone || !this.$refs.rootDropZone.contains(e.relatedTarget)) {
153
- this.designer.clearDragOverTarget()
154
- this.designer.clearDragInsertLine()
155
- this.designer.clearPreviewDragTarget()
156
- if (this._dropCache) clearDropCache(this._dropCache)
157
- }
158
- this._rootDragLeaveTimer = null
159
- }, 50)
160
- },
161
- isDraggingFromLibrary (e) {
162
- return e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types.includes('text/plain')
163
- },
164
- onRootDrop (e) {
165
- e.preventDefault()
166
-
167
- // 清除可能存在的离开定时器
168
- if (this._rootDragLeaveTimer) {
169
- clearTimeout(this._rootDragLeaveTimer)
170
- this._rootDragLeaveTimer = null
171
- }
172
-
173
- this.designer.clearDragOverTarget()
174
- this.designer.clearDragInsertLine()
175
- this.designer.clearPreviewDragTarget()
176
- const listEl = this.$el.querySelector('.epx-page-designer-widget-preview__draggable')
177
- if (!this._dropCache) this._dropCache = createDropCache()
178
- const index = insertIndex(this._dropCache, listEl, e.clientY)
179
- clearDropCache(this._dropCache)
180
-
181
- // 使用 designer 的统一拖拽处理方法;不在这里调用 drag-end,让 dragend 事件自然触发
182
- this.designer.handleDrop({ dataTransfer: e.dataTransfer, target: { type: 'root', widgetId: null, index } })
183
- },
184
-
185
- splitTemplate () {
186
- const { CONTENT } = this.widgetInfo
187
- if (CONTENT) {
188
- const config = JSON.parse(CONTENT)
189
- const { id } = this.designer.selectedWidget
190
- const { items, itemConfigs, JS: templateJs } = config
191
- const formatConfig = (arr) => {
192
- arr.forEach(compItem => {
193
- const oldId = compItem.id
194
- const newId = compItem.contentType + '_' + this.$util.genId()
195
- if (itemConfigs[oldId]) {
196
- itemConfigs[newId] = itemConfigs[oldId]
197
- delete itemConfigs[oldId]
198
- }
199
- compItem.id = newId
200
- if (compItem.items) {
201
- formatConfig(compItem.items)
202
- }
203
- })
204
- }
205
- formatConfig(items)
206
- const findWidgetPos = (arr, parent) => {
207
- for (let i = 0; i < arr.length; i++) {
208
- const item = arr[i]
209
- if (item.id === id) {
210
- return { parent: parent, index: i }
211
- } else if (item.items) {
212
- const child = findWidgetPos(item.items, item)
213
- if (child) return child
214
- }
215
- }
216
- }
217
- const widgetPos = findWidgetPos(this.designer.widgetList, null)
218
- if (widgetPos) {
219
- const { parent, index } = widgetPos
220
- if (parent) {
221
- parent.items.splice(index, 1, ...items)
222
- } else {
223
- this.designer.widgetList.splice(index, 1, ...items)
224
- }
225
- this.designer.mergeWidgetConfig(itemConfigs)
226
- delete this.designer.widgetConfig[id]
227
- if (templateJs) {
228
- let { JS = '' } = this.designer.pageConfig
229
- const result = JS.match(/export\sfunction\s(\w+)/g)
230
- const events = []
231
- if (result) {
232
- result.forEach(item => {
233
- events.push(item.replace(/export\sfunction\s/, ''))
234
- })
235
- }
236
- const templateJsResult = templateJs.split(/export\s+function\s+/)
237
- templateJsResult.forEach(item => {
238
- const funtionStr = item.replace(/\/\*(\n|.)+?\*\/[\n\s]+$/, '')
239
- if (funtionStr.replace(/[\n\s]+/g, '').length > 0) {
240
- const funtionName = funtionStr.split(/\s+\(/)[0]
241
- if (![...new Set(events)].includes(funtionName)) {
242
- JS += 'export function ' + funtionStr.replace(/^\w+/, funtionName)
243
- }
244
- }
245
- })
246
- this.designer.updatePageConfig({ JS })
247
- }
248
- this.designer.setSelected(items[0])
249
- }
250
- }
251
- },
252
-
253
- onDragUpdate () {
254
-
255
- },
256
- checkMove () {
257
-
258
- },
259
- handleWidgetClick (data) {
260
- this.$emit('widget-click', data)
261
- },
262
- handleWidgetHover (widgetId) {
263
- this.$emit('widget-hover', widgetId)
264
- }
265
- },
266
- created () {
267
- const { css } = this.designer.pageConfig
268
- if (css) {
269
- appendCss(this.designer.page.pageId, css)
270
- }
271
- },
272
- unmounted () {
273
- removeCss(this.designer.page.pageId)
274
-
275
- // 清除定时器
276
- if (this._rootDragLeaveTimer) {
277
- clearTimeout(this._rootDragLeaveTimer)
278
- this._rootDragLeaveTimer = null
279
- }
280
- if (this._dragFrame) {
281
- cancelAnimationFrame(this._dragFrame)
282
- this._dragFrame = null
283
- }
284
- }
285
- }
286
- </script>
287
-
288
- <style lang="scss">
289
- @include b(page-designer-widget-preview) {
290
- width: 100%;
291
- height: 100%;
292
- overflow: auto;
293
- @include e(draggable) {
294
- width: 100%;
295
- // height: 100%;
296
- min-height: 60px;
297
- position: relative;
298
- }
299
- @include e(draggable-list) {
300
- overflow: auto;
301
- }
302
- @include e(list) {
303
- min-height: 100%;
304
- }
305
- @include e(no-widget) {
306
- height: 100%;
307
- padding: 16px 0;
308
- box-sizing: border-box;
309
- display: flex;
310
- align-items: center;
311
- justify-content: center;
312
- text-align: center;
313
- color: #999999;
314
- background-color: #f0f0f0;
315
- border: 1px dotted #a7b1bd;
316
- pointer-events: none;
317
- }
318
- }
319
-
320
- // 悬停样式已由悬浮窗组件处理,这里不再需要
321
-
322
- </style>
1
+ <template>
2
+ <div :class="['epx-page-designer-widget-preview', 'css_' + designer.page.pageId]">
3
+ <div
4
+ ref="rootDropZone"
5
+ class="epx-page-designer-widget-preview__drop-zone"
6
+ @dragenter="onRootDragEnter"
7
+ @dragover.prevent="onRootDragOver"
8
+ @dragleave="onRootDragLeave"
9
+ @drop.prevent="onRootDrop"
10
+ >
11
+ <div class="epx-page-designer-widget-preview__draggable epx-page-designer-widget-preview__draggable-list el-row">
12
+ <template v-for="widget in designer.widgetList" :key="widget.id">
13
+ <!-- 模板 -->
14
+ <template-preview
15
+ v-if="widget.type === 'template'"
16
+
17
+ :widget="widget"
18
+ :designer="designer"
19
+ :parent-widget="null"
20
+ :pageRelationList="pageRelationList"
21
+ ></template-preview>
22
+ <!-- 普通组件 -->
23
+ <component
24
+ v-else
25
+ :key="widget.id"
26
+ :is="getWidgetName(widget)"
27
+ :widget="widget"
28
+ :designer="designer"
29
+ :parent-widget="null"
30
+ :pageRelationList="pageRelationList"
31
+ v-widget-designer="{ widget, designer, parentWidget: null, templateInfo: null }"
32
+ ></component>
33
+ </template>
34
+ <div class="epx-page-designer-widget-preview__no-widget" v-if="designer.widgetList.length===0">拖拽组件到这里</div>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script>
41
+ import util from '@epxing/core/src/runtime-utils/util'
42
+ import TemplatePreview from './Template'
43
+ import widgetDesignerDirective from './directive'
44
+ import { resolvePreviewName } from './resolvePreviewName'
45
+ import { createDropCache, clearDropCache, insertIndex, insertLineRect } from './dropPosition'
46
+
47
+ function appendCss (id, css) {
48
+ const formatCss = css.replace(/:current/g, '.css_' + id).replace(/url\s*\(([\w+-/.\s]+)\)/g, (str, $1) => {
49
+ return `url(${util.getFileUrl($1)})`
50
+ })
51
+ const element = document.getElementById('style_' + id)
52
+ if (element) {
53
+ element.textContent = formatCss
54
+ } else {
55
+ const style = document.createElement('style')
56
+ style.id = 'style_' + id
57
+ style.textContent = formatCss
58
+
59
+ style.setAttribute('type', 'text/css')
60
+ document.head.appendChild(style)
61
+ }
62
+ }
63
+ function removeCss (id) {
64
+ const element = document.getElementById('style_' + id)
65
+ if (element) document.head.removeChild(element)
66
+ }
67
+ export default {
68
+ name: 'epx-page-designer-widget-preview',
69
+
70
+ // T33:原为 module-level `Vue.directive('widget-designer', …)`(Vue3 无全局 Vue.directive)。
71
+ // 改成**局部注册** —— 最干净:不依赖 app 单例,也不会有「指令重复注册」的 dev 告警。
72
+ directives: { 'widget-designer': widgetDesignerDirective },
73
+
74
+ data () {
75
+ return {
76
+ }
77
+ },
78
+ components: {
79
+ TemplatePreview
80
+ },
81
+ props: {
82
+ designer: Object,
83
+ pageRelationList: Array
84
+ },
85
+ // emits: ['widget-click', 'widget-hover'],
86
+ computed: {
87
+ isContainer () {
88
+ return v => {
89
+ const widgetInfo = this.designer.getWidgetByType(v.code) || {}
90
+ return widgetInfo.CONTAINER === '1'
91
+ }
92
+ },
93
+ widgetInfo () {
94
+ return v => {
95
+ return this.designer.getWidgetByType(v.code) || {}
96
+ }
97
+ },
98
+ // 预览组件名解析统一走 resolvePreviewName(命中项有缓存)
99
+ getWidgetName () {
100
+ return widget => resolvePreviewName(this.designer, widget)
101
+ }
102
+ },
103
+ watch: {
104
+ 'designer.pageConfig.css' (v) {
105
+ appendCss(this.designer.page.pageId, v)
106
+ }
107
+ },
108
+ methods: {
109
+ // 根画布拖拽进入:重新测量一次根列表的 children,之后的 dragover 复用缓存
110
+ onRootDragEnter (e) {
111
+ if (this._rootDragLeaveTimer) {
112
+ clearTimeout(this._rootDragLeaveTimer)
113
+ this._rootDragLeaveTimer = null
114
+ }
115
+ if (!this.isDraggingFromLibrary(e)) return
116
+ if (!this._dropCache) this._dropCache = createDropCache()
117
+ clearDropCache(this._dropCache)
118
+ this.designer.setDragOverTarget({ type: 'root', widgetId: null })
119
+ this.designer.setDragOverTargetElement(this.$refs.rootDropZone)
120
+ // 同步到大纲树:设置根级拖拽目标
121
+ this.designer.setPreviewDragTarget({ widgetId: null, position: 'root' })
122
+ },
123
+ // 根画布拖拽悬停:只记坐标 + 允许放置;插入位置的计算与状态更新合并到下一帧
124
+ onRootDragOver (e) {
125
+ if (!this.isDraggingFromLibrary(e)) return
126
+ e.preventDefault()
127
+ // 拖画布已有组件用 move,组件库 / 模板库用 copy(不能在 dragover 里 getData,读拖拽状态即可)
128
+ e.dataTransfer.dropEffect = this.designer.dragState.dragSource === 'preview' ? 'move' : 'copy'
129
+ this._dragClientX = e.clientX
130
+ this._dragClientY = e.clientY
131
+ if (this._dragFrame) return
132
+ this._dragFrame = requestAnimationFrame(() => {
133
+ this._dragFrame = null
134
+ if (!this.designer.dragState.isDragging) return
135
+ this.designer.updateDragGhostPosition(this._dragClientX, this._dragClientY)
136
+ const listEl = this.$el.querySelector('.epx-page-designer-widget-preview__draggable')
137
+ if (!this._dropCache) this._dropCache = createDropCache()
138
+ const lineRect = insertLineRect(this._dropCache, listEl, this._dragClientY)
139
+ if (lineRect) this.designer.setDragInsertLine(lineRect)
140
+ // 同步到大纲树:更新插入位置
141
+ this.designer.setPreviewDragTarget({ widgetId: null, index: insertIndex(this._dropCache, listEl, this._dragClientY), position: 'root' })
142
+ })
143
+ },
144
+ onRootDragLeave (e) {
145
+ // 使用延迟检查,避免在子元素之间移动时误判
146
+ if (this._rootDragLeaveTimer) {
147
+ clearTimeout(this._rootDragLeaveTimer)
148
+ }
149
+
150
+ this._rootDragLeaveTimer = setTimeout(() => {
151
+ // 检查 relatedTarget 是否仍在根元素内
152
+ if (!this.$refs.rootDropZone || !this.$refs.rootDropZone.contains(e.relatedTarget)) {
153
+ this.designer.clearDragOverTarget()
154
+ this.designer.clearDragInsertLine()
155
+ this.designer.clearPreviewDragTarget()
156
+ if (this._dropCache) clearDropCache(this._dropCache)
157
+ }
158
+ this._rootDragLeaveTimer = null
159
+ }, 50)
160
+ },
161
+ isDraggingFromLibrary (e) {
162
+ return e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types.includes('text/plain')
163
+ },
164
+ onRootDrop (e) {
165
+ e.preventDefault()
166
+
167
+ // 清除可能存在的离开定时器
168
+ if (this._rootDragLeaveTimer) {
169
+ clearTimeout(this._rootDragLeaveTimer)
170
+ this._rootDragLeaveTimer = null
171
+ }
172
+
173
+ this.designer.clearDragOverTarget()
174
+ this.designer.clearDragInsertLine()
175
+ this.designer.clearPreviewDragTarget()
176
+ const listEl = this.$el.querySelector('.epx-page-designer-widget-preview__draggable')
177
+ if (!this._dropCache) this._dropCache = createDropCache()
178
+ const index = insertIndex(this._dropCache, listEl, e.clientY)
179
+ clearDropCache(this._dropCache)
180
+
181
+ // 使用 designer 的统一拖拽处理方法;不在这里调用 drag-end,让 dragend 事件自然触发
182
+ this.designer.handleDrop({ dataTransfer: e.dataTransfer, target: { type: 'root', widgetId: null, index } })
183
+ },
184
+
185
+ splitTemplate () {
186
+ const { CONTENT } = this.widgetInfo
187
+ if (CONTENT) {
188
+ const config = JSON.parse(CONTENT)
189
+ const { id } = this.designer.selectedWidget
190
+ const { items, itemConfigs, JS: templateJs } = config
191
+ const formatConfig = (arr) => {
192
+ arr.forEach(compItem => {
193
+ const oldId = compItem.id
194
+ const newId = compItem.contentType + '_' + this.$util.genId()
195
+ if (itemConfigs[oldId]) {
196
+ itemConfigs[newId] = itemConfigs[oldId]
197
+ delete itemConfigs[oldId]
198
+ }
199
+ compItem.id = newId
200
+ if (compItem.items) {
201
+ formatConfig(compItem.items)
202
+ }
203
+ })
204
+ }
205
+ formatConfig(items)
206
+ const findWidgetPos = (arr, parent) => {
207
+ for (let i = 0; i < arr.length; i++) {
208
+ const item = arr[i]
209
+ if (item.id === id) {
210
+ return { parent: parent, index: i }
211
+ } else if (item.items) {
212
+ const child = findWidgetPos(item.items, item)
213
+ if (child) return child
214
+ }
215
+ }
216
+ }
217
+ const widgetPos = findWidgetPos(this.designer.widgetList, null)
218
+ if (widgetPos) {
219
+ const { parent, index } = widgetPos
220
+ if (parent) {
221
+ parent.items.splice(index, 1, ...items)
222
+ } else {
223
+ this.designer.widgetList.splice(index, 1, ...items)
224
+ }
225
+ this.designer.mergeWidgetConfig(itemConfigs)
226
+ delete this.designer.widgetConfig[id]
227
+ if (templateJs) {
228
+ let { JS = '' } = this.designer.pageConfig
229
+ const result = JS.match(/export\sfunction\s(\w+)/g)
230
+ const events = []
231
+ if (result) {
232
+ result.forEach(item => {
233
+ events.push(item.replace(/export\sfunction\s/, ''))
234
+ })
235
+ }
236
+ const templateJsResult = templateJs.split(/export\s+function\s+/)
237
+ templateJsResult.forEach(item => {
238
+ const funtionStr = item.replace(/\/\*(\n|.)+?\*\/[\n\s]+$/, '')
239
+ if (funtionStr.replace(/[\n\s]+/g, '').length > 0) {
240
+ const funtionName = funtionStr.split(/\s+\(/)[0]
241
+ if (![...new Set(events)].includes(funtionName)) {
242
+ JS += 'export function ' + funtionStr.replace(/^\w+/, funtionName)
243
+ }
244
+ }
245
+ })
246
+ this.designer.updatePageConfig({ JS })
247
+ }
248
+ this.designer.setSelected(items[0])
249
+ }
250
+ }
251
+ },
252
+
253
+ onDragUpdate () {
254
+
255
+ },
256
+ checkMove () {
257
+
258
+ },
259
+ handleWidgetClick (data) {
260
+ this.$emit('widget-click', data)
261
+ },
262
+ handleWidgetHover (widgetId) {
263
+ this.$emit('widget-hover', widgetId)
264
+ }
265
+ },
266
+ created () {
267
+ const { css } = this.designer.pageConfig
268
+ if (css) {
269
+ appendCss(this.designer.page.pageId, css)
270
+ }
271
+ },
272
+ unmounted () {
273
+ removeCss(this.designer.page.pageId)
274
+
275
+ // 清除定时器
276
+ if (this._rootDragLeaveTimer) {
277
+ clearTimeout(this._rootDragLeaveTimer)
278
+ this._rootDragLeaveTimer = null
279
+ }
280
+ if (this._dragFrame) {
281
+ cancelAnimationFrame(this._dragFrame)
282
+ this._dragFrame = null
283
+ }
284
+ }
285
+ }
286
+ </script>
287
+
288
+ <style lang="scss">
289
+ @include b(page-designer-widget-preview) {
290
+ width: 100%;
291
+ height: 100%;
292
+ overflow: auto;
293
+ @include e(draggable) {
294
+ width: 100%;
295
+ // height: 100%;
296
+ min-height: 60px;
297
+ position: relative;
298
+ }
299
+ @include e(draggable-list) {
300
+ overflow: auto;
301
+ }
302
+ @include e(list) {
303
+ min-height: 100%;
304
+ }
305
+ @include e(no-widget) {
306
+ height: 100%;
307
+ padding: 16px 0;
308
+ box-sizing: border-box;
309
+ display: flex;
310
+ align-items: center;
311
+ justify-content: center;
312
+ text-align: center;
313
+ color: #999999;
314
+ background-color: #f0f0f0;
315
+ border: 1px dotted #a7b1bd;
316
+ pointer-events: none;
317
+ }
318
+ }
319
+
320
+ // 悬停样式已由悬浮窗组件处理,这里不再需要
321
+
322
+ </style>