@epxing/designer 0.0.0-stage → 5.3.0-beta.2

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 (491) hide show
  1. package/API.md +160 -0
  2. package/README.md +45 -2
  3. package/dist/_virtual/_plugin-vue_export-helper.js +10 -0
  4. package/dist/_virtual/preload-helper.js +88 -0
  5. package/dist/assets/default-icon-2193FMjv.png +0 -0
  6. package/dist/assets/technology_bg-oWIS2awO.jpg +0 -0
  7. package/dist/assets/theme_black-Ctdygcr4.png +0 -0
  8. package/dist/assets/theme_technology-DJk-2e7g.png +0 -0
  9. package/dist/assets/theme_white-uMQ6JYml.png +0 -0
  10. package/dist/src/assets/images/dashboard/theme_black.png.js +4 -0
  11. package/dist/src/assets/images/dashboard/theme_technology.png.js +4 -0
  12. package/dist/src/assets/images/dashboard/theme_white.png.js +4 -0
  13. package/dist/src/assets/images/default-icon.png.js +4 -0
  14. package/dist/src/index.js +53 -0
  15. package/dist/src/page-designer/PageConfigPreview.js +102 -0
  16. package/dist/src/page-designer/PageDesigner.js +844 -0
  17. package/dist/src/page-designer/designer.js +1120 -0
  18. package/dist/src/page-designer/index.js +52 -0
  19. package/dist/src/page-designer/mixins/dragSourceMixin.js +95 -0
  20. package/dist/src/page-designer/page-variable-panel/JsonEditor.js +106 -0
  21. package/dist/src/page-designer/page-variable-panel/PageVariablePanel.js +939 -0
  22. package/dist/src/page-designer/page-variable-panel/index.js +7 -0
  23. package/dist/src/page-designer/page-variable-panel/jsonlint.js +230 -0
  24. package/dist/src/page-designer/previews/add-form/Preview.js +8 -0
  25. package/dist/src/page-designer/previews/add-form/Preview.vue.js +328 -0
  26. package/dist/src/page-designer/previews/add-form-item/Preview.js +194 -0
  27. package/dist/src/page-designer/previews/button/Preview.js +30 -0
  28. package/dist/src/page-designer/previews/card/Preview.js +87 -0
  29. package/dist/src/page-designer/previews/carousel/CarouselItemPreview.js +33 -0
  30. package/dist/src/page-designer/previews/carousel/Preview.js +61 -0
  31. package/dist/src/page-designer/previews/collapse/CollapseItemPreview.js +118 -0
  32. package/dist/src/page-designer/previews/collapse/Preview.js +35 -0
  33. package/dist/src/page-designer/previews/dropdown/Preview.js +68 -0
  34. package/dist/src/page-designer/previews/entity-list/Preview.js +522 -0
  35. package/dist/src/page-designer/previews/entity-sub-list/Preview.js +352 -0
  36. package/dist/src/page-designer/previews/entity-virtual-list/Preview.js +11 -0
  37. package/dist/src/page-designer/previews/form-field/preview/Checkbox.js +91 -0
  38. package/dist/src/page-designer/previews/form-field/preview/Date.js +77 -0
  39. package/dist/src/page-designer/previews/form-field/preview/Input.js +74 -0
  40. package/dist/src/page-designer/previews/form-field/preview/InputNumber.js +74 -0
  41. package/dist/src/page-designer/previews/form-field/preview/Object.js +77 -0
  42. package/dist/src/page-designer/previews/form-field/preview/Radio.js +146 -0
  43. package/dist/src/page-designer/previews/form-field/preview/Select.js +78 -0
  44. package/dist/src/page-designer/previews/form-field/preview/Textarea.js +78 -0
  45. package/dist/src/page-designer/previews/grid/Preview.js +139 -0
  46. package/dist/src/page-designer/previews/html/Preview.js +18 -0
  47. package/dist/src/page-designer/previews/icon/Preview.js +20 -0
  48. package/dist/src/page-designer/previews/image/Preview.js +36 -0
  49. package/dist/src/page-designer/previews/index.js +74 -0
  50. package/dist/src/page-designer/previews/layout/ColumnPreview.js +47 -0
  51. package/dist/src/page-designer/previews/layout/Preview.js +110 -0
  52. package/dist/src/page-designer/previews/num/Preview.js +132 -0
  53. package/dist/src/page-designer/previews/page-tabs/Preview.js +75 -0
  54. package/dist/src/page-designer/previews/step/Preview.js +207 -0
  55. package/dist/src/page-designer/previews/tabs/Preview.js +95 -0
  56. package/dist/src/page-designer/previews/tabs/tab-pane/Preview.js +33 -0
  57. package/dist/src/page-designer/previews/text/Preview.js +38 -0
  58. package/dist/src/page-designer/previews/text-editor/Preview.js +23 -0
  59. package/dist/src/page-designer/previews/video/Preview.js +10 -0
  60. package/dist/src/page-designer/setting-panel/Advance.js +281 -0
  61. package/dist/src/page-designer/setting-panel/CodeEditor.js +94 -0
  62. package/dist/src/page-designer/setting-panel/Property.js +165 -0
  63. package/dist/src/page-designer/setting-panel/Setting.js +296 -0
  64. package/dist/src/page-designer/setting-panel/Style.js +1591 -0
  65. package/dist/src/page-designer/setting-panel/css-editor/CssEditor.js +98 -0
  66. package/dist/src/page-designer/setting-panel/css-editor/css-hint.js +84 -0
  67. package/dist/src/page-designer/setting-panel/index.js +11 -0
  68. package/dist/src/page-designer/template-attribute-panel/TemplateAttributePanel.js +487 -0
  69. package/dist/src/page-designer/template-attribute-panel/index.js +5 -0
  70. package/dist/src/page-designer/template-library/Library.js +219 -0
  71. package/dist/src/page-designer/template-library/index.js +5 -0
  72. package/dist/src/page-designer/widget-library/Base.js +170 -0
  73. package/dist/src/page-designer/widget-library/Library.js +213 -0
  74. package/dist/src/page-designer/widget-library/index.js +7 -0
  75. package/dist/src/page-designer/widget-preview/Container.js +80 -0
  76. package/dist/src/page-designer/widget-preview/DragGhost.js +54 -0
  77. package/dist/src/page-designer/widget-preview/DropZoneOverlay.js +42 -0
  78. package/dist/src/page-designer/widget-preview/HoverOverlay.js +61 -0
  79. package/dist/src/page-designer/widget-preview/Mixin.js +260 -0
  80. package/dist/src/page-designer/widget-preview/Placeholder.js +28 -0
  81. package/dist/src/page-designer/widget-preview/Preview.js +277 -0
  82. package/dist/src/page-designer/widget-preview/PreviewItem.js +83 -0
  83. package/dist/src/page-designer/widget-preview/SelectedOverlay.js +332 -0
  84. package/dist/src/page-designer/widget-preview/Template.js +66 -0
  85. package/dist/src/page-designer/widget-preview/WidgetWrapper.js +170 -0
  86. package/dist/src/page-designer/widget-preview/directive.js +159 -0
  87. package/dist/src/page-designer/widget-preview/dropPosition.js +50 -0
  88. package/dist/src/page-designer/widget-preview/index.js +23 -0
  89. package/dist/src/page-designer/widget-preview/overlayPositionMixin.js +87 -0
  90. package/dist/src/page-designer/widget-preview/resolvePreviewName.js +32 -0
  91. package/dist/src/page-designer/widget-tree/Item.js +580 -0
  92. package/dist/src/page-designer/widget-tree/Tree.js +855 -0
  93. package/dist/src/page-designer/widget-tree/index.js +7 -0
  94. package/dist/src/visual/AddForm.js +172 -0
  95. package/dist/src/visual/AddFormItem.js +480 -0
  96. package/dist/src/visual/AppIndex.js +243 -0
  97. package/dist/src/visual/ApplyForm.js +135 -0
  98. package/dist/src/visual/AttributeList.js +344 -0
  99. package/dist/src/visual/BasePage.js +77 -0
  100. package/dist/src/visual/Button.js +5 -0
  101. package/dist/src/visual/Button.vue.js +89 -0
  102. package/dist/src/visual/CardNum.js +74 -0
  103. package/dist/src/visual/CategoryList.js +569 -0
  104. package/dist/src/visual/Chart.js +27 -0
  105. package/dist/src/visual/ChartNew.js +5 -0
  106. package/dist/src/visual/ChartNew.vue.js +54 -0
  107. package/dist/src/visual/CheckForm.js +110 -0
  108. package/dist/src/visual/ClientList.js +41 -0
  109. package/dist/src/visual/CodeManage.js +113 -0
  110. package/dist/src/visual/Component.js +6 -0
  111. package/dist/src/visual/Component.vue.js +1332 -0
  112. package/dist/src/visual/ComponentList.js +280 -0
  113. package/dist/src/visual/Config.js +8 -0
  114. package/dist/src/visual/Config.vue.js +862 -0
  115. package/dist/src/visual/ConfigItem.js +8 -0
  116. package/dist/src/visual/ConfigItem.vue.js +192 -0
  117. package/dist/src/visual/ConfigSelectItems.js +8 -0
  118. package/dist/src/visual/ConfigSelectItems.vue.js +260 -0
  119. package/dist/src/visual/CreatePage.js +389 -0
  120. package/dist/src/visual/DashboardDiv.js +58 -0
  121. package/dist/src/visual/DashboardTabs.js +9 -0
  122. package/dist/src/visual/DashboardTabs.vue.js +127 -0
  123. package/dist/src/visual/DashboardWidget.js +5 -0
  124. package/dist/src/visual/DashboardWidget.vue.js +62 -0
  125. package/dist/src/visual/DblogList.js +82 -0
  126. package/dist/src/visual/EntityAddPage.js +49 -0
  127. package/dist/src/visual/EntityApplyPage.js +54 -0
  128. package/dist/src/visual/EntityCardList.js +455 -0
  129. package/dist/src/visual/EntityCheckPage.js +66 -0
  130. package/dist/src/visual/EntityFindPage.js +45 -0
  131. package/dist/src/visual/EntityList.js +6 -0
  132. package/dist/src/visual/EntityList.vue.js +1221 -0
  133. package/dist/src/visual/EntityListPage.js +43 -0
  134. package/dist/src/visual/EntityNoSubmitSubList.js +267 -0
  135. package/dist/src/visual/EntityRightSubList.js +29 -0
  136. package/dist/src/visual/EntitySubAdd.js +10 -0
  137. package/dist/src/visual/EntitySubGridItem.js +66 -0
  138. package/dist/src/visual/EntitySubList.js +434 -0
  139. package/dist/src/visual/EntityTreeFindPage.js +32 -0
  140. package/dist/src/visual/EntityTreeManage.js +49 -0
  141. package/dist/src/visual/EntityTreePage.js +42 -0
  142. package/dist/src/visual/ExcelPreview.js +10 -0
  143. package/dist/src/visual/FormField.js +5 -0
  144. package/dist/src/visual/FormField.vue.js +121 -0
  145. package/dist/src/visual/HeaderNew.js +161 -0
  146. package/dist/src/visual/Html.js +8 -0
  147. package/dist/src/visual/Html.vue.js +109 -0
  148. package/dist/src/visual/Import.js +53 -0
  149. package/dist/src/visual/InterfaceSubList.js +21 -0
  150. package/dist/src/visual/ListFirst.js +704 -0
  151. package/dist/src/visual/MEntityAddPage.js +66 -0
  152. package/dist/src/visual/MEntityList.js +485 -0
  153. package/dist/src/visual/MEntityListPage.js +40 -0
  154. package/dist/src/visual/MEntitySubList.js +237 -0
  155. package/dist/src/visual/MetaList.js +23 -0
  156. package/dist/src/visual/ModuleIndexPage.js +67 -0
  157. package/dist/src/visual/ModuleList.js +47 -0
  158. package/dist/src/visual/NavAddForm.js +173 -0
  159. package/dist/src/visual/NavFormCatalogItem.js +44 -0
  160. package/dist/src/visual/NumItem.js +70 -0
  161. package/dist/src/visual/NumStatistic.js +6 -0
  162. package/dist/src/visual/NumStatistic.vue.js +81 -0
  163. package/dist/src/visual/OrgChart.js +107 -0
  164. package/dist/src/visual/PageCatalog.js +27 -0
  165. package/dist/src/visual/PageConfig.js +223 -0
  166. package/dist/src/visual/PageTabs.js +49 -0
  167. package/dist/src/visual/Progress.js +40 -0
  168. package/dist/src/visual/ProgressItem.js +44 -0
  169. package/dist/src/visual/SystemManager.js +77 -0
  170. package/dist/src/visual/Title.js +45 -0
  171. package/dist/src/visual/TodoList.js +14 -0
  172. package/dist/src/visual/UserFormItem.js +41 -0
  173. package/dist/src/visual/UserManage.js +35 -0
  174. package/dist/src/visual/chart/CircularPie.js +9 -0
  175. package/dist/src/visual/chart/Column.js +70 -0
  176. package/dist/src/visual/chart/HoriColumn.js +9 -0
  177. package/dist/src/visual/chart/Line.js +9 -0
  178. package/dist/src/visual/chart/Pie.js +9 -0
  179. package/dist/src/visual/config/Background.js +526 -0
  180. package/dist/src/visual/config/Chart.js +154 -0
  181. package/dist/src/visual/config/Checkbox.js +63 -0
  182. package/dist/src/visual/config/Color.js +41 -0
  183. package/dist/src/visual/config/DesignReport.js +24 -0
  184. package/dist/src/visual/config/Event.js +304 -0
  185. package/dist/src/visual/config/Field.js +520 -0
  186. package/dist/src/visual/config/Font.js +202 -0
  187. package/dist/src/visual/config/FormItem.js +23 -0
  188. package/dist/src/visual/config/Function.js +114 -0
  189. package/dist/src/visual/config/Html.js +111 -0
  190. package/dist/src/visual/config/Image.js +102 -0
  191. package/dist/src/visual/config/Input.js +177 -0
  192. package/dist/src/visual/config/Input.vue.js +479 -0
  193. package/dist/src/visual/config/LazyDialog.js +41 -0
  194. package/dist/src/visual/config/List.js +65 -0
  195. package/dist/src/visual/config/ListField.js +2080 -0
  196. package/dist/src/visual/config/MField.js +733 -0
  197. package/dist/src/visual/config/Number.js +37 -0
  198. package/dist/src/visual/config/Object.js +168 -0
  199. package/dist/src/visual/config/Operate.js +1109 -0
  200. package/dist/src/visual/config/OperateItem.js +1186 -0
  201. package/dist/src/visual/config/Options.js +8 -0
  202. package/dist/src/visual/config/Options.vue.js +278 -0
  203. package/dist/src/visual/config/OrderField.js +505 -0
  204. package/dist/src/visual/config/Page.js +76 -0
  205. package/dist/src/visual/config/Params.js +353 -0
  206. package/dist/src/visual/config/Radio.js +127 -0
  207. package/dist/src/visual/config/Row.js +104 -0
  208. package/dist/src/visual/config/Scope.js +350 -0
  209. package/dist/src/visual/config/Select.js +95 -0
  210. package/dist/src/visual/config/Switch.js +37 -0
  211. package/dist/src/visual/config/Textarea.js +175 -0
  212. package/dist/src/visual/config/Textarea.vue.js +507 -0
  213. package/dist/src/visual/config/Tree.js +138 -0
  214. package/dist/src/visual/config/remote-cache.js +30 -0
  215. package/dist/src/visual/config/show-condition.js +20 -0
  216. package/dist/src/visual/config/variable-sources.js +27 -0
  217. package/dist/src/visual/config/wait-ref.js +19 -0
  218. package/dist/src/visual/config-page/ComponentLibrary.js +170 -0
  219. package/dist/src/visual/config-page/ComponentLibraryDialog.js +250 -0
  220. package/dist/src/visual/config-page/ComponentList.js +9 -0
  221. package/dist/src/visual/config-page/ComponentList.vue.js +292 -0
  222. package/dist/src/visual/config-page/ComponentPreview.js +8 -0
  223. package/dist/src/visual/config-page/ComponentPreview.vue.js +151 -0
  224. package/dist/src/visual/config-page/ConfigOption.js +13 -0
  225. package/dist/src/visual/config-page/ConfigPanel.js +302 -0
  226. package/dist/src/visual/config-page/Dashboard.js +2160 -0
  227. package/dist/src/visual/config-page/DashboardDesign.js +606 -0
  228. package/dist/src/visual/config-page/DashboardGlobalConfig.js +6 -0
  229. package/dist/src/visual/config-page/DashboardGlobalConfig.vue.js +292 -0
  230. package/dist/src/visual/config-page/DashboardMobile.js +1115 -0
  231. package/dist/src/visual/config-page/DashboardSetting.js +86 -0
  232. package/dist/src/visual/config-page/PagePreview.js +8 -0
  233. package/dist/src/visual/config-page/PagePreview.vue.js +72 -0
  234. package/dist/src/visual/config-page/StyleConfig.js +979 -0
  235. package/dist/src/visual/config-page/VisualConfigPage.js +645 -0
  236. package/dist/src/visual/config-page/dashboard-theme-setting/Background.js +180 -0
  237. package/dist/src/visual/config-page/dashboard-theme-setting/Border.js +314 -0
  238. package/dist/src/visual/config-page/dashboard-theme-setting/Font.js +192 -0
  239. package/dist/src/visual/config-page/dashboard-theme-setting/Index.js +545 -0
  240. package/dist/src/visual/config-page/dashboard-theme-setting/Shadow.js +174 -0
  241. package/dist/src/visual/config-page/index.js +90 -0
  242. package/dist/src/visual/index.js +151 -0
  243. package/dist/src/visual/mixins/innerGridMixin.js +122 -0
  244. package/dist/src/visual/search/Filter.js +49 -0
  245. package/dist/src/visual/step/Index.js +8 -0
  246. package/dist/src/visual/step/Index.vue.js +485 -0
  247. package/dist/src/visual/step/Item.js +139 -0
  248. package/dist/src/visual/widgets/CardFormItemVisual.js +45 -0
  249. package/dist/src/visual/widgets/CarouselVisual.js +8 -0
  250. package/dist/src/visual/widgets/CarouselVisual.vue.js +303 -0
  251. package/dist/src/visual/widgets/CollapseVisual.js +8 -0
  252. package/dist/src/visual/widgets/CollapseVisual.vue.js +202 -0
  253. package/dist/src/visual/widgets/DropdownVisual.js +8 -0
  254. package/dist/src/visual/widgets/DropdownVisual.vue.js +955 -0
  255. package/dist/src/visual/widgets/LayoutConfig.js +8 -0
  256. package/dist/src/visual/widgets/LayoutConfig.vue.js +168 -0
  257. package/dist/src/visual/widgets/ListVisual.js +349 -0
  258. package/dist/src/visual/widgets/MEntityListFindVisual.js +76 -0
  259. package/dist/src/visual/widgets/ProcessFormItemVisual.js +5 -0
  260. package/dist/src/visual/widgets/ProcessFormItemVisual.vue.js +45 -0
  261. package/dist/src/visual/widgets/TabsConfig.js +8 -0
  262. package/dist/src/visual/widgets/TabsConfig.vue.js +343 -0
  263. package/dist/style.css +9907 -0
  264. package/package.json +104 -3
  265. package/src/index.js +27 -0
  266. package/src/page-designer/PageConfigPreview.vue +103 -0
  267. package/src/page-designer/PageDesigner.vue +1017 -0
  268. package/src/page-designer/designer.js +1299 -0
  269. package/src/page-designer/index.js +38 -0
  270. package/src/page-designer/mixins/dragSourceMixin.js +113 -0
  271. package/src/page-designer/page-variable-panel/JsonEditor.vue +109 -0
  272. package/src/page-designer/page-variable-panel/PageVariablePanel.vue +781 -0
  273. package/src/page-designer/page-variable-panel/index.js +6 -0
  274. package/src/page-designer/page-variable-panel/jsonlint.js +2 -0
  275. package/src/page-designer/previews/add-form/Preview.vue +331 -0
  276. package/src/page-designer/previews/add-form-item/Preview.vue +167 -0
  277. package/src/page-designer/previews/button/Preview.vue +27 -0
  278. package/src/page-designer/previews/card/Preview.vue +78 -0
  279. package/src/page-designer/previews/carousel/CarouselItemPreview.vue +32 -0
  280. package/src/page-designer/previews/carousel/Preview.vue +36 -0
  281. package/src/page-designer/previews/collapse/CollapseItemPreview.vue +136 -0
  282. package/src/page-designer/previews/collapse/Preview.vue +28 -0
  283. package/src/page-designer/previews/dropdown/Preview.vue +21 -0
  284. package/src/page-designer/previews/entity-list/Preview.vue +382 -0
  285. package/src/page-designer/previews/entity-sub-list/Preview.vue +283 -0
  286. package/src/page-designer/previews/entity-virtual-list/Preview.vue +14 -0
  287. package/src/page-designer/previews/form-field/preview/Checkbox.vue +57 -0
  288. package/src/page-designer/previews/form-field/preview/Date.vue +56 -0
  289. package/src/page-designer/previews/form-field/preview/Input.vue +53 -0
  290. package/src/page-designer/previews/form-field/preview/InputNumber.vue +53 -0
  291. package/src/page-designer/previews/form-field/preview/Object.vue +53 -0
  292. package/src/page-designer/previews/form-field/preview/Radio.vue +69 -0
  293. package/src/page-designer/previews/form-field/preview/Select.vue +55 -0
  294. package/src/page-designer/previews/form-field/preview/Textarea.vue +57 -0
  295. package/src/page-designer/previews/grid/Preview.vue +156 -0
  296. package/src/page-designer/previews/html/Preview.vue +11 -0
  297. package/src/page-designer/previews/icon/Preview.vue +12 -0
  298. package/src/page-designer/previews/image/Preview.vue +37 -0
  299. package/src/page-designer/previews/index.js +74 -0
  300. package/src/page-designer/previews/layout/ColumnPreview.vue +89 -0
  301. package/src/page-designer/previews/layout/Preview.vue +96 -0
  302. package/src/page-designer/previews/num/Preview.vue +100 -0
  303. package/src/page-designer/previews/page-tabs/Preview.vue +53 -0
  304. package/src/page-designer/previews/step/Preview.vue +190 -0
  305. package/src/page-designer/previews/tabs/Preview.vue +66 -0
  306. package/src/page-designer/previews/tabs/tab-pane/Preview.vue +32 -0
  307. package/src/page-designer/previews/text/Preview.vue +26 -0
  308. package/src/page-designer/previews/text-editor/Preview.vue +14 -0
  309. package/src/page-designer/previews/video/Preview.vue +9 -0
  310. package/src/page-designer/setting-panel/Advance.vue +175 -0
  311. package/src/page-designer/setting-panel/CodeEditor.vue +88 -0
  312. package/src/page-designer/setting-panel/Property.vue +163 -0
  313. package/src/page-designer/setting-panel/Setting.vue +271 -0
  314. package/src/page-designer/setting-panel/Style.vue +1096 -0
  315. package/src/page-designer/setting-panel/css-editor/CssEditor.vue +93 -0
  316. package/src/page-designer/setting-panel/css-editor/css-hint.js +58 -0
  317. package/src/page-designer/setting-panel/index.js +10 -0
  318. package/src/page-designer/template-attribute-panel/TemplateAttributePanel.vue +383 -0
  319. package/src/page-designer/template-attribute-panel/index.js +2 -0
  320. package/src/page-designer/template-library/Library.vue +153 -0
  321. package/src/page-designer/template-library/index.js +4 -0
  322. package/src/page-designer/widget-library/Base.vue +156 -0
  323. package/src/page-designer/widget-library/Library.vue +282 -0
  324. package/src/page-designer/widget-library/index.js +6 -0
  325. package/src/page-designer/widget-preview/Container.vue +89 -0
  326. package/src/page-designer/widget-preview/DragGhost.vue +83 -0
  327. package/src/page-designer/widget-preview/DropZoneOverlay.vue +51 -0
  328. package/src/page-designer/widget-preview/HoverOverlay.vue +85 -0
  329. package/src/page-designer/widget-preview/Mixin.js +285 -0
  330. package/src/page-designer/widget-preview/Placeholder.vue +22 -0
  331. package/src/page-designer/widget-preview/Preview.vue +322 -0
  332. package/src/page-designer/widget-preview/PreviewItem.vue +162 -0
  333. package/src/page-designer/widget-preview/SelectedOverlay.vue +340 -0
  334. package/src/page-designer/widget-preview/Template.vue +77 -0
  335. package/src/page-designer/widget-preview/WidgetWrapper.vue +197 -0
  336. package/src/page-designer/widget-preview/directive.js +258 -0
  337. package/src/page-designer/widget-preview/dropPosition.js +51 -0
  338. package/src/page-designer/widget-preview/index.js +23 -0
  339. package/src/page-designer/widget-preview/overlayPositionMixin.js +88 -0
  340. package/src/page-designer/widget-preview/resolvePreviewName.js +33 -0
  341. package/src/page-designer/widget-tree/Item.vue +719 -0
  342. package/src/page-designer/widget-tree/Tree.vue +995 -0
  343. package/src/page-designer/widget-tree/index.js +6 -0
  344. package/src/visual/AddForm.vue +172 -0
  345. package/src/visual/AddFormItem.vue +482 -0
  346. package/src/visual/AppIndex.vue +245 -0
  347. package/src/visual/ApplyForm.vue +140 -0
  348. package/src/visual/AttributeList.vue +344 -0
  349. package/src/visual/BasePage.vue +76 -0
  350. package/src/visual/Button.vue +80 -0
  351. package/src/visual/CardNum.vue +73 -0
  352. package/src/visual/CategoryList.vue +563 -0
  353. package/src/visual/Chart.vue +29 -0
  354. package/src/visual/ChartNew.vue +49 -0
  355. package/src/visual/CheckForm.vue +106 -0
  356. package/src/visual/ClientList.vue +42 -0
  357. package/src/visual/CodeManage.vue +116 -0
  358. package/src/visual/Component.vue +1342 -0
  359. package/src/visual/ComponentList.vue +280 -0
  360. package/src/visual/Config.vue +881 -0
  361. package/src/visual/ConfigItem.vue +218 -0
  362. package/src/visual/ConfigSelectItems.vue +445 -0
  363. package/src/visual/CreatePage.vue +389 -0
  364. package/src/visual/DashboardDiv.vue +197 -0
  365. package/src/visual/DashboardTabs.vue +118 -0
  366. package/src/visual/DashboardWidget.vue +55 -0
  367. package/src/visual/DblogList.vue +84 -0
  368. package/src/visual/EntityAddPage.vue +52 -0
  369. package/src/visual/EntityApplyPage.vue +57 -0
  370. package/src/visual/EntityCardList.vue +449 -0
  371. package/src/visual/EntityCheckPage.vue +69 -0
  372. package/src/visual/EntityFindPage.vue +55 -0
  373. package/src/visual/EntityList.vue +838 -0
  374. package/src/visual/EntityListPage.vue +97 -0
  375. package/src/visual/EntityNoSubmitSubList.vue +273 -0
  376. package/src/visual/EntityRightSubList.vue +32 -0
  377. package/src/visual/EntitySubAdd.vue +11 -0
  378. package/src/visual/EntitySubGridItem.vue +67 -0
  379. package/src/visual/EntitySubList.vue +440 -0
  380. package/src/visual/EntityTreeFindPage.vue +36 -0
  381. package/src/visual/EntityTreeManage.vue +50 -0
  382. package/src/visual/EntityTreePage.vue +45 -0
  383. package/src/visual/ExcelPreview.vue +11 -0
  384. package/src/visual/FormField.vue +113 -0
  385. package/src/visual/HeaderNew.vue +176 -0
  386. package/src/visual/Html.vue +104 -0
  387. package/src/visual/Import.vue +55 -0
  388. package/src/visual/InterfaceSubList.vue +23 -0
  389. package/src/visual/ListFirst.vue +614 -0
  390. package/src/visual/MEntityAddPage.vue +71 -0
  391. package/src/visual/MEntityList.vue +488 -0
  392. package/src/visual/MEntityListPage.vue +46 -0
  393. package/src/visual/MEntitySubList.vue +237 -0
  394. package/src/visual/MetaList.vue +24 -0
  395. package/src/visual/ModuleIndexPage.vue +70 -0
  396. package/src/visual/ModuleList.vue +46 -0
  397. package/src/visual/NavAddForm.vue +177 -0
  398. package/src/visual/NavFormCatalogItem.vue +47 -0
  399. package/src/visual/NumItem.vue +69 -0
  400. package/src/visual/NumStatistic.vue +242 -0
  401. package/src/visual/OrgChart.vue +113 -0
  402. package/src/visual/PageCatalog.vue +26 -0
  403. package/src/visual/PageConfig.vue +278 -0
  404. package/src/visual/PageTabs.vue +55 -0
  405. package/src/visual/Progress.vue +39 -0
  406. package/src/visual/ProgressItem.vue +43 -0
  407. package/src/visual/SystemManager.vue +80 -0
  408. package/src/visual/Title.vue +44 -0
  409. package/src/visual/TodoList.vue +18 -0
  410. package/src/visual/UserFormItem.vue +49 -0
  411. package/src/visual/UserManage.vue +36 -0
  412. package/src/visual/chart/CircularPie.vue +7 -0
  413. package/src/visual/chart/Column.vue +73 -0
  414. package/src/visual/chart/HoriColumn.vue +7 -0
  415. package/src/visual/chart/Line.vue +7 -0
  416. package/src/visual/chart/Pie.vue +7 -0
  417. package/src/visual/config/Background.vue +398 -0
  418. package/src/visual/config/Chart.vue +139 -0
  419. package/src/visual/config/Checkbox.vue +64 -0
  420. package/src/visual/config/Color.vue +40 -0
  421. package/src/visual/config/DesignReport.vue +20 -0
  422. package/src/visual/config/Event.vue +220 -0
  423. package/src/visual/config/Field.vue +597 -0
  424. package/src/visual/config/Font.vue +149 -0
  425. package/src/visual/config/FormItem.vue +25 -0
  426. package/src/visual/config/Function.vue +78 -0
  427. package/src/visual/config/Html.vue +98 -0
  428. package/src/visual/config/Image.vue +132 -0
  429. package/src/visual/config/Input.vue +712 -0
  430. package/src/visual/config/LazyDialog.vue +44 -0
  431. package/src/visual/config/List.vue +68 -0
  432. package/src/visual/config/ListField.vue +1714 -0
  433. package/src/visual/config/MField.vue +601 -0
  434. package/src/visual/config/Number.vue +41 -0
  435. package/src/visual/config/Object.vue +177 -0
  436. package/src/visual/config/Operate.vue +1083 -0
  437. package/src/visual/config/OperateItem.vue +917 -0
  438. package/src/visual/config/Options.vue +330 -0
  439. package/src/visual/config/OrderField.vue +587 -0
  440. package/src/visual/config/Page.vue +45 -0
  441. package/src/visual/config/Params.vue +228 -0
  442. package/src/visual/config/Radio.vue +93 -0
  443. package/src/visual/config/Row.vue +78 -0
  444. package/src/visual/config/Scope.vue +363 -0
  445. package/src/visual/config/Select.vue +93 -0
  446. package/src/visual/config/Switch.vue +36 -0
  447. package/src/visual/config/Textarea.vue +754 -0
  448. package/src/visual/config/Tree.vue +135 -0
  449. package/src/visual/config/remote-cache.js +35 -0
  450. package/src/visual/config/show-condition.js +21 -0
  451. package/src/visual/config/variable-sources.js +27 -0
  452. package/src/visual/config/wait-ref.js +17 -0
  453. package/src/visual/config-page/ComponentLibrary.vue +220 -0
  454. package/src/visual/config-page/ComponentLibraryDialog.vue +262 -0
  455. package/src/visual/config-page/ComponentList.vue +580 -0
  456. package/src/visual/config-page/ComponentPreview.vue +206 -0
  457. package/src/visual/config-page/ConfigOption.vue +16 -0
  458. package/src/visual/config-page/ConfigPanel.vue +301 -0
  459. package/src/visual/config-page/Dashboard.vue +2331 -0
  460. package/src/visual/config-page/DashboardDesign.vue +656 -0
  461. package/src/visual/config-page/DashboardGlobalConfig.vue +158 -0
  462. package/src/visual/config-page/DashboardMobile.vue +1118 -0
  463. package/src/visual/config-page/DashboardSetting.vue +47 -0
  464. package/src/visual/config-page/PagePreview.vue +105 -0
  465. package/src/visual/config-page/StyleConfig.vue +656 -0
  466. package/src/visual/config-page/VisualConfigPage.vue +746 -0
  467. package/src/visual/config-page/dashboard-theme-setting/Background.vue +98 -0
  468. package/src/visual/config-page/dashboard-theme-setting/Border.vue +185 -0
  469. package/src/visual/config-page/dashboard-theme-setting/Font.vue +101 -0
  470. package/src/visual/config-page/dashboard-theme-setting/Index.vue +471 -0
  471. package/src/visual/config-page/dashboard-theme-setting/Shadow.vue +102 -0
  472. package/src/visual/config-page/index.js +93 -0
  473. package/src/visual/index.js +23 -0
  474. package/src/visual/mixins/innerGridMixin.js +128 -0
  475. package/src/visual/search/Filter.vue +50 -0
  476. package/src/visual/step/Index.vue +361 -0
  477. package/src/visual/step/Item.vue +140 -0
  478. package/src/visual/widgets/CardFormItemVisual.vue +46 -0
  479. package/src/visual/widgets/CarouselVisual.vue +291 -0
  480. package/src/visual/widgets/CollapseVisual.vue +203 -0
  481. package/src/visual/widgets/DropdownVisual.vue +541 -0
  482. package/src/visual/widgets/LayoutConfig.vue +186 -0
  483. package/src/visual/widgets/ListVisual.vue +349 -0
  484. package/src/visual/widgets/MEntityListFindVisual.vue +77 -0
  485. package/src/visual/widgets/ProcessFormItemVisual.vue +58 -0
  486. package/src/visual/widgets/TabsConfig.vue +266 -0
  487. package/types/index.d.ts +22 -0
  488. package/types/page-designer.d.ts +3 -0
  489. package/types/visual-component.d.ts +1 -0
  490. package/types/visual-entity-list.d.ts +1 -0
  491. package/types/visual-entity-sub-list.d.ts +1 -0
@@ -0,0 +1,2331 @@
1
+ <template>
2
+ <div class="config-container config-container--dashboard-designer" :class="{ 'config-container--new-window':newWindow, 'config-container--mobile-dashboard': isMobileDashboard }">
3
+ <!-- 头部 -->
4
+ <div class="page-header">
5
+ <i class="page-header__back el-icon-arrow-left" @click="back"></i>
6
+ <p class="page-title">
7
+ <span class="page-header__title">{{title}}</span>
8
+ <el-tag v-if="!chooseDesignTarget" size="small">{{ isMobileDashboard ? '移动端看板' : 'PC 看板' }}</el-tag>
9
+ </p>
10
+ <div class="page-header__operate">
11
+ <el-button v-if="configReady && !selectComponentList.length" size="small" :disabled="choosingDesignTarget" @click="chooseDesignTarget=true">选择设计端</el-button>
12
+ <template v-if="!chooseDesignTarget">
13
+ <p class="header-operate__item" @click="showPanel='style'"><i class="epx-icon-yangshi"></i>样式</p>
14
+ <p v-if="!isMobileDashboard" class="header-operate__item" @click="switchMobile"><i class="el-icon-mobile"></i>移动端设计</p>
15
+ <el-select v-if="isMobileDashboard" :model-value="mobileCanvasWidth" size="small" class="mobile-width-select" @change="v=>changeItemConfigs('page', { mobileCanvasWidth: v })">
16
+ <el-option v-for="width in [320, 375, 390, 414]" :key="width" :label="width + 'px'" :value="width"></el-option>
17
+ </el-select>
18
+ <span v-if="isMobileDashboard" class="mobile-save-status">{{ mobileDirty ? '未保存' : '已保存' }}</span>
19
+ <el-button v-if="isMobileDashboard" size="small" type="primary" :loading="mobileSaving" @click="saveMobileDashboard">保存</el-button>
20
+ <p class="header-operate__item" @click="preview"><i class="el-icon-view"></i>{{$t('preview')}}</p>
21
+ <p class="header-operate__item" @click="pageSettingDrawer=true"><i class="el-icon-setting"></i>全局设置</p>
22
+ <!-- <el-button type="primary" size="default" @click="saveConfigs">{{$t('save')}}</el-button> -->
23
+ </template>
24
+ </div>
25
+ </div>
26
+ <div v-if="chooseDesignTarget" class="design-target-picker">
27
+ <h2>选择看板设计端</h2>
28
+ <p>先选择主要展示端,再开始添加报表和组件。</p>
29
+ <div class="design-target-picker__options">
30
+ <el-button :loading="choosingDesignTarget" @click="selectDesignTarget('pc')">PC 端 · 桌面画布</el-button>
31
+ <el-button type="primary" :loading="choosingDesignTarget" @click="selectDesignTarget('mobile')">移动端 · 手机画布</el-button>
32
+ </div>
33
+ </div>
34
+ <div v-else class="page-content">
35
+ <!-- 导航tabs -->
36
+ <ul class="page-tabs">
37
+ <li :class="{'page-tabs__item': true}"
38
+ @click="openAddReportDialog">
39
+ <i class="epx-icon-color-tianjiabaobiao"></i>
40
+ <span>报表</span>
41
+ </li>
42
+ <li :class="{'page-tabs__item': true}" @click="addComponentDialog=true">
43
+ <i class="epx-icon-color-tianjiazujian"></i>
44
+ <span>组件</span>
45
+ </li>
46
+ <li :class="{'page-tabs__item': true}" @click="addTabsToDashboard">
47
+ <i class="epx-icon-color-tab"></i>
48
+ <span>标签页</span>
49
+ </li>
50
+ <li :class="{'page-tabs__item': true}" @click="copyComponentDialog=true">
51
+ <i class="epx-icon-color-yinyong"></i>
52
+ <span>引用</span>
53
+ </li>
54
+ </ul>
55
+ <div class="function-panel">
56
+ <div class="dashboard-theme" v-if="showPanel==='style'">
57
+ <div class="dashboard-theme__title">
58
+ <span>样式设置</span>
59
+ <el-radio-group v-model="styleType" size="small">
60
+ <el-radio-button label="presets" value="presets">预设</el-radio-button>
61
+ <el-radio-button label="custom" value="custom">自定义</el-radio-button>
62
+ </el-radio-group>
63
+ </div>
64
+ <div class="dashboard-theme__content">
65
+ <template v-if="styleType==='presets'&& !editTheme">
66
+ <ul class="dashboard-theme__list">
67
+ <li :class="['dashboard-theme__item', { active: activeTheme===theme.CODE }]" v-for="theme in themeList" :key="theme.CODE" @click="selectTheme(theme)">
68
+ <div class="dashboard-theme__preview">
69
+ <img :src="$util.getFileUrl(theme.THUMBNAIL)" alt="">
70
+ </div>
71
+ <p class="dashboard-theme__name">
72
+ <span class="dashboard-theme__name-text">{{theme.NAME}}<i v-if="theme.SCOPE!=='frame'" class="dashboard-theme__name-icon el-icon-user"></i></span>
73
+ <el-dropdown v-if="theme.SCOPE!=='frame' || $route.params.system==='epxing-frame'" class="fr" @click.stop @command="command=>themeHandleCommand(theme, command)">
74
+ <i class="el-icon-more"></i>
75
+ <template v-slot:dropdown><el-dropdown-menu>
76
+ <el-dropdown-item command="edit">编辑</el-dropdown-item>
77
+ <el-dropdown-item command="config">预设样式配置</el-dropdown-item>
78
+ <el-dropdown-item command="remove">删除</el-dropdown-item>
79
+ </el-dropdown-menu></template>
80
+ </el-dropdown>
81
+ </p>
82
+ <div class="dashboard-theme__selected">
83
+ <span></span>
84
+ <i class="el-icon-check"></i>
85
+ </div>
86
+ </li>
87
+ </ul>
88
+ </template>
89
+ <template v-else>
90
+ <dashboard-theme-setting :editTheme="editTheme" :value="themeStyles" @change="changethemeStyles" @save="savePreset" @mobile-edit="v=>themeMobilePreview=v" ></dashboard-theme-setting>
91
+ </template>
92
+ </div>
93
+ <div class="dashboard-theme__footer">
94
+ <el-button size="default" @click="cancelThemePancel">取消</el-button>
95
+ <el-button size="default" type="primary" @click="setTheme">确定</el-button>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ <!-- 页面预览 -->
100
+ <div v-if="!previewSuspended && !mobilePreviewVisible" class="page-preview">
101
+ <dashboard-mobile v-if="isMobileDashboard"
102
+ ref="dashboardDesign" standalone :source="mobileDesignSource" :canvas-width="mobileCanvasWidth"
103
+ :page-id="$query.id" :page-meta-id="currentMetaId" :all-component-list="componentList"
104
+ @select-item="selectMobileItem" @edit-data="editMobileData" @delete-item="deleteMobileItem" @add-into="addMobileInto"
105
+ @add-report="openAddReportDialog" @add-component="addComponentDialog=true">
106
+ <template #component-config>
107
+ <epx-visual-config-panel v-if="selectComponent" :component="selectComponent" :metaId="currentMetaId"
108
+ :globalConfigs="pageGlobalConfigs" :itemConfigs="allComponentConfigs" :relationList="relationList"
109
+ :pageParams="pageParams" :scopeConfigs="scopeConfigs" :grid-layout="true"></epx-visual-config-panel>
110
+ </template>
111
+ </dashboard-mobile>
112
+ <epx-visual-config-dashboard-design v-else
113
+ ref="dashboardDesign"
114
+ :up-comp-id="upCompId"
115
+ :component-list="this.selectComponentList"
116
+ :all-component-list="this.componentList"
117
+ :globalConfigs="pageGlobalConfigs"
118
+ :pageId="$query.id"
119
+ :pageMetaId="currentMetaId"
120
+ :itemConfigs="allComponentConfigs"
121
+ :theme="activeTheme"
122
+ :themeStyles="themeStyles"
123
+ :mobile-preview="themeMobilePreview"
124
+ @open-config="clickComponent"
125
+ @change-items="componentList=> selectComponentList=[...componentList]"
126
+ @add-component="addComponentDialog=true"
127
+ @delete-configs="deleteConfigs"
128
+ @add-report="openAddReportDialog"
129
+ @add-report-to-dashboard="addReportToDashboard"
130
+ @add-chart-to-dashboard="addChartToDashboard"
131
+ @add-component-to-dashboard="addComponentToDashboard"
132
+ ></epx-visual-config-dashboard-design>
133
+ </div>
134
+ <!-- 组件配置面板 v-if="selectComponent" -->
135
+ <el-drawer v-if="!isMobileDashboard" title="组件配置" append-to-body direction="rtl" v-model="showConfigPanel">
136
+ <div class="config-panel" v-if="showConfigPanel">
137
+ <!-- 获取组件对应的配置面板 -->
138
+ <epx-visual-config-panel
139
+ :component="selectComponent"
140
+ :metaId="currentMetaId"
141
+ :globalConfigs="pageGlobalConfigs"
142
+ :itemConfigs="allComponentConfigs"
143
+ :relationList="relationList"
144
+ :pageParams="pageParams"
145
+ :scopeConfigs="scopeConfigs"
146
+ :grid-layout="true"
147
+ ></epx-visual-config-panel>
148
+ </div>
149
+ </el-drawer>
150
+ <!-- 添加报表 -->
151
+ <el-dialog title="添加报表" append-to-body v-model="addReportDialog" width="640px">
152
+ <div class="add-report-body" v-if="addReportDialog">
153
+ <div class="add-report-item">
154
+ <label>报表类型:</label>
155
+ <ul class="report-type__list">
156
+ <li v-for="reportType in reportTypeList" :class="{ 'report-type__item': true, active: addReportForm.TYPE === reportType.type && (addReportForm.CHART_TYPE === reportType.chartType || addReportForm.TYPE === '1' || addReportForm.TYPE === 'numStatistic') }" :key="reportType.chartType || reportType.type" @click="setReportType(reportType)">
157
+ <i :class="reportType.icon"></i>
158
+ <span>{{reportType.text}}</span>
159
+ </li>
160
+ </ul>
161
+ </div>
162
+ <div class="add-report-item" v-show="addReportForm.TYPE!=='dashboardTitle' && addReportForm.TYPE!=='form'">
163
+ <label>统计对象:</label>
164
+ <epx-object v-model="addReportForm.OBJECT" :fieldConfigs="{attriName: 'OBJECT',dataType: 'object',attriLabel: '统计对象', codeKey: 'FM_ENTITY', state:'EDIT'}"></epx-object>
165
+ </div>
166
+ <div class="add-report-item" v-show="addReportForm.TYPE!=='numStatistic' && addReportForm.TYPE!=='dashboardTitle' && addReportForm.TYPE!=='form'">
167
+ <label>统计对象视图:</label>
168
+ <epx-object v-model="addReportForm.OBJECT_VIEW" :fieldConfigs="{attriName: 'OBJECT_VIEW',dataType: 'object',attriLabel: '统计对象', codeKey: 'FM_ENTITY_VIEW', scopeParams: [{field: 'ENTITY',values: addReportForm.OBJECT}], state:'EDIT'}"></epx-object>
169
+ </div>
170
+ <div class="add-report-item" v-show="addReportForm.TYPE==='form'">
171
+ <label>表单类型:</label>
172
+ <el-radio-group v-model="addReportForm.FORM_TYPE">
173
+ <el-radio label="formReport" value="formReport">Word</el-radio>
174
+ <el-radio label="excelReport" value="excelReport">Excel</el-radio>
175
+ </el-radio-group>
176
+ </div>
177
+ </div>
178
+ <div class="add-report-footer">
179
+ <el-button type="primary" @click="saveReport">保存</el-button>
180
+ <el-button @click="addReportDialog=false">返回</el-button>
181
+ </div>
182
+ </el-dialog>
183
+ <!-- 添加组件 -->
184
+ <el-dialog title="添加组件" append-to-body v-model="addComponentDialog" width="960px">
185
+ <epx-visual-component-library-dialog :initial-terminal="isMobileDashboard ? 'move' : 'pc'" @click="addComponentToDashboard"></epx-visual-component-library-dialog>
186
+ </el-dialog>
187
+ <!-- 引用组件 -->
188
+ <el-dialog class="dialog--noheader dialog--nopadding" append-to-body center v-model="copyComponentDialog" width="960px">
189
+ <el-tabs type="card">
190
+ <!-- <el-tab-pane label="从报表库选择">
191
+ <epx-search-fields class="dashboard-search" metaId="FM_REPORT_BASE" :showKeyword="false" :fields="['NAME', 'TYPE', 'CHART_TYPE', 'OBJECT']" :showFilter="false" @search="searchReport" ></epx-search-fields>
192
+ <ul class="report-list" v-loading="reportLoading">
193
+ <li :class="['report-item', { 'selected': selectedReportList.includes(report.ID)}]" v-for="report in reportList" :key="report.ID" @click="selectReport(report)">
194
+ <i :class="reportIconMap[report.CHART_TYPE || report.TYPE]"></i>
195
+ <span>{{ report.NAME }}</span>
196
+ <div class="report-item__select">
197
+ <span></span>
198
+ <i class="el-icon-check"></i>
199
+ </div>
200
+ </li>
201
+ <div class="no-data" v-if="!reportLoading && reportTotal===0">
202
+ <i class="epx-icon-kong"></i>
203
+ <p>暂无数据</p>
204
+ </div>
205
+ </ul>
206
+ <el-pagination
207
+ class="pagination"
208
+ @current-change="currentReportChange"
209
+ v-model:current-page="currentReportPage"
210
+ :page-size="20"
211
+ layout="prev, pager, next, jumper"
212
+ :total="reportTotal"
213
+ >
214
+ </el-pagination>
215
+ </el-tab-pane> -->
216
+ <el-tab-pane label="从数据看板选择">
217
+ <div class="dashboard-search">
218
+ <epx-search-fields metaId="FM_PAGE_CONFIG" :showKeyword="false" :fields="['TITLE', 'META_ID']" :showFilter="false" @search="searchDashboard" ></epx-search-fields>
219
+ </div>
220
+ <ul class="dashboard-list" v-loading="dashboardLoading">
221
+ <li :class="['dashboard-item', { fold: foldDashboardMap[dashboard.ID]}]" v-for="dashboard in dashboardList" :key="dashboard.ID" >
222
+ <div class="dashboard-header">
223
+ <el-checkbox :value="isDashboardSelectAll(dashboard)" :indeterminate="isDashboardSelect(dashboard)" @change="v=>changeDashboardSelect(dashboard, v)">{{ dashboard.TITLE }}</el-checkbox>
224
+ <i class="el-icon-arrow-up" @click="switchDashboardFoldFn(dashboard)"></i>
225
+ </div>
226
+ <div class="dashboard-body">
227
+ <ul class="dashboard-comp__list">
228
+ <li :class="['dashboard-comp__item', { 'selected': selectedDashboardCompList.includes(dashboard.ID+'-'+comp.id)}]" v-for="comp in dashboard.children" :key="comp.id" @click="selectDashboardComp(dashboard,comp)">
229
+ <i :class="compIcon(comp)"></i>
230
+ <span>{{ compTitle(comp) }}</span>
231
+ <div class="dashboard-comp__item__select">
232
+ <span></span>
233
+ <i class="el-icon-check"></i>
234
+ </div>
235
+ </li>
236
+ </ul>
237
+ </div>
238
+ </li>
239
+ <div class="no-data" v-if="!dashboardLoading && dashboardTotal===0">
240
+ <i class="epx-icon-kong"></i>
241
+ <p>暂无数据</p>
242
+ </div>
243
+ </ul>
244
+ <el-pagination
245
+ class="pagination"
246
+ v-model:current-page="currentDashboardPage"
247
+ :page-size="10"
248
+ layout="prev, pager, next, jumper"
249
+ :total="dashboardTotal"
250
+ >
251
+ </el-pagination>
252
+ </el-tab-pane>
253
+ </el-tabs>
254
+ <div class="dialog-footer">
255
+ <el-button type="primary" @click="quoteComp">引用</el-button>
256
+ <!-- <el-button type="primary" @click="copyComp">复制</el-button> -->
257
+ <el-button @click="copyComponentDialog = false">返回</el-button>
258
+ </div>
259
+ </el-dialog>
260
+ <!-- 保存为预设主题 -->
261
+ <el-dialog title="保存为预设主题" append-to-body v-model="saveThemeDialog" width="760px">
262
+ <epx-add-form-item v-if="saveThemeDialog" metaId="FM_CHART_THEME" :comp-configs="{componentType: 'EDIT',column: 1, fields: themeFields}" :formData="themeFormData"
263
+ @change="v=>themeFormData=v"
264
+ >
265
+ </epx-add-form-item>
266
+ <template #footer>
267
+ <div>
268
+ <el-button @click="saveThemeDialog=false">取消</el-button>
269
+ <el-button @click="saveTheme" type="primary">保存</el-button>
270
+ </div>
271
+ </template>
272
+ <!-- <epx-table-form class="epx-add-form-item__content" ref="form" metaId={this.$metaId} fieldsConfigs={this.fieldsConfigs} pageType={this.componentType} vModel={this.data} fieldRelation={this.fieldRelation} column={this.column} labelAlign={this.$configs.labelAlign} lineSpace={lineSpace} labelWidth={labelWidth} labelFontSize={labelFontSize} valueWidth={valueWidth} valueFontSize={valueFontSize} mFormStyle={mFormStyle} mFormPadding={mFormPadding} showRelyFlag={this.$configs.showRelyFlag !== false} valueRelyFlag={this.$configs.valueRelyFlag !== false} onChange-fields-configs={this.changeFieldsConfigs}></epx-table-form> -->
273
+ </el-dialog>
274
+ </div>
275
+ <el-drawer
276
+ :withHeader="false"
277
+ v-model="pageSettingDrawer"
278
+ append-to-body
279
+ direction="rtl"
280
+ :size="360"
281
+ >
282
+ <div class="page-setting">
283
+ <div class="page-setting__header">
284
+ <span class="title">全局设置</span>
285
+ <i class="el-icon-close" @click="pageSettingDrawer=false"></i>
286
+ </div>
287
+ <div class="page-setting__content">
288
+ <component
289
+ :metaId="currentMetaId"
290
+ ref="global"
291
+ id="page"
292
+ :is="'epx-visual-config-dashboard-setting'"
293
+ :comp-config="pageComponentConfigs"
294
+ :globalConfigs="pageGlobalConfigs"
295
+ :pageRelationList="relationList"
296
+ ></component>
297
+ </div>
298
+ <div class="page-setting__footer">
299
+ <el-button size="default" @click="pageSettingDrawer=false">返回</el-button>
300
+ <!-- <el-button type="primary" size="default" @click="saveGlobalConfigs">确定</el-button> -->
301
+ </div>
302
+ </div>
303
+ </el-drawer>
304
+ <el-dialog v-if="isMobileDashboard" v-model="mobilePreviewVisible" :title="'移动端预览 · ' + mobileCanvasWidth + 'px'" class="mobile-dashboard-preview-dialog" append-to-body align-center destroy-on-close :width="(mobileCanvasWidth + 12) * mobilePreviewScale + 48 + 'px'">
305
+ <div class="mobile-preview-viewport" :style="{ width: (mobileCanvasWidth + 12) * mobilePreviewScale + 'px', height: mobilePreviewPhoneHeight * mobilePreviewScale + 'px' }">
306
+ <div class="mobile-preview-phone" :style="{ width: (mobileCanvasWidth + 12) + 'px', height: mobilePreviewPhoneHeight + 'px', transform: 'scale(' + mobilePreviewScale + ')' }">
307
+ <div class="mobile-preview-phone__screen">
308
+ <div class="mobile-preview-phone__title" :title="title">{{ title || '数据看板' }}</div>
309
+ <div class="mobile-dashboard-preview">
310
+ <dashboard-preview v-if="mobilePreviewVisible" comp-id="mobile-dashboard-preview" :comp-configs="{ ...pageGlobalConfigs, themeStyles, items: selectComponentList, itemConfigs: allComponentConfigs }"></dashboard-preview>
311
+ </div>
312
+ <div class="mobile-preview-phone__home" aria-hidden="true"><span></span></div>
313
+ </div>
314
+ </div>
315
+ </div>
316
+ </el-dialog>
317
+ </div>
318
+ </template>
319
+
320
+ <script>
321
+ import DashboardThemeSetting from './dashboard-theme-setting/Index.vue'
322
+ import { selectableChartTypes } from '@epxing/utils/src/chart-registry'
323
+ import DashboardMobile from './DashboardMobile.vue'
324
+ import DashboardPreview from '@epxing/dashboard/src/Dashboard.vue'
325
+ import { DEFAULT_DASHBOARD_THEME, createDashboardConfig, getDashboardDesignTarget, removeDashboardItem } from '@epxing/dashboard/src/design-target'
326
+ import { indexDashboardItems } from '@epxing/dashboard/src/mobile-design'
327
+ import { mapState, mapGetters } from 'vuex'
328
+ import { CONFIG_VERSION, normalizeDashboardConfig, stripDashboardConfig, mergeGridConfigs, rescaleItemsToColNum } from '@epxing/dashboard/src/grid/model'
329
+
330
+ // 栅格项的 i 与 id 完全重复:持久化时剥离 i(stripDashboardConfig),加载/运行时再用 id 兜底补齐(网格引擎内部需要 i)
331
+ function ensureGridItemKey (items) {
332
+ if (!Array.isArray(items)) return items
333
+ items.forEach(item => {
334
+ if (item && typeof item === 'object') {
335
+ if (item.contentType && item.i == null && item.id != null) item.i = item.id
336
+ if (Array.isArray(item.items)) ensureGridItemKey(item.items)
337
+ }
338
+ })
339
+ return items
340
+ }
341
+
342
+ export default {
343
+ name: 'epx-visual-config-dashboard',
344
+ $componentType: 'component',
345
+ components: {
346
+ DashboardThemeSetting,
347
+ DashboardMobile,
348
+ DashboardPreview
349
+ },
350
+ navConfigs: {
351
+ flag: false
352
+ },
353
+ provide () {
354
+ const { id } = this.$query
355
+ return {
356
+ pageMetaId: this.currentMetaId,
357
+ pageId: id,
358
+ pageConfigs: this.page_config,
359
+ getAllComponentList: () => this.componentList,
360
+ getItemConfigs: () => this.allComponentConfigs,
361
+ // 当前 items 树(含容器子项):属性面板「布局」分组按 id 找真实 item 读初值
362
+ getComponentItems: () => this.selectComponentList,
363
+ getDefaultContainerItems: () => this.defaultContainerItems,
364
+ setContainerDefaultItems: this.setContainerDefaultItems,
365
+ changeItemConfigs: this.changeItemConfigs,
366
+ getPageMetaId: () => {
367
+ return this.currentMetaId
368
+ }
369
+ }
370
+ },
371
+ props: {
372
+ newWindow: Boolean
373
+ },
374
+ data () {
375
+ return {
376
+ // 页面配置版本:加载时经 normalizeDashboardConfig 升到 v3(补 grid / 容器 grid),保存时写回;这是 '3.0' 唯一的写入点
377
+ version: CONFIG_VERSION,
378
+ configReady: false,
379
+ chooseDesignTarget: false,
380
+ choosingDesignTarget: false,
381
+ mobileDirty: false,
382
+ mobileSaving: false,
383
+ mobileRevision: 0,
384
+ mobileAddParent: null,
385
+ mobilePreviewVisible: false,
386
+ previewSuspended: false,
387
+ previewPopupTimer: null,
388
+ previewViewportWidth: window.innerWidth,
389
+ previewViewportHeight: window.innerHeight,
390
+ styleType: 'presets',
391
+ componentList: [],
392
+ selectComponentList: [],
393
+ selectComponent: null,
394
+ showPanel: 'componentLibrary',
395
+ pageGlobalConfigs: {},
396
+ allComponentConfigs: {},
397
+ pageMetaId: null,
398
+ upCompId: null,
399
+ relationList: [],
400
+ pageParams: [],
401
+ scopeConfigs: {},
402
+ addReportDialog: false,
403
+ addComponentDialog: false,
404
+ copyComponentDialog: false,
405
+ pageSettingDrawer: false,
406
+ activeTheme: DEFAULT_DASHBOARD_THEME,
407
+ themeStyles: null,
408
+ themeMobilePreview: false, // 主题面板处于"移动端"编辑态:设计器加 .is-mobile-preview 预览移动端覆盖
409
+ themeList: [
410
+ { key: 'light', name: '经典白', preview: require('@/assets/images/dashboard/theme_white.png') },
411
+ { key: 'dark', name: '经典黑', preview: require('@/assets/images/dashboard/theme_black.png') },
412
+ { key: 'technology', name: '科幻大屏', preview: require('@/assets/images/dashboard/theme_technology.png') }
413
+ ],
414
+ reportList: [],
415
+ selectedReportList: [],
416
+ currentReportPage: 1,
417
+ reportTotal: 0,
418
+ dashboardList: [],
419
+ selectedDashboardCompList: [],
420
+ currentDashboardPage: 1,
421
+ dashboardTotal: 0,
422
+ foldDashboardMap: {},
423
+ reportIconMap: {
424
+ 1: 'epx-icon-tongjibiao',
425
+ pie: 'epx-icon-bingzhuangtu',
426
+ line: 'epx-icon-zhexiantu',
427
+ column: 'epx-icon-zhuzhuangtu',
428
+ funnel: 'epx-icon-loudoutu'
429
+ },
430
+ selectedReportDataList: [],
431
+ selectedDashboardCompDataList: [],
432
+ reportScopeParams: [],
433
+ dashboardScopeParams: [],
434
+ reportLoading: true,
435
+ dashboardLoading: true,
436
+ addReportForm: {},
437
+ reportTypeList: [
438
+ ...selectableChartTypes.map(({ type, text, icon }) => ({ icon, text, type: type === 'table' ? '1' : '2', chartType: type === 'table' ? '' : type })),
439
+ { icon: 'epx-icon-a-numbercard', text: '数字统计', type: 'numStatistic' },
440
+ { icon: 'epx-icon-dianzibiaodan', text: '电子表单', type: 'form' },
441
+ { icon: 'epx-icon-biaoti', text: '标题', type: 'dashboardTitle' },
442
+ { icon: 'epx-icon-container', text: '容器', type: 'dashboardDiv' }
443
+ ],
444
+ reportMap: {},
445
+ saveThemeDialog: false,
446
+ themeFormData: {},
447
+ editTheme: null
448
+ }
449
+ },
450
+ computed: {
451
+ isMobileDashboard () {
452
+ return getDashboardDesignTarget(this.pageGlobalConfigs) === 'mobile'
453
+ },
454
+ mobileCanvasWidth () {
455
+ return Number(this.pageGlobalConfigs.mobileCanvasWidth) || 375
456
+ },
457
+ mobilePreviewPhoneHeight () {
458
+ return Math.round(this.mobileCanvasWidth * 812 / 375) + 12
459
+ },
460
+ mobilePreviewScale () {
461
+ return Math.max(0.1, Math.min(1, (this.previewViewportWidth - 80) / (this.mobileCanvasWidth + 12), (this.previewViewportHeight - 160) / this.mobilePreviewPhoneHeight))
462
+ },
463
+ mobileDesignSource () {
464
+ return { componentList: this.selectComponentList, itemConfigs: this.allComponentConfigs, globalConfigs: this.pageGlobalConfigs, theme: this.activeTheme, themeStyles: this.themeStyles }
465
+ },
466
+ ...mapState({
467
+ showMenu: state => state.config.showMenu,
468
+ showAppNav: state => state.config.showAppNav
469
+ }),
470
+ ...mapGetters([
471
+ 'getMeta',
472
+ 'getPageById'
473
+ ]),
474
+ $meta () {
475
+ if (this.$metaId) {
476
+ const meta = this.getMeta(this.$metaId)
477
+ return meta
478
+ } else {
479
+ return null
480
+ }
481
+ },
482
+ $metaKey () {
483
+ if (this.$meta) {
484
+ return this.$meta.getKey() || 'ID'
485
+ } else {
486
+ return 'ID'
487
+ }
488
+ },
489
+ currentPage () {
490
+ const page = this.getPageById(this.$query.id)
491
+ return page || {}
492
+ },
493
+ currentMetaId () {
494
+ return this.$query.entityId || this.pageMetaId
495
+ },
496
+ currentMeta () {
497
+ return this.metas[this.currentMetaId] || null
498
+ },
499
+ page_config () {
500
+ const { config = '{}' } = this.$query
501
+ if (typeof config === 'string') {
502
+ try {
503
+ // eslint-disable-next-line no-eval
504
+ return eval('(' + config + ')')
505
+ } catch (error) {
506
+ return {}
507
+ }
508
+ }
509
+ return config
510
+ },
511
+ pageComponentConfigs () {
512
+ const configs = { ...this.pageGlobalConfigs }
513
+ if (configs.title) {
514
+ configs.componentName = configs.title
515
+ }
516
+ return configs
517
+ },
518
+ title () {
519
+ const { title } = this.pageGlobalConfigs
520
+ return title || this.currentPage.title || this.$query.title
521
+ },
522
+ isDashboardSelectAll () {
523
+ return dashboard => {
524
+ return dashboard.children.every(item => this.selectedDashboardCompList.includes(dashboard.ID + '-' + item.id))
525
+ }
526
+ },
527
+ isDashboardSelect () {
528
+ return dashboard => {
529
+ return !dashboard.children.every(item => this.selectedDashboardCompList.includes(dashboard.ID + '-' + item.id)) && dashboard.children.some(item => this.selectedDashboardCompList.includes(dashboard.ID + '-' + item.id))
530
+ }
531
+ },
532
+ compTitle () {
533
+ return comp => {
534
+ if (comp.contentType === 'report-chart') {
535
+ const report = this.reportMap[comp.configs.id] || {}
536
+ return report.NAME || comp.title
537
+ }
538
+ return comp.title
539
+ }
540
+ },
541
+ compIcon () {
542
+ return comp => {
543
+ if (comp.contentType === 'report-chart') {
544
+ const report = this.reportMap[comp.configs.id] || {}
545
+ return this.reportIconMap[report.CHART_TYPE || report.TYPE] || 'epx-icon-component'
546
+ }
547
+ return 'epx-icon-component'
548
+ }
549
+ },
550
+ showConfigPanel: {
551
+ get () {
552
+ return !!this.selectComponent
553
+ },
554
+ set () {
555
+ this.selectComponent = null
556
+ }
557
+ },
558
+ themeFields () {
559
+ return this.$route.params.system === 'epxing-frame' ? ['CODE', 'NAME', 'THUMBNAIL', 'SCOPE'] : ['CODE', 'NAME', 'THUMBNAIL']
560
+ }
561
+ },
562
+ methods: {
563
+ async selectDesignTarget (target) {
564
+ if (this.choosingDesignTarget || this.selectComponentList.length) return
565
+ this.choosingDesignTarget = true
566
+ if (this.timer) { clearTimeout(this.timer); this.timer = null }
567
+ const previous = this.pageGlobalConfigs
568
+ try {
569
+ const firstChoice = !['pc', 'mobile'].includes(this.currentPage?.config?.designTarget)
570
+ const grid = firstChoice ? { ...previous.grid, colNum: 24 } : previous.grid
571
+ const configs = createDashboardConfig({ ...previous, grid, items: [] }, target)
572
+ delete configs.items
573
+ if (target === 'pc' && previous.designTarget === 'mobile') {
574
+ configs.grid = { ...normalizeDashboardConfig({}).grid, colNum: 24 }
575
+ configs.autoHeight = configs.grid.rowHeight === 'auto'
576
+ }
577
+ this.pageGlobalConfigs = mergeGridConfigs(configs).configs
578
+ await this.$nextTick()
579
+ if (await this.saveConfigs() !== true) {
580
+ this.pageGlobalConfigs = previous
581
+ return
582
+ }
583
+ this.$store.commit('DELETE_PAGE', { pageId: this.$query.id })
584
+ this.mobileDirty = false
585
+ this.chooseDesignTarget = false
586
+ } catch (e) {
587
+ this.pageGlobalConfigs = previous
588
+ this.$message.error(e.message || '保存设计端失败,请重试')
589
+ } finally {
590
+ await this.$nextTick()
591
+ this.choosingDesignTarget = false
592
+ }
593
+ },
594
+ addMobileInto (item) {
595
+ this.mobileAddParent = item.id
596
+ this.addComponentDialog = true
597
+ },
598
+ selectMobileItem (item, tab) {
599
+ if (!item) return
600
+ const info = this.componentList.find(component => component.CODE === item.contentType) || { CODE: item.contentType }
601
+ const configs = { ...item, ...item.configs, ...this.allComponentConfigs[item.id] }
602
+ this.clickComponent(item.id, info, configs, undefined, tab)
603
+ },
604
+ editMobileData (item) {
605
+ this.selectMobileItem(item)
606
+ const configs = { ...item.configs, ...this.allComponentConfigs[item.id] }
607
+ const callback = () => {
608
+ const owner = this.selectComponentList.find(root => indexDashboardItems([root]).has(String(item.id))) || item
609
+ this.$refs.dashboardDesign.reloadComponent[owner.id] = true
610
+ this.$nextTick(() => { this.$refs.dashboardDesign.reloadComponent[owner.id] = false })
611
+ }
612
+ if (item.contentType === 'report-chart') {
613
+ this.goPage({ openMode: '2', component: 'report-design', params: { defaultFullscreen: true, withHeader: false, id: configs.id, callback } })
614
+ return
615
+ }
616
+ if (item.contentType === 'report-html') {
617
+ if (!configs.id) return
618
+ return this.$http.get({ entityId: 'FM_FORM', id: configs.id })
619
+ .then(result => this.goPage({ component: result.data.TYPE === 'excelReport' ? 'excel-design' : 'form-design', metaId: 'FM_FORM', params: { id: configs.id, callback } }))
620
+ .catch(e => this.$message.error(e.message || '打开报表设计失败'))
621
+ }
622
+ if (item.contentType !== 'chart') return
623
+ this.$createPage({
624
+ metaId: 'FM_REPORT_BASE',
625
+ openType: '2',
626
+ defaultFullscreen: true,
627
+ withHeader: false,
628
+ component: 'chart-design',
629
+ chartConfigs: configs,
630
+ setChartConfig: configs => {
631
+ this.changeItemConfigs(item.id, this.$_.cloneDeep(configs), null, 'cover')
632
+ callback()
633
+ }
634
+ })
635
+ },
636
+ async deleteMobileItem (item) {
637
+ try {
638
+ await this.$confirm('删除该组件及其内部组件?', '删除组件', { type: 'warning' })
639
+ } catch (e) { return }
640
+ removeDashboardItem(this.selectComponentList, item.id, this.allComponentConfigs)
641
+ this.selectComponent = null
642
+ this.$refs.dashboardDesign.selectComponent = null
643
+ },
644
+ async saveMobileDashboard () {
645
+ if (this.mobileSaving) return false
646
+ this.mobileSaving = true
647
+ const revision = this.mobileRevision
648
+ try {
649
+ const saved = await this.saveConfigs()
650
+ if (saved) {
651
+ if (revision === this.mobileRevision) this.mobileDirty = false
652
+ this.$store.commit('DELETE_PAGE', { pageId: this.$query.id })
653
+ this.$message.success('移动端看板已保存')
654
+ }
655
+ return saved
656
+ } catch (e) {
657
+ this.$message.error(e.message || '保存移动端看板失败')
658
+ return false
659
+ } finally { this.mobileSaving = false }
660
+ },
661
+ warnUnsavedMobile (event) {
662
+ if (this.isMobileDashboard && this.mobileDirty) {
663
+ event.preventDefault()
664
+ event.returnValue = ''
665
+ }
666
+ },
667
+ async confirmLeaveMobile () {
668
+ if (!this.isMobileDashboard || !this.mobileDirty) return true
669
+ try {
670
+ await this.$confirm('移动端看板有未保存的修改,是否离开?', '未保存修改', { confirmButtonText: '离开', cancelButtonText: '继续设计', type: 'warning', customClass: 'dashboard-leave-confirm', closeOnClickModal: false })
671
+ return true
672
+ } catch (e) { return false }
673
+ },
674
+ $refesh () {
675
+ if (this.$refs.dashboardDesign) this.$refs.dashboardDesign.$refesh()
676
+ },
677
+ getPageInfo () {
678
+ return this.getPageId()
679
+ .then(page => {
680
+ const { metaId } = page
681
+ if (metaId) this.pageMetaId = metaId
682
+ this.getMetaId()
683
+ .then(() => {
684
+ this.getDefaultConfig()
685
+ this.getThemeList()
686
+ .then(() => {
687
+ this.getConfigThemeStyles()
688
+ })
689
+ this.loadConfig = true
690
+ })
691
+ return page
692
+ })
693
+ },
694
+ getPageId () {
695
+ // 获取当前page
696
+ if (!this.$query.id || !this.$_.isEmpty(this.currentPage)) {
697
+ return Promise.resolve(this.currentPage)
698
+ }
699
+ return this.$store.dispatch({
700
+ type: 'ADD_PAGE',
701
+ pageId: this.$query.id
702
+ })
703
+ },
704
+ getMetaId () {
705
+ if (!this.currentMetaId || this.currentMeta) {
706
+ return Promise.resolve(this.currentMeta)
707
+ } else {
708
+ return this.$store.dispatch({
709
+ type: 'ADD_META',
710
+ metaId: this.currentMetaId
711
+ })
712
+ }
713
+ },
714
+ getComponetName (component) {
715
+ if (component && component.PATH) {
716
+ let project = 'frame'
717
+ let pathName = ''
718
+ const pagePath = component.PATH
719
+ const rootMatch = pagePath.match(/^@\/\w+\//)
720
+ if (rootMatch) {
721
+ project = rootMatch[0].replace(/[@|/]/g, '')
722
+ pathName = pagePath.split(rootMatch)[1].replace('.vue', '')
723
+ }
724
+ // 根据路径定义组件名 SubList 转为 sub-list layout/SubList 转为 layout-sub-list
725
+ const componentPath = pathName.replace('views/', '').replace('components/', '').replace('packages/', '').replace(/\//g, '-').replace(/(\w)([A-Z])/g, '$1-$2').toLowerCase()
726
+ const componentName = (project === 'frame' ? '' : (project + '-')) + componentPath
727
+
728
+ return componentName
729
+ }
730
+ return null
731
+ },
732
+ getVisualComponent (component) {
733
+ if (component && component.VISUAL_CONFIG_PATH) {
734
+ let pathName = ''
735
+ const pagePath = component.VISUAL_CONFIG_PATH
736
+ const rootMatch = pagePath.match(/^@\/(frame\/|product\/|project\/)?/)
737
+ if (rootMatch) {
738
+ pathName = pagePath.split(rootMatch[0])[1].replace('.vue', '')
739
+ }
740
+ // 根据路径定义组件名 SubList 转为 sub-list layout/SubList 转为 layout-sub-list
741
+ const componentPath = pathName.replace('views/', '').replace('components/', '').replace('packages/', '').replace(/\//g, '-').replace(/(\w)([A-Z])/g, '$1-$2').toLowerCase()
742
+ const componentName = componentPath
743
+
744
+ return componentName
745
+ }
746
+ return null
747
+ },
748
+ getComponentList () {
749
+ this.$http.list({
750
+ entityId: 'FM_PAGE',
751
+ 'scope.TYPE': '01',
752
+ order_field: 'ORDER_NUM',
753
+ order_mode: 'asc'
754
+ })
755
+ .then(data => {
756
+ const componentList = data.entitys
757
+ componentList.forEach(item => {
758
+ item.componentName = item.CODE
759
+ if (item.COMPONENT_TYPE === 'page') {
760
+ const componentName = this.getComponetName(item)
761
+ item.componentName = componentName
762
+ }
763
+ const visualComponentName = this.getVisualComponent(item)
764
+ item.visualComponentName = visualComponentName
765
+ })
766
+ this.componentList = [...componentList]
767
+ })
768
+ },
769
+ getDefaultConfig () {
770
+ // 获取默认组件
771
+ const { dashboardType, compId, componentInfo = {}, itemConfigs: queryItemConfigs = {} } = this.$query
772
+ const { config: pageConfigs = {} } = this.currentPage || {}
773
+ this.chooseDesignTarget = dashboardType !== 'component' && !(pageConfigs.items || []).length && !['pc', 'mobile'].includes(pageConfigs.designTarget)
774
+ // 加载即按 v3 规范化(深拷贝:补页面 grid、历史容器显式 grid、version '3.0';旧字段如 autoHeight 保留),
775
+ // 保存时原样写回——旧页面打开设计器就会被写成 v3,运行态两种版本都能读
776
+ if (dashboardType === 'component') {
777
+ this.upCompId = compId
778
+ const { config = {} } = componentInfo
779
+ const { items = [], ...globalConfigs } = normalizeDashboardConfig({ ...config, ...(queryItemConfigs[compId] || {}) })
780
+ this.selectComponentList = ensureGridItemKey(items) // 已选组件
781
+ this.pageGlobalConfigs = mergeGridConfigs(globalConfigs).configs // 页面全局配置(autoHeight 与 grid 对齐)
782
+ this.allComponentConfigs = this.$_.cloneDeep(queryItemConfigs) // 组件配置
783
+ } else {
784
+ const { itemConfigs = {}, items = [], ...globalConfigs } = normalizeDashboardConfig(pageConfigs)
785
+ this.selectComponentList = ensureGridItemKey(items) // 已选组件
786
+ this.pageGlobalConfigs = mergeGridConfigs(globalConfigs).configs // 页面全局配置(autoHeight 与 grid 对齐)
787
+ this.allComponentConfigs = itemConfigs // 组件配置
788
+ if (pageConfigs.version !== this.version) {
789
+ this.upgradePageConfig()
790
+ }
791
+ }
792
+ if (!this.pageGlobalConfigs.theme) this.pageGlobalConfigs.theme = DEFAULT_DASHBOARD_THEME
793
+ // 如果是组件,获取组件内子组件
794
+ // 深度拷贝 防止修改pageConfigs参数
795
+ // this.pageSetting()
796
+ this.getScopeConfigs()
797
+ this.getEntityRelation()
798
+ this.$nextTick(() => { this.configReady = true })
799
+ },
800
+ upgradePageConfig () {
801
+ // 判断组件是否存在重复id,存在则重新生成,不存在则查找对应层级的配置,如果有则更新配置
802
+ const ids = []
803
+ const upgradeWidget = (arr, parentId) => {
804
+ arr.forEach(item => {
805
+ const oldId = item.id
806
+ if (parentId) {
807
+ while (ids.includes(item.id)) {
808
+ const code = item.contentType.replace(/-/g, '_')
809
+ item.id = code + '_' + this.$util.genId()
810
+ }
811
+ ids.push(item.id)
812
+ item.i = item.id
813
+ const oldWidgetConifg = this.allComponentConfigs[parentId + '-' + oldId]
814
+ if (oldWidgetConifg) {
815
+ delete this.allComponentConfigs[parentId + '-' + oldId]
816
+ this.allComponentConfigs = { ...this.allComponentConfigs, [item.id]: { ...oldWidgetConifg } }
817
+ }
818
+ }
819
+ if (item.items) {
820
+ upgradeWidget(item.items, parentId ? parentId + '-' + oldId : oldId)
821
+ }
822
+ })
823
+ }
824
+ upgradeWidget(this.selectComponentList)
825
+ this.pageGlobalConfigs.version = this.version
826
+ },
827
+ getReportList () {
828
+ this.reportLoading = true
829
+ this.$http.list({
830
+ entityId: 'FM_REPORT_BASE',
831
+ 'scope.SYSTEM': this.SYSTEM,
832
+ scopeParams: JSON.stringify(this.reportScopeParams),
833
+ page: this.currentReportPage,
834
+ limit: 20
835
+ })
836
+ .then(data => {
837
+ this.reportList = data.entitys
838
+ this.reportTotal = data.total
839
+ this.reportList.forEach(item => (this.reportMap[item.ID] = item))
840
+ setTimeout(() => {
841
+ this.reportLoading = false
842
+ }, 300)
843
+ })
844
+ .catch(err => {
845
+ this.reportLoading = false
846
+ this.$message.error(err.message)
847
+ })
848
+ },
849
+ getThemeList () {
850
+ return this.$http.list({
851
+ entityId: 'FM_CHART_THEME',
852
+ order_field: 'SCOPE,ORDER_NUM',
853
+ order_mode: 'desc,asc',
854
+ scopeParams: [
855
+ { field: 'SCOPE', values: 'frame', link: 'or' },
856
+ { field: 'CLIENT', values: this.CLIENT }
857
+ ]
858
+ })
859
+ .then(data => {
860
+ this.themeList = data.entitys
861
+ return this.themeList
862
+ // if (this.pageGlobalConfigs.theme) this.activeTheme = this.pageGlobalConfigs.theme
863
+ })
864
+ },
865
+ savePreset () {
866
+ this.saveThemeDialog = true
867
+ const themeItem = this.themeList.find(item => item.CODE === this.activeTheme)
868
+ this.themeFormData = {
869
+ STYLE: themeItem?.STYLE
870
+ }
871
+ },
872
+ saveTheme () {
873
+ const formData = {
874
+ SCOPE: 'client'
875
+ }
876
+ for (const key in this.themeFormData) {
877
+ if (!key.includes('#')) {
878
+ formData[key] = this.themeFormData[key]
879
+ }
880
+ }
881
+ if (!this.isEditTheme || !this.themeFormData.ID) formData.CONTENT = JSON.stringify(this.themeStyles)
882
+ const params = {
883
+ entityId: 'FM_CHART_THEME',
884
+ bean: {
885
+ ...formData,
886
+ CLIENT: this.CLIENT,
887
+ SYSTEM: this.SYSTEM
888
+ }
889
+ }
890
+ if (this.themeFormData.ID) {
891
+ params.action = 'update'
892
+ }
893
+ return this.$http.save(params)
894
+ .then(() => {
895
+ this.$message.success(this.$t('save successfully'))
896
+ this.isEditTheme = false
897
+ this.saveThemeDialog = false
898
+ this.getThemeList()
899
+ })
900
+ .catch(err => {
901
+ this.$message.error(err.message || this.$t('fail to save'))
902
+ })
903
+ },
904
+ themeHandleCommand (theme, command) {
905
+ if (command === 'edit') {
906
+ this.saveThemeDialog = true
907
+ this.isEditTheme = true
908
+ this.themeFormData = { ...theme }
909
+ } else if (command === 'remove') {
910
+ this.$confirm('是否删除该预设?', '提示', {
911
+ confirmButtonText: '确定',
912
+ cancelButtonText: '取消',
913
+ type: 'warning'
914
+ }).then(() => {
915
+ this.$http.removeMulti({
916
+ entityId: 'FM_CHART_THEME',
917
+ ids: theme.ID
918
+ })
919
+ .then(() => {
920
+ this.$message.success(this.$t('delete successfully'))
921
+ this.getThemeList()
922
+ })
923
+ .catch(err => {
924
+ this.$message.error(err.message || this.$t('fail to delete'))
925
+ })
926
+ })
927
+ } else if (command === 'config') {
928
+ this.editTheme = theme
929
+ this.isEditTheme = false
930
+ }
931
+ },
932
+ currentReportChange (v) {
933
+ this.currentReportPage = v
934
+ this.getReportList()
935
+ },
936
+ searchReport (v) {
937
+ this.reportScopeParams = v
938
+ this.currentReportPage = 1
939
+ this.getReportList()
940
+ },
941
+ getDashboardList () {
942
+ this.dashboardLoading = true
943
+ this.$http.list({
944
+ entityId: 'FM_PAGE_CONFIG',
945
+ 'scope.SYSTEM': this.SYSTEM,
946
+ 'scope.PAGE|CODE': 'dashboard',
947
+ scopeParams: JSON.stringify(this.dashboardScopeParams),
948
+ page: this.currentDashbaordPage,
949
+ limit: 10
950
+ })
951
+ .then(data => {
952
+ this.dashboardTotal = data.total
953
+ setTimeout(() => {
954
+ this.dashboardLoading = false
955
+ }, 300)
956
+ // 获取所有组件和配置
957
+ data.entitys.forEach(item => {
958
+ const pageConfig = item.CONTENT ? JSON.parse(item.CONTENT) : {}
959
+ const { items = [], itemConfigs = {} } = pageConfig
960
+ const children = []
961
+ items.forEach(comp => {
962
+ children.push({
963
+ ...comp,
964
+ configs: itemConfigs[comp.id] || {}
965
+ })
966
+ if (comp.items) {
967
+ comp.items.forEach(tab => {
968
+ tab.items.forEach(child => {
969
+ children.push({
970
+ ...child,
971
+ configs: itemConfigs[comp.id + '-' + child.id] || {}
972
+ })
973
+ })
974
+ })
975
+ }
976
+ })
977
+ item.children = children
978
+ })
979
+ this.dashboardList = data.entitys.map(item => {
980
+ item.children = item.children.filter(child => child.contentType === 'chart')
981
+ return item
982
+ })
983
+ })
984
+ .catch(err => {
985
+ this.dashboardLoading = false
986
+ this.$message.error(err.message)
987
+ })
988
+ },
989
+ currentDashbaordChange (v) {
990
+ this.currentDashboardPage = v
991
+ this.getDashboardList()
992
+ },
993
+ searchDashboard (v) {
994
+ this.dashboardScopeParams = v
995
+ this.currentDashboardPage = 1
996
+ this.getDashboardList()
997
+ },
998
+ selectReport (item) {
999
+ const index = this.selectedReportList.findIndex(report => report === item.ID)
1000
+ if (index !== -1) {
1001
+ this.selectedReportList.splice(index, 1)
1002
+ this.selectedReportDataList.splice(index, 1)
1003
+ } else {
1004
+ this.selectedReportList.push(item.ID)
1005
+ this.selectedReportDataList.push(item)
1006
+ }
1007
+ },
1008
+ selectDashboardComp (dashbaord, item) {
1009
+ const id = dashbaord.ID + '-' + item.id
1010
+ const index = this.selectedDashboardCompList.findIndex(comp => comp === id)
1011
+ if (index !== -1) {
1012
+ this.selectedDashboardCompList.splice(index, 1)
1013
+ this.selectedDashboardCompDataList.splice(index, 1)
1014
+ } else {
1015
+ this.selectedDashboardCompList.push(id)
1016
+ this.selectedDashboardCompDataList.push(item)
1017
+ }
1018
+ },
1019
+ changeDashboardSelect (dashboard, v) {
1020
+ dashboard.children.forEach(item => {
1021
+ const id = dashboard.ID + '-' + item.id
1022
+ const index = this.selectedDashboardCompList.indexOf(id)
1023
+ if (index !== -1) {
1024
+ if (!v) this.selectedDashboardCompList.splice(index, 1)
1025
+ } else {
1026
+ if (v) this.selectedDashboardCompList.push(id)
1027
+ }
1028
+ })
1029
+ },
1030
+ switchDashboardFoldFn (dashboard) {
1031
+ this.foldDashboardMap[dashboard.ID] = !this.foldDashboardMap[dashboard.ID]
1032
+ },
1033
+ quoteComp () {
1034
+ for (let i = 0; i < this.selectedDashboardCompDataList.length; i++) {
1035
+ const comp = this.selectedDashboardCompDataList[i]
1036
+ if (comp) {
1037
+ this.addComponentToDashboard({
1038
+ w: comp.w,
1039
+ h: comp.h,
1040
+ TITLE: comp.title,
1041
+ CODE: comp.contentType
1042
+ }, { ...comp.configs })
1043
+ }
1044
+ }
1045
+ this.copyComponentDialog = false
1046
+ this.selectedDashboardCompDataList = []
1047
+ this.selectedReportDataList = []
1048
+ this.selectedReportList = []
1049
+ this.selectedDashboardCompList = []
1050
+ },
1051
+ copyReport (id) {
1052
+ return this.$http.save({
1053
+ entityId: 'FM_REPORT_BASE',
1054
+ action: 'copy',
1055
+ oldRecordId: id
1056
+ })
1057
+ },
1058
+ async copyComp () {
1059
+ // 获取选中组件,添加
1060
+ for (let i = 0; i < this.selectedReportDataList.length; i++) {
1061
+ const report = this.selectedReportDataList[i]
1062
+
1063
+ if (report) {
1064
+ const data = await this.copyReport(report.ID)
1065
+ this.addReportToDashboard({ id: data.id })
1066
+ }
1067
+ }
1068
+ for (let i = 0; i < this.selectedDashboardCompDataList.length; i++) {
1069
+ const comp = this.selectedDashboardCompDataList[i]
1070
+ if (comp) {
1071
+ if (comp.contentType === 'report-chart') {
1072
+ const data = await this.copyReport(comp.configs.id)
1073
+ this.addComponentToDashboard({
1074
+ w: comp.w,
1075
+ h: comp.h,
1076
+ TITLE: comp.title,
1077
+ CODE: comp.contentType
1078
+ }, { ...comp.configs, id: data.id })
1079
+ } else {
1080
+ this.addComponentToDashboard({
1081
+ w: comp.w,
1082
+ h: comp.h,
1083
+ TITLE: comp.title,
1084
+ CODE: comp.contentType
1085
+ })
1086
+ }
1087
+ }
1088
+ }
1089
+ this.copyComponentDialog = false
1090
+ this.selectedDashboardCompDataList = []
1091
+ this.selectedReportDataList = []
1092
+ this.selectedReportList = []
1093
+ this.selectedDashboardCompList = []
1094
+ },
1095
+ setReportType (reportType) {
1096
+ this.addReportForm.TYPE = reportType.type
1097
+ if (reportType.type === '1') {
1098
+ this.addReportForm.CHART_TYPE = null
1099
+ } else {
1100
+ this.addReportForm.CHART_TYPE = reportType.chartType
1101
+ }
1102
+ },
1103
+ openAddReportDialog () {
1104
+ this.addReportDialog = true
1105
+ this.addReportForm.OBJECT = this.currentMetaId
1106
+ },
1107
+ saveReport () {
1108
+ if (this.addReportForm.TYPE === 'numStatistic') {
1109
+ const newComp = this.addComponentToDashboard({ TITLE: '数字统计', CODE: 'num-statistic' })
1110
+ if (this.addReportForm.OBJECT) {
1111
+ this.changeItemConfigs(newComp.id, { metaId: this.addReportForm.OBJECT.id })
1112
+ }
1113
+ this.addReportForm = {}
1114
+ this.addReportDialog = false
1115
+ } else if (this.addReportForm.TYPE === 'dashboardTitle') {
1116
+ this.addComponentToDashboard({ TITLE: '标题', CODE: 'dashboard-title', w: 48, h: 3 })
1117
+ this.addReportForm = {}
1118
+ this.addReportDialog = false
1119
+ } else if (this.addReportForm.TYPE === 'dashboardDiv') {
1120
+ this.addComponentToDashboard({ TITLE: '容器', CODE: 'dashboard-div', w: 10, h: 10 })
1121
+ this.addReportForm = {}
1122
+ this.addReportDialog = false
1123
+ } else if (this.addReportForm.TYPE === 'form') {
1124
+ if (!this.addReportForm.FORM_TYPE) {
1125
+ this.$message.error('请选择报表类型')
1126
+ return
1127
+ }
1128
+ this.$http.save({
1129
+ entityId: 'FM_FORM',
1130
+ 'bean.CLIENT': this.CLIENT,
1131
+ 'bean.SYSTEM': this.SYSTEM,
1132
+ 'bean.TYPE': this.addReportForm.FORM_TYPE
1133
+ })
1134
+ .then(data => {
1135
+ this.addComponentToDashboard({ TITLE: '报表', CODE: 'report-html' }, { id: data })
1136
+ this.addReportForm = {}
1137
+ this.addReportDialog = false
1138
+ })
1139
+ .catch(err => this.$message.error(err.message))
1140
+ } else {
1141
+ const metaId = this.addReportForm.OBJECT ? this.addReportForm.OBJECT.id || this.addReportForm.OBJECT : ''
1142
+ const metaViewId = this.addReportForm.OBJECT_VIEW ? this.addReportForm.OBJECT_VIEW.id || this.addReportForm.OBJECT_VIEW : ''
1143
+ this.addChartToDashboard({ type: this.addReportForm.TYPE === '1' ? 'table' : this.addReportForm.CHART_TYPE, metaId, metaViewId })
1144
+ this.addReportForm = {}
1145
+ this.addReportDialog = false
1146
+ }
1147
+ },
1148
+ async back () {
1149
+ if (!await this.confirmLeaveMobile()) return
1150
+ this.mobileDirty = false
1151
+ if (this.newWindow) {
1152
+ window.close()
1153
+ } else if (this.upCompId) {
1154
+ this.backPage()
1155
+ } else {
1156
+ this.$store.commit('DELETE_PAGE', { pageId: this.$query.id })
1157
+ this.backPage({ reload: true })
1158
+ }
1159
+ },
1160
+ getEntityRelation () {
1161
+ this.$http.$get({
1162
+ entityId: 'FM_ENTITY_RELATION',
1163
+ action: 'getEntityRelationTree',
1164
+ mainEntity: this.currentMetaId
1165
+ })
1166
+ .then(data => {
1167
+ data.forEach(relation => {
1168
+ relation.label = relation.title
1169
+ relation.value = relation.flag
1170
+ relation.children = relation.childrens
1171
+ if (relation.childrens) {
1172
+ relation.childrens.forEach(childRelation => {
1173
+ childRelation.value = relation.flag + '#' + childRelation.flag
1174
+ childRelation.label = childRelation.title
1175
+ })
1176
+ }
1177
+ })
1178
+ this.relationList = data
1179
+ })
1180
+ },
1181
+ /**
1182
+ * 获取查询配置
1183
+ */
1184
+ getScopeConfigs () {
1185
+ this.$http.list({
1186
+ action: 'getAllSearchConfig',
1187
+ entityId: 'FM_SEARCH_CONFIG'
1188
+ })
1189
+ .then(data => {
1190
+ this.scopeConfigs = data
1191
+ })
1192
+ },
1193
+ setComponentId (str) {
1194
+ // const formatStr = str.replace(/-/g, '_')
1195
+ // let id = formatStr
1196
+ // let index = 0
1197
+ // const getIsExit = (code, arr = this.selectComponentList) => {
1198
+ // for (const item of arr) {
1199
+ // if (item.id === id) {
1200
+ // return true
1201
+ // } else if (item.items) {
1202
+ // const flag = getIsExit(code, item.items)
1203
+ // if (flag) return flag
1204
+ // }
1205
+ // }
1206
+ // }
1207
+ // while (getIsExit(id)) {
1208
+ // id = formatStr + '_' + ++index
1209
+ // }
1210
+ return str + '_' + this.$util.genId()
1211
+ },
1212
+ changeItemConfigs (key, configs = {}, type, mode) {
1213
+ // 如果在
1214
+ if (key === 'page') {
1215
+ if (configs.componentName !== undefined) {
1216
+ configs.title = configs.componentName
1217
+ delete configs.componentName
1218
+ }
1219
+ // 全局面板的布局扁平键折进 grid(autoHeight 与 grid.rowHeight 'auto' 双向同步);列数变了先问是否按比例换算现有组件
1220
+ const { configs: next, colNum } = mergeGridConfigs(this.pageGlobalConfigs, configs)
1221
+ if (colNum) {
1222
+ this.confirmRescale(colNum).then(rescale => {
1223
+ if (rescale) {
1224
+ rescaleItemsToColNum(this.selectComponentList, colNum.from, colNum.to)
1225
+ this.selectComponentList = [...this.selectComponentList]
1226
+ }
1227
+ this.pageGlobalConfigs = next
1228
+ })
1229
+ return
1230
+ }
1231
+ this.pageGlobalConfigs = next
1232
+ } else {
1233
+ // this.upCompId ? this.upCompId + '-' + key :
1234
+ const compId = key
1235
+ const itemConfig = this.allComponentConfigs[compId] || {}
1236
+ // 组件属性
1237
+ const { flex, layout, direction, justify, align, style, componentName: title, visualComponentName, span, xsspan, items, ...otherConfigs } = configs
1238
+ let componentAttris = {
1239
+ flex,
1240
+ layout,
1241
+ direction,
1242
+ justify,
1243
+ align,
1244
+ style,
1245
+ title,
1246
+ span,
1247
+ xsspan,
1248
+ items
1249
+ }
1250
+ if (type !== 'component') {
1251
+ if (mode === 'cover') {
1252
+ this.allComponentConfigs[compId] = { ...otherConfigs }
1253
+ } else {
1254
+ this.allComponentConfigs[compId] = { ...itemConfig, ...otherConfigs }
1255
+ }
1256
+ } else {
1257
+ componentAttris = { ...componentAttris, ...configs }
1258
+ }
1259
+ // 设置组件属性
1260
+ const selectComponentList = [...this.selectComponentList]
1261
+ const id = key
1262
+ const changeItem = (componentList) => {
1263
+ for (const component of componentList) {
1264
+ if (component.id === id) {
1265
+ for (const attri in componentAttris) {
1266
+ if (componentAttris[attri] !== undefined) {
1267
+ component[attri] = componentAttris[attri]
1268
+ if (component[attri] === null) delete component[attri]
1269
+ }
1270
+ }
1271
+ if (this.selectComponent && compId === this.selectComponent.id) {
1272
+ this.selectComponent = { ...this.selectComponent, ...(this.isMobileDashboard ? { config: { ...component, ...component.configs, ...this.allComponentConfigs[compId] } } : { component }) }
1273
+ }
1274
+ } else if (component.items && component.items.length > 0) {
1275
+ changeItem(component.items)
1276
+ }
1277
+ if (!component.items) component.items = []
1278
+ }
1279
+ }
1280
+ changeItem(selectComponentList)
1281
+ this.selectComponentList = [...selectComponentList]
1282
+ }
1283
+ },
1284
+ // 改列数:询问是否按比例换算现有组件的位置与宽度(取消 = 只改参数、坐标不动)。resolve 布尔值,永不 reject
1285
+ confirmRescale ({ from, to }) {
1286
+ return this.$confirm(`列数将从 ${from} 改为 ${to},按比例换算现有组件位置与宽度?(不换算则组件保持原网格坐标)`, '修改列数', {
1287
+ confirmButtonText: '换算',
1288
+ cancelButtonText: '不换算',
1289
+ customClass: 'dashboard-grid-rescale-confirm',
1290
+ type: 'warning',
1291
+ closeOnClickModal: false
1292
+ }).then(() => true).catch(() => false)
1293
+ },
1294
+ addComponent (component, upId = 'root') {
1295
+ const newComp = {
1296
+ id: component.id,
1297
+ title: component.TITLE,
1298
+ contentType: component.componentName || component.CODE
1299
+ }
1300
+ if (upId === 'root') {
1301
+ // 增加upId配置
1302
+ this.selectComponentList.push(newComp)
1303
+ } else {
1304
+ // 查找其父组件
1305
+ const selectComponentList = [...this.selectComponentList]
1306
+ const ids = upId.split('-')
1307
+ const componentList = ids.reduce((componentList, id) => {
1308
+ const componentItem = componentList.find(item => item.id === id) || {}
1309
+ if (!componentItem.items) componentItem.items = []
1310
+ return componentItem.items
1311
+ }, selectComponentList)
1312
+ componentList.push(newComp)
1313
+ this.selectComponentList = selectComponentList
1314
+ this.$forceUpdate()
1315
+ }
1316
+ },
1317
+ addComponentToDashboard (component, configs) {
1318
+ this.addComponentDialog = false
1319
+ const dashboard = this.$refs.dashboardDesign
1320
+ // 获取最后一个元素的位置
1321
+ let max = 0
1322
+ // let maxItem = null
1323
+ const parent = this.isMobileDashboard && this.mobileAddParent
1324
+ ? indexDashboardItems(this.selectComponentList).get(String(this.mobileAddParent)) : null
1325
+ const destination = parent ? (parent.items || (parent.items = [])) : this.selectComponentList
1326
+ for (const item of (this.isMobileDashboard ? destination : dashboard.layout)) {
1327
+ if (!max) {
1328
+ max = item.y + item.h
1329
+ // maxItem = item
1330
+ } else if (item.y + item.h > max) {
1331
+ max = item.y + item.h
1332
+ // maxItem = item
1333
+ }
1334
+ }
1335
+ const id = this.setComponentId(component.CODE)
1336
+ const newComp = {
1337
+ x: 0,
1338
+ y: max, // puts it at the bottom
1339
+ w: this.isMobileDashboard ? (['num-statistic', 'card-num'].includes(component.CODE) ? this.pageGlobalConfigs.grid.colNum / 2 : this.pageGlobalConfigs.grid.colNum) : component.w || 10,
1340
+ h: component.h || (this.isMobileDashboard && ['chart', 'report-chart', 'dashboard-tabs', 'dashboard-div'].includes(component.CODE) ? 16 : 10),
1341
+ i: id,
1342
+ id: id,
1343
+ title: component.TITLE,
1344
+ contentType: component.CODE
1345
+ }
1346
+ if (this.isMobileDashboard) {
1347
+ if (component.CODE === 'dashboard-tabs') newComp.items = [{ id: 'tabpane_' + this.$util.genId(), name: '标签项1', items: [] }]
1348
+ destination.push(newComp)
1349
+ // 配置更新会替换主布局数组;先插入再写配置,避免向旧数组添加后丢失报表。
1350
+ if (configs) this.changeItemConfigs(id, configs)
1351
+ this.mobileAddParent = null
1352
+ this.$nextTick(() => dashboard.openConfig(newComp))
1353
+ return newComp
1354
+ }
1355
+ dashboard.layout.push(newComp)
1356
+ this.selectComponentList.push(newComp)
1357
+ if (configs) this.changeItemConfigs(id, configs)
1358
+ return newComp
1359
+ },
1360
+ addChartToDashboard (data, configs = {}) {
1361
+ if (data) {
1362
+ this.addComponentToDashboard({ CODE: 'chart', TITLE: '未命名统计报表', ...configs }, { ...data })
1363
+ }
1364
+ },
1365
+ addReportToDashboard (data, configs = {}) {
1366
+ if (data) {
1367
+ this.addComponentToDashboard({ CODE: 'report-chart', TITLE: '报表', ...configs }, { id: data.id })
1368
+ }
1369
+ },
1370
+ addTabsToDashboard () {
1371
+ this.addComponentToDashboard({ CODE: 'dashboard-tabs', TITLE: '标签页' })
1372
+ },
1373
+ deleteSelectComponent (id, e) {
1374
+ e && e.stopPropagation()
1375
+ const selectComponentList = [...this.selectComponentList]
1376
+ const ids = id.split('-')
1377
+ ids.reduce((componentList, id, index) => {
1378
+ if (index === ids.length - 1) {
1379
+ const componentIndex = componentList.findIndex(item => item.id === id) || {}
1380
+ componentList.splice(componentIndex, 1)
1381
+ } else {
1382
+ const componentItem = componentList.find(item => item.id === id) || {}
1383
+ return componentItem.items
1384
+ }
1385
+ }, selectComponentList)
1386
+ this.selectComponentList = selectComponentList
1387
+ this.$forceUpdate()
1388
+ },
1389
+ changeConfigs (id, newConfigs) {
1390
+ const configs = this.componentConfigs[id] || {}
1391
+ this.componentConfigs[id] = { ...configs, ...newConfigs }
1392
+ },
1393
+ deleteConfigs (id) {
1394
+ delete this.allComponentConfigs[id]
1395
+ },
1396
+ pageSetting () {
1397
+ const { visualConfigPath } = this.currentPage
1398
+ const name = this.getVisualComponent({ VISUAL_CONFIG_PATH: visualConfigPath })
1399
+ this.selectComponent = { type: 'page', id: 'page', ...this.currentPage, visualComponentName: name, config: this.pageGlobalConfigs }
1400
+ },
1401
+ // tab:抽屉打开时定位的 tab(chart 项操作条的「布局」按钮传 'style',R29);openSeq 每次打开递增,面板据此区分「打开」与配置改动引起的对象替换
1402
+ clickComponent (componentId, componentInfo, component, upId, tab) {
1403
+ this.openSeq = (this.openSeq || 0) + 1
1404
+ this.selectComponent = { id: componentId, ...componentInfo, config: component, upId, openTab: tab, openSeq: this.openSeq }
1405
+ },
1406
+ scrollToConfig (componentId) {
1407
+ // const component = this.$refs.visualComponent
1408
+ // if (!component) return
1409
+ // const configComponent = component.$refs[`config-${componentId}`]
1410
+ // if (configComponent) {
1411
+ // const el = configComponent.$el || configComponent
1412
+ // const configContainer = this.$refs.configContainer
1413
+ // configContainer.scrollTop = el.offsetTop - 20
1414
+ // }
1415
+ },
1416
+ setComponentConfig (componentList, itemConfigs = {}, upId) {
1417
+ componentList.forEach(component => {
1418
+ const componentId = upId ? upId + '-' + component.id : component.id
1419
+ const configComponentOuter = this.$refs[`config-${component.id}`]
1420
+ if (configComponentOuter) {
1421
+ const configComponent = configComponentOuter.$refs.component
1422
+ if (configComponent) {
1423
+ const configs = configComponent.getConfigs() || {}
1424
+ const { span, flex, componentName } = configs
1425
+ if (span) component.span = span
1426
+ delete component.configs
1427
+ if (componentName) {
1428
+ component.title = componentName
1429
+ delete configs.componentName
1430
+ }
1431
+ if (flex) {
1432
+ component.flex = flex
1433
+ delete configs.flex
1434
+ }
1435
+ const defaulConfigs = itemConfigs[componentId] || {}
1436
+ itemConfigs[componentId] = { ...defaulConfigs, ...configs }
1437
+ }
1438
+ }
1439
+ const { items = [] } = component
1440
+ if (items.length > 0) {
1441
+ this.setComponentConfig(items, itemConfigs, componentId)
1442
+ }
1443
+ })
1444
+ },
1445
+ setContainerDefaultItems (id, items) {
1446
+ if (id === 'page') {
1447
+ const { config: pageConfigs = {} } = this.currentPage || {}
1448
+ if (!pageConfigs.items) this.selectComponentList = items
1449
+ } else {
1450
+ const selectComponentList = [...this.selectComponentList]
1451
+ const ids = id.split('-')
1452
+ ids.reduce((componentList, id, index) => {
1453
+ const componentItem = componentList.find(item => item.id === id) || {}
1454
+ if (!componentItem.items) {
1455
+ if (index === ids.length - 1) componentItem.items = items
1456
+ else componentItem.items = []
1457
+ }
1458
+ return componentItem.items
1459
+ }, selectComponentList)
1460
+
1461
+ this.selectComponentList = selectComponentList
1462
+ }
1463
+ },
1464
+ cancelThemePancel () {
1465
+ if (this.editTheme) {
1466
+ this.editTheme = null
1467
+ } else {
1468
+ this.showPanel = ''
1469
+ this.activeTheme = this.pageGlobalConfigs.theme
1470
+ }
1471
+ // 还原themeStyles
1472
+ this.getConfigThemeStyles()
1473
+ },
1474
+ selectTheme (theme) {
1475
+ this.activeTheme = theme.CODE
1476
+ this.changethemeStyles(JSON.parse(theme.CONTENT))
1477
+ },
1478
+ getConfigThemeStyles () {
1479
+ const { theme, themeStyles } = this.pageGlobalConfigs
1480
+ // 缺少主题时选择经典白;主题列表返回实际 CODE 后同步到页面配置,避免空值覆盖默认选择。
1481
+ let selectedTheme = theme || DEFAULT_DASHBOARD_THEME
1482
+ let themeItem = this.themeList.find(item => item.CODE === selectedTheme)
1483
+ if (!themeItem && selectedTheme === DEFAULT_DASHBOARD_THEME) {
1484
+ themeItem = this.themeList.find(item => item.NAME === '经典白' && item.CODE)
1485
+ if (themeItem) selectedTheme = themeItem.CODE
1486
+ }
1487
+ if (this.pageGlobalConfigs.theme !== selectedTheme) this.pageGlobalConfigs.theme = selectedTheme
1488
+ this.activeTheme = selectedTheme
1489
+ if (themeStyles) {
1490
+ this.styleType = 'custom'
1491
+ this.themeStyles = themeStyles
1492
+ } else {
1493
+ this.styleType = 'presets'
1494
+ this.themeStyles = themeItem?.CONTENT ? (typeof themeItem.CONTENT === 'string' ? JSON.parse(themeItem.CONTENT) : themeItem.CONTENT) : null
1495
+ }
1496
+ },
1497
+ changethemeStyles (v) {
1498
+ this.themeStyles = v
1499
+ // this.changeItemConfigs('page', { themeStyles: v })
1500
+ },
1501
+ setTheme () {
1502
+ if (this.editTheme) {
1503
+ this.themeFormData = { ...this.editTheme }
1504
+ this.saveTheme()
1505
+ .then(() => {
1506
+ this.editTheme = null
1507
+ })
1508
+ } else {
1509
+ this.showPanel = ''
1510
+ if (this.styleType === 'custom') {
1511
+ this.changeItemConfigs('page', { themeStyles: this.themeStyles })
1512
+ } else {
1513
+ this.changeItemConfigs('page', { theme: this.activeTheme, themeStyles: null })
1514
+ }
1515
+ }
1516
+ },
1517
+ delaySaveConfigs () {
1518
+ if (this.chooseDesignTarget || this.choosingDesignTarget) return
1519
+ if (this.isMobileDashboard) {
1520
+ if (this.configReady) {
1521
+ this.mobileDirty = true
1522
+ this.mobileRevision++
1523
+ }
1524
+ return
1525
+ }
1526
+ if (this.timer) {
1527
+ clearTimeout(this.timer)
1528
+ }
1529
+ this.timer = setTimeout(() => {
1530
+ this.saveConfigs()
1531
+ clearTimeout(this.timer)
1532
+ this.timer = null
1533
+ }, 1000)
1534
+ },
1535
+ saveConfigs (event, next, errorFn) {
1536
+ const selectComponentList = [...this.selectComponentList]
1537
+ const rawItemConfigs = { ...this.allComponentConfigs }
1538
+ this.setComponentConfig(selectComponentList, rawItemConfigs, '')
1539
+ // 持久化形态(深拷贝,不影响设计器内存中正在使用的数据):剥离与 id 重复的 i、剥掉漏进 itemConfigs 的网格项布局键(x/y/w/h/i/float/z/static/min·max、容器的 grid);
1540
+ // 下面的空值清洗也只在这份拷贝上做——就地删内存里的键会触发 allComponentConfigs 的 deep watch、多发一次保存
1541
+ const { itemConfigs, ...config } = stripDashboardConfig({ ...this.pageGlobalConfigs, version: this.version, items: selectComponentList, itemConfigs: rawItemConfigs })
1542
+ for (const key in itemConfigs) {
1543
+ const itemConfig = itemConfigs[key]
1544
+ for (const itemKey in itemConfig) {
1545
+ if (itemConfig[itemKey] === null || itemConfig[itemKey] === undefined) {
1546
+ delete itemConfig[itemKey]
1547
+ }
1548
+ }
1549
+ if (this.$_.isEmpty(itemConfig)) {
1550
+ delete itemConfigs[key]
1551
+ }
1552
+ }
1553
+ // 获取所有的配置
1554
+ this.selectComponentList = [...selectComponentList]
1555
+ if (this.upCompId) {
1556
+ // 设置组件和配置
1557
+ const { setCompConfigs } = this.$query
1558
+ setCompConfigs(config, itemConfigs)
1559
+ } else {
1560
+ // 更改组件名称和flex布局
1561
+ config.itemConfigs = itemConfigs
1562
+ return import(/* webpackChunkName: "standalone" */'@babel/standalone')
1563
+ .then(babel => {
1564
+ // 获取页面全局配置
1565
+ const es5 = babel.transform(config.JS || '', { presets: ['env'] })
1566
+ config.compileJS = es5.code
1567
+ for (const key in config) {
1568
+ if (config[key] === null) {
1569
+ delete config[key]
1570
+ }
1571
+ }
1572
+ return this.savePageConfigs(config, next, errorFn)
1573
+ })
1574
+ }
1575
+ },
1576
+ saveGlobalConfigs () {
1577
+ this.pageSettingDrawer = false
1578
+ },
1579
+ savePageConfigs (config) {
1580
+ // 获取全局参数
1581
+ let formParams = {}
1582
+ const globalConfig = this.$refs.globalConfig
1583
+ if (globalConfig) {
1584
+ const formComp = this.getComponentById('form', globalConfig)
1585
+ if (formComp) {
1586
+ formParams = formComp.getFormData()
1587
+ if (!formParams) return
1588
+ }
1589
+ }
1590
+ // 自定义保存目标:常用报表看板写回 FM_CA_REPORT_BOARD.DASHBOARD_CONFIG;
1591
+ // 未配置 saveEntityId 时按原逻辑写 FM_PAGE_CONFIG.CONTENT
1592
+ const saveEntityId = this.$query.saveEntityId
1593
+ const saveField = this.$query.saveField || 'CONTENT'
1594
+ return this.$http.update({
1595
+ entityId: saveEntityId || this.$metaId,
1596
+ ...formParams,
1597
+ [`bean.${this.$metaKey}`]: this.$query.id,
1598
+ [`bean.${saveField}`]: JSON.stringify(config, null, '\t')
1599
+ })
1600
+ .then(data => {
1601
+ // this.$message.success(this.$t('save successfully'))
1602
+ // this.$store.commit('DELETE_PAGE', { pageId: this.$query.id })
1603
+ // 重新获取页面
1604
+ // this.$store.dispatch('ADD_PAGE', { pageId: this.$query.id })
1605
+ if (this.newWindow) {
1606
+ // 直接用 URL 打开设计器时没有 opener,判空以免保存成功却弹错误提示(与 PageDesigner 一致)
1607
+ if (window.opener) window.opener.postMessage({ pageId: this.$query.id, type: 'configPage' }, '/')
1608
+ }
1609
+ return true
1610
+ })
1611
+ .catch(err => {
1612
+ this.$message.error(err.message || this.$t('fail to save'))
1613
+ return false
1614
+ })
1615
+ },
1616
+ switchMobile () {
1617
+ const { mItems } = this.pageGlobalConfigs
1618
+ this.openSuspendedPopup({
1619
+ component: 'visual-config-dashboard-mobile',
1620
+ params: {
1621
+ withHeader: false,
1622
+ componentList: this.selectComponentList,
1623
+ mobileComponentList: mItems,
1624
+ theme: this.activeTheme,
1625
+ themeStyles: this.themeStyles,
1626
+ itemConfigs: this.allComponentConfigs,
1627
+ // 页面全局配置:移动端设计器据其 grid 推网格参数(行高沿用页面、间距换成移动端 [8,8]),与运行态移动端一致
1628
+ globalConfigs: this.pageGlobalConfigs,
1629
+ changeMItems: (v) => {
1630
+ this.pageGlobalConfigs.mItems = v
1631
+ this.mobileComponentList = v
1632
+ }
1633
+ }
1634
+ })
1635
+ },
1636
+ updatePreviewViewport () {
1637
+ this.previewViewportWidth = window.innerWidth
1638
+ this.previewViewportHeight = window.innerHeight
1639
+ },
1640
+ openSuspendedPopup (page) {
1641
+ this.previewSuspended = true
1642
+ this.$nextTick(() => {
1643
+ const previousPopups = new Set(window.openedPopup || [])
1644
+ this.goPage(page)
1645
+ const popup = (window.openedPopup || []).find(item => !previousPopups.has(item) && !item.closed)
1646
+ if (!popup) {
1647
+ this.previewSuspended = false
1648
+ return
1649
+ }
1650
+ if (this.previewPopupTimer) clearInterval(this.previewPopupTimer)
1651
+ this.previewPopupTimer = setInterval(() => {
1652
+ if (!popup.disposed) return
1653
+ clearInterval(this.previewPopupTimer)
1654
+ this.previewPopupTimer = null
1655
+ this.previewSuspended = false
1656
+ }, 200)
1657
+ })
1658
+ },
1659
+ preview () {
1660
+ if (this.isMobileDashboard) {
1661
+ this.updatePreviewViewport()
1662
+ this.mobilePreviewVisible = true
1663
+ return
1664
+ }
1665
+ this.$store.commit('DELETE_PAGE', { pageId: this.$query.id })
1666
+ setTimeout(() => {
1667
+ this.openSuspendedPopup({
1668
+ pageId: this.$query.id
1669
+ })
1670
+ }, 100)
1671
+ }
1672
+ },
1673
+ watch: {
1674
+ pageGlobalConfigs: {
1675
+ handler (v) {
1676
+ if (!this.$_.isEqual(this.oldPageGlobalConfigs, v)) {
1677
+ this.delaySaveConfigs()
1678
+ }
1679
+ // R21:此前误写成 oldSelectComponentList,全局配置一变就把组件列表的对账基线冲掉,保存后替换 selectComponentList 又触发一次保存(每次操作 2 条 POST)
1680
+ this.oldPageGlobalConfigs = this.$_.cloneDeep(v)
1681
+ },
1682
+ deep: true
1683
+ },
1684
+ selectComponentList: {
1685
+ handler (v) {
1686
+ if (!this.$_.isEqual(this.oldSelectComponentList, v)) {
1687
+ this.delaySaveConfigs()
1688
+ }
1689
+ this.oldSelectComponentList = this.$_.cloneDeep(v)
1690
+ },
1691
+ deep: true
1692
+ },
1693
+ allComponentConfigs: {
1694
+ handler (v) {
1695
+ if (!this.$_.isEqual(this.oldAllComponentConfigs, v)) {
1696
+ this.delaySaveConfigs()
1697
+ }
1698
+ this.oldAllComponentConfigs = this.$_.cloneDeep(v)
1699
+ },
1700
+ deep: true
1701
+ }
1702
+ },
1703
+ created () {
1704
+ window.addEventListener('resize', this.updatePreviewViewport)
1705
+ window.addEventListener('beforeunload', this.warnUnsavedMobile)
1706
+ this.removeMobileRouteGuard = this.$router.beforeEach(() => this.confirmLeaveMobile())
1707
+ if (this.showMenu) {
1708
+ this.changeMenuFlag = true
1709
+ this.$store.commit('SWITCH_MENU_SHOW', false)
1710
+ }
1711
+ if (this.showAppNav) {
1712
+ this.changeAppNavFlag = true
1713
+ this.$store.commit('SWITCH_APP_NAV_SHOW', false)
1714
+ }
1715
+ this.getPageInfo()
1716
+ if (this.$query.dashboardType === 'component') {
1717
+ this.getDefaultConfig()
1718
+ }
1719
+ this.getComponentList()
1720
+ this.getReportList()
1721
+ this.getDashboardList()
1722
+ },
1723
+ beforeUnmount () {
1724
+ window.removeEventListener('resize', this.updatePreviewViewport)
1725
+ if (this.previewPopupTimer) clearInterval(this.previewPopupTimer)
1726
+ if (this.timer) clearTimeout(this.timer)
1727
+ window.removeEventListener('beforeunload', this.warnUnsavedMobile)
1728
+ if (this.removeMobileRouteGuard) this.removeMobileRouteGuard()
1729
+ if (this.changeMenuFlag) {
1730
+ this.$store.commit('SWITCH_MENU_SHOW', true)
1731
+ }
1732
+ if (this.changeAppNavFlag) {
1733
+ this.$store.commit('SWITCH_APP_NAV_SHOW', true)
1734
+ }
1735
+ }
1736
+ }
1737
+ </script>
1738
+
1739
+ <style scoped lang="scss">
1740
+ :global(.el-message-box.dashboard-grid-rescale-confirm),
1741
+ :global(.el-message-box.dashboard-leave-confirm) {
1742
+ width: 440px;
1743
+ max-width: min(440px, calc(100vw - 32px));
1744
+ }
1745
+ .design-target-picker {
1746
+ flex: 1;
1747
+ display: flex;
1748
+ flex-direction: column;
1749
+ align-items: center;
1750
+ justify-content: center;
1751
+ gap: 20px;
1752
+ background: var(--epx-bg-page, #f3f5f8);
1753
+ p { color: var(--epx-text-secondary, #909399); }
1754
+ &__options { display: flex; gap: 16px; }
1755
+ }
1756
+ :global(.el-dialog.mobile-dashboard-preview-dialog) {
1757
+ max-width: calc(100vw - 32px);
1758
+ padding: 0;
1759
+ }
1760
+ :global(.mobile-dashboard-preview-dialog .el-dialog__header) {
1761
+ padding: 16px 24px;
1762
+ margin-right: 0;
1763
+ }
1764
+ :global(.mobile-dashboard-preview-dialog .el-dialog__body) {
1765
+ padding: 16px 24px 24px;
1766
+ background: var(--epx-bg-page, #f3f5f8);
1767
+ }
1768
+ .mobile-preview-viewport { margin: 0 auto; }
1769
+ .mobile-preview-phone {
1770
+ position: relative;
1771
+ box-sizing: border-box;
1772
+ transform-origin: top left;
1773
+ padding: 6px;
1774
+ border-radius: 40px;
1775
+ background: #25282e;
1776
+ box-shadow: 0 16px 40px rgba(26, 32, 44, .12), 0 2px 6px rgba(26, 32, 44, .08), 0 0 0 1px #8b9098, inset 0 0 0 1px #555b64;
1777
+ }
1778
+ .mobile-preview-phone__screen {
1779
+ display: flex;
1780
+ flex-direction: column;
1781
+ height: 100%;
1782
+ overflow: hidden;
1783
+ border-radius: 34px;
1784
+ background: #fff;
1785
+ }
1786
+ .mobile-preview-phone__title {
1787
+ flex: none;
1788
+ padding: 0 24px;
1789
+ height: 48px;
1790
+ line-height: 48px;
1791
+ text-align: center;
1792
+ overflow: hidden;
1793
+ white-space: nowrap;
1794
+ text-overflow: ellipsis;
1795
+ border-bottom: 1px solid #eef0f3;
1796
+ color: #20242b;
1797
+ font-size: 16px;
1798
+ font-weight: 600;
1799
+ }
1800
+ .mobile-preview-phone__home {
1801
+ flex: none;
1802
+ display: flex;
1803
+ align-items: center;
1804
+ justify-content: center;
1805
+ height: 22px;
1806
+ span { width: 100px; height: 4px; border-radius: 4px; background: #24272d; }
1807
+ }
1808
+ .mobile-dashboard-preview {
1809
+ flex: 1;
1810
+ min-height: 0;
1811
+ overflow: auto;
1812
+ background: var(--epx-bg-card, #fff);
1813
+ :deep(> .epx-dashboard) { height: 100%; }
1814
+ }
1815
+ .mobile-width-select {
1816
+ width: 100px;
1817
+ margin-right: 12px;
1818
+ }
1819
+ .mobile-save-status {
1820
+ font-size: 12px;
1821
+ color: var(--epx-text-secondary, #909399);
1822
+ margin-right: 12px;
1823
+ }
1824
+ .config-container--mobile-dashboard {
1825
+ .page-preview {
1826
+ padding: 0;
1827
+ min-width: 0;
1828
+ }
1829
+ .function-panel:not(:has(.dashboard-theme)) {
1830
+ display: none;
1831
+ }
1832
+ }
1833
+ .config-container {
1834
+ position: relative;
1835
+ left: -10px;
1836
+ top: -10px;
1837
+ width: calc(100% + 20px);
1838
+ height: calc(100% + 20px);
1839
+ overflow: hidden;
1840
+ display: flex;
1841
+ flex-direction: column;
1842
+ }
1843
+
1844
+ .config-container--new-window {
1845
+ left: 0;
1846
+ top: 0;
1847
+ width: 100%;
1848
+ height: 100%;
1849
+ }
1850
+
1851
+ .page-header {
1852
+ display: flex;
1853
+ align-items: center;
1854
+ padding: 0 20px;
1855
+ height: 46px;
1856
+ background: var(--epx-bg-card);
1857
+ border-bottom: 1px solid #e8e8e8;
1858
+ }
1859
+
1860
+ .page-header__left {
1861
+ display: flex;
1862
+ }
1863
+
1864
+ .page-header__back {
1865
+ font-size: 24px;
1866
+ color: #666;
1867
+ cursor: pointer;
1868
+ }
1869
+
1870
+ .page-title {
1871
+ display: flex;
1872
+ align-items: center;
1873
+ gap: 12px;
1874
+ margin: 0;
1875
+ line-height: 24px;
1876
+ }
1877
+ .page-header__title {
1878
+ font-size: var(--epx-font-size-l);
1879
+ padding: 0 20px;
1880
+ font-weight: 600;
1881
+ border-right: 1px solid var(--epx-border);
1882
+ }
1883
+ .page-header__subtitle {
1884
+ font-size: var(--epx-font-size-base);
1885
+ color: #666;
1886
+ }
1887
+ .page-header__operate {
1888
+ display: flex;
1889
+ align-items: center;
1890
+ margin-left: 24px;
1891
+ }
1892
+ .header-operate__item {
1893
+ color: #444;
1894
+ cursor: pointer;
1895
+ margin: 20px;
1896
+ i {
1897
+ margin-right: 4px;
1898
+ }
1899
+ &:hover {
1900
+ @include font_color_primary
1901
+ }
1902
+ }
1903
+ .page-content {
1904
+ flex:1;
1905
+ display: flex;
1906
+ overflow: hidden;
1907
+ }
1908
+ .page-tabs {
1909
+ width: 50px;
1910
+ height: 100%;
1911
+ background: var(--epx-bg-card);
1912
+ border-right: 1px solid var(--epx-border);
1913
+ padding: 20px 0;
1914
+ flex-shrink: 0;
1915
+ }
1916
+ .page-tabs__item {
1917
+ padding: 10px 0;
1918
+ width: 100%;
1919
+ margin-bottom: 10px;
1920
+ text-align: center;
1921
+ line-height: 1;
1922
+ font-size: var(--epx-font-size-s);
1923
+ color: #444;
1924
+ margin-bottom: 12px;
1925
+ >i {
1926
+ font-size: 24px;
1927
+ display: block;
1928
+ margin-bottom: 8px;
1929
+ }
1930
+ cursor: pointer;
1931
+ &:hover, &.active {
1932
+ @include bg_color_primary(.2);
1933
+ @include font_color_primary
1934
+ }
1935
+ }
1936
+ .page-preview {
1937
+ flex: 1;
1938
+ overflow: hidden;
1939
+ }
1940
+ .config-panel {
1941
+ width: 100%;
1942
+ flex-shrink: 0;
1943
+
1944
+ :deep(.config-container) {
1945
+ width: 100%;
1946
+ left: 0;
1947
+ }
1948
+
1949
+ }
1950
+ .function-panel {
1951
+ position: relative;
1952
+ flex-shrink: 0;
1953
+ }
1954
+ .dashboard-theme {
1955
+ position: absolute;
1956
+ top: 0;
1957
+ background: var(--epx-bg-card);
1958
+ width: 340px;
1959
+ height: 100%;
1960
+ box-sizing: border-box;
1961
+ z-index: 10;
1962
+ display: flex;
1963
+ flex-direction: column;
1964
+ padding-bottom: 12px;
1965
+ }
1966
+ .dashboard-theme__title {
1967
+ font-size: var(--epx-font-size-l);
1968
+ line-height: 32px;
1969
+ display: flex;
1970
+ justify-content: space-between;
1971
+ align-items: center;
1972
+ padding: 12px;
1973
+ border-bottom: 1px solid #e3e3e3;
1974
+ }
1975
+ .dashboard-theme__content {
1976
+ flex: 1;
1977
+ overflow: auto;
1978
+ }
1979
+ .dashboard-theme__list {
1980
+ padding: 0 12px;
1981
+ }
1982
+ .dashboard-theme__item {
1983
+ border: 1px solid var(--epx-border);
1984
+ margin-top: 20px;
1985
+ cursor: pointer;
1986
+ position: relative;
1987
+ &:hover, &.active {
1988
+ @include border_color_primary;
1989
+ }
1990
+ &.active {
1991
+ .dashboard-theme__selected {
1992
+ display: block;
1993
+ }
1994
+ }
1995
+ }
1996
+ .dashboard-theme__selected {
1997
+ display: none;
1998
+ position: absolute;
1999
+ top: 0;
2000
+ right: 0;
2001
+ width: 24px;
2002
+ height: 24px;
2003
+ font-size: 10px;
2004
+ color: #fff;
2005
+ text-align: right;
2006
+ line-height: 24px;
2007
+ span {
2008
+ position: absolute;
2009
+ display: block;
2010
+ width: 0;
2011
+ height: 0;
2012
+ border: 12px solid;
2013
+ @include border_color_primary;
2014
+ border-left-color: transparent!important;
2015
+ border-bottom-color: transparent!important;
2016
+ }
2017
+ i {
2018
+ position: relative;
2019
+ right: 2px;
2020
+ top: -4px;
2021
+ z-index: 1;
2022
+ }
2023
+ }
2024
+ .dashboard-theme__preview {
2025
+ height: 154px;
2026
+ width: 100%;
2027
+ background: #F2F3F7;
2028
+ >img {
2029
+ display: block;
2030
+ width: 100%;
2031
+ height: 100%;
2032
+ object-fit: cover;
2033
+ }
2034
+ }
2035
+ .dashboard-theme__name {
2036
+ padding: 0 16px;
2037
+ line-height: 34px;
2038
+ text-align: center;
2039
+ }
2040
+ .dashboard-theme__name-icon {
2041
+ @include font_color_primary;
2042
+ margin-left: 4px;
2043
+ }
2044
+ .dashboard-theme__footer {
2045
+ position: relative;
2046
+ left: -10px;
2047
+ width: calc(100% + 20px);
2048
+ padding-top: 12px;
2049
+ border-top: 1px solid #e3e3e3;
2050
+ text-align: center;
2051
+ }
2052
+ .page-setting{
2053
+ width: 100%;
2054
+ height: 100%;
2055
+ display: flex;
2056
+ flex-direction: column;
2057
+ }
2058
+ .page-setting__header {
2059
+ height: 46px;
2060
+ padding: 0 16px;
2061
+ display: flex;
2062
+ justify-content: space-between;
2063
+ border-bottom: 1px solid #e3e3e3;
2064
+ align-items: center;
2065
+ >span {
2066
+ font-size: var(--epx-font-size-l);
2067
+ font-weight: 600;
2068
+ color: #222222;
2069
+ position: relative;
2070
+ padding-left: 8px;
2071
+ &::before {
2072
+ content: '';
2073
+ position: absolute;
2074
+ display: block;
2075
+ left: 0;
2076
+ top: 50%;
2077
+ margin-top: -8px;
2078
+ width: 4px;
2079
+ height: 16px;
2080
+ border-radius: var(--epx-radius-s);
2081
+ @include bg_color_primary;
2082
+ }
2083
+ }
2084
+ >i {
2085
+ cursor: pointer;
2086
+ }
2087
+ }
2088
+ .page-setting__content {
2089
+ flex: 1;
2090
+ padding: 20px 0;
2091
+ }
2092
+ .page-setting__footer {
2093
+ padding: 20px 0;
2094
+ text-align: center;
2095
+
2096
+ :deep(.el-button) {
2097
+ margin: 0 12px;
2098
+ }
2099
+
2100
+ }
2101
+ .report-list{
2102
+ display: flex;
2103
+ flex-wrap: wrap;
2104
+ align-content: flex-start;
2105
+ height: 400px;
2106
+ overflow: auto;
2107
+ padding: 0 10px;
2108
+ position: relative;
2109
+ }
2110
+ .report-item {
2111
+ width: calc(25% - 20px);
2112
+ box-sizing: border-box;
2113
+ height: 80px;
2114
+ margin: 10px;
2115
+ line-height: 24px;
2116
+ display: flex;
2117
+ align-items: center;
2118
+ padding: 0 20px;
2119
+ background: #F5F7FA;
2120
+ border-radius: var(--epx-radius-base);
2121
+ position: relative;
2122
+ cursor: pointer;
2123
+ overflow: hidden;
2124
+ i {
2125
+ color: #666;
2126
+ margin-right: 8px;
2127
+ }
2128
+ &.selected {
2129
+ .report-item__select {
2130
+ span {
2131
+ @include bg_color_primary
2132
+ }
2133
+ }
2134
+ }
2135
+ }
2136
+ .report-item__select {
2137
+ position: absolute;
2138
+ right: 0;
2139
+ top: 0;
2140
+ >span {
2141
+ display: block;
2142
+ background: #E2E4E8;
2143
+ width: 36px;
2144
+ height: 36px;
2145
+ transform: rotate(45deg);
2146
+ position: absolute;
2147
+ top: -18px;
2148
+ right: -18px;
2149
+ }
2150
+ >i {
2151
+ position: absolute;
2152
+ top: 2px;
2153
+ right: -6px;
2154
+ font-size: var(--epx-font-size-s);
2155
+ color: #fff;
2156
+ }
2157
+ }
2158
+ .dashboard-list {
2159
+ padding: 0 20px;
2160
+ height: 400px;
2161
+ box-sizing: border-box;
2162
+ overflow: auto;
2163
+ position: relative;
2164
+ }
2165
+ .dashboard-item {
2166
+ background: #F5F7FA;
2167
+ border-radius: var(--epx-radius-s);
2168
+ margin-bottom: 20px;
2169
+ .el-icon-arrow-up {
2170
+ cursor: pointer;
2171
+ transition: all .5s;
2172
+ }
2173
+ &.fold {
2174
+ .dashboard-header {
2175
+ border: 0;
2176
+ }
2177
+ .el-icon-arrow-up {
2178
+ transform: rotate(180deg);
2179
+ }
2180
+ .dashboard-body {
2181
+ display: none;
2182
+ }
2183
+ }
2184
+ }
2185
+ .dashboard-header {
2186
+ display: flex;
2187
+ height: 50px;
2188
+ padding: 0 20px;
2189
+ justify-content: space-between;
2190
+ align-items: center;
2191
+ border-bottom: 1px solid var(--epx-border);
2192
+ }
2193
+
2194
+ .dashboard-comp__list{
2195
+ display: flex;
2196
+ flex-wrap: wrap;
2197
+ padding: 10px;
2198
+ }
2199
+ .dashboard-comp__item {
2200
+ width: calc(25% - 20px);
2201
+ box-sizing: border-box;
2202
+ height: 80px;
2203
+ margin: 10px;
2204
+ line-height: 24px;
2205
+ display: flex;
2206
+ align-items: center;
2207
+ padding: 0 20px;
2208
+ background: var(--epx-bg-card);
2209
+ border-radius: var(--epx-radius-base);
2210
+ position: relative;
2211
+ cursor: pointer;
2212
+ overflow: hidden;
2213
+ &:hover {
2214
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.15);
2215
+ }
2216
+ i {
2217
+ color: #666;
2218
+ margin-right: 8px;
2219
+ }
2220
+ &.selected {
2221
+ .dashboard-comp__item__select {
2222
+ span {
2223
+ @include bg_color_primary
2224
+ }
2225
+ }
2226
+ }
2227
+ }
2228
+ .dashboard-comp__item__select {
2229
+ position: absolute;
2230
+ right: 0;
2231
+ top: 0;
2232
+ >span {
2233
+ display: block;
2234
+ background: #E2E4E8;
2235
+ width: 36px;
2236
+ height: 36px;
2237
+ transform: rotate(45deg);
2238
+ position: absolute;
2239
+ top: -18px;
2240
+ right: -18px;
2241
+ }
2242
+ >i {
2243
+ position: absolute;
2244
+ top: 2px;
2245
+ right: -6px;
2246
+ font-size: var(--epx-font-size-s);
2247
+ color: #fff;
2248
+ }
2249
+ }
2250
+ .dialog-footer {
2251
+ border-top: 1px solid #e3e3e3;
2252
+ padding: 10px 0;
2253
+ text-align: center;
2254
+ }
2255
+ .pagination {
2256
+ padding: 10px;
2257
+ }
2258
+ .dashboard-search {
2259
+ margin: -5px 10px 0;
2260
+
2261
+ :deep(.table-form-item__content) {
2262
+ .el-input, .el-input-number--medium {
2263
+ width: 180px;
2264
+ }
2265
+ }
2266
+
2267
+ }
2268
+ .no-data {
2269
+ width: 100%;
2270
+ text-align: center;
2271
+ color: #999;
2272
+ margin-top: 60px;
2273
+ i {
2274
+ font-size: 100px;
2275
+ }
2276
+ }
2277
+ .add-report-item {
2278
+ display: flex;
2279
+ align-items: center;
2280
+ padding: 10px 0;
2281
+ >label {
2282
+ width: 120px;
2283
+ margin-right: 4px;
2284
+ text-align: right;
2285
+ flex-shrink:0;
2286
+ }
2287
+ }
2288
+ .report-type__list {
2289
+ width: 100%;
2290
+ display: flex;
2291
+ flex-wrap: wrap;
2292
+ }
2293
+ .report-type__item {
2294
+ width: 70px;
2295
+ height: 70px;
2296
+ display: flex;
2297
+ flex-direction: column;
2298
+ justify-content: center;
2299
+ align-items: center;
2300
+ cursor: pointer;
2301
+ line-height: 20px;
2302
+ &:hover {
2303
+ background: #F2F3F7;
2304
+ border-radius: var(--epx-radius-base);
2305
+ }
2306
+ &.active {
2307
+ i, span {
2308
+ @include font_color_primary;
2309
+ }
2310
+ }
2311
+ i {
2312
+ font-size: 18px;
2313
+ color: #666;
2314
+ margin-bottom: 8px;
2315
+ }
2316
+ span {
2317
+ font-size: var(--epx-font-size-s);
2318
+ color: #444
2319
+ }
2320
+ }
2321
+ .add-report-footer {
2322
+ text-align: center;
2323
+ padding: 20px 0;
2324
+
2325
+ :deep(.el-button) {
2326
+ width: 120px;
2327
+ margin: 0 20px;
2328
+ }
2329
+
2330
+ }
2331
+ </style>