@cicctencent/formily 0.0.0-stage → 0.0.1

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 (308) hide show
  1. package/.eslintrc.js +40 -0
  2. package/.prettierrc.js +28 -0
  3. package/.vscode/launch.json +23 -0
  4. package/CHANGELOG.md +8 -0
  5. package/README.md +22 -2
  6. package/babel.config.js +3 -0
  7. package/build/build.js +96 -0
  8. package/build/rollup.config.bundle.js +63 -0
  9. package/build/update.version.js +35 -0
  10. package/dist/index.css +2516 -0
  11. package/dist/index.js +8377 -0
  12. package/dist/schema-field/index.css +2466 -0
  13. package/dist/schema-field/index.js +8213 -0
  14. package/dist/transform/index.js +551 -0
  15. package/dist/validate/index.js +1104 -0
  16. package/dist/vue-form/index.css +2516 -0
  17. package/dist/vue-form/index.js +8359 -0
  18. package/docs/.vuepress/client.ts +15 -0
  19. package/docs/.vuepress/components/code-preview.vue +203 -0
  20. package/docs/.vuepress/components/highlight.ts +53 -0
  21. package/docs/.vuepress/config.ts +39 -0
  22. package/docs/.vuepress/util.ts +7 -0
  23. package/docs/README.md +30 -0
  24. package/docs/components/anyOf.md +26 -0
  25. package/docs/components/array-cards.md +12 -0
  26. package/docs/components/array-collapse.md +12 -0
  27. package/docs/components/array-items.md +12 -0
  28. package/docs/components/array-table.md +12 -0
  29. package/docs/components/array-tabs.md +16 -0
  30. package/docs/components/cascader.md +12 -0
  31. package/docs/components/checkbox.md +12 -0
  32. package/docs/components/event.md +27 -0
  33. package/docs/components/hotArea.md +25 -0
  34. package/docs/components/index.md +4 -0
  35. package/docs/components/input.md +30 -0
  36. package/docs/components/layout-group.md +19 -0
  37. package/docs/components/link.md +22 -0
  38. package/docs/components/oneOf.md +8 -0
  39. package/docs/components/radio.md +12 -0
  40. package/docs/components/rich-editor.md +21 -0
  41. package/docs/components/select.md +34 -0
  42. package/docs/components/space.md +11 -0
  43. package/docs/components/switch.md +20 -0
  44. package/docs/components/text.md +21 -0
  45. package/docs/components/time-picker.md +11 -0
  46. package/docs/components/transfer.md +14 -0
  47. package/docs/components/upload-button.md +28 -0
  48. package/docs/demos/any-of/index.vue +66 -0
  49. package/docs/demos/array-cards/index.vue +105 -0
  50. package/docs/demos/array-collapse/index.vue +155 -0
  51. package/docs/demos/array-items/index.vue +171 -0
  52. package/docs/demos/array-table/index.vue +115 -0
  53. package/docs/demos/array-tabs/index.vue +56 -0
  54. package/docs/demos/cascader/index.vue +297 -0
  55. package/docs/demos/checkbox/index.vue +39 -0
  56. package/docs/demos/event/index.vue +436 -0
  57. package/docs/demos/hotArea/index.vue +240 -0
  58. package/docs/demos/index.vue +36 -0
  59. package/docs/demos/input/index.vue +46 -0
  60. package/docs/demos/layout-group/index.vue +51 -0
  61. package/docs/demos/link/index.vue +32 -0
  62. package/docs/demos/radio/index.vue +36 -0
  63. package/docs/demos/rich-editor/index.vue +22 -0
  64. package/docs/demos/select/index.vue +76 -0
  65. package/docs/demos/space/index.vue +93 -0
  66. package/docs/demos/switch/index.vue +31 -0
  67. package/docs/demos/text/index.vue +38 -0
  68. package/docs/demos/time-picker/index.vue +39 -0
  69. package/docs/demos/transfer/index.vue +26 -0
  70. package/docs/demos/upload-button/index.vue +27 -0
  71. package/docs/demos/x-data/add-button-title.vue +101 -0
  72. package/docs/demos/x-data/send-message.vue +33 -0
  73. package/docs/demos/x-reactions/any-of.vue +40 -0
  74. package/docs/demos/x-reactions/x-reactions.vue +39 -0
  75. package/docs/guide/component-extend.md +23 -0
  76. package/docs/guide/extra-bury-report.md +64 -0
  77. package/docs/guide/schema.md +22 -0
  78. package/docs/guide/x-data.md +41 -0
  79. package/docs/guide/x-reactions.md +20 -0
  80. package/example/.browserslistrc +4 -0
  81. package/example/.eslintrc.js +20 -0
  82. package/example/README.md +24 -0
  83. package/example/index.html +15 -0
  84. package/example/jest.config.js +26 -0
  85. package/example/package.json +50 -0
  86. package/example/public/favicon.ico +0 -0
  87. package/example/public/index.html +17 -0
  88. package/example/src/App.vue +25 -0
  89. package/example/src/assets/logo.png +0 -0
  90. package/example/src/components/HelloWorld.vue +148 -0
  91. package/example/src/components/group/index.vue +16 -0
  92. package/example/src/components/uploadBtn/index.vue +44 -0
  93. package/example/src/components/uploadBtn/upload-icon.svg +6 -0
  94. package/example/src/layout/component/Aside.vue +39 -0
  95. package/example/src/layout/component/Main.vue +9 -0
  96. package/example/src/layout/index.vue +15 -0
  97. package/example/src/main.ts +17 -0
  98. package/example/src/router/index.ts +99 -0
  99. package/example/src/shims-vue.d.ts +6 -0
  100. package/example/src/store/index.ts +9 -0
  101. package/example/src/views/demo/any-of/data.ts +38 -0
  102. package/example/src/views/demo/any-of/index.vue +35 -0
  103. package/example/src/views/demo/array-cards/data.ts +65 -0
  104. package/example/src/views/demo/array-cards/index.vue +33 -0
  105. package/example/src/views/demo/array-items/data.ts +29 -0
  106. package/example/src/views/demo/array-items/index.vue +33 -0
  107. package/example/src/views/demo/cloud-button/data.ts +14 -0
  108. package/example/src/views/demo/cloud-button/index.vue +22 -0
  109. package/example/src/views/demo/color-group/data.ts +15 -0
  110. package/example/src/views/demo/color-group/index.vue +22 -0
  111. package/example/src/views/demo/color-picker/data.ts +21 -0
  112. package/example/src/views/demo/color-picker/index.vue +33 -0
  113. package/example/src/views/demo/datatime/data.ts +62 -0
  114. package/example/src/views/demo/datatime/index.vue +22 -0
  115. package/example/src/views/demo/event/data.ts +184 -0
  116. package/example/src/views/demo/event/index.vue +33 -0
  117. package/example/src/views/demo/hot-area/data.ts +196 -0
  118. package/example/src/views/demo/hot-area/index.vue +33 -0
  119. package/example/src/views/demo/input/data.ts +39 -0
  120. package/example/src/views/demo/input/index.vue +33 -0
  121. package/example/src/views/demo/link/data.ts +23 -0
  122. package/example/src/views/demo/link/index.vue +22 -0
  123. package/example/src/views/demo/one-of/data.ts +139 -0
  124. package/example/src/views/demo/one-of/index.vue +33 -0
  125. package/example/src/views/demo/rich-editor/data.ts +12 -0
  126. package/example/src/views/demo/rich-editor/index.vue +24 -0
  127. package/example/src/views/demo/select/data.ts +38 -0
  128. package/example/src/views/demo/select/index.vue +33 -0
  129. package/example/src/views/demo/upload-button/data1.ts +11 -0
  130. package/example/src/views/demo/upload-button/data2.ts +12 -0
  131. package/example/src/views/demo/upload-button/index.vue +42 -0
  132. package/example/tsconfig.json +32 -0
  133. package/example/vite.config.ts +12 -0
  134. package/jest.config.js +4 -0
  135. package/package.json +92 -4
  136. package/src/components/__builtins__/configs/index.ts +1 -0
  137. package/src/components/__builtins__/index.ts +2 -0
  138. package/src/components/__builtins__/shared/create-context.ts +54 -0
  139. package/src/components/__builtins__/shared/index.ts +7 -0
  140. package/src/components/__builtins__/shared/loading.ts +20 -0
  141. package/src/components/__builtins__/shared/portal.ts +43 -0
  142. package/src/components/__builtins__/shared/resolve-component.ts +22 -0
  143. package/src/components/__builtins__/shared/transform-component.ts +33 -0
  144. package/src/components/__builtins__/shared/types.ts +8 -0
  145. package/src/components/__builtins__/shared/utils.ts +35 -0
  146. package/src/components/__builtins__/styles/common.scss +22 -0
  147. package/src/components/__builtins__/styles/element-plus.scss +1094 -0
  148. package/src/components/any-of/index.ts +20 -0
  149. package/src/components/array-base/index.ts +413 -0
  150. package/src/components/array-base/style.scss +53 -0
  151. package/src/components/array-base/style.ts +2 -0
  152. package/src/components/array-cards/index.ts +253 -0
  153. package/src/components/array-cards/style.scss +33 -0
  154. package/src/components/array-cards/style.ts +7 -0
  155. package/src/components/array-collapse/index.ts +381 -0
  156. package/src/components/array-collapse/style.scss +38 -0
  157. package/src/components/array-collapse/style.ts +10 -0
  158. package/src/components/array-items/index.ts +213 -0
  159. package/src/components/array-items/style.scss +82 -0
  160. package/src/components/array-items/style.ts +4 -0
  161. package/src/components/array-table/index.ts +567 -0
  162. package/src/components/array-table/style.scss +84 -0
  163. package/src/components/array-table/style.ts +11 -0
  164. package/src/components/array-tabs/index.ts +141 -0
  165. package/src/components/array-tabs/style.scss +16 -0
  166. package/src/components/array-tabs/style.ts +5 -0
  167. package/src/components/base/AnyOf/index.ts +155 -0
  168. package/src/components/base/AnyOf/index.vue +111 -0
  169. package/src/components/base/CloudButton/index.ts +46 -0
  170. package/src/components/base/CloudButton/index.vue +128 -0
  171. package/src/components/base/ColorGroup/index.ts +57 -0
  172. package/src/components/base/ColorGroup/index.vue +30 -0
  173. package/src/components/base/ColorPicker/index.ts +45 -0
  174. package/src/components/base/ColorPicker/index.vue +50 -0
  175. package/src/components/base/Container/index.vue +39 -0
  176. package/src/components/base/HotArea/index.ts +698 -0
  177. package/src/components/base/HotArea/index.vue +565 -0
  178. package/src/components/base/HotArea/type.ts +18 -0
  179. package/src/components/base/Input/index.vue +150 -0
  180. package/src/components/base/LayoutGroup/index.vue +40 -0
  181. package/src/components/base/Link/index.vue +43 -0
  182. package/src/components/base/Middleware/index.ts +235 -0
  183. package/src/components/base/Middleware/index.vue +169 -0
  184. package/src/components/base/OneOf/index.ts +105 -0
  185. package/src/components/base/OneOf/index.vue +85 -0
  186. package/src/components/base/RichEditor/index.ts +13 -0
  187. package/src/components/base/RichEditor/index.vue +120 -0
  188. package/src/components/base/RichEditor/options.ts +24 -0
  189. package/src/components/base/Select/index.ts +106 -0
  190. package/src/components/base/Select/index.vue +161 -0
  191. package/src/components/base/Switch/index.vue +42 -0
  192. package/src/components/base/Text/index.vue +47 -0
  193. package/src/components/base/event/index.ts +226 -0
  194. package/src/components/base/event/index.vue +356 -0
  195. package/src/components/cascader/index.ts +48 -0
  196. package/src/components/cascader/style.ts +5 -0
  197. package/src/components/checkbox/index.ts +166 -0
  198. package/src/components/checkbox/style.ts +5 -0
  199. package/src/components/cloud-button/index.ts +21 -0
  200. package/src/components/color-group/index.ts +18 -0
  201. package/src/components/color-picker/index.ts +18 -0
  202. package/src/components/container/index.ts +18 -0
  203. package/src/components/data-time/index.ts +24 -0
  204. package/src/components/date-picker/index.ts +51 -0
  205. package/src/components/date-picker/style.ts +4 -0
  206. package/src/components/editable/index.ts +261 -0
  207. package/src/components/editable/style.scss +55 -0
  208. package/src/components/editable/style.ts +5 -0
  209. package/src/components/el-form-item/index.ts +21 -0
  210. package/src/components/el-form-item/style.ts +3 -0
  211. package/src/components/event/index.ts +16 -0
  212. package/src/components/form/index.ts +94 -0
  213. package/src/components/form/style.scss +0 -0
  214. package/src/components/form/style.ts +3 -0
  215. package/src/components/form-button-group/index.ts +74 -0
  216. package/src/components/form-button-group/style.scss +0 -0
  217. package/src/components/form-button-group/style.ts +4 -0
  218. package/src/components/form-collapse/index.ts +215 -0
  219. package/src/components/form-collapse/style.scss +6 -0
  220. package/src/components/form-collapse/style.ts +4 -0
  221. package/src/components/form-dialog/index.ts +433 -0
  222. package/src/components/form-dialog/style.ts +4 -0
  223. package/src/components/form-drawer/index.ts +424 -0
  224. package/src/components/form-drawer/style.scss +21 -0
  225. package/src/components/form-drawer/style.ts +4 -0
  226. package/src/components/form-grid/index.ts +181 -0
  227. package/src/components/form-grid/style.scss +5 -0
  228. package/src/components/form-grid/style.ts +1 -0
  229. package/src/components/form-item/animation.scss +72 -0
  230. package/src/components/form-item/grid.scss +171 -0
  231. package/src/components/form-item/index.ts +642 -0
  232. package/src/components/form-item/style.scss +521 -0
  233. package/src/components/form-item/style.ts +2 -0
  234. package/src/components/form-item/var.scss +17 -0
  235. package/src/components/form-layout/index.ts +161 -0
  236. package/src/components/form-layout/style.scss +6 -0
  237. package/src/components/form-layout/style.ts +1 -0
  238. package/src/components/form-layout/useResponsiveFormLayout.ts +118 -0
  239. package/src/components/form-step/index.ts +210 -0
  240. package/src/components/form-step/style.ts +2 -0
  241. package/src/components/form-tab/index.ts +172 -0
  242. package/src/components/form-tab/style.scss +6 -0
  243. package/src/components/form-tab/style.ts +4 -0
  244. package/src/components/hot-area/index.ts +20 -0
  245. package/src/components/index.ts +49 -0
  246. package/src/components/input/index.ts +35 -0
  247. package/src/components/input/style.ts +4 -0
  248. package/src/components/input-number/index.ts +36 -0
  249. package/src/components/input-number/style.ts +3 -0
  250. package/src/components/layout-group/index.ts +18 -0
  251. package/src/components/link/index.ts +18 -0
  252. package/src/components/middleware/index.ts +21 -0
  253. package/src/components/one-of/index.ts +20 -0
  254. package/src/components/placeholder-input/index.ts +21 -0
  255. package/src/components/placeholder-input/index.vue +87 -0
  256. package/src/components/preview-text/index.ts +303 -0
  257. package/src/components/preview-text/style.ts +9 -0
  258. package/src/components/radio/index.ts +109 -0
  259. package/src/components/radio/style.ts +3 -0
  260. package/src/components/reset/index.ts +52 -0
  261. package/src/components/reset/style.ts +1 -0
  262. package/src/components/rich-editor/index.ts +18 -0
  263. package/src/components/row/index.ts +20 -0
  264. package/src/components/row/index.vue +53 -0
  265. package/src/components/select/index.ts +19 -0
  266. package/src/components/select/style.ts +5 -0
  267. package/src/components/space/index.ts +98 -0
  268. package/src/components/space/style.scss +24 -0
  269. package/src/components/space/style.ts +1 -0
  270. package/src/components/submit/index.ts +59 -0
  271. package/src/components/submit/style.ts +1 -0
  272. package/src/components/switch/index.ts +9 -0
  273. package/src/components/switch/style.ts +1 -0
  274. package/src/components/text/index.ts +21 -0
  275. package/src/components/time-picker/index.ts +21 -0
  276. package/src/components/time-picker/style.ts +4 -0
  277. package/src/components/transfer/index.ts +12 -0
  278. package/src/components/transfer/style.ts +1 -0
  279. package/src/components/upload/index.ts +136 -0
  280. package/src/components/upload/style.ts +2 -0
  281. package/src/components/upload-button/index.ts +21 -0
  282. package/src/components/upload-button/index.vue +199 -0
  283. package/src/createScemaField.ts +14 -0
  284. package/src/index.ts +41 -0
  285. package/src/schema-field/index.ts +11 -0
  286. package/src/scope.ts +29 -0
  287. package/src/transform/core.ts +404 -0
  288. package/src/transform/index.ts +11 -0
  289. package/src/transform/transform.ts +59 -0
  290. package/src/transform/utils/constant.ts +79 -0
  291. package/src/transform/utils/func.ts +145 -0
  292. package/src/typings/common.ts +37 -0
  293. package/src/typings/vue-shim.d.ts +7 -0
  294. package/src/typings/vue-test-utils.d.ts +11 -0
  295. package/src/utils/anyof_utils.ts +95 -0
  296. package/src/utils/common.ts +15 -0
  297. package/src/validate/index.ts +648 -0
  298. package/src/validate/utils/constant.ts +2 -0
  299. package/src/vue-form/index.ts +18 -0
  300. package/src/vue-form/index.vue +106 -0
  301. package/src/vue-form/useForm.ts +112 -0
  302. package/tests/data/anyof.ts +40 -0
  303. package/tests/data/image.ts +472 -0
  304. package/tests/fixtures/validate.ts +63 -0
  305. package/tests/unit/transform.spec.ts +253 -0
  306. package/tests/unit/utils.spec.ts +10 -0
  307. package/tests/unit/validate.spec.ts +256 -0
  308. package/tsconfig.json +23 -0
@@ -0,0 +1,698 @@
1
+ import {
2
+ computed,
3
+ ref,
4
+ watch,
5
+ onMounted,
6
+ nextTick,
7
+ getCurrentInstance,
8
+ reactive,
9
+ } from 'vue';
10
+ import { EditHotArea } from './type';
11
+ import { cloneDeep } from '@cicctencent/ark-util';
12
+ import Konva from 'konva';
13
+ import { ElMessage, ElMessageBox } from '@cicctencent/jtui';
14
+ import { createForm, onFormInit, onFormValuesChange } from '@formily/core';
15
+ import { useParentForm } from '@formily/vue';
16
+ import { transformSchema } from '../../../transform';
17
+ import { FormilyValidate } from '../../../validate/index';
18
+ export default function (props, emit) {
19
+ const editHotArea = ref<EditHotArea>({});
20
+ // 热区列表
21
+ const list = ref<Array<any>>([]);
22
+ const imgUrl = ref<string>(null);
23
+ const dialogVisible = ref<boolean>(false);
24
+ const ctx = getCurrentInstance();
25
+ /** refs */
26
+ const imgRef = ref();
27
+ const stageRef = ref();
28
+ const layersRef = ref();
29
+ const hotAreaShapesRef = ref();
30
+
31
+ /** use */
32
+ const formRef: any = useParentForm();
33
+
34
+ /** computed */
35
+ const shapeValidator = computed(() => {
36
+ return editHotArea.value.hotArea
37
+ ? !editHotArea.value.hotArea.shape
38
+ : false;
39
+ });
40
+
41
+ const hexValidator = computed(() => {
42
+ return editHotArea.value.hotArea
43
+ ? !editHotArea.value.hotArea.style.hex
44
+ : false;
45
+ });
46
+
47
+ const event = computed(() => JSON.parse(props.event));
48
+ const schemaConfig = computed(() => {
49
+ return transformSchema({ schema: event.value?.properties?.list?.items ?? {}, ctx, layout: "horizontal" });
50
+ });
51
+ const layerShape = computed(() => {
52
+ return editHotArea.value?.hotArea?.shape;
53
+ });
54
+ // 编辑状态: 是否已编辑
55
+ const editorState = computed(() => {
56
+ return props?.value?.length
57
+ })
58
+
59
+ const curSelect = computed(() => {
60
+ // @ts-ignore
61
+ if (editHotArea.value?.hotArea?.usemap) {
62
+ // @ts-ignore
63
+ return editHotArea.value?.hotArea?.usemap;
64
+ }
65
+ return null;
66
+ });
67
+
68
+ const imageList = computed(() => {
69
+ return list.value.filter(v => v.element?.options?.imageUrl);
70
+ });
71
+ /** util */
72
+ // 获取上传的图片地址
73
+ const getUploadImageUrl = (file, done) => {
74
+ const reader = new FileReader();
75
+ // 表单中显示图片
76
+ const image = new Image();
77
+ reader.addEventListener("load", function () {
78
+ // @ts-ignore
79
+ image.src = reader.result;
80
+ }, false);
81
+ reader.readAsDataURL(file.raw);
82
+ image.onload = () => {
83
+ done(image.src);
84
+ renderImage(image.src);
85
+ };
86
+ }
87
+
88
+ // 渲染图片
89
+ const renderImage = (imageUrl) => {
90
+ const index = editHotArea.value.index;
91
+ if (index === undefined) return;
92
+ const { top, left, width, height } = editHotArea.value.hotArea.style;
93
+ if (editHotArea.value.hotArea.shape === 'rect') {
94
+ list.value[index].element = {
95
+ options: { ...list.value[index].element?.options || {}, imageUrl },
96
+ style: {
97
+ top: top + 'px',
98
+ left: left + 'px',
99
+ width: width + 'px',
100
+ height: height + 'px',
101
+ }
102
+ }
103
+ } else {
104
+ list.value[index].element = {
105
+ options: { ...list.value[index].element?.options || {}, imageUrl },
106
+ style: {
107
+ top: top - width + 'px',
108
+ left: left - width + 'px',
109
+ width: width * 2 + 'px',
110
+ height: width * 2 + 'px',
111
+ borderRadius: '50%',
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ const getImgUrl = () => {
118
+ // 从父级遍历查找图片,这种方式解决了层次嵌套的问题
119
+ const parent = formRef.value?.value ?? formRef.value?.values ?? {};
120
+
121
+ if('imgUrl' in parent && parent['imgUrl']){
122
+ imgUrl.value = parent['imgUrl'];
123
+ }
124
+
125
+ return imgUrl.value;
126
+ };
127
+
128
+ /** watch */
129
+ // watch(
130
+ // () => props.value,
131
+ // () => {
132
+ // // init();
133
+ // }
134
+ // );
135
+ // watch(
136
+ // () => dialogVisible.value,
137
+ // val => {
138
+ // if (val) {
139
+ // // 对话框显示的时候,重新初始化
140
+ // // init();
141
+ // }
142
+ // }
143
+ // );
144
+
145
+ /** 生命周期 */
146
+ onMounted(() => {
147
+ // init();
148
+ });
149
+ /** method */
150
+ function init() {
151
+ const data = cloneDeep(props.value);
152
+ // 数据回显
153
+ list.value = data
154
+ .filter(
155
+ (v: any) => v.style && v.style.width > 0 && v.style.height > 0
156
+ )
157
+ .map((v: any, i) => {
158
+ v.style = initStyle(v.style,v?.benchmark);
159
+ const element: any = { style: {} };
160
+ if (v.event.list[0].type === 'mounted') {
161
+ element.options = v.event.list[0].handler.options;
162
+ element.style = {
163
+ top: v.style.top + 'px',
164
+ left: v.style.left + 'px',
165
+ width: v.style.width + 'px',
166
+ height: v.style.height + 'px',
167
+ }
168
+ }
169
+ return {
170
+ ...v,
171
+ config: getSchemaConfig(v.event.list[0].handler.name),
172
+ lastName: v.event.list[0].handler.name,
173
+ form:createForm({
174
+ effects() {
175
+ onFormValuesChange(form => {
176
+ console.log('onFormValuesChange1',form.values)
177
+
178
+
179
+ editHotArea.value.index = i;
180
+ editHotArea.value.hotArea = v;
181
+ // 判断事件名是否修改 (第一次是初始化,不执行)
182
+
183
+ changeEventNameEffect(form,i);
184
+
185
+ });
186
+ onFormInit(form=>{
187
+ form.setValues(v.event.list[0]);
188
+ })
189
+ },
190
+ readOnly: props.readOnly,
191
+ }),
192
+ element,
193
+ };
194
+ });
195
+ }
196
+ /**
197
+ * 修改事件名Effect
198
+ * @param form
199
+ * @param index
200
+ */
201
+ function changeEventNameEffect(form, index){
202
+
203
+ if(list.value.length && list.value[index]?.lastName !== form.values?.handler?.name){
204
+ // 记录事件名
205
+ list.value[index].lastName = form.values?.handler?.name
206
+ // 重新设置Schema
207
+ list.value[index].config = getSchemaConfig(form.values?.handler?.name);
208
+ //回收字段模型
209
+ form.clearFormGraph("handler.options.*")
210
+ }
211
+
212
+ if (list.value.length) {
213
+ const imageUrl = form.values.handler?.options?.imageUrl;
214
+ imageUrl !==undefined && renderImage(imageUrl);
215
+ }
216
+ }
217
+
218
+ // 初始化style,对旧数据进行兼容
219
+ function initStyle(data,benchmark){
220
+
221
+ const stage =stageRef.value?.getNode() ?? null;
222
+ // 热区编辑的宽度
223
+ let curWidth =stage && stage.getWidth();
224
+
225
+
226
+
227
+ // 基准尺寸, 用于还原热区渲染
228
+ const { width:bWidth , height:bHeight } = benchmark
229
+
230
+ // 做兼容,防止出现0有问题
231
+ if(!curWidth || !bWidth){
232
+ return data;
233
+ }
234
+ // 如果不相等,说明是旧版的热区信息
235
+ if(curWidth !== bWidth){
236
+ // 变动的比例
237
+ let scale = 0;
238
+ if(bWidth - curWidth > 0){
239
+ // 旧数据的热区宽度比目前的热区宽度大
240
+ // 拿到大的比例
241
+ scale = (bWidth - curWidth) / bWidth;
242
+ }else{
243
+ // 旧数据的热区宽度比目前的热区宽度小
244
+ // 拿到小的比例
245
+ scale = (bWidth - curWidth)/curWidth;
246
+ }
247
+ // 生成新的style
248
+ let newStyle:any = {};
249
+ if(scale > 0){
250
+ // 比例是正的,说明以前的配置比现在的配置大,需要对热区进行缩小
251
+ newStyle.height = data?.height - data?.height * scale;
252
+ newStyle.left = data?.left - data?.left * scale;
253
+ newStyle.top = data?.top - data?.top * scale;
254
+ newStyle.width =data?.width - data?.width * scale;
255
+ }else{
256
+ // 比例是负的,说明以前的配置比现在的配置小,需要对热区进行放大
257
+ newStyle.height = data?.height + data?.height * scale;
258
+ newStyle.left = data?.left + data?.left * scale;
259
+ newStyle.top = data?.top + data?.top * scale;
260
+ newStyle.width =data?.width + data?.width * scale;
261
+ }
262
+
263
+ return Object.assign({},data,newStyle);
264
+ }
265
+ // 相等不需要做处理
266
+ return data;
267
+ }
268
+
269
+ function onEventChange(evt: any) {
270
+ editHotArea.value.hotArea.event = cloneDeep(evt.newValue);
271
+ }
272
+
273
+ function openDialog() {
274
+ if (getImgUrl()) {
275
+ dialogVisible.value = true;
276
+ init();
277
+ } else {
278
+ ElMessage.error({message: '请先上传图片', zIndex: 9999});
279
+ }
280
+ }
281
+
282
+ async function onDialogOpened() {
283
+ // 绘制区域的宽高必须与图片一致
284
+ let rect: any = {};
285
+
286
+ if (!imgRef.value.complete) {
287
+ await new Promise((resolve, reject) => {
288
+ imgRef.value.onload = () => {
289
+ rect = imgRef.value.getBoundingClientRect();
290
+ resolve(true);
291
+ };
292
+ });
293
+ await nextTick(function () { });
294
+ } else {
295
+ rect = imgRef.value.getBoundingClientRect();
296
+ }
297
+
298
+ const stage = stageRef.value.getNode();
299
+ stage.setWidth(rect.width);
300
+ stage.setHeight(rect.height);
301
+ init();
302
+ stage.on('click tap', e => {
303
+ // 如果点击的空白区域, 则去掉所有 transformers
304
+ if (e.target === stage) {
305
+ editHotArea.value.hotArea = undefined;
306
+ editHotArea.value.index = undefined;
307
+ editHotArea.value.shape = undefined;
308
+
309
+ const trs = stage.find('.transformer');
310
+ if (trs.length) {
311
+ trs.forEach(v => v.destroy());
312
+ }
313
+ const layer = layersRef.value.getNode();
314
+ layer.draw();
315
+ return;
316
+ }
317
+ // 如果点击的不是热区区域, 则不处理
318
+ if (!e.target.name().startsWith('hotarea')) {
319
+ return;
320
+ }
321
+ // 去掉所有 transformers, 重新绘制 transformers
322
+ // 也可以判断下当前选择状态是否有 transformers
323
+ const trs = stage.find('.transformer');
324
+ if (trs.length) {
325
+ trs.forEach(v => v.destroy());
326
+ }
327
+
328
+ // create new transformer
329
+ var tr = new Konva.Transformer({
330
+ name: 'transformer',
331
+ rotateEnabled: false,
332
+ });
333
+ e.target.parent.add(tr);
334
+ tr.nodes([e.target]);
335
+ e.target.parent.draw();
336
+ });
337
+ }
338
+ function onTransformendEnd(e) {
339
+ editHotArea.value.tr = null;
340
+ const { element = { style: {} }, style, shape } = editHotArea.value.hotArea;
341
+ style.top = e.target.y();
342
+ style.left = e.target.x();
343
+ if (shape === 'rect') {
344
+ style.width = e.target.width() * e.target.scaleX();
345
+ style.height = e.target.height() * e.target.scaleY();
346
+ element.style.top = style.top + 'px';
347
+ element.style.left = style.left + 'px';
348
+ element.style.width = style.width + 'px';
349
+ element.style.height = style.height + 'px';
350
+ } else {
351
+ style.width = e.target.width() * e.target.scaleX() / 2;
352
+ element.style.top = style.top - style.width + 'px';
353
+ element.style.left = style.left - style.width + 'px';
354
+ element.style.width = style.width * 2 + 'px';
355
+ element.style.height = style.width * 2 + 'px';
356
+ element.style.borderRadius = '50%';
357
+ }
358
+ e.target.scaleX(1);
359
+ e.target.scaleY(1);
360
+ // this.$forceUpdate();
361
+ }
362
+ function onDialogClose() {
363
+ const stage = stageRef.value.getNode();
364
+ // stage.off('click tap');
365
+ // stage.destroy();
366
+ }
367
+ function onDialogClosed() {
368
+ editHotArea.value = {};
369
+ if (props.value && props.value.length) {
370
+ list.value = cloneDeep(props.value);
371
+ } else {
372
+ list.value = [];
373
+ }
374
+ }
375
+
376
+ function onShapeClick(i) {
377
+ editHotArea.value.hotArea = list.value[i];
378
+ editHotArea.value.index = i;
379
+ // this.$forceUpdate()
380
+ }
381
+
382
+ function onShapeChange(e, i) {
383
+
384
+ if(layerShape.value === e){
385
+ // 重复点击
386
+ return;
387
+ }
388
+
389
+ const shape = hotAreaShapesRef.value[i];
390
+ const shapeNode = shape.getNode();
391
+ const shapeNodeAttrs = shapeNode.attrs;
392
+ const item = list.value[i];
393
+ item.element = { ...item.element, style: {} };
394
+ const scaleX = shapeNodeAttrs.scaleX || 1;
395
+ const scaleY = shapeNodeAttrs.scaleY || 1;
396
+ if (e === 'rect') {
397
+ // 圆形 => 方形
398
+ item.style.top = shapeNodeAttrs.y - shapeNodeAttrs.radius * scaleY;
399
+ item.style.left = shapeNodeAttrs.x - shapeNodeAttrs.radius * scaleX;
400
+ item.style.width = shapeNodeAttrs.radius * scaleX * 2;
401
+ item.style.height = shapeNodeAttrs.radius * scaleY * 2;
402
+ item.shape = 'rect';
403
+ item.element.style.top = item.style.top + 'px';
404
+ item.element.style.left = item.style.left + 'px';
405
+ item.element.style.width = item.style.width + 'px';
406
+ item.element.style.height = item.style.height + 'px';
407
+ } else if (e === 'circle') {
408
+ // 方形 => 圆形
409
+ item.style.top =
410
+ shapeNodeAttrs.y + (shapeNodeAttrs.height * scaleY) / 2;
411
+ item.style.left =
412
+ shapeNodeAttrs.x + (shapeNodeAttrs.width * scaleX) / 2;
413
+ item.style.width = (shapeNodeAttrs.width * scaleX) / 2;
414
+ item.shape = 'circle';
415
+ item.element.style.top = item.style.top - item.style.width + 'px';
416
+ item.element.style.left = shapeNodeAttrs.x + 'px';
417
+ item.element.style.width = shapeNodeAttrs.width * scaleX + 'px';
418
+ item.element.style.height = shapeNodeAttrs.width * scaleX + 'px';
419
+ item.element.style.borderRadius = '50%';
420
+ }
421
+ const trs = shapeNode.parent.find('.transformer');
422
+ if (trs && trs[0]) {
423
+ nextTick(function () {
424
+ const shapeUpdated = hotAreaShapesRef.value[i];
425
+ const shapeUpdatedNode = shapeUpdated.getNode();
426
+ trs[0].nodes([shapeUpdatedNode]);
427
+ trs[0].update();
428
+ });
429
+ }
430
+ shapeNode.parent.draw();
431
+ }
432
+ function onStageMouseDown(e) {
433
+ if (!e?.evt) {
434
+ return;
435
+ }
436
+ // 拖动变化大小时, 不需要后续逻辑
437
+ if (
438
+ e.target &&
439
+ e.target.parent &&
440
+ e.target.parent.hasName('transformer')
441
+ ) {
442
+ editHotArea.value.tr = e.target.parent;
443
+ return;
444
+ }
445
+ // 操作已有热区
446
+ if (e.target && e.target.name().startsWith('hotarea')) {
447
+ editHotArea.value.shape = e.target;
448
+ return;
449
+ }
450
+ // 按下删除按钮
451
+ if(e.target && e.target.name().startsWith('delete-hotarea')){
452
+ onHotAreaDelete(curSelect.value);
453
+ return;
454
+ }
455
+
456
+ // 非操作已有热区, 则记录原点, 并生成热区配置
457
+ const origin = { x: e.evt.layerX, y: e.evt.layerY };
458
+ editHotArea.value.shape = null;
459
+ editHotArea.value.origin = origin;
460
+ list.value.push({
461
+ style: {
462
+ left: origin.x,
463
+ top: origin.y,
464
+ width: 0,
465
+ height: 0,
466
+ hex: '#e9bc8280',
467
+ },
468
+ link: undefined,
469
+ shape: 'rect',
470
+ usemap: '#' + Date.now().toString(),
471
+ event: {},
472
+ });
473
+ // 加index 形成闭包, 解决之前使用list.value.length - 1, 导致我操作第一个热区,结果倒数第一热区发生了改变
474
+ let index = list.value.length - 1;
475
+ list.value[list.value.length -1].config = cloneDeep(getSchemaConfig(null));
476
+ list.value[index].form = createForm({
477
+ effects() {
478
+ onFormValuesChange(form => {
479
+ console.log('onFormValuesChange1',form.values)
480
+ changeEventNameEffect(form,index)
481
+ editHotArea.value.index = list.value.length - 1;
482
+ editHotArea.value.hotArea = list.value[list.value.length - 1];
483
+ });
484
+ },
485
+ })
486
+ }
487
+
488
+
489
+ function getSchemaConfig(name){
490
+ // 动态Schema
491
+ try {
492
+ const DYNAMIC_INJECT_SCHEMA = cloneDeep(event.value.properties.list.items.properties.handler.properties.options)
493
+ let config;
494
+ if(!DYNAMIC_INJECT_SCHEMA[name]){
495
+ config = cloneDeep(event.value.properties.list.items)
496
+ config.properties.handler.properties.options.properties = {}
497
+ }else{
498
+ // 存在动态schema
499
+ config = cloneDeep(event.value.properties.list.items)
500
+ config.properties.handler.properties.options = DYNAMIC_INJECT_SCHEMA[name]
501
+ }
502
+ return transformSchema({ schema: cloneDeep(config) ?? {}, ctx, layout: "horizontal" });
503
+ } catch (error) {
504
+ console.error('err getSchemaConfig', error)
505
+ }
506
+
507
+ }
508
+
509
+ function onStageMouseMove(e) {
510
+ if (!e?.evt) {
511
+ return;
512
+ }
513
+ // 如果是拖动编辑热区大小, 无需后续响应
514
+ // 如果是编辑已有热区, 则是移动位置, 这里不用响应
515
+ if (editHotArea.value.tr || editHotArea.value.shape) {
516
+ return;
517
+ }
518
+ // 如果没有原点记录 origin, 也不需要响应
519
+ if (!editHotArea.value.origin) {
520
+ return;
521
+ }
522
+ // 最后一个热区就是当前编辑热区
523
+ const hotArea = list.value[list.value.length - 1];
524
+ if (!hotArea) {
525
+ return;
526
+ }
527
+ const end = { x: e.evt.layerX, y: e.evt.layerY };
528
+ const origin = editHotArea.value.origin;
529
+ hotArea.style.left = Math.min(end.x, origin.x);
530
+ hotArea.style.top = Math.min(end.y, origin.y);
531
+ hotArea.style.width = Math.abs(end.x - origin.x);
532
+ hotArea.style.height = Math.abs(origin.y - end.y);
533
+ }
534
+ function onStageMouseUp(e) {
535
+ if (!e?.evt) {
536
+ return;
537
+ }
538
+ // 编辑已有热区, 这里不用响应
539
+ if (editHotArea.value.tr || editHotArea.value.shape) {
540
+ return;
541
+ }
542
+ const end = { x: e.evt.layerX, y: e.evt.layerY };
543
+ const origin = editHotArea.value.origin;
544
+ const offsetX = Math.abs(end.x - origin.x);
545
+ const offsetY = Math.abs(end.y - origin.y);
546
+ if (offsetX < 20 || offsetY < 20) {
547
+ // ElMessage.error('热区区域面积过小, 不利于操作, 请重新设置');
548
+ list.value.splice(list.value.length - 1, 1);
549
+ }
550
+ editHotArea.value.origin = null;
551
+ }
552
+ function onShapeDragEnd(e, i) {
553
+ if (editHotArea.value.shape) {
554
+ editHotArea.value.shape = undefined;
555
+ }
556
+ if (e?.target?.attrs) {
557
+ const item = list.value[i];
558
+ const attrs = e?.target?.attrs;
559
+ item.style.left = attrs.x;
560
+ item.style.top = attrs.y;
561
+ if (!item.element) item.element = { style: {} };
562
+ if (attrs.type === 'rect') {
563
+ item.style.width = attrs.width;
564
+ item.style.height = attrs.height;
565
+ item.element.style.left = attrs.x +'px';
566
+ item.element.style.top = attrs.y +'px';
567
+ item.element.style.width = attrs.width +'px';
568
+ item.element.style.height = attrs.height +'px';
569
+ } else {
570
+ item.style.width = attrs.radius;
571
+ item.element.style.left = attrs.x - attrs.radius + 'px';
572
+ item.element.style.top = attrs.y - attrs.radius + 'px';
573
+ item.element.style.width = attrs.radius * 2 + 'px';
574
+ item.element.style.height = attrs.radius * 2 + 'px';
575
+ item.element.style.borderRadius = '50%';
576
+ }
577
+ }
578
+ }
579
+ async function onCancel() {
580
+ // ElMessageBox.confirm('此操作将不会保存所做变更,确认取消?', '提示', {
581
+ // confirmButtonText: '确定',
582
+ // cancelButtonText: '取消',
583
+ // type: 'warning',
584
+ // }).then(val => {
585
+ // //todo 取消操作
586
+ // dialogVisible.value = false;
587
+ // });
588
+ dialogVisible.value = false;
589
+ }
590
+ function onConfirm() {
591
+ if (shapeValidator.value || hexValidator.value) return;
592
+ const hotAreas = list.value.map((v, i) => {
593
+ const shape = hotAreaShapesRef.value[i];
594
+ const shapeNode = shape.getNode();
595
+ const shapeAttrs = shapeNode.attrs;
596
+ const hotArea = { ...v };
597
+
598
+ hotArea.shape = shapeNode.name().replace('hotarea-', '');
599
+ hotArea.style.top = shapeAttrs.y;
600
+ hotArea.style.left = shapeAttrs.x;
601
+
602
+ // TODO: 不好改 schema, 先再每一个热区中增加基准尺寸, 用于还原热区渲染, 后面改 schema, 把基准挪出去
603
+ const stage = stageRef.value.getNode();
604
+ hotArea.benchmark = {
605
+ width: stage.attrs.width,
606
+ height: stage.attrs.height,
607
+ };
608
+
609
+ if (hotArea.shape === 'rect') {
610
+ hotArea.style.width = shapeAttrs.width;
611
+ hotArea.style.height = shapeAttrs.height;
612
+ } else if (hotArea.shape === 'circle') {
613
+ hotArea.style.width = shapeAttrs.radius;
614
+ }
615
+ return hotArea;
616
+ });
617
+ list.value = hotAreas;
618
+
619
+ let forms = list.value.map(m => m.form);
620
+ forms.forEach(form => form.validate())
621
+ let valideFlag = true;
622
+ for(let i = 0; i<list.value.length;i++){
623
+ const res = new FormilyValidate({ schema: list.value[i].config, data: list.value[i].form.values }).validate();
624
+ if(res.length || !list.value[i].form.values?.handler?.name){
625
+ valideFlag = false;
626
+ break;
627
+ }
628
+ }
629
+
630
+ if (valideFlag) {
631
+ ElMessage.success('设置成功');
632
+ const datas = list.value.map(m => {
633
+ const data = {...m.form.values }
634
+ data.handler = Object.assign(data.handler || {}, { _validateKey: data?.handler?.name})
635
+ return {
636
+ style: m?.style ?? {},
637
+ shape: m?.shape,
638
+ usemap: m?.usemap,
639
+ event: {
640
+ list: [{ ...data }],
641
+ },
642
+ benchmark: m?.benchmark ?? {},
643
+ };
644
+ });
645
+ emit('change', datas);
646
+ dialogVisible.value = false;
647
+ }else{
648
+ ElMessage.error({message: "请完善信息再提交", zIndex: 9999});
649
+ }
650
+ }
651
+ function onHotAreaDelete(usemap) {
652
+ const layer = layersRef.value;
653
+ const layerNode = layer.getNode();
654
+ const trs = layerNode.find('.transformer');
655
+ if (trs.length) {
656
+ trs.forEach(v => v.destroy());
657
+ }
658
+
659
+ const index = list.value.findIndex(m => m.usemap === usemap);
660
+
661
+ list.value.splice(index, 1);
662
+ editHotArea.value.hotArea = undefined;
663
+ editHotArea.value.index = undefined;
664
+ editHotArea.value.shape = null;
665
+ }
666
+ return {
667
+ hexValidator,
668
+ shapeValidator,
669
+ stageRef,
670
+ imgRef,
671
+ imgUrl,
672
+ layersRef,
673
+ hotAreaShapesRef,
674
+ dialogVisible,
675
+ list,
676
+ layerShape,
677
+ editHotArea,
678
+ curSelect,
679
+ editorState,
680
+ onHotAreaDelete,
681
+ onConfirm,
682
+ onCancel,
683
+ onShapeDragEnd,
684
+ onStageMouseUp,
685
+ onStageMouseMove,
686
+ onStageMouseDown,
687
+ onShapeChange,
688
+ onShapeClick,
689
+ onDialogClosed,
690
+ onDialogClose,
691
+ onTransformendEnd,
692
+ onDialogOpened,
693
+ openDialog,
694
+ onEventChange,
695
+ getUploadImageUrl,
696
+ imageList,
697
+ };
698
+ }